From 06d1877811fa6aa97dddc0e03bcde4e766928c87 Mon Sep 17 00:00:00 2001 From: vovanec Date: Thu, 7 Feb 2008 13:36:34 +0000 Subject: new directory structure git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@232 90c681e8-e032-0410-971d-27865f9a5e38 --- src/CMakeLists.txt | 2 + src/aboutdialog.cpp | 63 - src/aboutdialog.h | 44 - src/aboutdialog.ui | 174 -- src/addurldialog.cpp | 67 - src/addurldialog.h | 51 - src/addurldialog.ui | 76 - src/balancebar.cpp | 132 - src/balancebar.h | 66 - src/button.cpp | 58 - src/button.h | 54 - src/configdialog.cpp | 469 ---- src/configdialog.h | 78 - src/configdialog.ui | 1118 --------- src/default/balance.png | Bin 1464 -> 0 bytes src/default/cbuttons.png | Bin 3148 -> 0 bytes src/default/eq_ex.png | Bin 4423 -> 0 bytes src/default/eqmain.png | Bin 34985 -> 0 bytes src/default/main.png | Bin 25055 -> 0 bytes src/default/monoster.png | Bin 1060 -> 0 bytes src/default/numbers.png | Bin 210 -> 0 bytes src/default/playpaus.png | Bin 179 -> 0 bytes src/default/pledit.png | Bin 19730 -> 0 bytes src/default/pledit.txt | 6 - src/default/posbar.png | Bin 3279 -> 0 bytes src/default/shufrep.png | Bin 2560 -> 0 bytes src/default/text.png | Bin 525 -> 0 bytes src/default/titlebar.png | Bin 11329 -> 0 bytes src/default/viscolor.txt | 24 - src/default/volume.png | Bin 1727 -> 0 bytes src/display.cpp | 290 --- src/display.h | 106 - src/dock.cpp | 257 -- src/dock.h | 63 - src/eqgraph.cpp | 163 -- src/eqgraph.h | 56 - src/eqpreset.cpp | 56 - src/eqpreset.h | 47 - src/eqslider.cpp | 147 -- src/eqslider.h | 71 - src/eqtitlebar.cpp | 182 -- src/eqtitlebar.h | 73 - src/eqwidget.cpp | 417 ---- src/eqwidget.h | 103 - src/fft.c | 296 --- src/fft.h | 45 - src/filedialog.cpp | 299 --- src/filedialog.h | 109 - src/fileloader.cpp | 108 - src/fileloader.h | 72 - src/html/about_cs.html | 81 - src/html/about_en.html | 81 - src/html/about_ru.html | 81 - src/html/about_zh_CN.html | 81 - src/html/authors_cs.txt | 12 - src/html/authors_en.txt | 12 - src/html/authors_ru.txt | 9 - src/html/authors_zh_CN.txt | 16 - src/html/thanks_cs.txt | 3 - src/html/thanks_en.txt | 3 - src/html/thanks_ru.txt | 3 - src/html/thanks_zh_CN.txt | 3 - src/images/advanced.png | Bin 757 -> 0 bytes src/images/images.qrc | 14 - src/images/interface.png | Bin 779 -> 0 bytes src/images/logo-qmmp.png | Bin 61213 -> 0 bytes src/images/pause.png | Bin 315 -> 0 bytes src/images/play.png | Bin 364 -> 0 bytes src/images/playlist.png | Bin 383 -> 0 bytes src/images/plugins.png | Bin 471 -> 0 bytes src/images/qmmp.xpm | 278 --- src/images/stop.png | Bin 323 -> 0 bytes src/inlines.h | 505 ---- src/jumptotrackdialog.cpp | 128 - src/jumptotrackdialog.h | 62 - src/jumptotrackdialog.ui | 110 - src/keyboardmanager.cpp | 260 -- src/keyboardmanager.h | 71 - src/listwidget.cpp | 482 ---- src/listwidget.h | 126 - src/logscale.cpp | 74 - src/logscale.h | 31 - src/mainvisual.cpp | 628 ----- src/mainvisual.h | 172 -- src/mainwindow.cpp | 819 ------ src/mainwindow.h | 140 -- src/mediafile.cpp | 162 -- src/mediafile.h | 78 - src/monostereo.cpp | 68 - src/monostereo.h | 50 - src/mp3player.cpp | 48 - src/number.cpp | 45 - src/number.h | 49 - src/pixmapwidget.cpp | 46 - src/pixmapwidget.h | 50 - src/playlist.cpp | 471 ---- src/playlist.h | 124 - src/playlistcontrol.cpp | 55 - src/playlistcontrol.h | 52 - src/playlistformat.cpp | 289 --- src/playlistformat.h | 120 - src/playlistmodel.cpp | 899 ------- src/playlistmodel.h | 377 --- src/playlistslider.cpp | 135 - src/playlistslider.h | 63 - src/playlisttitlebar.cpp | 284 --- src/playlisttitlebar.h | 78 - src/playstate.cpp | 138 - src/playstate.h | 109 - src/playstatus.cpp | 63 - src/playstatus.h | 55 - src/pluginitem.cpp | 152 -- src/pluginitem.h | 112 - src/plugins/CMakeLists.txt | 4 + src/plugins/Effect/CMakeLists.txt | 8 + src/plugins/Effect/Effect.pro | 4 + src/plugins/Effect/srconverter/CMakeLists.txt | 76 + .../srconverter/effectsrconverterfactory.cpp | 57 + .../Effect/srconverter/effectsrconverterfactory.h | 46 + src/plugins/Effect/srconverter/settingsdialog.cpp | 48 + src/plugins/Effect/srconverter/settingsdialog.h | 46 + src/plugins/Effect/srconverter/settingsdialog.ui | 124 + src/plugins/Effect/srconverter/srconverter.cpp | 125 + src/plugins/Effect/srconverter/srconverter.h | 59 + src/plugins/Effect/srconverter/srconverter.pro | 34 + src/plugins/General/General.pro | 4 + src/plugins/General/dbuscontrol/dbusadaptor.cpp | 62 + src/plugins/General/dbuscontrol/dbusadaptor.h | 47 + src/plugins/General/dbuscontrol/dbuscontrol.cpp | 61 + src/plugins/General/dbuscontrol/dbuscontrol.h | 43 + src/plugins/General/dbuscontrol/dbuscontrol.pro | 39 + .../General/dbuscontrol/dbuscontrolfactory.cpp | 55 + .../General/dbuscontrol/dbuscontrolfactory.h | 45 + src/plugins/General/scrobbler/scrobbler.cpp | 259 ++ src/plugins/General/scrobbler/scrobbler.h | 75 + src/plugins/General/scrobbler/scrobbler.pro | 41 + src/plugins/General/scrobbler/scrobblerfactory.cpp | 59 + src/plugins/General/scrobbler/scrobblerfactory.h | 45 + src/plugins/General/scrobbler/settingsdialog.cpp | 51 + src/plugins/General/scrobbler/settingsdialog.h | 48 + src/plugins/General/scrobbler/settingsdialog.ui | 92 + src/plugins/General/statusicon/images/images.qrc | 8 + .../General/statusicon/images/tray_pause.png | Bin 0 -> 569 bytes .../General/statusicon/images/tray_play.png | Bin 0 -> 706 bytes .../General/statusicon/images/tray_stop.png | Bin 0 -> 503 bytes src/plugins/General/statusicon/settingsdialog.cpp | 55 + src/plugins/General/statusicon/settingsdialog.h | 48 + src/plugins/General/statusicon/settingsdialog.ui | 173 ++ src/plugins/General/statusicon/statusicon.cpp | 109 + src/plugins/General/statusicon/statusicon.h | 58 + src/plugins/General/statusicon/statusicon.pro | 36 + .../General/statusicon/statusiconfactory.cpp | 59 + src/plugins/General/statusicon/statusiconfactory.h | 45 + src/plugins/Input/CMakeLists.txt | 49 + src/plugins/Input/Input.pro | 26 + src/plugins/Input/ffmpeg/CMakeLists.txt | 94 + src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp | 342 +++ src/plugins/Input/ffmpeg/decoder_ffmpeg.h | 78 + src/plugins/Input/ffmpeg/decoderffmpegfactory.cpp | 93 + src/plugins/Input/ffmpeg/decoderffmpegfactory.h | 54 + src/plugins/Input/ffmpeg/detailsdialog.cpp | 103 + src/plugins/Input/ffmpeg/detailsdialog.h | 45 + src/plugins/Input/ffmpeg/detailsdialog.ui | 332 +++ src/plugins/Input/ffmpeg/ffmpeg.pro | 35 + .../Input/ffmpeg/translations/ffmpeg_plugin_cs.ts | 150 ++ .../Input/ffmpeg/translations/ffmpeg_plugin_ru.qm | Bin 0 -> 2221 bytes .../Input/ffmpeg/translations/ffmpeg_plugin_ru.ts | 149 ++ .../Input/ffmpeg/translations/translations.qrc | 6 + src/plugins/Input/flac/CMakeLists.txt | 86 + src/plugins/Input/flac/decoder_flac.cpp | 567 +++++ src/plugins/Input/flac/decoder_flac.h | 124 + src/plugins/Input/flac/decoderflacfactory.cpp | 95 + src/plugins/Input/flac/decoderflacfactory.h | 54 + src/plugins/Input/flac/detailsdialog.cpp | 118 + src/plugins/Input/flac/detailsdialog.h | 49 + src/plugins/Input/flac/detailsdialog.ui | 349 +++ src/plugins/Input/flac/flac.pro | 36 + .../Input/flac/translations/flac_plugin_ru.qm | Bin 0 -> 2218 bytes .../Input/flac/translations/flac_plugin_ru.ts | 154 ++ .../Input/flac/translations/translations.qrc | 6 + src/plugins/Input/mad/CMakeLists.txt | 90 + src/plugins/Input/mad/decoder_mad.cpp | 572 +++++ src/plugins/Input/mad/decoder_mad.h | 95 + src/plugins/Input/mad/decodermadfactory.cpp | 188 ++ src/plugins/Input/mad/decodermadfactory.h | 53 + src/plugins/Input/mad/detailsdialog.cpp | 294 +++ src/plugins/Input/mad/detailsdialog.h | 63 + src/plugins/Input/mad/detailsdialog.ui | 392 +++ src/plugins/Input/mad/mad.pro | 39 + src/plugins/Input/mad/settingsdialog.cpp | 107 + src/plugins/Input/mad/settingsdialog.h | 52 + src/plugins/Input/mad/settingsdialog.ui | 306 +++ .../Input/mad/translations/mad_plugin_ru.qm | Bin 0 -> 3625 bytes .../Input/mad/translations/mad_plugin_ru.ts | 242 ++ .../Input/mad/translations/translations.qrc | 6 + src/plugins/Input/mad/ui_detailsdialog.h | 400 +++ src/plugins/Input/mad/ui_settingsdialog.h | 245 ++ src/plugins/Input/mpc/CMakeLists.txt | 86 + src/plugins/Input/mpc/Makefile | 254 ++ src/plugins/Input/mpc/decoder_mpc.cpp | 386 +++ src/plugins/Input/mpc/decoder_mpc.h | 80 + src/plugins/Input/mpc/decodermpcfactory.cpp | 95 + src/plugins/Input/mpc/decodermpcfactory.h | 54 + src/plugins/Input/mpc/detailsdialog.cpp | 115 + src/plugins/Input/mpc/detailsdialog.h | 49 + src/plugins/Input/mpc/detailsdialog.ui | 349 +++ src/plugins/Input/mpc/mpc.pro | 32 + .../Input/mpc/translations/mpc_plugin_ru.qm | Bin 0 -> 2230 bytes .../Input/mpc/translations/mpc_plugin_ru.ts | 149 ++ .../Input/mpc/translations/translations.qrc | 6 + src/plugins/Input/sndfile/CMakeLists.txt | 74 + src/plugins/Input/sndfile/decoder_sndfile.cpp | 282 +++ src/plugins/Input/sndfile/decoder_sndfile.h | 66 + .../Input/sndfile/decodersndfilefactory.cpp | 126 + src/plugins/Input/sndfile/decodersndfilefactory.h | 54 + src/plugins/Input/sndfile/sndfile.pro | 28 + src/plugins/Input/vorbis/CMakeLists.txt | 96 + src/plugins/Input/vorbis/decoder_vorbis.cpp | 425 ++++ src/plugins/Input/vorbis/decoder_vorbis.h | 63 + src/plugins/Input/vorbis/decodervorbisfactory.cpp | 105 + src/plugins/Input/vorbis/decodervorbisfactory.h | 54 + src/plugins/Input/vorbis/detailsdialog.cpp | 120 + src/plugins/Input/vorbis/detailsdialog.h | 49 + src/plugins/Input/vorbis/detailsdialog.ui | 384 +++ .../Input/vorbis/translations/translations.qrc | 6 + .../Input/vorbis/translations/vorbis_plugin_ru.qm | Bin 0 -> 2569 bytes .../Input/vorbis/translations/vorbis_plugin_ru.ts | 164 ++ src/plugins/Input/vorbis/vorbis.pro | 35 + .../Misc/CommandLineOptions/IncDecVolumeOption.pro | 2 + .../IncDecVolumeOption/IncDecVolumeOption.pro | 26 + .../CommandLineOptions/IncDecVolumeOption/Makefile | 301 +++ .../IncDecVolumeOption/incdecvolumeoption.cpp | 53 + .../IncDecVolumeOption/incdecvolumeoption.h | 23 + src/plugins/Misc/FileDialogs/FileDialogs.pro | 3 + src/plugins/Misc/FileDialogs/Makefile | 134 + .../FileDialogs/QmmpFileDialog/QmmpFileDialog.pro | 28 + .../FileDialogs/QmmpFileDialog/images/cdup.png | Bin 0 -> 736 bytes .../FileDialogs/QmmpFileDialog/images/detail.png | Bin 0 -> 551 bytes .../FileDialogs/QmmpFileDialog/images/images.qrc | 8 + .../FileDialogs/QmmpFileDialog/images/list.png | Bin 0 -> 547 bytes .../FileDialogs/QmmpFileDialog/qmmpfiledialog.cpp | 44 + .../FileDialogs/QmmpFileDialog/qmmpfiledialog.h | 40 + .../FileDialogs/QmmpFileDialog/qmmpfiledialog.ui | 216 ++ .../QmmpFileDialog/qmmpfiledialogimpl.cpp | 109 + .../QmmpFileDialog/qmmpfiledialogimpl.h | 33 + .../FileDialogs/Qt3FileDialog/Qt3FileDialog.pro | 28 + .../FileDialogs/Qt3FileDialog/qt3filedialog.cpp | 35 + .../Misc/FileDialogs/Qt3FileDialog/qt3filedialog.h | 23 + .../Qt3FileDialog/qt3filedialogfactory.cpp | 20 + .../Qt3FileDialog/qt3filedialogfactory.h | 19 + src/plugins/Misc/FileDialogs/Qt3FileDialog/readme | 14 + src/plugins/Misc/FileDialogs/libQmmpFileDialog.so | Bin 0 -> 137806 bytes src/plugins/Misc/FileDialogs/libQt3FileDialog.so | Bin 0 -> 104681 bytes .../CSVPlaylistFormat/CSVPlaylistFormat.pro | 20 + .../PlaylistFormats/CSVPlaylistFormat/Makefile | 213 ++ .../CSVPlaylistFormat/csvplaylistformat.cpp | 72 + .../CSVPlaylistFormat/csvplaylistformat.h | 33 + .../CSVPlaylistFormat/moc_csvplaylistformat.cpp | 64 + .../Misc/PlaylistFormats/CSVPlaylistFormat/readme | 12 + src/plugins/Misc/PlaylistFormats/Makefile | 112 + .../Misc/PlaylistFormats/PlaylistFormats.pro | 2 + .../Misc/PlaylistFormats/libCSVPlaylistFormat.so | Bin 0 -> 38452 bytes src/plugins/Output/CMakeLists.txt | 24 + src/plugins/Output/Output.pro | 26 + src/plugins/Output/alsa/CMakeLists.txt | 65 + src/plugins/Output/alsa/alsa.pro | 37 + src/plugins/Output/alsa/outputalsa.cpp | 539 ++++ src/plugins/Output/alsa/outputalsa.h | 85 + src/plugins/Output/alsa/outputalsafactory.cpp | 63 + src/plugins/Output/alsa/outputalsafactory.h | 48 + src/plugins/Output/alsa/settingsdialog.cpp | 237 ++ src/plugins/Output/alsa/settingsdialog.h | 59 + src/plugins/Output/alsa/settingsdialog.ui | 261 ++ .../Output/alsa/translations/alsa_plugin_cs.ts | 90 + .../Output/alsa/translations/alsa_plugin_ru.qm | Bin 0 -> 1580 bytes .../Output/alsa/translations/alsa_plugin_ru.ts | 89 + .../Output/alsa/translations/translations.qrc | 6 + src/plugins/Output/jack/CMakeLists.txt | 74 + src/plugins/Output/jack/bio2jack.c | 2635 ++++++++++++++++++++ src/plugins/Output/jack/bio2jack.h | 145 ++ src/plugins/Output/jack/jack.pro | 33 + src/plugins/Output/jack/outputjack.cpp | 208 ++ src/plugins/Output/jack/outputjack.h | 49 + src/plugins/Output/jack/outputjackfactory.cpp | 60 + src/plugins/Output/jack/outputjackfactory.h | 48 + .../Output/jack/translations/jack_plugin_ru.qm | Bin 0 -> 540 bytes .../Output/jack/translations/jack_plugin_ru.ts | 26 + .../Output/jack/translations/translations.qrc | 6 + src/plugins/Output/oss/CMakeLists.txt | 67 + src/plugins/Output/oss/oss.pro | 36 + src/plugins/Output/oss/outputoss.cpp | 505 ++++ src/plugins/Output/oss/outputoss.h | 76 + src/plugins/Output/oss/outputossfactory.cpp | 70 + src/plugins/Output/oss/outputossfactory.h | 48 + src/plugins/Output/oss/settingsdialog.cpp | 60 + src/plugins/Output/oss/settingsdialog.h | 47 + src/plugins/Output/oss/settingsdialog.ui | 309 +++ .../Output/oss/translations/oss_plugin_cs.ts | 90 + src/plugins/Visual/CMakeLists.txt | 8 + src/plugins/Visual/Visual.pro | 3 + src/plugins/Visual/analyzer/CMakeLists.txt | 70 + src/plugins/Visual/analyzer/analyzer.cpp | 308 +++ src/plugins/Visual/analyzer/analyzer.h | 102 + src/plugins/Visual/analyzer/analyzer.pro | 35 + src/plugins/Visual/analyzer/colorwidget.cpp | 56 + src/plugins/Visual/analyzer/colorwidget.h | 50 + src/plugins/Visual/analyzer/fft.c | 296 +++ src/plugins/Visual/analyzer/fft.h | 45 + src/plugins/Visual/analyzer/inlines.h | 505 ++++ src/plugins/Visual/analyzer/settingsdialog.cpp | 62 + src/plugins/Visual/analyzer/settingsdialog.h | 46 + src/plugins/Visual/analyzer/settingsdialog.ui | 403 +++ .../Visual/analyzer/visualanalyzerfactory.cpp | 57 + .../Visual/analyzer/visualanalyzerfactory.h | 46 + src/plugins/plugins.pri | 2 + src/plugins/plugins.pro | 7 + src/positionbar.cpp | 137 - src/positionbar.h | 72 - src/preseteditor.cpp | 79 - src/preseteditor.h | 57 - src/preseteditor.ui | 88 - src/qmmp/CMakeLists.txt | 68 + src/qmmp/buffer.h | 44 + src/qmmp/constants.h | 19 + src/qmmp/decoder.cpp | 409 +++ src/qmmp/decoder.h | 197 ++ src/qmmp/decoderfactory.h | 64 + src/qmmp/downloader.cpp | 344 +++ src/qmmp/downloader.h | 86 + src/qmmp/effect.cpp | 148 ++ src/qmmp/effect.h | 87 + src/qmmp/effectfactory.h | 53 + src/qmmp/equ/iir.c | 85 + src/qmmp/equ/iir.h | 84 + src/qmmp/equ/iir_cfs.c | 237 ++ src/qmmp/equ/iir_cfs.h | 39 + src/qmmp/equ/iir_fpu.c | 210 ++ src/qmmp/equ/iir_fpu.h | 39 + src/qmmp/filetag.cpp | 100 + src/qmmp/filetag.h | 67 + src/qmmp/output.cpp | 269 ++ src/qmmp/output.h | 208 ++ src/qmmp/outputfactory.h | 53 + src/qmmp/qmmp.pro | 66 + src/qmmp/recycler.cpp | 120 + src/qmmp/recycler.h | 49 + src/qmmp/soundcore.cpp | 440 ++++ src/qmmp/soundcore.h | 208 ++ src/qmmp/streamreader.cpp | 139 ++ src/qmmp/streamreader.h | 85 + src/qmmp/visual.cpp | 151 ++ src/qmmp/visual.h | 69 + src/qmmp/visualfactory.h | 50 + src/qmmpstarter.cpp | 158 -- src/qmmpstarter.h | 72 - src/qmmpui/general.cpp | 157 ++ src/qmmpui/general.h | 86 + src/qmmpui/generalfactory.h | 52 + src/qmmpui/generalhandler.cpp | 143 ++ src/qmmpui/generalhandler.h | 69 + src/qmmpui/qmmpui.pro | 38 + src/qmmpui/songinfo.cpp | 137 + src/qmmpui/songinfo.h | 76 + src/shadedbar.cpp | 139 -- src/shadedbar.h | 77 - src/shadedvisual.cpp | 205 -- src/shadedvisual.h | 69 - src/skin.cpp | 771 ------ src/skin.h | 340 --- src/skinreader.cpp | 144 -- src/skinreader.h | 46 - src/src.pro | 152 -- src/stuff.qrc | 28 - src/symboldisplay.cpp | 91 - src/symboldisplay.h | 64 - src/textscroller.cpp | 116 - src/textscroller.h | 66 - src/timeindicator.cpp | 127 - src/timeindicator.h | 63 - src/titlebar.cpp | 226 -- src/titlebar.h | 82 - src/titlebarcontrol.cpp | 58 - src/titlebarcontrol.h | 54 - src/togglebutton.cpp | 81 - src/togglebutton.h | 61 - src/translations/qmmp_cs.ts | 716 ------ src/translations/qmmp_locales.qrc | 8 - src/translations/qmmp_ru.qm | Bin 8812 -> 0 bytes src/translations/qmmp_ru.ts | 645 ----- src/translations/qmmp_tr.qm | Bin 8960 -> 0 bytes src/translations/qmmp_tr.ts | 644 ----- src/translations/qmmp_zh_CN.qm | Bin 7081 -> 0 bytes src/translations/qmmp_zh_CN.ts | 507 ---- src/ui/aboutdialog.cpp | 63 + src/ui/aboutdialog.h | 44 + src/ui/addurldialog.cpp | 67 + src/ui/addurldialog.h | 51 + src/ui/balancebar.cpp | 132 + src/ui/balancebar.h | 66 + src/ui/button.cpp | 58 + src/ui/button.h | 54 + src/ui/commandlineoption.cpp | 216 ++ src/ui/commandlineoption.h | 94 + src/ui/configdialog.cpp | 509 ++++ src/ui/configdialog.h | 80 + src/ui/default/balance.png | Bin 0 -> 1464 bytes src/ui/default/cbuttons.png | Bin 0 -> 3148 bytes src/ui/default/eq_ex.png | Bin 0 -> 4423 bytes src/ui/default/eqmain.png | Bin 0 -> 34985 bytes src/ui/default/main.png | Bin 0 -> 25055 bytes src/ui/default/monoster.png | Bin 0 -> 1060 bytes src/ui/default/numbers.png | Bin 0 -> 210 bytes src/ui/default/playpaus.png | Bin 0 -> 179 bytes src/ui/default/pledit.png | Bin 0 -> 19730 bytes src/ui/default/pledit.txt | 6 + src/ui/default/posbar.png | Bin 0 -> 3279 bytes src/ui/default/shufrep.png | Bin 0 -> 2560 bytes src/ui/default/text.png | Bin 0 -> 525 bytes src/ui/default/titlebar.png | Bin 0 -> 11329 bytes src/ui/default/viscolor.txt | 24 + src/ui/default/volume.png | Bin 0 -> 1727 bytes src/ui/display.cpp | 290 +++ src/ui/display.h | 106 + src/ui/dock.cpp | 257 ++ src/ui/dock.h | 63 + src/ui/eqgraph.cpp | 163 ++ src/ui/eqgraph.h | 56 + src/ui/eqpreset.cpp | 56 + src/ui/eqpreset.h | 47 + src/ui/eqslider.cpp | 147 ++ src/ui/eqslider.h | 71 + src/ui/eqtitlebar.cpp | 182 ++ src/ui/eqtitlebar.h | 73 + src/ui/eqwidget.cpp | 417 ++++ src/ui/eqwidget.h | 103 + src/ui/fft.c | 296 +++ src/ui/fft.h | 45 + src/ui/filedialog.cpp | 296 +++ src/ui/filedialog.h | 109 + src/ui/fileloader.cpp | 108 + src/ui/fileloader.h | 72 + src/ui/forms/aboutdialog.ui | 174 ++ src/ui/forms/addurldialog.ui | 76 + src/ui/forms/configdialog.ui | 944 +++++++ src/ui/forms/jumptotrackdialog.ui | 110 + src/ui/forms/preseteditor.ui | 88 + src/ui/html/about_cs.html | 81 + src/ui/html/about_en.html | 81 + src/ui/html/about_ru.html | 81 + src/ui/html/about_zh_CN.html | 81 + src/ui/html/authors_cs.txt | 12 + src/ui/html/authors_en.txt | 12 + src/ui/html/authors_ru.txt | 9 + src/ui/html/authors_zh_CN.txt | 16 + src/ui/html/thanks_cs.txt | 3 + src/ui/html/thanks_en.txt | 3 + src/ui/html/thanks_ru.txt | 3 + src/ui/html/thanks_zh_CN.txt | 3 + src/ui/images/advanced.png | Bin 0 -> 1420 bytes src/ui/images/images.qrc | 12 + src/ui/images/interface.png | Bin 0 -> 1439 bytes src/ui/images/logo-qmmp.png | Bin 0 -> 61213 bytes src/ui/images/network.png | Bin 0 -> 1953 bytes src/ui/images/playlist.png | Bin 0 -> 1085 bytes src/ui/images/plugins.png | Bin 0 -> 2237 bytes src/ui/images/qmmp.xpm | 278 +++ src/ui/inlines.h | 505 ++++ src/ui/jumptotrackdialog.cpp | 128 + src/ui/jumptotrackdialog.h | 62 + src/ui/keyboardmanager.cpp | 260 ++ src/ui/keyboardmanager.h | 71 + src/ui/listwidget.cpp | 482 ++++ src/ui/listwidget.h | 126 + src/ui/logscale.cpp | 74 + src/ui/logscale.h | 31 + src/ui/mainvisual.cpp | 628 +++++ src/ui/mainvisual.h | 172 ++ src/ui/mainwindow.cpp | 848 +++++++ src/ui/mainwindow.h | 141 ++ src/ui/mediafile.cpp | 169 ++ src/ui/mediafile.h | 79 + src/ui/monostereo.cpp | 68 + src/ui/monostereo.h | 50 + src/ui/mp3player.cpp | 48 + src/ui/number.cpp | 45 + src/ui/number.h | 49 + src/ui/pixmapwidget.cpp | 46 + src/ui/pixmapwidget.h | 50 + src/ui/playlist.cpp | 471 ++++ src/ui/playlist.h | 124 + src/ui/playlistcontrol.cpp | 55 + src/ui/playlistcontrol.h | 52 + src/ui/playlistformat.cpp | 287 +++ src/ui/playlistformat.h | 116 + src/ui/playlistmodel.cpp | 899 +++++++ src/ui/playlistmodel.h | 377 +++ src/ui/playlistslider.cpp | 135 + src/ui/playlistslider.h | 63 + src/ui/playlisttitlebar.cpp | 284 +++ src/ui/playlisttitlebar.h | 78 + src/ui/playstate.cpp | 138 + src/ui/playstate.h | 109 + src/ui/playstatus.cpp | 63 + src/ui/playstatus.h | 55 + src/ui/pluginitem.cpp | 182 ++ src/ui/pluginitem.h | 132 + src/ui/positionbar.cpp | 137 + src/ui/positionbar.h | 72 + src/ui/preseteditor.cpp | 79 + src/ui/preseteditor.h | 57 + src/ui/qmmpstarter.cpp | 154 ++ src/ui/qmmpstarter.h | 73 + src/ui/shadedbar.cpp | 139 ++ src/ui/shadedbar.h | 77 + src/ui/shadedvisual.cpp | 205 ++ src/ui/shadedvisual.h | 69 + src/ui/skin.cpp | 771 ++++++ src/ui/skin.h | 340 +++ src/ui/skinreader.cpp | 148 ++ src/ui/skinreader.h | 46 + src/ui/stuff.qrc | 28 + src/ui/symboldisplay.cpp | 91 + src/ui/symboldisplay.h | 64 + src/ui/textscroller.cpp | 116 + src/ui/textscroller.h | 66 + src/ui/timeindicator.cpp | 127 + src/ui/timeindicator.h | 63 + src/ui/titlebar.cpp | 226 ++ src/ui/titlebar.h | 82 + src/ui/titlebarcontrol.cpp | 58 + src/ui/titlebarcontrol.h | 54 + src/ui/togglebutton.cpp | 81 + src/ui/togglebutton.h | 61 + src/ui/translations/qmmp_cs.ts | 716 ++++++ src/ui/translations/qmmp_locales.qrc | 8 + src/ui/translations/qmmp_ru.qm | Bin 0 -> 8812 bytes src/ui/translations/qmmp_ru.ts | 645 +++++ src/ui/translations/qmmp_tr.qm | Bin 0 -> 8960 bytes src/ui/translations/qmmp_tr.ts | 644 +++++ src/ui/translations/qmmp_zh_CN.qm | Bin 0 -> 7081 bytes src/ui/translations/qmmp_zh_CN.ts | 507 ++++ src/ui/ui.pro | 149 ++ src/ui/unixdomainsocket.cpp | 67 + src/ui/unixdomainsocket.h | 46 + src/ui/version.h | 11 + src/ui/visualmenu.cpp | 53 + src/ui/visualmenu.h | 40 + src/ui/volumebar.cpp | 130 + src/ui/volumebar.h | 71 + src/unixdomainsocket.cpp | 67 - src/unixdomainsocket.h | 46 - src/version.h | 11 - src/visualmenu.cpp | 53 - src/visualmenu.h | 40 - src/volumebar.cpp | 130 - src/volumebar.h | 71 - 556 files changed, 48239 insertions(+), 20558 deletions(-) delete mode 100644 src/aboutdialog.cpp delete mode 100644 src/aboutdialog.h delete mode 100644 src/aboutdialog.ui delete mode 100644 src/addurldialog.cpp delete mode 100644 src/addurldialog.h delete mode 100644 src/addurldialog.ui delete mode 100644 src/balancebar.cpp delete mode 100644 src/balancebar.h delete mode 100644 src/button.cpp delete mode 100644 src/button.h delete mode 100644 src/configdialog.cpp delete mode 100644 src/configdialog.h delete mode 100644 src/configdialog.ui delete mode 100644 src/default/balance.png delete mode 100644 src/default/cbuttons.png delete mode 100644 src/default/eq_ex.png delete mode 100644 src/default/eqmain.png delete mode 100644 src/default/main.png delete mode 100644 src/default/monoster.png delete mode 100644 src/default/numbers.png delete mode 100644 src/default/playpaus.png delete mode 100644 src/default/pledit.png delete mode 100644 src/default/pledit.txt delete mode 100644 src/default/posbar.png delete mode 100644 src/default/shufrep.png delete mode 100644 src/default/text.png delete mode 100644 src/default/titlebar.png delete mode 100644 src/default/viscolor.txt delete mode 100644 src/default/volume.png delete mode 100644 src/display.cpp delete mode 100644 src/display.h delete mode 100644 src/dock.cpp delete mode 100644 src/dock.h delete mode 100644 src/eqgraph.cpp delete mode 100644 src/eqgraph.h delete mode 100644 src/eqpreset.cpp delete mode 100644 src/eqpreset.h delete mode 100644 src/eqslider.cpp delete mode 100644 src/eqslider.h delete mode 100644 src/eqtitlebar.cpp delete mode 100644 src/eqtitlebar.h delete mode 100644 src/eqwidget.cpp delete mode 100644 src/eqwidget.h delete mode 100644 src/fft.c delete mode 100644 src/fft.h delete mode 100644 src/filedialog.cpp delete mode 100644 src/filedialog.h delete mode 100644 src/fileloader.cpp delete mode 100644 src/fileloader.h delete mode 100644 src/html/about_cs.html delete mode 100644 src/html/about_en.html delete mode 100644 src/html/about_ru.html delete mode 100644 src/html/about_zh_CN.html delete mode 100644 src/html/authors_cs.txt delete mode 100644 src/html/authors_en.txt delete mode 100644 src/html/authors_ru.txt delete mode 100644 src/html/authors_zh_CN.txt delete mode 100644 src/html/thanks_cs.txt delete mode 100644 src/html/thanks_en.txt delete mode 100644 src/html/thanks_ru.txt delete mode 100644 src/html/thanks_zh_CN.txt delete mode 100644 src/images/advanced.png delete mode 100644 src/images/images.qrc delete mode 100644 src/images/interface.png delete mode 100644 src/images/logo-qmmp.png delete mode 100644 src/images/pause.png delete mode 100644 src/images/play.png delete mode 100644 src/images/playlist.png delete mode 100644 src/images/plugins.png delete mode 100644 src/images/qmmp.xpm delete mode 100644 src/images/stop.png delete mode 100644 src/inlines.h delete mode 100644 src/jumptotrackdialog.cpp delete mode 100644 src/jumptotrackdialog.h delete mode 100644 src/jumptotrackdialog.ui delete mode 100644 src/keyboardmanager.cpp delete mode 100644 src/keyboardmanager.h delete mode 100644 src/listwidget.cpp delete mode 100644 src/listwidget.h delete mode 100644 src/logscale.cpp delete mode 100644 src/logscale.h delete mode 100644 src/mainvisual.cpp delete mode 100644 src/mainvisual.h delete mode 100644 src/mainwindow.cpp delete mode 100644 src/mainwindow.h delete mode 100644 src/mediafile.cpp delete mode 100644 src/mediafile.h delete mode 100644 src/monostereo.cpp delete mode 100644 src/monostereo.h delete mode 100644 src/mp3player.cpp delete mode 100644 src/number.cpp delete mode 100644 src/number.h delete mode 100644 src/pixmapwidget.cpp delete mode 100644 src/pixmapwidget.h delete mode 100644 src/playlist.cpp delete mode 100644 src/playlist.h delete mode 100644 src/playlistcontrol.cpp delete mode 100644 src/playlistcontrol.h delete mode 100644 src/playlistformat.cpp delete mode 100644 src/playlistformat.h delete mode 100644 src/playlistmodel.cpp delete mode 100644 src/playlistmodel.h delete mode 100644 src/playlistslider.cpp delete mode 100644 src/playlistslider.h delete mode 100644 src/playlisttitlebar.cpp delete mode 100644 src/playlisttitlebar.h delete mode 100644 src/playstate.cpp delete mode 100644 src/playstate.h delete mode 100644 src/playstatus.cpp delete mode 100644 src/playstatus.h delete mode 100644 src/pluginitem.cpp delete mode 100644 src/pluginitem.h create mode 100644 src/plugins/CMakeLists.txt create mode 100644 src/plugins/Effect/CMakeLists.txt create mode 100644 src/plugins/Effect/Effect.pro create mode 100644 src/plugins/Effect/srconverter/CMakeLists.txt create mode 100644 src/plugins/Effect/srconverter/effectsrconverterfactory.cpp create mode 100644 src/plugins/Effect/srconverter/effectsrconverterfactory.h create mode 100644 src/plugins/Effect/srconverter/settingsdialog.cpp create mode 100644 src/plugins/Effect/srconverter/settingsdialog.h create mode 100644 src/plugins/Effect/srconverter/settingsdialog.ui create mode 100644 src/plugins/Effect/srconverter/srconverter.cpp create mode 100644 src/plugins/Effect/srconverter/srconverter.h create mode 100644 src/plugins/Effect/srconverter/srconverter.pro create mode 100644 src/plugins/General/General.pro create mode 100644 src/plugins/General/dbuscontrol/dbusadaptor.cpp create mode 100644 src/plugins/General/dbuscontrol/dbusadaptor.h create mode 100644 src/plugins/General/dbuscontrol/dbuscontrol.cpp create mode 100644 src/plugins/General/dbuscontrol/dbuscontrol.h create mode 100644 src/plugins/General/dbuscontrol/dbuscontrol.pro create mode 100644 src/plugins/General/dbuscontrol/dbuscontrolfactory.cpp create mode 100644 src/plugins/General/dbuscontrol/dbuscontrolfactory.h create mode 100644 src/plugins/General/scrobbler/scrobbler.cpp create mode 100644 src/plugins/General/scrobbler/scrobbler.h create mode 100644 src/plugins/General/scrobbler/scrobbler.pro create mode 100644 src/plugins/General/scrobbler/scrobblerfactory.cpp create mode 100644 src/plugins/General/scrobbler/scrobblerfactory.h create mode 100644 src/plugins/General/scrobbler/settingsdialog.cpp create mode 100644 src/plugins/General/scrobbler/settingsdialog.h create mode 100644 src/plugins/General/scrobbler/settingsdialog.ui create mode 100644 src/plugins/General/statusicon/images/images.qrc create mode 100644 src/plugins/General/statusicon/images/tray_pause.png create mode 100644 src/plugins/General/statusicon/images/tray_play.png create mode 100644 src/plugins/General/statusicon/images/tray_stop.png create mode 100644 src/plugins/General/statusicon/settingsdialog.cpp create mode 100644 src/plugins/General/statusicon/settingsdialog.h create mode 100644 src/plugins/General/statusicon/settingsdialog.ui create mode 100644 src/plugins/General/statusicon/statusicon.cpp create mode 100644 src/plugins/General/statusicon/statusicon.h create mode 100644 src/plugins/General/statusicon/statusicon.pro create mode 100644 src/plugins/General/statusicon/statusiconfactory.cpp create mode 100644 src/plugins/General/statusicon/statusiconfactory.h create mode 100644 src/plugins/Input/CMakeLists.txt create mode 100644 src/plugins/Input/Input.pro create mode 100644 src/plugins/Input/ffmpeg/CMakeLists.txt create mode 100644 src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp create mode 100644 src/plugins/Input/ffmpeg/decoder_ffmpeg.h create mode 100644 src/plugins/Input/ffmpeg/decoderffmpegfactory.cpp create mode 100644 src/plugins/Input/ffmpeg/decoderffmpegfactory.h create mode 100644 src/plugins/Input/ffmpeg/detailsdialog.cpp create mode 100644 src/plugins/Input/ffmpeg/detailsdialog.h create mode 100644 src/plugins/Input/ffmpeg/detailsdialog.ui create mode 100644 src/plugins/Input/ffmpeg/ffmpeg.pro create mode 100644 src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_cs.ts create mode 100644 src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.qm create mode 100644 src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.ts create mode 100644 src/plugins/Input/ffmpeg/translations/translations.qrc create mode 100644 src/plugins/Input/flac/CMakeLists.txt create mode 100644 src/plugins/Input/flac/decoder_flac.cpp create mode 100644 src/plugins/Input/flac/decoder_flac.h create mode 100644 src/plugins/Input/flac/decoderflacfactory.cpp create mode 100644 src/plugins/Input/flac/decoderflacfactory.h create mode 100644 src/plugins/Input/flac/detailsdialog.cpp create mode 100644 src/plugins/Input/flac/detailsdialog.h create mode 100644 src/plugins/Input/flac/detailsdialog.ui create mode 100644 src/plugins/Input/flac/flac.pro create mode 100644 src/plugins/Input/flac/translations/flac_plugin_ru.qm create mode 100644 src/plugins/Input/flac/translations/flac_plugin_ru.ts create mode 100644 src/plugins/Input/flac/translations/translations.qrc create mode 100644 src/plugins/Input/mad/CMakeLists.txt create mode 100644 src/plugins/Input/mad/decoder_mad.cpp create mode 100644 src/plugins/Input/mad/decoder_mad.h create mode 100644 src/plugins/Input/mad/decodermadfactory.cpp create mode 100644 src/plugins/Input/mad/decodermadfactory.h create mode 100644 src/plugins/Input/mad/detailsdialog.cpp create mode 100644 src/plugins/Input/mad/detailsdialog.h create mode 100644 src/plugins/Input/mad/detailsdialog.ui create mode 100644 src/plugins/Input/mad/mad.pro create mode 100644 src/plugins/Input/mad/settingsdialog.cpp create mode 100644 src/plugins/Input/mad/settingsdialog.h create mode 100644 src/plugins/Input/mad/settingsdialog.ui create mode 100644 src/plugins/Input/mad/translations/mad_plugin_ru.qm create mode 100644 src/plugins/Input/mad/translations/mad_plugin_ru.ts create mode 100644 src/plugins/Input/mad/translations/translations.qrc create mode 100644 src/plugins/Input/mad/ui_detailsdialog.h create mode 100644 src/plugins/Input/mad/ui_settingsdialog.h create mode 100644 src/plugins/Input/mpc/CMakeLists.txt create mode 100644 src/plugins/Input/mpc/Makefile create mode 100644 src/plugins/Input/mpc/decoder_mpc.cpp create mode 100644 src/plugins/Input/mpc/decoder_mpc.h create mode 100644 src/plugins/Input/mpc/decodermpcfactory.cpp create mode 100644 src/plugins/Input/mpc/decodermpcfactory.h create mode 100644 src/plugins/Input/mpc/detailsdialog.cpp create mode 100644 src/plugins/Input/mpc/detailsdialog.h create mode 100644 src/plugins/Input/mpc/detailsdialog.ui create mode 100644 src/plugins/Input/mpc/mpc.pro create mode 100644 src/plugins/Input/mpc/translations/mpc_plugin_ru.qm create mode 100644 src/plugins/Input/mpc/translations/mpc_plugin_ru.ts create mode 100644 src/plugins/Input/mpc/translations/translations.qrc create mode 100644 src/plugins/Input/sndfile/CMakeLists.txt create mode 100644 src/plugins/Input/sndfile/decoder_sndfile.cpp create mode 100644 src/plugins/Input/sndfile/decoder_sndfile.h create mode 100644 src/plugins/Input/sndfile/decodersndfilefactory.cpp create mode 100644 src/plugins/Input/sndfile/decodersndfilefactory.h create mode 100644 src/plugins/Input/sndfile/sndfile.pro create mode 100644 src/plugins/Input/vorbis/CMakeLists.txt create mode 100644 src/plugins/Input/vorbis/decoder_vorbis.cpp create mode 100644 src/plugins/Input/vorbis/decoder_vorbis.h create mode 100644 src/plugins/Input/vorbis/decodervorbisfactory.cpp create mode 100644 src/plugins/Input/vorbis/decodervorbisfactory.h create mode 100644 src/plugins/Input/vorbis/detailsdialog.cpp create mode 100644 src/plugins/Input/vorbis/detailsdialog.h create mode 100644 src/plugins/Input/vorbis/detailsdialog.ui create mode 100644 src/plugins/Input/vorbis/translations/translations.qrc create mode 100644 src/plugins/Input/vorbis/translations/vorbis_plugin_ru.qm create mode 100644 src/plugins/Input/vorbis/translations/vorbis_plugin_ru.ts create mode 100644 src/plugins/Input/vorbis/vorbis.pro create mode 100644 src/plugins/Misc/CommandLineOptions/IncDecVolumeOption.pro create mode 100644 src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/IncDecVolumeOption.pro create mode 100644 src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/Makefile create mode 100644 src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/incdecvolumeoption.cpp create mode 100644 src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/incdecvolumeoption.h create mode 100644 src/plugins/Misc/FileDialogs/FileDialogs.pro create mode 100644 src/plugins/Misc/FileDialogs/Makefile create mode 100644 src/plugins/Misc/FileDialogs/QmmpFileDialog/QmmpFileDialog.pro create mode 100644 src/plugins/Misc/FileDialogs/QmmpFileDialog/images/cdup.png create mode 100644 src/plugins/Misc/FileDialogs/QmmpFileDialog/images/detail.png create mode 100644 src/plugins/Misc/FileDialogs/QmmpFileDialog/images/images.qrc create mode 100644 src/plugins/Misc/FileDialogs/QmmpFileDialog/images/list.png create mode 100644 src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.cpp create mode 100644 src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.h create mode 100644 src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.ui create mode 100644 src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialogimpl.cpp create mode 100644 src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialogimpl.h create mode 100644 src/plugins/Misc/FileDialogs/Qt3FileDialog/Qt3FileDialog.pro create mode 100644 src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialog.cpp create mode 100644 src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialog.h create mode 100644 src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialogfactory.cpp create mode 100644 src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialogfactory.h create mode 100644 src/plugins/Misc/FileDialogs/Qt3FileDialog/readme create mode 100755 src/plugins/Misc/FileDialogs/libQmmpFileDialog.so create mode 100755 src/plugins/Misc/FileDialogs/libQt3FileDialog.so create mode 100644 src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/CSVPlaylistFormat.pro create mode 100644 src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/Makefile create mode 100644 src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/csvplaylistformat.cpp create mode 100644 src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/csvplaylistformat.h create mode 100644 src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/moc_csvplaylistformat.cpp create mode 100644 src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/readme create mode 100644 src/plugins/Misc/PlaylistFormats/Makefile create mode 100644 src/plugins/Misc/PlaylistFormats/PlaylistFormats.pro create mode 100755 src/plugins/Misc/PlaylistFormats/libCSVPlaylistFormat.so create mode 100644 src/plugins/Output/CMakeLists.txt create mode 100644 src/plugins/Output/Output.pro create mode 100644 src/plugins/Output/alsa/CMakeLists.txt create mode 100644 src/plugins/Output/alsa/alsa.pro create mode 100644 src/plugins/Output/alsa/outputalsa.cpp create mode 100644 src/plugins/Output/alsa/outputalsa.h create mode 100644 src/plugins/Output/alsa/outputalsafactory.cpp create mode 100644 src/plugins/Output/alsa/outputalsafactory.h create mode 100644 src/plugins/Output/alsa/settingsdialog.cpp create mode 100644 src/plugins/Output/alsa/settingsdialog.h create mode 100644 src/plugins/Output/alsa/settingsdialog.ui create mode 100644 src/plugins/Output/alsa/translations/alsa_plugin_cs.ts create mode 100644 src/plugins/Output/alsa/translations/alsa_plugin_ru.qm create mode 100644 src/plugins/Output/alsa/translations/alsa_plugin_ru.ts create mode 100644 src/plugins/Output/alsa/translations/translations.qrc create mode 100644 src/plugins/Output/jack/CMakeLists.txt create mode 100644 src/plugins/Output/jack/bio2jack.c create mode 100644 src/plugins/Output/jack/bio2jack.h create mode 100644 src/plugins/Output/jack/jack.pro create mode 100644 src/plugins/Output/jack/outputjack.cpp create mode 100644 src/plugins/Output/jack/outputjack.h create mode 100644 src/plugins/Output/jack/outputjackfactory.cpp create mode 100644 src/plugins/Output/jack/outputjackfactory.h create mode 100644 src/plugins/Output/jack/translations/jack_plugin_ru.qm create mode 100644 src/plugins/Output/jack/translations/jack_plugin_ru.ts create mode 100644 src/plugins/Output/jack/translations/translations.qrc create mode 100644 src/plugins/Output/oss/CMakeLists.txt create mode 100644 src/plugins/Output/oss/oss.pro create mode 100644 src/plugins/Output/oss/outputoss.cpp create mode 100644 src/plugins/Output/oss/outputoss.h create mode 100644 src/plugins/Output/oss/outputossfactory.cpp create mode 100644 src/plugins/Output/oss/outputossfactory.h create mode 100644 src/plugins/Output/oss/settingsdialog.cpp create mode 100644 src/plugins/Output/oss/settingsdialog.h create mode 100644 src/plugins/Output/oss/settingsdialog.ui create mode 100644 src/plugins/Output/oss/translations/oss_plugin_cs.ts create mode 100644 src/plugins/Visual/CMakeLists.txt create mode 100644 src/plugins/Visual/Visual.pro create mode 100644 src/plugins/Visual/analyzer/CMakeLists.txt create mode 100644 src/plugins/Visual/analyzer/analyzer.cpp create mode 100644 src/plugins/Visual/analyzer/analyzer.h create mode 100644 src/plugins/Visual/analyzer/analyzer.pro create mode 100644 src/plugins/Visual/analyzer/colorwidget.cpp create mode 100644 src/plugins/Visual/analyzer/colorwidget.h create mode 100644 src/plugins/Visual/analyzer/fft.c create mode 100644 src/plugins/Visual/analyzer/fft.h create mode 100644 src/plugins/Visual/analyzer/inlines.h create mode 100644 src/plugins/Visual/analyzer/settingsdialog.cpp create mode 100644 src/plugins/Visual/analyzer/settingsdialog.h create mode 100644 src/plugins/Visual/analyzer/settingsdialog.ui create mode 100644 src/plugins/Visual/analyzer/visualanalyzerfactory.cpp create mode 100644 src/plugins/Visual/analyzer/visualanalyzerfactory.h create mode 100644 src/plugins/plugins.pri create mode 100644 src/plugins/plugins.pro delete mode 100644 src/positionbar.cpp delete mode 100644 src/positionbar.h delete mode 100644 src/preseteditor.cpp delete mode 100644 src/preseteditor.h delete mode 100644 src/preseteditor.ui create mode 100644 src/qmmp/CMakeLists.txt create mode 100644 src/qmmp/buffer.h create mode 100644 src/qmmp/constants.h create mode 100644 src/qmmp/decoder.cpp create mode 100644 src/qmmp/decoder.h create mode 100644 src/qmmp/decoderfactory.h create mode 100644 src/qmmp/downloader.cpp create mode 100644 src/qmmp/downloader.h create mode 100644 src/qmmp/effect.cpp create mode 100644 src/qmmp/effect.h create mode 100644 src/qmmp/effectfactory.h create mode 100644 src/qmmp/equ/iir.c create mode 100644 src/qmmp/equ/iir.h create mode 100644 src/qmmp/equ/iir_cfs.c create mode 100644 src/qmmp/equ/iir_cfs.h create mode 100644 src/qmmp/equ/iir_fpu.c create mode 100644 src/qmmp/equ/iir_fpu.h create mode 100644 src/qmmp/filetag.cpp create mode 100644 src/qmmp/filetag.h create mode 100644 src/qmmp/output.cpp create mode 100644 src/qmmp/output.h create mode 100644 src/qmmp/outputfactory.h create mode 100644 src/qmmp/qmmp.pro create mode 100644 src/qmmp/recycler.cpp create mode 100644 src/qmmp/recycler.h create mode 100644 src/qmmp/soundcore.cpp create mode 100644 src/qmmp/soundcore.h create mode 100644 src/qmmp/streamreader.cpp create mode 100644 src/qmmp/streamreader.h create mode 100644 src/qmmp/visual.cpp create mode 100644 src/qmmp/visual.h create mode 100644 src/qmmp/visualfactory.h delete mode 100644 src/qmmpstarter.cpp delete mode 100644 src/qmmpstarter.h create mode 100644 src/qmmpui/general.cpp create mode 100644 src/qmmpui/general.h create mode 100644 src/qmmpui/generalfactory.h create mode 100644 src/qmmpui/generalhandler.cpp create mode 100644 src/qmmpui/generalhandler.h create mode 100644 src/qmmpui/qmmpui.pro create mode 100644 src/qmmpui/songinfo.cpp create mode 100644 src/qmmpui/songinfo.h delete mode 100644 src/shadedbar.cpp delete mode 100644 src/shadedbar.h delete mode 100644 src/shadedvisual.cpp delete mode 100644 src/shadedvisual.h delete mode 100644 src/skin.cpp delete mode 100644 src/skin.h delete mode 100644 src/skinreader.cpp delete mode 100644 src/skinreader.h delete mode 100644 src/src.pro delete mode 100644 src/stuff.qrc delete mode 100644 src/symboldisplay.cpp delete mode 100644 src/symboldisplay.h delete mode 100644 src/textscroller.cpp delete mode 100644 src/textscroller.h delete mode 100644 src/timeindicator.cpp delete mode 100644 src/timeindicator.h delete mode 100644 src/titlebar.cpp delete mode 100644 src/titlebar.h delete mode 100644 src/titlebarcontrol.cpp delete mode 100644 src/titlebarcontrol.h delete mode 100644 src/togglebutton.cpp delete mode 100644 src/togglebutton.h delete mode 100644 src/translations/qmmp_cs.ts delete mode 100644 src/translations/qmmp_locales.qrc delete mode 100644 src/translations/qmmp_ru.qm delete mode 100644 src/translations/qmmp_ru.ts delete mode 100644 src/translations/qmmp_tr.qm delete mode 100644 src/translations/qmmp_tr.ts delete mode 100644 src/translations/qmmp_zh_CN.qm delete mode 100644 src/translations/qmmp_zh_CN.ts create mode 100644 src/ui/aboutdialog.cpp create mode 100644 src/ui/aboutdialog.h create mode 100644 src/ui/addurldialog.cpp create mode 100644 src/ui/addurldialog.h create mode 100644 src/ui/balancebar.cpp create mode 100644 src/ui/balancebar.h create mode 100644 src/ui/button.cpp create mode 100644 src/ui/button.h create mode 100644 src/ui/commandlineoption.cpp create mode 100644 src/ui/commandlineoption.h create mode 100644 src/ui/configdialog.cpp create mode 100644 src/ui/configdialog.h create mode 100644 src/ui/default/balance.png create mode 100644 src/ui/default/cbuttons.png create mode 100644 src/ui/default/eq_ex.png create mode 100644 src/ui/default/eqmain.png create mode 100644 src/ui/default/main.png create mode 100644 src/ui/default/monoster.png create mode 100644 src/ui/default/numbers.png create mode 100644 src/ui/default/playpaus.png create mode 100644 src/ui/default/pledit.png create mode 100644 src/ui/default/pledit.txt create mode 100644 src/ui/default/posbar.png create mode 100644 src/ui/default/shufrep.png create mode 100644 src/ui/default/text.png create mode 100644 src/ui/default/titlebar.png create mode 100644 src/ui/default/viscolor.txt create mode 100644 src/ui/default/volume.png create mode 100644 src/ui/display.cpp create mode 100644 src/ui/display.h create mode 100644 src/ui/dock.cpp create mode 100644 src/ui/dock.h create mode 100644 src/ui/eqgraph.cpp create mode 100644 src/ui/eqgraph.h create mode 100644 src/ui/eqpreset.cpp create mode 100644 src/ui/eqpreset.h create mode 100644 src/ui/eqslider.cpp create mode 100644 src/ui/eqslider.h create mode 100644 src/ui/eqtitlebar.cpp create mode 100644 src/ui/eqtitlebar.h create mode 100644 src/ui/eqwidget.cpp create mode 100644 src/ui/eqwidget.h create mode 100644 src/ui/fft.c create mode 100644 src/ui/fft.h create mode 100644 src/ui/filedialog.cpp create mode 100644 src/ui/filedialog.h create mode 100644 src/ui/fileloader.cpp create mode 100644 src/ui/fileloader.h create mode 100644 src/ui/forms/aboutdialog.ui create mode 100644 src/ui/forms/addurldialog.ui create mode 100644 src/ui/forms/configdialog.ui create mode 100644 src/ui/forms/jumptotrackdialog.ui create mode 100644 src/ui/forms/preseteditor.ui create mode 100644 src/ui/html/about_cs.html create mode 100644 src/ui/html/about_en.html create mode 100644 src/ui/html/about_ru.html create mode 100644 src/ui/html/about_zh_CN.html create mode 100644 src/ui/html/authors_cs.txt create mode 100644 src/ui/html/authors_en.txt create mode 100644 src/ui/html/authors_ru.txt create mode 100644 src/ui/html/authors_zh_CN.txt create mode 100644 src/ui/html/thanks_cs.txt create mode 100644 src/ui/html/thanks_en.txt create mode 100644 src/ui/html/thanks_ru.txt create mode 100644 src/ui/html/thanks_zh_CN.txt create mode 100644 src/ui/images/advanced.png create mode 100644 src/ui/images/images.qrc create mode 100644 src/ui/images/interface.png create mode 100644 src/ui/images/logo-qmmp.png create mode 100644 src/ui/images/network.png create mode 100644 src/ui/images/playlist.png create mode 100644 src/ui/images/plugins.png create mode 100644 src/ui/images/qmmp.xpm create mode 100644 src/ui/inlines.h create mode 100644 src/ui/jumptotrackdialog.cpp create mode 100644 src/ui/jumptotrackdialog.h create mode 100644 src/ui/keyboardmanager.cpp create mode 100644 src/ui/keyboardmanager.h create mode 100644 src/ui/listwidget.cpp create mode 100644 src/ui/listwidget.h create mode 100644 src/ui/logscale.cpp create mode 100644 src/ui/logscale.h create mode 100644 src/ui/mainvisual.cpp create mode 100644 src/ui/mainvisual.h create mode 100644 src/ui/mainwindow.cpp create mode 100644 src/ui/mainwindow.h create mode 100644 src/ui/mediafile.cpp create mode 100644 src/ui/mediafile.h create mode 100644 src/ui/monostereo.cpp create mode 100644 src/ui/monostereo.h create mode 100644 src/ui/mp3player.cpp create mode 100644 src/ui/number.cpp create mode 100644 src/ui/number.h create mode 100644 src/ui/pixmapwidget.cpp create mode 100644 src/ui/pixmapwidget.h create mode 100644 src/ui/playlist.cpp create mode 100644 src/ui/playlist.h create mode 100644 src/ui/playlistcontrol.cpp create mode 100644 src/ui/playlistcontrol.h create mode 100644 src/ui/playlistformat.cpp create mode 100644 src/ui/playlistformat.h create mode 100644 src/ui/playlistmodel.cpp create mode 100644 src/ui/playlistmodel.h create mode 100644 src/ui/playlistslider.cpp create mode 100644 src/ui/playlistslider.h create mode 100644 src/ui/playlisttitlebar.cpp create mode 100644 src/ui/playlisttitlebar.h create mode 100644 src/ui/playstate.cpp create mode 100644 src/ui/playstate.h create mode 100644 src/ui/playstatus.cpp create mode 100644 src/ui/playstatus.h create mode 100644 src/ui/pluginitem.cpp create mode 100644 src/ui/pluginitem.h create mode 100644 src/ui/positionbar.cpp create mode 100644 src/ui/positionbar.h create mode 100644 src/ui/preseteditor.cpp create mode 100644 src/ui/preseteditor.h create mode 100644 src/ui/qmmpstarter.cpp create mode 100644 src/ui/qmmpstarter.h create mode 100644 src/ui/shadedbar.cpp create mode 100644 src/ui/shadedbar.h create mode 100644 src/ui/shadedvisual.cpp create mode 100644 src/ui/shadedvisual.h create mode 100644 src/ui/skin.cpp create mode 100644 src/ui/skin.h create mode 100644 src/ui/skinreader.cpp create mode 100644 src/ui/skinreader.h create mode 100644 src/ui/stuff.qrc create mode 100644 src/ui/symboldisplay.cpp create mode 100644 src/ui/symboldisplay.h create mode 100644 src/ui/textscroller.cpp create mode 100644 src/ui/textscroller.h create mode 100644 src/ui/timeindicator.cpp create mode 100644 src/ui/timeindicator.h create mode 100644 src/ui/titlebar.cpp create mode 100644 src/ui/titlebar.h create mode 100644 src/ui/titlebarcontrol.cpp create mode 100644 src/ui/titlebarcontrol.h create mode 100644 src/ui/togglebutton.cpp create mode 100644 src/ui/togglebutton.h create mode 100644 src/ui/translations/qmmp_cs.ts create mode 100644 src/ui/translations/qmmp_locales.qrc create mode 100644 src/ui/translations/qmmp_ru.qm create mode 100644 src/ui/translations/qmmp_ru.ts create mode 100644 src/ui/translations/qmmp_tr.qm create mode 100644 src/ui/translations/qmmp_tr.ts create mode 100644 src/ui/translations/qmmp_zh_CN.qm create mode 100644 src/ui/translations/qmmp_zh_CN.ts create mode 100644 src/ui/ui.pro create mode 100644 src/ui/unixdomainsocket.cpp create mode 100644 src/ui/unixdomainsocket.h create mode 100644 src/ui/version.h create mode 100644 src/ui/visualmenu.cpp create mode 100644 src/ui/visualmenu.h create mode 100644 src/ui/volumebar.cpp create mode 100644 src/ui/volumebar.h delete mode 100644 src/unixdomainsocket.cpp delete mode 100644 src/unixdomainsocket.h delete mode 100644 src/version.h delete mode 100644 src/visualmenu.cpp delete mode 100644 src/visualmenu.h delete mode 100644 src/volumebar.cpp delete mode 100644 src/volumebar.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e0ec01195..be0d02e78 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -79,6 +79,7 @@ SET(libsrc_SRCS shadedvisual.cpp titlebarcontrol.cpp shadedbar.cpp + commandlineoption.cpp ) SET(libsrc_MOC_HDRS @@ -134,6 +135,7 @@ SET(libsrc_MOC_HDRS shadedvisual.h titlebarcontrol.h shadedbar.h + commandlineoption.h ) SET(libsrc_RCCS images/images.qrc stuff.qrc translations/qmmp_locales.qrc) diff --git a/src/aboutdialog.cpp b/src/aboutdialog.cpp deleted file mode 100644 index a8b80e6cd..000000000 --- a/src/aboutdialog.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2006 by Ilya Kotov * -* forkotov02@hotmail.ru * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ - - -#include "aboutdialog.h" - -#include -#include - -static QString getstringFromResource(const QString& res_file) -{ - QString ret_string; - QFile file(res_file); - if (file.open(QIODevice::ReadOnly)) - { - QTextStream ts(&file); - ts.setCodec("UTF-8"); - ret_string = ts.readAll(); - file.close(); - } - return ret_string; -} - -AboutDialog::AboutDialog(QWidget* parent, Qt::WFlags fl) - : QDialog( parent, fl ) -{ - setupUi(this); - setAttribute(Qt::WA_QuitOnClose, FALSE); - licenseTextEdit->setPlainText(getstringFromResource(":COPYING")); - aboutTextEdit->setHtml(getstringFromResource(tr(":/html/about_en.html"))); - authorsTextEdit->setPlainText(getstringFromResource(tr(":/html/authors_en.txt"))); - thanksToTextEdit->setPlainText(getstringFromResource(tr(":/html/thanks_en.txt"))); -} - -AboutDialog::~AboutDialog() -{} - -/*$SPECIALIZATION$*/ -void AboutDialog::accept() -{ - QDialog::accept(); -} - - - - diff --git a/src/aboutdialog.h b/src/aboutdialog.h deleted file mode 100644 index 10dcde4a5..000000000 --- a/src/aboutdialog.h +++ /dev/null @@ -1,44 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2006 by Ilya Kotov * -* forkotov02@hotmail.ru * -* * -* This program is free software; 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. * -***************************************************************************/ - -#ifndef ABOUTDIALOG_H -#define ABOUTDIALOG_H - -#include -#include "ui_aboutdialog.h" - -/** - @author Vladimir Kuznetsov - */ - -class AboutDialog : public QDialog, private Ui::AboutDialog -{ - Q_OBJECT -public: - AboutDialog(QWidget* parent = 0, Qt::WFlags fl = 0 ); - ~AboutDialog(); - -protected slots: - virtual void accept(); - -}; - -#endif - diff --git a/src/aboutdialog.ui b/src/aboutdialog.ui deleted file mode 100644 index 56fbef9c5..000000000 --- a/src/aboutdialog.ui +++ /dev/null @@ -1,174 +0,0 @@ - - AboutDialog - - - - 0 - 0 - 518 - 414 - - - - About Qmmp - - - - 9 - - - 6 - - - - - - - - :/logo-qmmp.png - - - Qt::AlignCenter - - - - - - - 0 - - - - About - - - - 9 - - - 6 - - - - - true - - - - - - - - Authors - - - - 9 - - - 6 - - - - - true - - - - - - - - Thanks To - - - - 9 - - - 6 - - - - - true - - - - - - - - License Agreement - - - - 9 - - - 6 - - - - - true - - - true - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - AboutDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - AboutDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/addurldialog.cpp b/src/addurldialog.cpp deleted file mode 100644 index 6746a2de1..000000000 --- a/src/addurldialog.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "addurldialog.h" - -#include "playlistmodel.h" - -AddUrlDialog::AddUrlDialog( QWidget * parent, Qt::WindowFlags f) : QDialog(parent,f) -{ - setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); -} - -AddUrlDialog::~AddUrlDialog() -{} - - - -QPointer AddUrlDialog::instance = 0; - -void AddUrlDialog::popup(QWidget* parent,PlayListModel* model ) -{ - if(!instance) - { - instance = new AddUrlDialog(parent); - instance->setModel(model); - } - - instance->show(); - instance->raise(); -} - -void AddUrlDialog::accept( ) -{ - if(!urlComboBox->currentText().isEmpty()) - { - QString s = urlComboBox->currentText(); - if(!s.startsWith("http://")) - s.prepend("http://"); - - m_model->addFile(s); - } - - QDialog::accept(); -} - -void AddUrlDialog::setModel( PlayListModel *m ) -{ - m_model = m; -} diff --git a/src/addurldialog.h b/src/addurldialog.h deleted file mode 100644 index 86a065703..000000000 --- a/src/addurldialog.h +++ /dev/null @@ -1,51 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ - -#ifndef ADDURLDIALOG_H -#define ADDURLDIALOG_H - -#include "ui_addurldialog.h" -#include -#include - - -class PlayListModel; - -/** - @author Vladimir Kuznetsov - */ - -class AddUrlDialog : public QDialog , private Ui::AddUrlDialog -{ - Q_OBJECT -public: - static void popup(QWidget* parent ,PlayListModel*); -protected: - AddUrlDialog( QWidget * parent = 0, Qt::WindowFlags f = 0 ); - ~AddUrlDialog(); -protected slots: - virtual void accept(); -private: - void setModel(PlayListModel*); - static QPointer instance; - PlayListModel* m_model; - -}; -#endif //ADDURLDIALOG_H diff --git a/src/addurldialog.ui b/src/addurldialog.ui deleted file mode 100644 index 46031b849..000000000 --- a/src/addurldialog.ui +++ /dev/null @@ -1,76 +0,0 @@ - - AddUrlDialog - - - - 0 - 0 - 394 - 80 - - - - Enter URL to add - - - - 9 - - - 6 - - - - - true - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - AddUrlDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - AddUrlDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/src/balancebar.cpp b/src/balancebar.cpp deleted file mode 100644 index 3089e0cbd..000000000 --- a/src/balancebar.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include - -#include "skin.h" -#include "button.h" -#include "mainwindow.h" - -#include "balancebar.h" - - -BalanceBar::BalanceBar(QWidget *parent) - : PixmapWidget(parent) -{ - m_skin = Skin::getPointer(); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); - setPixmap(m_skin->getBalanceBar(0)); - m_moving = FALSE; - m_min = -100; - m_max = 100; - m_old = m_value = 0; - draw(FALSE); -} - - -BalanceBar::~BalanceBar() -{} - -void BalanceBar::mousePressEvent(QMouseEvent *e) -{ - - m_moving = TRUE; - press_pos = e->x(); - if(m_posx() && e->x()x()-m_pos; - } - else - { - m_value = convert(qMax(qMin(width()-18,e->x()-6),0)); - press_pos = 6; - if (m_value!=m_old) - { - emit sliderMoved(m_value); - - } - } - draw(); -} - -void BalanceBar::mouseMoveEvent (QMouseEvent *e) -{ - if(m_moving) - { - int po = e->x(); - po = po - press_pos; - - if(0<=po && po<=width()-13) - { - m_value = convert(po); - draw(); - emit sliderMoved(m_value); - } - } -} - -void BalanceBar::mouseReleaseEvent(QMouseEvent*) -{ - m_moving = FALSE; - draw(FALSE); - m_old = m_value; -} - -void BalanceBar::setValue(int v) -{ - if (m_moving || m_max == 0) - return; - m_value = v; - draw(FALSE); -} - -void BalanceBar::setMax(int max) -{ - m_max = max; - draw(FALSE); -} - -void BalanceBar::updateSkin() -{ - draw(FALSE); -} - -void BalanceBar::draw(bool pressed) -{ - if(abs(m_value)<6) - m_value = 0; - int p=int(ceil(double(m_value-m_min)*(width()-13)/(m_max-m_min))); - m_pixmap = m_skin->getBalanceBar(abs(27*m_value/m_max)); - QPainter paint(&m_pixmap); - if(pressed) - paint.drawPixmap(p,1,m_skin->getButton(Skin::BT_BAL_P)); - else - paint.drawPixmap(p,1,m_skin->getButton(Skin::BT_BAL_N)); - setPixmap(m_pixmap); - m_pos = p; -} - -int BalanceBar::convert(int p) -{ - return int(ceil(double(m_max-m_min)*(p)/(width()-13)+m_min)); -} - diff --git a/src/balancebar.h b/src/balancebar.h deleted file mode 100644 index 6704671f9..000000000 --- a/src/balancebar.h +++ /dev/null @@ -1,66 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef BALANCEBAR_H -#define BALANCEBAR_H - -#include - -class Skin; - -/** - @author Ilya Kotov -*/ -class BalanceBar : public PixmapWidget -{ -Q_OBJECT -public: - BalanceBar(QWidget *parent = 0); - - ~BalanceBar(); - - int value() {return m_value; }; - -public slots: - void setValue(int); - void setMax(int); - -signals: - void sliderMoved (int); - -private slots: - void updateSkin(); - -private: - Skin *m_skin; - bool m_moving; - int press_pos; - int m_max, m_min, m_pos, m_value, m_old; - QPixmap m_pixmap; - int convert(int); // value = convert(position); - void draw(bool pressed = TRUE); - -protected: - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); - -}; - -#endif diff --git a/src/button.cpp b/src/button.cpp deleted file mode 100644 index 8bd006ed3..000000000 --- a/src/button.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "button.h" -#include "skin.h" - -Button::Button ( QWidget *parent, uint normal, uint pressed ) - : PixmapWidget ( parent ) -{ - name_normal = normal; - name_pressed = pressed; - skin = Skin::getPointer(); - setON ( FALSE ); - connect ( skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); -} - - -Button::~Button() -{} - -void Button::updateSkin() -{ - setPixmap ( skin->getButton ( name_normal ) ); -} - -void Button::setON ( bool on ) -{ - if ( on ) - setPixmap ( skin->getButton ( name_pressed ) ); - else - setPixmap ( skin->getButton ( name_normal ) ); -} -void Button::mousePressEvent ( QMouseEvent* ) -{ - setON ( TRUE ); -} - -void Button::mouseReleaseEvent ( QMouseEvent* ) -{ - setON ( FALSE ); - emit clicked(); -} diff --git a/src/button.h b/src/button.h deleted file mode 100644 index 7f2d8f314..000000000 --- a/src/button.h +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef BUTTON_H -#define BUTTON_H - -#include "pixmapwidget.h" - -class Skin; - -/** - @author Ilya Kotov -*/ -class Button : public PixmapWidget -{ -Q_OBJECT -public: - Button(QWidget *parent, uint normal, uint pressed); - - ~Button(); - -signals: - void clicked(); - -private slots: - void updateSkin(); - -private: - Skin *skin; - void setON(bool); - uint name_normal, name_pressed; - -protected: - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); -}; - -#endif diff --git a/src/configdialog.cpp b/src/configdialog.cpp deleted file mode 100644 index 958453a27..000000000 --- a/src/configdialog.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "skin.h" -#include "filedialog.h" -#include "pluginitem.h" -#include "configdialog.h" -#include "skinreader.h" - -ConfigDialog::ConfigDialog ( QWidget *parent ) - : QDialog ( parent ) -{ - ui.setupUi ( this ); - setAttribute(Qt::WA_QuitOnClose, FALSE); - setAttribute(Qt::WA_DeleteOnClose, FALSE); - connect ( ui. contentsWidget, - SIGNAL ( currentItemChanged ( QListWidgetItem *, QListWidgetItem * ) ), - this, SLOT ( changePage ( QListWidgetItem *, QListWidgetItem* ) ) ); - connect ( ui.mainFontButton, SIGNAL ( clicked() ), SLOT ( setMainFont() ) ); - connect ( ui.plFontButton, SIGNAL ( clicked() ), SLOT ( setPlFont() ) ); - connect ( ui.preferencesButton, SIGNAL ( clicked() ), SLOT (showPluginSettings())); - connect ( ui.informationButton, SIGNAL ( clicked() ), SLOT (showPluginInfo())); - connect ( this, SIGNAL(accepted()),SLOT(saveSettings())); - ui.listWidget->setIconSize ( QSize ( 69,29 ) ); - m_skin = Skin::getPointer(); - ui.fileDialogComboBox->insertItems(0,FileDialog::registeredFactories()); - readSettings(); - SkinReader reader; - reader.updateCache(); - loadSkins(); - loadPluginsInfo(); - loadFonts(); - createMenus(); -} - -ConfigDialog::~ConfigDialog() -{ - while (!m_outputPluginItems.isEmpty()) - delete m_outputPluginItems.takeFirst(); - while (!m_inputPluginItems.isEmpty()) - delete m_outputPluginItems.takeFirst(); - while (!m_visualPluginItems.isEmpty()) - delete m_visualPluginItems.takeFirst(); - while (!m_effectPluginItems.isEmpty()) - delete m_effectPluginItems.takeFirst(); -} - -void ConfigDialog::readSettings() -{ - QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); - ui.formatLineEdit->setText( - settings.value ( "PlayList/title_format", "%p - %t").toString()); - ui.metadataCheckBox->setChecked( - settings.value ( "PlayList/load_metadata", TRUE).toBool()); - ui.trayCheckBox->setChecked( - settings.value("Tray/enabled",TRUE).toBool()); - ui.messageCheckBox->setChecked( - settings.value("Tray/show_message",TRUE).toBool()); - ui.messageDelaySpinBox->setValue(settings.value("Tray/message_delay", - 2000).toInt()); - ui.messageCheckBox->setEnabled(ui.trayCheckBox->isChecked()); - ui.messageDelaySpinBox->setEnabled(ui.trayCheckBox->isChecked() || - ui.messageCheckBox->isChecked() ); - ui.toolTipCheckBox->setEnabled(ui.trayCheckBox->isChecked()); - ui.toolTipCheckBox->setChecked( - settings.value("Tray/show_tooltip",FALSE).toBool()); - - ui.hideToTrayRadioButton->setChecked(settings.value("Tray/hide_on_close", FALSE).toBool()); - ui.closeGroupBox->setEnabled(ui.trayCheckBox->isChecked()); - - QString f_dialogName = - settings.value("FileDialog",QtFileDialogFactory::QtFileDialogFactoryName).toString(); - - int ind = FileDialog::registeredFactories().indexOf(f_dialogName); - if (ind != -1) - ui.fileDialogComboBox->setCurrentIndex(ind); - else - ui.fileDialogComboBox->setCurrentIndex(0); - - //proxy settings - ui.enableProxyCheckBox->setChecked( - settings.value ("Proxy/use_proxy", FALSE).toBool()); - ui.authProxyCheckBox->setChecked( - settings.value ("Proxy/authentication", FALSE).toBool()); - - ui.hostLineEdit->setText(settings.value("Proxy/host").toString()); - ui.portLineEdit->setText(settings.value("Proxy/port").toString()); - ui.proxyUserLineEdit->setText(settings.value("Proxy/user").toString()); - ui.proxyPasswLineEdit->setText(settings.value("Proxy/passw").toString()); - - ui.hostLineEdit->setEnabled(ui.enableProxyCheckBox->isChecked()); - ui.portLineEdit->setEnabled(ui.enableProxyCheckBox->isChecked()); - ui.proxyUserLineEdit->setEnabled(ui.authProxyCheckBox->isChecked()); - ui.proxyPasswLineEdit->setEnabled(ui.authProxyCheckBox->isChecked()); -} - -void ConfigDialog::changePage ( QListWidgetItem *current, QListWidgetItem *previous ) -{ - if ( !current ) - current = previous; - ui.stackedWidget->setCurrentIndex ( ui.contentsWidget->row ( current ) ); -} - -void ConfigDialog::changeSkin() -{ - int row = ui.listWidget->currentRow(); - QString path = m_skinList.at ( row ).canonicalFilePath(); - m_skin->setSkin ( path ); -} - -void ConfigDialog::loadSkins() -{ - m_skinList.clear(); - //findSkins(":/"); - - QFileInfo fileInfo (":/default"); - QPixmap preview = Skin::getPixmap ("main", QDir (fileInfo.filePath())); - QListWidgetItem *item = new QListWidgetItem (fileInfo.fileName ()); - item->setIcon ( preview ); - ui.listWidget->addItem ( item ); - m_skinList << fileInfo; - - findSkins(QDir::homePath() +"/.qmmp/skins"); - findSkins(QDir::homePath() +"/.qmmp/cache/skins"); - connect ( ui.listWidget, SIGNAL ( itemClicked ( QListWidgetItem* ) ), - this, SLOT ( changeSkin() ) ); -} - -void ConfigDialog::findSkins(const QString &path) -{ - QDir dir(path); - dir.setFilter ( QDir::Dirs | QDir::NoDotAndDotDot); - QList fileList = dir.entryInfoList(); - if ( fileList.count() == 0 ) - return; - foreach (QFileInfo fileInfo, fileList) - { - QPixmap preview = Skin::getPixmap ( "main", QDir ( fileInfo.filePath() ) ); - if ( !preview.isNull() ) - { - QListWidgetItem *item = new QListWidgetItem ( fileInfo.fileName () ); - item->setIcon ( preview ); - ui.listWidget->addItem ( item ); - m_skinList << fileInfo; - } - } -} - -void ConfigDialog::loadPluginsInfo() -{ - /* - load input plugins information - */ - QList *decoders = 0; - decoders = Decoder::decoderFactories(); - QStringList files = Decoder::decoderFiles(); - ui.inputPluginTable->setColumnCount ( 3 ); - ui.inputPluginTable->verticalHeader()->hide(); - ui.inputPluginTable->setHorizontalHeaderLabels ( QStringList() - << tr ( "Enabled" ) << tr ( "Description" ) << tr ( "Filename" ) ); - ui.inputPluginTable->setRowCount ( decoders->count () ); - for ( int i = 0; i < decoders->count (); ++i ) - { - InputPluginItem *item = new InputPluginItem(this,decoders->at(i),files.at(i)); - QCheckBox* checkBox = new QCheckBox ( ui.inputPluginTable ); - connect(checkBox, SIGNAL(toggled(bool)), item, SLOT(setSelected(bool))); - checkBox->setChecked(item->isSelected()); - ui.inputPluginTable->setCellWidget ( i, 0, checkBox ); - ui.inputPluginTable->setItem ( i,1, - new QTableWidgetItem (item->factory()->properties().name) ); - ui.inputPluginTable->setItem ( i,2, new QTableWidgetItem (files.at (i)) ); - } - ui.inputPluginTable->resizeColumnToContents ( 0 ); - ui.inputPluginTable->resizeColumnToContents ( 1 ); - ui.inputPluginTable->resizeRowsToContents (); - /* - load output plugins information - */ - QList *outputs = 0; - outputs = Output::outputFactories(); - files = Output::outputFiles(); - ui.outputPluginTable->setColumnCount ( 3 ); - ui.outputPluginTable->verticalHeader()->hide(); - ui.outputPluginTable->setHorizontalHeaderLabels ( QStringList() - << tr ( "Enabled" ) << tr ( "Description" ) << tr ( "Filename" ) ); - ui.outputPluginTable->setRowCount ( outputs->count () ); - - for ( int i = 0; i < outputs->count (); ++i ) - { - OutputPluginItem *item = new OutputPluginItem(this,outputs->at(i),files.at(i)); - m_outputPluginItems.append(item); - QRadioButton* button = new QRadioButton ( ui.outputPluginTable ); - connect(button, SIGNAL(pressed ()), item, SLOT(select())); - button->setChecked ( item->isSelected() ); - ui.outputPluginTable->setCellWidget ( i, 0, button ); - ui.outputPluginTable->setItem (i,1, - new QTableWidgetItem (item->factory()->name())); - ui.outputPluginTable->setItem (i,2, new QTableWidgetItem (files.at(i))); - } - - ui.outputPluginTable->resizeColumnToContents ( 0 ); - ui.outputPluginTable->resizeColumnToContents ( 1 ); - ui.outputPluginTable->resizeRowsToContents (); - /* - load visual plugin information - */ - QList *visuals = 0; - visuals = Visual::visualFactories(); - files = Visual::visualFiles(); - ui.visualPluginTable->setColumnCount ( 3 ); - ui.visualPluginTable->verticalHeader()->hide(); - ui.visualPluginTable->setHorizontalHeaderLabels ( QStringList() - << tr ( "Enabled" ) << tr ( "Description" ) << tr ( "Filename" ) ); - ui.visualPluginTable->setRowCount ( visuals->count () ); - - for ( int i = 0; i < visuals->count (); ++i ) - { - VisualPluginItem *item = new VisualPluginItem(this,visuals->at(i),files.at(i)); - m_visualPluginItems.append(item); - QCheckBox* button = new QCheckBox (ui.visualPluginTable); - connect(button, SIGNAL(clicked (bool)), item, SLOT(select(bool))); - button->setChecked (item->isSelected()); - ui.visualPluginTable->setCellWidget ( i, 0, button ); - ui.visualPluginTable->setItem (i,1, - new QTableWidgetItem (item->factory()->properties().name)); - ui.visualPluginTable->setItem (i,2, new QTableWidgetItem (files.at(i))); - } - - ui.visualPluginTable->resizeColumnToContents ( 0 ); - ui.visualPluginTable->resizeColumnToContents ( 1 ); - ui.visualPluginTable->resizeRowsToContents (); - - /* - load effect plugin information - */ - QList *effects = 0; - effects = Effect::effectFactories(); - files = Effect::effectFiles(); - ui.effectPluginTable->setColumnCount ( 3 ); - ui.effectPluginTable->verticalHeader()->hide(); - ui.effectPluginTable->setHorizontalHeaderLabels ( QStringList() - << tr ( "Enabled" ) << tr ( "Description" ) << tr ( "Filename" ) ); - ui.effectPluginTable->setRowCount ( visuals->count () ); - - for ( int i = 0; i < effects->count (); ++i ) - { - EffectPluginItem *item = new EffectPluginItem(this,effects->at(i),files.at(i)); - m_effectPluginItems.append(item); - QCheckBox* button = new QCheckBox (ui.effectPluginTable); - connect(button, SIGNAL(clicked (bool)), item, SLOT(select(bool))); - button->setChecked (item->isSelected()); - ui.effectPluginTable->setCellWidget ( i, 0, button ); - ui.effectPluginTable->setItem (i,1, - new QTableWidgetItem (item->factory()->properties().name)); - ui.effectPluginTable->setItem (i,2, new QTableWidgetItem (files.at(i))); - } - - ui.effectPluginTable->resizeColumnToContents ( 0 ); - ui.effectPluginTable->resizeColumnToContents ( 1 ); - ui.effectPluginTable->resizeRowsToContents (); -} - - -void ConfigDialog::loadFonts() -{ - QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); - QString fontname = settings.value ( "PlayList/Font","" ).toString(); - if ( fontname.isEmpty () ) - fontname = QFont ( "Helvetica [Cronyx]", 10 ).toString(); - ui.plFontLabel -> setText ( fontname ); - - fontname = settings.value ( "MainWindow/Font","" ).toString(); - if ( fontname.isEmpty () ) - fontname = QFont ( "Helvetica [Cronyx]", 9 ).toString(); - ui.mainFontLabel -> setText ( fontname ); -} - -void ConfigDialog::setPlFont() -{ - bool ok; - QFont font; - font.fromString ( ui.plFontLabel->text() ); - font = QFontDialog::getFont ( &ok, font, this ); - if ( ok ) - { - ui.plFontLabel -> setText ( font.toString () ); - QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); - settings.setValue ( "PlayList/Font", font.toString() ); - } -} - -void ConfigDialog::setMainFont() -{ - bool ok; - QFont font; - font.fromString ( ui.plFontLabel->text() ); - font = QFontDialog::getFont ( &ok, font, this ); - if ( ok ) - { - ui.mainFontLabel -> setText ( font.toString () ); - QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); - settings.setValue ( "MainWindow/Font", font.toString() ); - } -} - -void ConfigDialog::showPluginSettings() -{ - switch ( ( int ) ui.pluginsTab -> currentIndex () ) - { - case 0: - { - QList *decoders = 0; - decoders = Decoder::decoderFactories(); - int row = ui.inputPluginTable->currentRow (); - if ( !decoders || row<0 ) - return; - - decoders->at ( row )->showSettings ( this ); - break; - } - case 1: - { - int row = ui.outputPluginTable->currentRow (); - if ( m_outputPluginItems.isEmpty() || row < 0 ) - return; - m_outputPluginItems.at(row)->factory()->showSettings ( this ); - break; - } - case 2: - { - int row = ui.visualPluginTable->currentRow (); - if ( m_visualPluginItems.isEmpty() || row < 0 ) - return; - m_visualPluginItems.at(row)->factory()->showSettings ( this ); - break; - } - case 3: - { - int row = ui.effectPluginTable->currentRow (); - if ( m_effectPluginItems.isEmpty() || row < 0 ) - return; - m_effectPluginItems.at(row)->factory()->showSettings ( this ); - break; - } - } -} - -void ConfigDialog::showPluginInfo() -{ - switch ( ( int ) ui.pluginsTab -> currentIndex () ) - { - case 0: - { - QList *decoders = 0; - decoders = Decoder::decoderFactories(); - int row = ui.inputPluginTable->currentRow (); - if ( !decoders || row<0 ) - return; - - decoders->at ( row )->showAbout ( this ); - break; - } - case 1: - { - int row = ui.outputPluginTable->currentRow (); - if ( m_outputPluginItems.isEmpty() || row < 0 ) - return; - m_outputPluginItems.at(row)->factory()->showAbout ( this ); - break; - } - case 2: - { - int row = ui.visualPluginTable->currentRow (); - if ( m_visualPluginItems.isEmpty() || row < 0 ) - return; - m_visualPluginItems.at(row)->factory()->showAbout ( this ); - break; - } - case 3: - { - int row = ui.effectPluginTable->currentRow (); - if ( m_effectPluginItems.isEmpty() || row < 0 ) - return; - m_effectPluginItems.at(row)->factory()->showAbout ( this ); - break; - } - } -} - -void ConfigDialog::createMenus() -{ - QMenu *menu = new QMenu(this); - - menu->addAction(tr("Artist"))->setData("%p"); - menu->addAction(tr("Album"))->setData("%a"); - menu->addAction(tr("Title"))->setData("%t"); - menu->addAction(tr("Tracknumber"))->setData("%n"); - menu->addAction(tr("Genre"))->setData("%g"); - menu->addAction(tr("Filename"))->setData("%f"); - menu->addAction(tr("Filepath"))->setData("%F"); - menu->addAction(tr("Date"))->setData("%d"); - menu->addAction(tr("Year"))->setData("%y"); - menu->addAction(tr("Comment"))->setData("%c"); - ui.titleButton->setMenu(menu); - ui.titleButton->setPopupMode(QToolButton::InstantPopup); - connect( menu, SIGNAL(triggered ( QAction * )), SLOT(addTitleString( QAction * ))); -} - -void ConfigDialog::addTitleString( QAction * a) -{ - if (ui.formatLineEdit->cursorPosition () < 1) - ui.formatLineEdit->insert(a->data().toString()); - else - ui.formatLineEdit->insert(" - "+a->data().toString()); -} - -void ConfigDialog::saveSettings() -{ - QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); - settings.setValue ("PlayList/title_format", ui.formatLineEdit->text()); - settings.setValue ("PlayList/load_metadata", ui.metadataCheckBox->isChecked()); - settings.setValue ("MainWindow/tray_enabled", ui.trayCheckBox->isChecked()); - settings.setValue ("Tray/enabled", ui.trayCheckBox->isChecked()); - settings.setValue ("Tray/show_message", ui.messageCheckBox->isChecked()); - settings.setValue ("Tray/message_delay", ui.messageDelaySpinBox->value()); - settings.setValue ("Tray/show_tooltip", ui.toolTipCheckBox->isChecked()); - settings.setValue ("Tray/hide_on_close",ui.hideToTrayRadioButton->isChecked()); - settings.setValue ("FileDialog", ui.fileDialogComboBox->currentText()); - settings.setValue ("Proxy/use_proxy", ui.enableProxyCheckBox->isChecked()); - settings.setValue ("Proxy/authentication", ui.authProxyCheckBox->isChecked()); - settings.setValue ("Proxy/host",ui.hostLineEdit->text()); - settings.setValue ("Proxy/port",ui.portLineEdit->text()); - settings.setValue ("Proxy/user",ui.proxyUserLineEdit->text()); - settings.setValue ("Proxy/passw",ui.proxyPasswLineEdit->text()); -} - diff --git a/src/configdialog.h b/src/configdialog.h deleted file mode 100644 index a5c632cc6..000000000 --- a/src/configdialog.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef CONFIGDIALOG_H -#define CONFIGDIALOG_H - -#include -#include - -#include "ui_configdialog.h" - - -/** - @author Ilya Kotov -*/ -class QFileInfo; - -class Skin; -class InputPluginItem; -class OutputPluginItem; -class VisualPluginItem; -class EffectPluginItem; - -class ConfigDialog : public QDialog -{ - Q_OBJECT -public: - ConfigDialog(QWidget *parent = 0); - - ~ConfigDialog(); - -private slots: - void changePage(QListWidgetItem *current, QListWidgetItem *previous); - void changeSkin(); - void setPlFont(); - void setMainFont(); - void showPluginSettings(); - void showPluginInfo(); - void addTitleString( QAction * ); - void saveSettings(); - -private: - void readSettings(); - void loadSkins(); - void findSkins(const QString &path); - void loadPluginsInfo(); - void loadFonts(); - void createMenus(); - - - QList m_skinList; - Ui::ConfigDialog ui; - Skin *m_skin; - QPixmap pixmap; - - QList m_inputPluginItems; - QList m_outputPluginItems; - QList m_visualPluginItems; - QList m_effectPluginItems; -}; - -#endif diff --git a/src/configdialog.ui b/src/configdialog.ui deleted file mode 100644 index 1f6f45516..000000000 --- a/src/configdialog.ui +++ /dev/null @@ -1,1118 +0,0 @@ - - ConfigDialog - - - - 0 - 0 - 601 - 375 - - - - Qmmp Settings - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - - 170 - 16777215 - - - - - 38 - 38 - - - - QListView::Static - - - QListView::TopToBottom - - - false - - - QListView::Adjust - - - QListView::ListMode - - - false - - - 100 - - - false - - - 0 - - - - Appearance - - - :/interface.png - - - - - Playlist - - - :/playlist.png - - - - - Plugins - - - :/plugins.png - - - - - Advanced - - - :/advanced.png - - - - - Connectivity - - - - - - - - - 0 - 0 - - - - QFrame::Raised - - - 0 - - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - Skins - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - QListView::Static - - - QListView::TopToBottom - - - QListView::ListMode - - - 0 - - - - - - - - - - Fonts - - - - 9 - - - 9 - - - 9 - - - 9 - - - 6 - - - 6 - - - - - - 80 - 16777215 - - - - Player: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - - 80 - 16777215 - - - - Playlist: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - QFrame::Panel - - - QFrame::Sunken - - - ??? - - - - - - - ... - - - - - - - QFrame::Panel - - - QFrame::Sunken - - - ??? - - - - - - - ... - - - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - 6 - - - 6 - - - - - Metadata - - - - 9 - - - 9 - - - 9 - - - 9 - - - 6 - - - 6 - - - - - Load metadata from files - - - - - - - - - - Song Display - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - Title format: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - ... - - - - - - - - - - Qt::Vertical - - - - 20 - 121 - - - - - - - - - - 9 - - - 9 - - - 9 - - - 9 - - - 6 - - - 6 - - - - - Preferences - - - - - - - Information - - - - - - - Qt::Horizontal - - - - 101 - 20 - - - - - - - - QTabWidget::North - - - QTabWidget::Rounded - - - 0 - - - - Input - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - 0 - - - 0 - - - - - - - - Output - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - - - - - - Visualization - - - - - - QAbstractItemView::SingleSelection - - - QAbstractItemView::SelectRows - - - - - - - - Effects - - - - - - QAbstractItemView::SelectRows - - - - - - - - File Dialog - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - Tray Icon - - - - 9 - - - 9 - - - 9 - - - 9 - - - 6 - - - 6 - - - - - Show tooltip - - - - - - - Show message - - - - - - - 100 - - - 10000 - - - 100 - - - 1000 - - - - - - - Message delay, ms: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - Show tray icon - - - - - - - - - - Action On Close - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - Hide to tray - - - - - - - Quit - - - true - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - Proxy - - - false - - - false - - - - - - Enable proxy usage - - - - - - - Proxy host name: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Proxy port: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Use authentication with proxy - - - - - - - Proxy user name: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - - - Proxy password: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - QLineEdit::Password - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - - - - Qt::Horizontal - - - - - - - 6 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::Horizontal - - - - 341 - 20 - - - - - - - - Close - - - - - - - - - - - - - closeButton - clicked() - ConfigDialog - accept() - - - 590 - 364 - - - 316 - 340 - - - - - trayCheckBox - toggled(bool) - toolTipCheckBox - setEnabled(bool) - - - 550 - 64 - - - 383 - 118 - - - - - trayCheckBox - toggled(bool) - messageDelaySpinBox - setEnabled(bool) - - - 208 - 55 - - - 469 - 148 - - - - - trayCheckBox - toggled(bool) - messageCheckBox - setEnabled(bool) - - - 262 - 55 - - - 258 - 76 - - - - - messageCheckBox - toggled(bool) - messageDelaySpinBox - setEnabled(bool) - - - 307 - 82 - - - 469 - 148 - - - - - trayCheckBox - clicked(bool) - closeGroupBox - setEnabled(bool) - - - 376 - 56 - - - 436 - 175 - - - - - enableProxyCheckBox - toggled(bool) - hostLineEdit - setEnabled(bool) - - - 305 - 52 - - - 424 - 82 - - - - - enableProxyCheckBox - toggled(bool) - portLineEdit - setEnabled(bool) - - - 506 - 56 - - - 506 - 116 - - - - - authProxyCheckBox - toggled(bool) - proxyUserLineEdit - setEnabled(bool) - - - 318 - 142 - - - 326 - 163 - - - - - authProxyCheckBox - toggled(bool) - proxyPasswLineEdit - setEnabled(bool) - - - 264 - 138 - - - 334 - 204 - - - - - diff --git a/src/default/balance.png b/src/default/balance.png deleted file mode 100644 index 5fa10cce8..000000000 Binary files a/src/default/balance.png and /dev/null differ diff --git a/src/default/cbuttons.png b/src/default/cbuttons.png deleted file mode 100644 index 7a1369b59..000000000 Binary files a/src/default/cbuttons.png and /dev/null differ diff --git a/src/default/eq_ex.png b/src/default/eq_ex.png deleted file mode 100644 index 974004590..000000000 Binary files a/src/default/eq_ex.png and /dev/null differ diff --git a/src/default/eqmain.png b/src/default/eqmain.png deleted file mode 100644 index b28b818de..000000000 Binary files a/src/default/eqmain.png and /dev/null differ diff --git a/src/default/main.png b/src/default/main.png deleted file mode 100644 index 6b7c8597a..000000000 Binary files a/src/default/main.png and /dev/null differ diff --git a/src/default/monoster.png b/src/default/monoster.png deleted file mode 100644 index 7ddb9d0e5..000000000 Binary files a/src/default/monoster.png and /dev/null differ diff --git a/src/default/numbers.png b/src/default/numbers.png deleted file mode 100644 index 46f1e1f63..000000000 Binary files a/src/default/numbers.png and /dev/null differ diff --git a/src/default/playpaus.png b/src/default/playpaus.png deleted file mode 100644 index 0cfbd6835..000000000 Binary files a/src/default/playpaus.png and /dev/null differ diff --git a/src/default/pledit.png b/src/default/pledit.png deleted file mode 100644 index 3c2943cea..000000000 Binary files a/src/default/pledit.png and /dev/null differ diff --git a/src/default/pledit.txt b/src/default/pledit.txt deleted file mode 100644 index 5435dd2fd..000000000 --- a/src/default/pledit.txt +++ /dev/null @@ -1,6 +0,0 @@ -[Text] -Normal=#C0C0C0 -Current=#8080FF -NormalBG=#400080 -SelectedBG=#408080 -Font=Tahoma Bold \ No newline at end of file diff --git a/src/default/posbar.png b/src/default/posbar.png deleted file mode 100644 index 271106557..000000000 Binary files a/src/default/posbar.png and /dev/null differ diff --git a/src/default/shufrep.png b/src/default/shufrep.png deleted file mode 100644 index 107fd50bb..000000000 Binary files a/src/default/shufrep.png and /dev/null differ diff --git a/src/default/text.png b/src/default/text.png deleted file mode 100644 index d37241405..000000000 Binary files a/src/default/text.png and /dev/null differ diff --git a/src/default/titlebar.png b/src/default/titlebar.png deleted file mode 100644 index c1e7818cd..000000000 Binary files a/src/default/titlebar.png and /dev/null differ diff --git a/src/default/viscolor.txt b/src/default/viscolor.txt deleted file mode 100644 index 65490ebb6..000000000 --- a/src/default/viscolor.txt +++ /dev/null @@ -1,24 +0,0 @@ -0,64,128 -0,64,128 -55,105,155 -63,111,159 -71,117,163 -79,123,167 -87,129,171 -95,135,175 -103,141,179 -111,147,183 -119,153,187 -127,159,191 -135,165,195 -143,171,199 -151,177,203 -159,183,207 -167,189,211 -175,195,215 -255,255,255 -167,189,211 -135,165,195 -119,153,187 -87,129,171 -87,179,160 diff --git a/src/default/volume.png b/src/default/volume.png deleted file mode 100644 index b4f457453..000000000 Binary files a/src/default/volume.png and /dev/null differ diff --git a/src/display.cpp b/src/display.cpp deleted file mode 100644 index d2cce8165..000000000 --- a/src/display.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include -#include -#include - -#include -#include "skin.h" -#include "mainvisual.h" -#include "button.h" -#include "titlebar.h" -#include "positionbar.h" -#include "number.h" -#include "togglebutton.h" -#include "symboldisplay.h" -#include "textscroller.h" -#include "monostereo.h" -#include "playstatus.h" -#include "volumebar.h" -#include "balancebar.h" -#include "mainwindow.h" -#include "timeindicator.h" - -#include "display.h" - -MainDisplay::MainDisplay ( QWidget *parent ) - : PixmapWidget ( parent ) -{ - m_skin = Skin::getPointer(); - setPixmap ( m_skin->getMain() ); - setMaximumSize ( QSize ( 275,116 ) ); - setMinimumSize ( QSize ( 275,116 ) ); - - m_mw = qobject_cast(parent); - - Button *previous = new Button ( this, - Skin::BT_PREVIOUS_N, Skin::BT_PREVIOUS_P ); - previous->move ( 16, 88 ); - connect ( previous,SIGNAL ( clicked() ),parent,SLOT ( previous() ) ); - Button *play = new Button ( this, - Skin::BT_PLAY_N, Skin::BT_PLAY_P ); - play->move ( 39, 88 ); - connect ( play,SIGNAL ( clicked() ),parent,SLOT ( play() ) ); - Button *pause = new Button ( this, Skin::BT_PAUSE_N,Skin::BT_PAUSE_P ); - pause->move ( 62, 88 ); - connect ( pause,SIGNAL ( clicked() ),parent,SLOT ( pause() ) ); - Button *stop = new Button ( this, Skin::BT_STOP_N,Skin::BT_STOP_P ); - stop->move ( 85, 88 ); - connect ( stop,SIGNAL ( clicked() ),parent,SLOT ( stop() ) ); - connect ( stop,SIGNAL ( clicked() ),this,SLOT ( hideTimeDisplay() ) ); - Button *next = new Button ( this, Skin::BT_NEXT_N,Skin::BT_NEXT_P ); - next->move ( 108, 88 ); - connect ( next,SIGNAL ( clicked() ),parent,SLOT ( next() ) ); - Button *eject = new Button ( this, Skin::BT_EJECT_N,Skin::BT_EJECT_P ); - eject->move ( 136, 89 ); - connect ( eject,SIGNAL ( clicked() ),parent,SLOT ( addFile() ) ); - connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); - posbar = new PositionBar ( this ); - posbar->move ( 16,72 ); - //connect(posbar, SIGNAL(sliderMoved(int)), SLOT(setTime(int))); - MainVisual* vis = new MainVisual (this); - vis->move(24,39); - vis->show(); - - m_eqButton = new ToggleButton ( this,Skin::BT_EQ_ON_N,Skin::BT_EQ_ON_P, - Skin::BT_EQ_OFF_N,Skin::BT_EQ_OFF_P ); - m_eqButton->move ( 219,58 ); - m_eqButton->show(); - m_plButton = new ToggleButton ( this,Skin::BT_PL_ON_N,Skin::BT_PL_ON_P, - Skin::BT_PL_OFF_N,Skin::BT_PL_OFF_P ); - m_plButton->move ( 241,58 ); - m_plButton->show(); - - m_repeatButton = new ToggleButton ( this,Skin::REPEAT_ON_N,Skin::REPEAT_ON_P, - Skin::REPEAT_OFF_N,Skin::REPEAT_OFF_P ); - connect(m_repeatButton,SIGNAL(clicked(bool)),this,SIGNAL(repeatableToggled(bool))); - - m_repeatButton->move ( 210,89 ); - m_repeatButton->show(); - - m_shuffleButton = new ToggleButton ( this,Skin::SHUFFLE_ON_N,Skin::SHUFFLE_ON_P, - Skin::SHUFFLE_OFF_N,Skin::SHUFFLE_OFF_P ); - connect(m_shuffleButton,SIGNAL(clicked(bool)),this,SIGNAL(shuffleToggled(bool))); - m_shuffleButton->move ( 164,89 ); - m_shuffleButton->show(); - - m_kbps = new SymbolDisplay( this,3 ); - m_kbps -> move ( 111,43 ); - m_kbps -> show(); - - m_freq = new SymbolDisplay( this,2 ); - m_freq -> move ( 156,43 ); - m_freq -> show(); - - TextScroller *m_text = new TextScroller ( this ); - m_text->resize ( 154,15 ); - m_text->move ( 109,23 ); - m_text->show(); - - m_monoster = new MonoStereo ( this ); - m_monoster->move ( 212,41 ); - m_monoster->show(); - - m_playstatus = new PlayStatus(this); - m_playstatus->move(24,28); - m_playstatus->show(); - - m_volumeBar = new VolumeBar(this); - connect(m_volumeBar, SIGNAL(sliderMoved(int)),SLOT(updateVolume())); - m_volumeBar->move(107,57); - m_volumeBar->show(); - - m_balanceBar = new BalanceBar(this); - connect(m_balanceBar, SIGNAL(sliderMoved(int)),SLOT(updateVolume())); - m_balanceBar->move(177,57); - m_balanceBar->show(); - m_timeIndicator = new TimeIndicator(this); - m_timeIndicator->move(34,26); - m_timeIndicator->show(); -} - - -MainDisplay::~MainDisplay() -{ - QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); - settings.setValue ( "Playlist/visible",m_plButton->isChecked() ); - settings.setValue ( "Equalizer/visible",m_eqButton->isChecked() ); -} - -void MainDisplay::setTime ( int t ) -{ - posbar->setValue ( t ); - m_timeIndicator->setTime(t); -} -void MainDisplay::setMaxTime ( long mt ) // TODO: should be removed -{ - posbar->setMax ( mt ); - m_timeIndicator->setSongDuration(mt); -} - - -void MainDisplay::updateSkin() -{ - setPixmap ( m_skin->getMain() ); -} - -void MainDisplay::setEQ ( QWidget* w ) -{ - m_equlizer = w; - m_eqButton->setON ( m_equlizer->isVisible() ); - connect (m_eqButton, SIGNAL (clicked(bool)), m_equlizer, SLOT (setVisible (bool))); - connect (m_equlizer, SIGNAL (closed ()), m_eqButton, SLOT (click())); -} - -void MainDisplay::setPL ( QWidget* w ) -{ - m_playlist = w; - m_plButton->setON ( m_playlist->isVisible() ); - connect (m_plButton, SIGNAL (clicked (bool)), m_playlist, SLOT (setVisible (bool))); - connect (m_playlist, SIGNAL (closed ()), m_plButton, SLOT (click())); -} - -void MainDisplay::setInfo(const OutputState &st) -{ - - - switch ( ( int ) st.type() ) - { - case OutputState::Info: - { - //if ( seeking ) - // break; - setTime ( st.elapsedSeconds() ); - m_kbps->display ( st.bitrate() ); - m_freq->display ( st.frequency() /1000 ); - m_monoster->setChannels ( st.channels() ); - update(); - break; - } - case OutputState::Playing: - { - m_playstatus->setStatus(PlayStatus::PLAY); - m_timeIndicator->setNeedToShowTime(true); - break; - } - case OutputState::Buffering: - { - //ui.label->setText("Buffering"); - break; - } - case OutputState::Paused: - { - m_playstatus->setStatus(PlayStatus::PAUSE); - break; - } - case OutputState::Stopped: - { - m_playstatus->setStatus(PlayStatus::STOP); - m_monoster->setChannels (0); - //m_timeIndicator->setNeedToShowTime(false); - break; - } - case OutputState::Volume: - //qDebug("volume %d, %d", st.rightVolume(), st.leftVolume()); - int maxVol = qMax(st.leftVolume(),st.rightVolume()); - m_volumeBar->setValue(maxVol); - if (maxVol && !m_volumeBar->isPressed()) - m_balanceBar->setValue((st.rightVolume()-st.leftVolume())*100/maxVol); - break; - - } -} - -bool MainDisplay::isPlaylistVisible() const -{ - return m_plButton->isChecked(); -} - -bool MainDisplay::isEqualizerVisible() const -{ - return m_eqButton->isChecked(); -} - -void MainDisplay::updateVolume() -{ - m_mw->setVolume(m_volumeBar->value(), m_balanceBar->value()); -} - -void MainDisplay::wheelEvent (QWheelEvent *e) -{ - m_mw->setVolume(m_volumeBar->value()+e->delta()/10, m_balanceBar->value()); -} - -bool MainDisplay::isRepeatable() const -{ - return m_repeatButton->isChecked(); -} - -bool MainDisplay::isShuffle() const -{ - return m_shuffleButton->isChecked(); -} - -void MainDisplay::setIsRepeatable(bool yes) -{ - m_repeatButton->setON(yes); -} - -void MainDisplay::setIsShuffle(bool yes) -{ - m_shuffleButton->setON(yes); -} - - -void MainDisplay::hideTimeDisplay() -{ - m_timeIndicator->setNeedToShowTime(false); -} - - -void MainDisplay::mousePressEvent(QMouseEvent *e) -{ - if ( e->button() == Qt::RightButton) - { - m_mw->menu()->exec(e->globalPos()); - } - PixmapWidget::mousePressEvent(e); -} - - diff --git a/src/display.h b/src/display.h deleted file mode 100644 index 15e0111d6..000000000 --- a/src/display.h +++ /dev/null @@ -1,106 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef DISPLAY_H -#define DISPLAY_H - -#include - -class TimeIndicator; - - -#include "pixmapwidget.h" - -/** - @author Ilya Kotov -*/ -class QPushButton; -class QLabel; - -class TitleBar; -class PositionBar; -class Number; -class Skin; -class ToggleButton; -class OutputState; -class NumberDisplay; -class SymbolDisplay; -class MonoStereo; -class PlayStatus; -class VolumeBar; -class BalanceBar; -class MainWindow; - -class MainDisplay : public PixmapWidget -{ - Q_OBJECT -public: - MainDisplay(QWidget *parent = 0); - - ~MainDisplay(); - - void setMaxTime(long); - void setEQ(QWidget*); - void setPL(QWidget*); - void setInfo(const OutputState &st); - bool isEqualizerVisible()const; - bool isPlaylistVisible()const; - bool isRepeatable()const; - bool isShuffle()const; - void setIsRepeatable(bool); - void setIsShuffle(bool); - -public slots: - void setTime(int); - void hideTimeDisplay(); -signals: - void repeatableToggled(bool); - void shuffleToggled(bool); -protected: - void wheelEvent(QWheelEvent *); - void mousePressEvent(QMouseEvent*); - -private slots: - void updateSkin(); - void updateVolume(); - -private: - QWidget* m_equlizer; - QWidget* m_playlist; - QPixmap pixmap; - QPushButton *button; - QLabel *label; - Skin *m_skin; - TitleBar *titleBar; - PositionBar *posbar; - ToggleButton *m_eqButton; - ToggleButton *m_plButton; - ToggleButton *m_shuffleButton; - ToggleButton *m_repeatButton; - SymbolDisplay* m_kbps; - SymbolDisplay* m_freq; - MonoStereo* m_monoster; - PlayStatus* m_playstatus; - VolumeBar* m_volumeBar; - BalanceBar* m_balanceBar; - MainWindow* m_mw; - TimeIndicator* m_timeIndicator; -}; - -#endif diff --git a/src/dock.cpp b/src/dock.cpp deleted file mode 100644 index 2a755a9b9..000000000 --- a/src/dock.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -#include "dock.h" - - -Dock *Dock::pointer = 0; - -Dock *Dock::getPointer() -{ - if ( !pointer ) - pointer = new Dock(); - return pointer; -} - -Dock::Dock ( QObject *parent ) - : QObject ( parent ) -{ - pointer = this; - m_mainWidget = 0; -} - -Dock::~Dock() -{} - -void Dock::setMainWidget ( QWidget *widget ) -{ - m_mainWidget = widget; - m_widgetList.prepend ( widget ); - m_dockedList.prepend ( FALSE ); -} - - -QPoint Dock::snap ( QPoint npos, QWidget* mv, QWidget* st ) -{ - int nx = npos.x() - st->x(); - int ny = abs ( npos.y() - st->y() + mv->height() ); - - if ( abs ( nx ) < 13 && ny < 13 ) //above - npos.rx() = st->x(); - if ( ny < 13 && nx > -mv->width() && nx < st->width() ) - npos.ry() = st->y() - mv->height(); - nx = abs ( npos.x() + mv->width() - st->x() - st->width() ); - if ( nx < 13 && ny < 13 ) - npos.rx() = st->x() + st->width() - mv->width(); - - /***********/ - nx = npos.x() - st->x(); - ny = abs ( npos.y() - st->y() - st->height() ); - - if ( abs ( nx ) < 13 && ny < 13 ) //near - npos.rx() = st->x(); - if ( ny < 13 && nx > -mv->width() && nx < st->width() ) - npos.ry() = st->y() + st->height(); - nx = abs ( npos.x() + mv->width() - st->x() - st->width() ); - if ( nx < 13 && ny < 13 ) - npos.rx() = st->x() + st->width() - mv->width(); - /**************/ - nx = abs ( npos.x() - st->x() + mv->width() ); - ny = npos.y() - st->y(); - - if ( nx < 13 && abs ( ny ) < 13 ) //left - npos.ry() = st->y(); - if ( nx < 13 && ny > -mv->height() && ny < st->height() ) - npos.rx() = st->x() - mv->width(); - - ny = abs ( npos.y() + mv->height() - st->y() - st->height() ); - if ( nx < 13 && ny < 13 ) - npos.ry() = st->y() + st->height() - mv->height(); - /*****************/ - nx = abs ( npos.x() - st->x() - st->width() ); - ny = npos.y() - st->y(); - - if ( nx < 13 && abs ( ny ) < 13 ) //right - npos.ry() = st->y(); - if ( nx < 13 && ny > -mv->height() && ny < st->height() ) - npos.rx() = st->x() + st->width(); - - ny = abs ( npos.y() + mv->height() - st->y() - st->height() ); - if ( nx < 13 && ny < 13 ) - npos.ry() = st->y() + st->height() - mv->height(); - - return ( npos ); -} - -void Dock::addWidget ( QWidget *widget ) -{ - m_widgetList.append ( widget ); - m_dockedList.append ( FALSE ); - widget->addActions(m_actions); - -} - -void Dock::move ( QWidget* mv, QPoint npos ) -{ - if ( mv == m_mainWidget ) - { - - for ( int i = 1; iisVisible() ) - npos = snap ( npos, mv, m_widgetList.at ( i ) ); - - } - else - { - QPoint pos = QPoint ( npos.x() + x_list.at ( i ), - npos.y() + y_list.at ( i ) ); - for ( int j = 1; jisVisible() ) - { - pos = snap ( pos, m_widgetList.at ( i ), m_widgetList.at ( j ) ); - npos = QPoint ( pos.x() - x_list.at ( i ), - pos.y() - y_list.at ( i ) ); - } - } - } - } - mv->move ( npos ); - for ( int i = 1; imove ( npos.x() + x_list.at ( i ), - npos.y() + y_list.at ( i ) ); - } - } - else - { - for ( int i = 0; iisVisible() ) - { - npos = snap ( npos, mv, m_widgetList.at ( i ) ); - } - } - mv->move ( npos ); - } -} - -void Dock::calculateDistances() -{ - x_list.clear(); - y_list.clear(); - foreach ( QWidget *w, m_widgetList ) - { - if ( w!=m_mainWidget ) - { - x_list.append ( - m_mainWidget->x() + w->x() ); - y_list.append ( - m_mainWidget->y() + w->y() ); - } - else - { - x_list.prepend ( 0 ); - y_list.prepend ( 0 ); - } - } -} - -void Dock::updateDock() -{ - QWidget *mv = m_widgetList.at ( 0 ); - for ( int j = 1; jx() - st->x(); - int ny = abs ( mv->y() - st->y() + mv->height() ); - if ( ny < 2 && nx > -mv->width() && nx < st->width() ) //above - return TRUE; - - /***********/ - nx = mv->x() - st->x(); - ny = abs ( mv->y() - st->y() - st->height() ); - if ( ny < 2 && nx > -mv->width() && nx < st->width() ) //near - return TRUE; - - /**************/ - nx = abs ( mv->x() - st->x() + mv->width() ); - ny = mv->y() - st->y(); - if ( nx < 2 && ny > -mv->height() && ny < st->height() ) //left - return TRUE; - - /*****************/ - nx = abs ( mv->x() - st->x() - st->width() ); - ny = mv->y() - st->y(); - if ( nx < 2 && ny > -mv->height() && ny < st->height() ) //right - return TRUE; - return FALSE; -} - -void Dock::addActions ( QList actions ) -{ - m_actions << actions; - for ( int i = 0; iaddActions ( actions ); -} - -bool Dock::isUnder(QWidget* upper, QWidget* nether, int dy) -{ - int nx = upper->x() - nether->x(); - return abs (upper->y() + upper->height() -dy - nether->y()) < 2 && - nx > -upper->width() && nx < nether->width(); -} - -void Dock::align(QWidget* w, int dy) -{ - for (int i = 0; imove(m_widgetList.at(i)->x(), m_widgetList.at(i)->y()+dy); - align(m_widgetList.at(i), dy); - } - } -} diff --git a/src/dock.h b/src/dock.h deleted file mode 100644 index b4b62dda2..000000000 --- a/src/dock.h +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef DOCK_H -#define DOCK_H - -#include -#include -#include - -/** - @author Ilya Kotov -*/ - -class QAction; - -class Dock : public QObject -{ - Q_OBJECT -public: - Dock(QObject *parent = 0); - - ~Dock(); - - static Dock *getPointer(); - void setMainWidget(QWidget*); - void addWidget(QWidget *); - void move(QWidget*, QPoint); - void calculateDistances(); - void updateDock(); - QPoint snap(QPoint, QWidget*, QWidget*); - void addActions(QList actions); - void align(QWidget*, int dy); - -private: - bool isDocked(QWidget*, QWidget*); - bool isUnder(QWidget*, QWidget*, int); - static Dock *pointer; - QWidget *m_mainWidget; - QList m_widgetList; - QList m_dockedList; - QList x_list; - QList y_list; - QList m_actions; -}; - -#endif diff --git a/src/eqgraph.cpp b/src/eqgraph.cpp deleted file mode 100644 index 314e504d9..000000000 --- a/src/eqgraph.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include - -#include "skin.h" -#include "eqgraph.h" - -EQGraph::EQGraph ( QWidget *parent ) - : PixmapWidget ( parent ) -{ - m_skin = Skin::getPointer(); - setPixmap ( m_skin->getEqPart ( Skin::EQ_GRAPH ) ); - clear(); - draw(); - connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); -} - - -EQGraph::~EQGraph() -{} - -void EQGraph::addValue ( int value ) -{ - if ( m_values.size() >= 10 ) - return; - m_values.append ( value ); - if ( m_values.size() == 10 ) - { - draw(); - } -} - -void EQGraph::clear () -{ - m_values.clear(); - update(); -} - -void EQGraph::init_spline ( double * x, double * y, int n, double * y2 ) -{ - int i, k; - double p, qn, sig, un, *u; - - //u = ( gfloat * ) g_malloc ( n * sizeof ( gfloat ) ); - u = new double[n]; - - 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 ); - delete[] u; -} - -double EQGraph::eval_spline ( double xa[], double ya[], 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 ); -} - -void EQGraph::draw() -{ - if(m_values.size()!=10) - { - setPixmap ( m_skin->getEqPart ( Skin::EQ_GRAPH ) ); - return; - } - - int i, y, ymin, ymax, py = 0; - double x[] = { 0, 11, 23, 35, 47, 59, 71, 83, 97, 109 }, yf[10]; - double *bands = new double[10]; - - for ( int i = 0; i<10; ++i ) - { - bands[i] = m_values.at ( i ); - } - QPixmap pixmap = m_skin->getEqPart ( Skin::EQ_GRAPH ); - - init_spline ( x, bands, 10, yf ); - for ( i = 0; i < 109; i++ ) - { - y = 9 - - ( int ) ( ( eval_spline ( x, bands, yf, 10, i ) * - 9.0 ) / 20.0 ); - if ( y < 0 ) - y = 0; - if ( y > 18 ) - y = 18; - if ( !i ) - py = y; - if ( y < py ) - { - ymin = y; - ymax = py; - } - else - { - ymin = py; - ymax = y; - } - py = y; - - QPainter paint ( &pixmap ); - paint.drawPixmap ( i, y, m_skin->getEqSpline ( y ) ) ; - - - } - setPixmap ( pixmap ); - delete [] bands; -} - -void EQGraph::updateSkin() -{ - draw(); -} - diff --git a/src/eqgraph.h b/src/eqgraph.h deleted file mode 100644 index 4f6bf1882..000000000 --- a/src/eqgraph.h +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef EQGRAPH_H -#define EQGRAPH_H - -#include "pixmapwidget.h" - -/** - @author Ilya Kotov -*/ - -class Skin; - -class EQGraph : public PixmapWidget -{ - Q_OBJECT -public: - EQGraph ( QWidget *parent = 0 ); - - ~EQGraph(); - - void addValue ( int ); - void clear(); - -/*protected: - void paintEvent ( QPaintEvent * );*/ -private slots: - void updateSkin(); - -private: - QList m_values; - Skin *m_skin; - void init_spline ( double * x, double * y, int n, double * y2 ); - double eval_spline ( double xa[], double ya[], double y2a[], int n, double x ); - void draw(); - -}; - -#endif diff --git a/src/eqpreset.cpp b/src/eqpreset.cpp deleted file mode 100644 index 760dea9d2..000000000 --- a/src/eqpreset.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "eqpreset.h" - -EQPreset::EQPreset() - : QListWidgetItem() -{ - m_preamp = 0; - for(int i = 0; i < 10; ++i) - m_bands[i] = 0; -} - - -EQPreset::~EQPreset() -{} - -void EQPreset::setGain(int n, int value) -{ - if(n > 9 || n < 0) - return; - m_bands[n] = value; -} - -void EQPreset::setPreamp(int preamp) -{ - m_preamp = preamp; -} - -int EQPreset::gain(int n) -{ - if(n > 9 || n < 0) - return 0; - return m_bands[n]; -} - -int EQPreset::preamp() -{ - return m_preamp; -} diff --git a/src/eqpreset.h b/src/eqpreset.h deleted file mode 100644 index 80f31747e..000000000 --- a/src/eqpreset.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef EQPRESET_H -#define EQPRESET_H - -#include - -/** - @author Ilya Kotov -*/ -class EQPreset : public QListWidgetItem -{ -public: - EQPreset(); - - ~EQPreset(); - - void setGain(int n, int value); - void setPreamp(int); - - int gain(int n); - int preamp(); - -private: - int m_bands[10]; - int m_preamp; - -}; - -#endif diff --git a/src/eqslider.cpp b/src/eqslider.cpp deleted file mode 100644 index bdc4ec4e2..000000000 --- a/src/eqslider.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include - -#include "skin.h" - -#include "eqslider.h" - - -EqSlider::EqSlider(QWidget *parent) - : PixmapWidget(parent) -{ - m_skin = Skin::getPointer(); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); - setPixmap(m_skin->getEqSlider(0)); - m_moving = FALSE; - m_min = -20; - m_max = 20; - m_old = m_value = 0; - draw(FALSE); -} - - -EqSlider::~EqSlider() -{} - -void EqSlider::mousePressEvent(QMouseEvent *e) -{ - m_moving = TRUE; - press_pos = e->y(); - if (m_posy() && e->y()y()-m_pos; - } - else - { - m_value = convert(qMax(qMin(height()-12,e->y()-6),0)); - press_pos = 6; - if (m_value!=m_old) - { - emit sliderMoved(m_value); - m_old = m_value; - //qDebug ("%d",m_value); - } - } - draw(); -} - -void EqSlider::mouseReleaseEvent(QMouseEvent*) -{ - m_moving = FALSE; - draw(FALSE); -} - -void EqSlider::mouseMoveEvent(QMouseEvent* e) -{ - if (m_moving) - { - int po = e->y(); - po = po - press_pos; - - if (0<=po && po<=height()-12) - { - m_value = convert(po); - draw(); - if (m_value!=m_old) - { - - m_old = m_value; - //qDebug ("%d",-m_value); - emit sliderMoved(-m_value); - } - } - } -} - -int EqSlider::value() -{ - return -m_value; -} - -void EqSlider::setValue(int p) -{ - if (m_moving) - return; - m_value = -p; - draw(FALSE); -} - -void EqSlider::setMax(int m) -{ - m_max = m; - draw(FALSE); -} - -void EqSlider::updateSkin() -{ - draw(FALSE); -} - -void EqSlider::draw(bool pressed) -{ - int p=int(ceil(double(m_value-m_min)*(height()-12)/(m_max-m_min))); - m_pixmap = m_skin->getEqSlider(27-27*(m_value-m_min)/(m_max-m_min)); - QPainter paint(&m_pixmap); - if (pressed) - paint.drawPixmap(1,p,m_skin->getButton(Skin::EQ_BT_BAR_P)); - else - paint.drawPixmap(1,p,m_skin->getButton(Skin::EQ_BT_BAR_N)); - setPixmap(m_pixmap); - m_pos = p; -} - -int EqSlider::convert(int p) -{ - return int(ceil(double(m_max-m_min)*(p)/(height()-12)+m_min)); -} - -void EqSlider::wheelEvent(QWheelEvent *e) -{ - m_value -= e->delta()/60; - m_value = m_value > m_max ? m_max : m_value; - m_value = m_value < m_min ? m_min : m_value; - draw(FALSE); - emit sliderMoved(m_value); -} - diff --git a/src/eqslider.h b/src/eqslider.h deleted file mode 100644 index 54dc9f285..000000000 --- a/src/eqslider.h +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef EQSLIDER_H -#define EQSLIDER_H - -#include - -/** - @author Ilya Kotov -*/ -class QMouseEvent; -class QWheelEvent; - -class Skin; - -class EqSlider : public PixmapWidget -{ -Q_OBJECT -public: - EqSlider(QWidget *parent = 0); - - ~EqSlider(); - - int value(); - -public slots: - void setValue(int); - void setMax(int); - -signals: - void sliderMoved (int); - -private slots: - void updateSkin(); - -private: - Skin *m_skin; - bool m_moving; - int press_pos; - int m_max, m_min, m_pos, m_value, m_old; - QPixmap m_pixmap; - int convert(int); // value = convert(position); - void draw(bool pressed = TRUE); - -protected: - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); - void wheelEvent(QWheelEvent *); - - -}; - -#endif diff --git a/src/eqtitlebar.cpp b/src/eqtitlebar.cpp deleted file mode 100644 index 5420831f8..000000000 --- a/src/eqtitlebar.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include - -#include "skin.h" -#include "shadedbar.h" -#include "dock.h" -#include "mainwindow.h" -#include "button.h" - -#include "eqtitlebar.h" - -EqTitleBar::EqTitleBar(QWidget *parent) - : PixmapWidget(parent) -{ - m_volumeBar = 0; - m_balanceBar = 0; - m_shade2 = 0; - m_left = 0; - m_right = 0; - m_shaded = FALSE; - m_align = FALSE; - m_skin = Skin::getPointer(); - m_eq = parentWidget(); - m_mw = qobject_cast(m_eq->parent()); - m_close = new Button(this, Skin::EQ_BT_CLOSE_N, Skin::EQ_BT_CLOSE_P); - connect(m_close, SIGNAL(clicked()),m_eq, SIGNAL(closed())); - m_close->move(264,3); - m_shade = new Button(this, Skin::EQ_BT_SHADE1_N, Skin::EQ_BT_SHADE1_P); - connect(m_shade, SIGNAL(clicked()), SLOT(shade())); - m_shade->move(254,3); - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - if (settings.value("Equalizer/shaded", FALSE).toBool()) - shade(); - m_align = TRUE; - setActive(FALSE); -} - - -EqTitleBar::~EqTitleBar() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - settings.setValue("Equalizer/shaded", m_shaded); -} - -void EqTitleBar::setActive(bool active) -{ - if (active) - { - if (m_shaded) - { - setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_SHADED_A)); - m_shade2->show(); - } - else - { - setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_A)); - m_shade->show(); - } - m_close->show(); - } - else - { - if (m_shaded) - { - setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_SHADED_I)); - m_shade2->hide(); - } - else - { - setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_I)); - m_shade->hide(); - } - m_close->hide(); - } -} - -void EqTitleBar::setVolume(int left, int right) -{ - m_left = left; - m_right = right; - if (m_volumeBar && m_balanceBar) - { - int maxVol = qMax(left, right); - m_volumeBar->setValue(maxVol); - if (maxVol && !m_volumeBar->isPressed()) - m_balanceBar->setValue((right - left)*100/maxVol); - } -} - -void EqTitleBar::mousePressEvent(QMouseEvent* event) -{ - switch ((int) event->button ()) - { - case Qt::LeftButton: - { - m_pos = event->pos(); - break; - } - case Qt::RightButton: - { - m_mw->menu()->exec(event->globalPos()); - } - } -} - -void EqTitleBar::mouseMoveEvent(QMouseEvent* event) -{ - QPoint npos = (event->globalPos()-m_pos); - Dock::getPointer()->move(m_eq, npos); -} - -void EqTitleBar::mouseReleaseEvent(QMouseEvent*) -{ - Dock::getPointer()->updateDock(); -} - -void EqTitleBar::shade() -{ - m_shaded = !m_shaded; - - if (m_shaded) - { - m_eq->setFixedSize(275,14); - setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_SHADED_A)); - m_shade->hide(); - m_shade2 = new Button(this, Skin::EQ_BT_SHADE2_N, Skin::EQ_BT_SHADE2_P); - m_shade2->move(254,3); - connect(m_shade2, SIGNAL(clicked()), SLOT(shade())); - m_shade2->show(); - m_volumeBar = new ShadedBar(this, Skin::EQ_VOLUME1, Skin::EQ_VOLUME2, Skin::EQ_VOLUME3); - m_volumeBar->move(61,4); - m_volumeBar->show(); - connect(m_volumeBar, SIGNAL(sliderMoved(int)),SLOT(updateVolume())); - m_balanceBar = new ShadedBar(this, Skin::EQ_BALANCE1, Skin::EQ_BALANCE2, Skin::EQ_BALANCE3); - m_balanceBar->move(164,4); - m_balanceBar->setFixedSize(42,7); - m_balanceBar->setRange(-100,100); - m_balanceBar->show(); - connect(m_balanceBar, SIGNAL(sliderMoved(int)),SLOT(updateVolume())); - setVolume(m_left, m_right); //show current volume and balance - } - else - { - m_eq->setFixedSize(275,116); - setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_A)); - delete m_shade2; - delete m_volumeBar; - delete m_balanceBar; - m_volumeBar = 0; - m_balanceBar = 0; - m_shade2 = 0; - m_shade->show(); - } - if (m_align) - Dock::getPointer()->align(m_eq, m_shaded? -102: 102); -} - -void EqTitleBar::updateVolume() -{ - m_mw->setVolume(m_volumeBar->value(), m_balanceBar->value()); -} - diff --git a/src/eqtitlebar.h b/src/eqtitlebar.h deleted file mode 100644 index d3e9a0452..000000000 --- a/src/eqtitlebar.h +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef EQTITLEBAR_H -#define EQTITLEBAR_H - -#include - -/** - @author Ilya Kotov -*/ - -class QMouseEvent; - -class Skin; -class MainWindow; -class Button; -class ShadedBar; - -class EqTitleBar : public PixmapWidget -{ -Q_OBJECT -public: - EqTitleBar(QWidget *parent = 0); - - ~EqTitleBar(); - - void setActive(bool); - void setVolume(int left, int right); - -private slots: - void shade(); - void updateVolume(); - -private: - Skin* m_skin; - bool m_active; - int m_left; - int m_right; - QPoint m_pos; - QWidget* m_eq; - MainWindow* m_mw; - Button* m_close; - Button* m_shade; - Button* m_shade2; - bool m_shaded, m_align; - ShadedBar* m_volumeBar; - ShadedBar* m_balanceBar; - -protected: - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); - -}; - -#endif diff --git a/src/eqwidget.cpp b/src/eqwidget.cpp deleted file mode 100644 index d86ab45d2..000000000 --- a/src/eqwidget.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include - -#include "filedialog.h" -#include "skin.h" -#include "eqslider.h" -#include "eqtitlebar.h" -#include "togglebutton.h" -#include "eqgraph.h" -#include "button.h" -#include "eqpreset.h" -#include "preseteditor.h" -#include "mainwindow.h" -#include "playlist.h" -#include "eqwidget.h" - - - -EqWidget::EqWidget ( QWidget *parent ) - : PixmapWidget ( parent ) -{ - m_skin = Skin::getPointer(); - setWindowFlags ( Qt::Dialog | Qt::FramelessWindowHint ); - setPixmap ( m_skin->getEqPart ( Skin::EQ_MAIN ) ); - //setPixmap(QPixmap(275,116)); - m_titleBar = new EqTitleBar ( this ); - m_titleBar -> move ( 0,0 ); - m_titleBar -> show(); - connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); - - m_preamp = new EqSlider ( this ); - m_preamp->show(); - m_preamp->move ( 21,38 ); - connect ( m_preamp,SIGNAL ( sliderMoved ( int ) ),SLOT ( setPreamp () ) ); - - m_on = new ToggleButton ( this,Skin::EQ_BT_ON_N,Skin::EQ_BT_ON_P, - Skin::EQ_BT_OFF_N,Skin::EQ_BT_OFF_P ); - m_on->show(); - m_on->move ( 14,18 ); - connect (m_on, SIGNAL (clicked(bool)), SIGNAL(valueChanged())); - - m_autoButton = new ToggleButton(this, Skin::EQ_BT_AUTO_1_N, Skin::EQ_BT_AUTO_1_P, - Skin::EQ_BT_AUTO_0_N, Skin::EQ_BT_AUTO_0_P); - m_autoButton->move(39, 18); - m_autoButton->show(); - - m_eqg = new EQGraph(this); - m_eqg->move(87,17); - m_eqg->show(); - - m_presetsMenu = new QMenu(this); - - m_presetButton = new Button ( this, Skin::EQ_BT_PRESETS_N, Skin::EQ_BT_PRESETS_P); - m_presetButton->move(217,18); - m_presetButton->show(); - - connect(m_presetButton, SIGNAL(clicked()), SLOT(showPresetsMenu())); - - for ( int i = 0; i<10; ++i ) - { - m_sliders << new EqSlider ( this ); - m_sliders.at ( i )->move ( 78+i*18,38 ); - m_sliders.at ( i )->show(); - connect (m_sliders.at (i), SIGNAL ( sliderMoved (int) ),SLOT (setGain())); - } - readSettings(); - createActions(); -} - -EqWidget::~EqWidget() -{ - while (!m_presets.isEmpty()) - delete m_presets.takeFirst(); - while (!m_autoPresets.isEmpty()) - delete m_autoPresets.takeFirst(); -} - -int EqWidget::preamp() -{ - return m_preamp->value(); -} - -int EqWidget::gain ( int g ) -{ - return m_sliders.at ( g )->value(); -} - -void EqWidget::changeEvent ( QEvent * event ) -{ - if (event->type() == QEvent::ActivationChange) - { - m_titleBar->setActive(isActiveWindow()); - } -} - -void EqWidget::closeEvent ( QCloseEvent* ) -{ - writeSettings(); -} - -void EqWidget::updateSkin() -{ - m_titleBar->setActive ( FALSE ); - setPixmap ( m_skin->getEqPart ( Skin::EQ_MAIN ) ); -} - -void EqWidget::readSettings() -{ - QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); - settings.beginGroup ( "Equalizer" ); - //geometry - move ( settings.value ( "pos", QPoint ( 100, 216 ) ).toPoint() ); - //equalizer - for (int i = 0; i < m_sliders.size(); ++i) - m_sliders.at(i)->setValue(settings.value("band_"+ - QString("%1").arg(i), 0).toInt()); - m_preamp->setValue(settings.value("preamp", 0).toInt()); - m_on->setON(settings.value("enabled", FALSE).toBool()); - settings.endGroup(); - setGain(); - //equalizer presets - QSettings eq_preset (QDir::homePath() +"/.qmmp/eq.preset", QSettings::IniFormat ); - for (int i = 1; TRUE; ++i) - { - if (eq_preset.contains("Presets/Preset"+QString("%1").arg(i))) - { - QString name = eq_preset.value("Presets/Preset"+QString("%1").arg(i), - tr("preset")).toString(); - EQPreset *preset = new EQPreset(); - preset->setText(name); - eq_preset.beginGroup(name); - for (int j = 0; j < 10; ++j) - { - preset->setGain(j,eq_preset.value("Band"+QString("%1").arg(j), - 0).toInt()); - } - preset->setPreamp(eq_preset.value("Preamp",0).toInt()); - m_presets.append(preset); - eq_preset.endGroup(); - } - else - break; - } - //equalizer auto-load presets - QSettings eq_auto (QDir::homePath() +"/.qmmp/eq.auto_preset", QSettings::IniFormat ); - for (int i = 1; TRUE; ++i) - { - if (eq_auto.contains("Presets/Preset"+QString("%1").arg(i))) - { - QString name = eq_auto.value("Presets/Preset"+QString("%1").arg(i), - tr("preset")).toString(); - EQPreset *preset = new EQPreset(); - preset->setText(name); - eq_auto.beginGroup(name); - for (int j = 0; j < 10; ++j) - { - preset->setGain(j,eq_auto.value("Band"+QString("%1").arg(j), - 0).toInt()); - } - preset->setPreamp(eq_auto.value("Preamp",0).toInt()); - m_autoPresets.append(preset); - eq_auto.endGroup(); - } - else - break; - } -} - -void EqWidget::writeSettings() -{ - QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); - settings.beginGroup ( "Equalizer" ); - //geometry - settings.setValue ( "pos", this->pos() ); - //equalizer - for (int i = 0; i < m_sliders.size(); ++i) - settings.setValue("band_"+QString("%1").arg(i), m_sliders.at(i)->value()); - settings.setValue("preamp", m_preamp->value()); - settings.setValue("enabled",m_on->isChecked()); - settings.endGroup(); - //equalizer presets - QSettings eq_preset (QDir::homePath() +"/.qmmp/eq.preset", QSettings::IniFormat ); - eq_preset.clear (); - for (int i = 0; i < m_presets.size(); ++i) - { - eq_preset.setValue("Presets/Preset"+QString("%1").arg(i+1), - m_presets.at(i)->text()); - eq_preset.beginGroup(m_presets.at(i)->text()); - for (int j = 0; j < 10; ++j) - { - eq_preset.setValue("Band"+QString("%1").arg(j),m_presets.at(i)->gain(j)); - } - eq_preset.setValue("Preamp",m_presets.at(i)->preamp()); - eq_preset.endGroup(); - } - //equalizer auto-load presets - QSettings eq_auto (QDir::homePath() +"/.qmmp/eq.auto_preset", - QSettings::IniFormat ); - eq_auto.clear(); - for (int i = 0; i < m_autoPresets.size(); ++i) - { - eq_auto.setValue("Presets/Preset"+QString("%1").arg(i+1), - m_autoPresets.at(i)->text()); - eq_auto.beginGroup(m_autoPresets.at(i)->text()); - for (int j = 0; j < 10; ++j) - { - eq_auto.setValue("Band"+QString("%1").arg(j),m_autoPresets.at(i)->gain(j)); - } - eq_auto.setValue("Preamp",m_autoPresets.at(i)->preamp()); - eq_auto.endGroup(); - } -} - -void EqWidget::setPreamp () -{ - emit valueChanged(); -} - -void EqWidget::setGain() -{ - m_eqg->clear(); - for (int i=0; i<10; ++i) - { - int value = m_sliders.at(i)->value(); - m_eqg->addValue(value); - } - emit valueChanged(); -} - -bool EqWidget::isEQEnabled() -{ - return m_on->isChecked(); -} - -void EqWidget::createActions() -{ - m_presetsMenu->addAction(tr("&Load/Delete"),this, SLOT(showEditor())); - m_presetsMenu->addSeparator(); - m_presetsMenu->addAction(tr("&Save Preset"),this,SLOT(savePreset())); - m_presetsMenu->addAction(tr("&Save Auto-load Preset"),this,SLOT(saveAutoPreset())); - m_presetsMenu->addAction(tr("&Import"),this,SLOT(importWinampEQF())); - m_presetsMenu->addSeparator(); - m_presetsMenu->addAction(tr("&Clear"),this, SLOT(reset())); -} - -void EqWidget::showPresetsMenu() -{ - m_presetsMenu->exec(m_presetButton->mapToGlobal(QPoint(0, 0))); -} - -void EqWidget::reset() -{ - for (int i = 0; i < m_sliders.size(); ++i) - m_sliders.at(i)->setValue(0); - m_preamp->setValue(0); - setGain(); -} - -void EqWidget::showEditor() -{ - PresetEditor *editor = new PresetEditor(this); - editor->addPresets(m_presets); - editor->addAutoPresets(m_autoPresets); - connect (editor, SIGNAL(presetLoaded(EQPreset*)), SLOT(setPreset(EQPreset*))); - connect (editor, SIGNAL(presetDeleted(EQPreset*)), SLOT(deletePreset(EQPreset*))); - editor->show(); -} - -void EqWidget::savePreset() -{ - bool ok; - QString text = QInputDialog::getText(this, tr("Saving Preset"), - tr("Preset name:"), QLineEdit::Normal, - tr("preset #")+QString("%1").arg(m_presets.size()+1), &ok); - if (ok) - { - EQPreset* preset = new EQPreset; - preset->setText(text); - preset->setPreamp(m_preamp->value()); - for (int i = 0; i<10; ++i) - { - preset->setGain(i, m_sliders.at (i)->value()); - } - m_presets.append(preset); - } -} - -void EqWidget::saveAutoPreset() -{ - PlayList* playlist = qobject_cast(parent())->getPLPointer(); - if (!playlist->currentItem()) - return; - //delete preset if it already exists - EQPreset* preset = findPreset(playlist->currentItem()->fileName()); - if (preset) - deletePreset(preset); - //create new preset - preset = new EQPreset(); - preset->setText(playlist->currentItem()->fileName()); - preset->setPreamp(m_preamp->value()); - for (int i = 0; i<10; ++i) - { - preset->setGain(i, m_sliders.at (i)->value()); - } - m_autoPresets.append(preset); -} - -void EqWidget::setPreset(EQPreset* preset) -{ - for (int i = 0; i<10; ++i) - m_sliders.at(i)->setValue(preset->gain(i)); - m_preamp->setValue(preset->preamp()); - setGain(); -} - -void EqWidget::deletePreset(EQPreset* preset) -{ - int p = m_presets.indexOf(preset); - if (p != -1) - { - delete m_presets.takeAt(p); - return; - } - p = m_autoPresets.indexOf(preset); - if (p != -1) - { - delete m_autoPresets.takeAt(p); - return; - } -} - -void EqWidget::loadPreset(const QString &name) -{ - if (m_autoButton->isChecked()) - { - EQPreset *preset = findPreset(name); - if (preset) - setPreset(preset); - else - reset(); - } -} - -void EqWidget::setInfo(const OutputState &st) -{ - if (st.type() == OutputState::Volume) - { - m_titleBar->setVolume(st.leftVolume(),st.rightVolume()); - - } -} - -EQPreset *EqWidget::findPreset(const QString &name) -{ - foreach(EQPreset *preset, m_autoPresets) - { - if (preset->text() == name) - return preset; - } - return 0; -} - -void EqWidget::importWinampEQF() -{ - char header[31]; - char name[257]; - char bands[11]; - QString path = FileDialog::getOpenFileName(this, tr("Import Preset"), - "/home", - QString("Winamp EQF (*.q1)"),NULL,true); - - QFile file(path); - file.open(QIODevice::ReadOnly); - file.read ( header, 31); - if (QString::fromAscii(header).contains("Winamp EQ library file v1.1")) - { - - while (file.read ( name, 257)) - { - EQPreset* preset = new EQPreset; - preset->setText(QString::fromAscii(name)); - - file.read(bands,11); - - for (int i = 0; i<10; ++i) - { - preset->setGain(i, 20 - bands[i]*40/64); - } - preset->setPreamp(20 - bands[10]*40/64); - m_presets.append(preset); - } - - } - file.close(); - -} diff --git a/src/eqwidget.h b/src/eqwidget.h deleted file mode 100644 index 94cd564d5..000000000 --- a/src/eqwidget.h +++ /dev/null @@ -1,103 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef EQWIDGET_H -#define EQWIDGET_H - -#include -#include - -/** - @author Ilya Kotov -*/ - -class QMenu; -class Skin; -class EqTitleBar; -class EqSlider; -class ToggleButton; -class EQGraph; -class Button; -class EQPreset; -class MediaFile; - -class EqWidget : public PixmapWidget -{ - Q_OBJECT -public: - EqWidget(QWidget *parent = 0); - - ~EqWidget(); - - int preamp(); - int gain(int); - bool isEQEnabled(); - /*! - * necessary for auto-load presets - */ - void loadPreset(const QString &name); - - /*! - * shows output volume and balance. Necessare for the shaded mode - */ - void setInfo(const OutputState &st); - -signals: - void valueChanged(); - void closed(); - -private slots: - void updateSkin(); - void setPreamp(); - void setGain(); - void showPresetsMenu(); - void reset(); - void showEditor(); - void savePreset(); - void saveAutoPreset(); - void setPreset(EQPreset*); - void deletePreset(EQPreset*); - void importWinampEQF(); - -private: - void readSettings(); - void writeSettings(); - void createActions(); - EQPreset *findPreset(const QString &name); - Skin *m_skin; - EqTitleBar *m_titleBar; - EqSlider *m_preamp; - Button *m_presetButton; - QList m_sliders; - QPoint m_pos; - ToggleButton *m_on; - ToggleButton *m_autoButton; - EQGraph *m_eqg; - QMenu *m_presetsMenu; - QList m_presets; - QList m_autoPresets; - QString m_autoName; - -protected: - virtual void changeEvent(QEvent*); - virtual void closeEvent(QCloseEvent*); - -}; - -#endif diff --git a/src/fft.c b/src/fft.c deleted file mode 100644 index 7ca1978a5..000000000 --- a/src/fft.c +++ /dev/null @@ -1,296 +0,0 @@ -/* fft.c: Iterative implementation of a FFT - * Copyright (C) 1999 Richard Boulton - * Convolution stuff by Ralph Loader - * - * This program is free software; 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. - */ - -/* - * TODO - * Remove compiling in of FFT_BUFFER_SIZE? (Might slow things down, but would - * be nice to be able to change size at runtime.) - * Finish making / checking thread-safety. - * More optimisations. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "fft.h" - -//#include -#include -#include -#ifndef PI -#ifdef M_PI -#define PI M_PI -#else -#define PI 3.14159265358979323846 /* pi */ -#endif -#endif - -/* ########### */ -/* # Structs # */ -/* ########### */ - -struct _struct_fft_state { - /* Temporary data stores to perform FFT in. */ - float real[FFT_BUFFER_SIZE]; - float imag[FFT_BUFFER_SIZE]; -}; - -/* ############################# */ -/* # Local function prototypes # */ -/* ############################# */ - -static void fft_prepare(const sound_sample * input, float *re, float *im); -static void fft_calculate(float *re, float *im); -static void fft_output(const float *re, const float *im, float *output); -static int reverseBits(unsigned int initial); - -/* #################### */ -/* # Global variables # */ -/* #################### */ - -/* Table to speed up bit reverse copy */ -static unsigned int bitReverse[FFT_BUFFER_SIZE]; - -/* The next two tables could be made to use less space in memory, since they - * overlap hugely, but hey. */ -static float sintable[FFT_BUFFER_SIZE / 2]; -static float costable[FFT_BUFFER_SIZE / 2]; - -/* ############################## */ -/* # Externally called routines # */ -/* ############################## */ - -/* --------- */ -/* FFT stuff */ -/* --------- */ - -/* - * Initialisation routine - sets up tables and space to work in. - * Returns a pointer to internal state, to be used when performing calls. - * On error, returns NULL. - * The pointer should be freed when it is finished with, by fft_close(). - */ -fft_state * -fft_init(void) -{ - fft_state *state; - unsigned int i; - - state = (fft_state *) malloc(sizeof(fft_state)); - if (!state) - return NULL; - - for (i = 0; i < FFT_BUFFER_SIZE; i++) { - bitReverse[i] = reverseBits(i); - } - for (i = 0; i < FFT_BUFFER_SIZE / 2; i++) { - float j = 2 * PI * i / FFT_BUFFER_SIZE; - costable[i] = cos(j); - sintable[i] = sin(j); - } - - return state; -} - -/* - * Do all the steps of the FFT, taking as input sound data (as described in - * sound.h) and returning the intensities of each frequency as floats in the - * range 0 to ((FFT_BUFFER_SIZE / 2) * 32768) ^ 2 - * - * FIXME - the above range assumes no frequencies present have an amplitude - * larger than that of the sample variation. But this is false: we could have - * a wave such that its maximums are always between samples, and it's just - * inside the representable range at the places samples get taken. - * Question: what _is_ the maximum value possible. Twice that value? Root - * two times that value? Hmmm. Think it depends on the frequency, too. - * - * The input array is assumed to have FFT_BUFFER_SIZE elements, - * and the output array is assumed to have (FFT_BUFFER_SIZE / 2 + 1) elements. - * state is a (non-NULL) pointer returned by fft_init. - */ -void -fft_perform(const sound_sample * input, float *output, fft_state * state) -{ - /* Convert data from sound format to be ready for FFT */ - fft_prepare(input, state->real, state->imag); - - /* Do the actual FFT */ - fft_calculate(state->real, state->imag); - - /* Convert the FFT output into intensities */ - fft_output(state->real, state->imag, output); -} - -/* - * Free the state. - */ -void -fft_close(fft_state * state) -{ - if (state) - free(state); -} - -/* ########################### */ -/* # Locally called routines # */ -/* ########################### */ - -/* - * Prepare data to perform an FFT on - */ -static void -fft_prepare(const sound_sample * input, float *re, float *im) -{ - unsigned int i; - float *realptr = re; - float *imagptr = im; - - /* Get input, in reverse bit order */ - for (i = 0; i < FFT_BUFFER_SIZE; i++) { - *realptr++ = input[bitReverse[i]]; - *imagptr++ = 0; - } -} - -/* - * Take result of an FFT and calculate the intensities of each frequency - * Note: only produces half as many data points as the input had. - * This is roughly a consequence of the Nyquist sampling theorm thingy. - * (FIXME - make this comment better, and helpful.) - * - * The two divisions by 4 are also a consequence of this: the contributions - * returned for each frequency are split into two parts, one at i in the - * table, and the other at FFT_BUFFER_SIZE - i, except for i = 0 and - * FFT_BUFFER_SIZE which would otherwise get float (and then 4* when squared) - * the contributions. - */ -static void -fft_output(const float *re, const float *im, float *output) -{ - float *outputptr = output; - const float *realptr = re; - const float *imagptr = im; - float *endptr = output + FFT_BUFFER_SIZE / 2; - -#ifdef DEBUG - unsigned int i, j; -#endif - - while (outputptr <= endptr) { - *outputptr = (*realptr * *realptr) + (*imagptr * *imagptr); - outputptr++; - realptr++; - imagptr++; - } - /* Do divisions to keep the constant and highest frequency terms in scale - * with the other terms. */ - *output /= 4; - *endptr /= 4; - -#ifdef DEBUG - printf("Recalculated input:\n"); - for (i = 0; i < FFT_BUFFER_SIZE; i++) { - float val_real = 0; - float val_imag = 0; - for (j = 0; j < FFT_BUFFER_SIZE; j++) { - float fact_real = cos(-2 * j * i * PI / FFT_BUFFER_SIZE); - float fact_imag = sin(-2 * j * i * PI / FFT_BUFFER_SIZE); - val_real += fact_real * re[j] - fact_imag * im[j]; - val_imag += fact_real * im[j] + fact_imag * re[j]; - } - printf("%5d = %8f + i * %8f\n", i, - val_real / FFT_BUFFER_SIZE, val_imag / FFT_BUFFER_SIZE); - } - printf("\n"); -#endif -} - -/* - * Actually perform the FFT - */ -static void -fft_calculate(float *re, float *im) -{ - unsigned int i, j, k; - unsigned int exchanges; - float fact_real, fact_imag; - float tmp_real, tmp_imag; - unsigned int factfact; - - /* Set up some variables to reduce calculation in the loops */ - exchanges = 1; - factfact = FFT_BUFFER_SIZE / 2; - - /* Loop through the divide and conquer steps */ - for (i = FFT_BUFFER_SIZE_LOG; i != 0; i--) { - /* In this step, we have 2 ^ (i - 1) exchange groups, each with - * 2 ^ (FFT_BUFFER_SIZE_LOG - i) exchanges - */ - /* Loop through the exchanges in a group */ - for (j = 0; j != exchanges; j++) { - /* Work out factor for this exchange - * factor ^ (exchanges) = -1 - * So, real = cos(j * PI / exchanges), - * imag = sin(j * PI / exchanges) - */ - fact_real = costable[j * factfact]; - fact_imag = sintable[j * factfact]; - - /* Loop through all the exchange groups */ - for (k = j; k < FFT_BUFFER_SIZE; k += exchanges << 1) { - int k1 = k + exchanges; - /* newval[k] := val[k] + factor * val[k1] - * newval[k1] := val[k] - factor * val[k1] - **/ -#ifdef DEBUG - printf("%d %d %d\n", i, j, k); - printf("Exchange %d with %d\n", k, k1); - printf("Factor %9f + i * %8f\n", fact_real, fact_imag); -#endif - /* FIXME - potential scope for more optimization here? */ - tmp_real = fact_real * re[k1] - fact_imag * im[k1]; - tmp_imag = fact_real * im[k1] + fact_imag * re[k1]; - re[k1] = re[k] - tmp_real; - im[k1] = im[k] - tmp_imag; - re[k] += tmp_real; - im[k] += tmp_imag; -#ifdef DEBUG - for (k1 = 0; k1 < FFT_BUFFER_SIZE; k1++) { - printf("%5d = %8f + i * %8f\n", k1, real[k1], imag[k1]); - } -#endif - } - } - exchanges <<= 1; - factfact >>= 1; - } -} - -static int -reverseBits(unsigned int initial) -{ - unsigned int reversed = 0, loop; - for (loop = 0; loop < FFT_BUFFER_SIZE_LOG; loop++) { - reversed <<= 1; - reversed += (initial & 1); - initial >>= 1; - } - return reversed; -} diff --git a/src/fft.h b/src/fft.h deleted file mode 100644 index 431afa365..000000000 --- a/src/fft.h +++ /dev/null @@ -1,45 +0,0 @@ -/* fft.h: Header for iterative implementation of a FFT - * Copyright (C) 1999 Richard Boulton - * - * This program is free software; 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. - */ - -#ifndef _FFT_H_ -#define _FFT_H_ - -#define FFT_BUFFER_SIZE_LOG 9 - -#define FFT_BUFFER_SIZE (1 << FFT_BUFFER_SIZE_LOG) - -/* sound sample - should be an signed 16 bit value */ -typedef short int sound_sample; - -#ifdef __cplusplus -extern "C" { -#endif - -/* FFT library */ - typedef struct _struct_fft_state fft_state; - fft_state *fft_init(void); - void fft_perform(const sound_sample * input, float *output, - fft_state * state); - void fft_close(fft_state * state); - - - -#ifdef __cplusplus -} -#endif -#endif /* _FFT_H_ */ diff --git a/src/filedialog.cpp b/src/filedialog.cpp deleted file mode 100644 index 29195acef..000000000 --- a/src/filedialog.cpp +++ /dev/null @@ -1,299 +0,0 @@ -#include "filedialog.h" - -#include - - -#include -#include - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - -#include "playlistmodel.h" - -FileDialog* FileDialog::_instance = 0; - -QMap FileDialog::factories = QMap(); - -FileDialog::FileDialog() : QObject(), m_initialized(false) -{ -} - - -bool FileDialog::isModal() -{ - return instance()->modal(); -} - -void FileDialog::init(QObject* o) -{ - qWarning("void FileDialog::init(QObject* o)"); - if(!m_initialized && !instance()->modal()) - { - PlayListModel* model = NULL; - if( ( model = qobject_cast(o)) ) - { - connect(this,SIGNAL(filesAdded(const QStringList&)),model,SLOT(addFileList(const QStringList&))); - m_initialized = true; - } - } -} - - - -QString FileDialog::getExistingDirectory( QWidget * parent, const QString & caption, const QString & dir,bool def) -{ - QString s; - if(def) - s = defaultInstance()->existingDirectory(parent,caption,dir); - else - s = instance()->existingDirectory(parent,caption,dir); - delete _instance; - _instance = 0; - return s; -} - -QString FileDialog::getOpenFileName(QWidget * parent, - const QString & caption, - const QString & dir, - const QString & filter, - QString * selectedFilter,bool def) -{ - QString s; - if(def) - s = defaultInstance()->openFileName(parent,caption,dir,filter,selectedFilter); - else - s = instance()->openFileName(parent,caption,dir,filter,selectedFilter); - delete _instance; - _instance = 0; - return s; -} - -QStringList FileDialog::getOpenFileNames(QWidget * parent, const QString & caption , const QString & dir , - const QString & filter, QString * selectedFilter,bool def) -{ - QStringList sl; - if(def) - sl = defaultInstance()->openFileNames(parent,caption ,dir ,filter, selectedFilter); - else - sl = instance()->openFileNames(parent,caption,dir,filter,selectedFilter); - delete _instance; - _instance = 0; - return sl; -} - -QString FileDialog::getSaveFileName ( QWidget * parent, const QString & caption, - const QString & dir, const QString & filter, QString * selectedFilter,bool def) -{ - QString s; - if(def) - s = defaultInstance()->saveFileName(parent,caption,dir,filter,selectedFilter); - else - s = instance()->saveFileName(parent,caption,dir,filter,selectedFilter); - delete _instance; - _instance = 0; - return s; -} - - -QString FileDialog::existingDirectory(QWidget *, const QString &, const QString &) -{ - return QString(); -} - -QString FileDialog::openFileName(QWidget *, const QString &, const QString &, const QString &, QString *) -{ - return QString(); -} - -QStringList FileDialog::openFileNames(QWidget *, const QString &, const QString &, const QString &, QString *) -{ - return QStringList(); -} - -QString FileDialog::saveFileName(QWidget *, const QString &, const QString &, const QString &, QString *) -{ - return QString(); -} - - -void FileDialog::registerBuiltinFactories() -{ - registerFactory(new QtFileDialogFactory()); - //registerFactory(new QmmpFileDialogFactory()); -} - -void FileDialog::registerExternalFactories() -{ - QDir pluginsDir (QDir::homePath()+"/.qmmp/plugins/FileDialogs"); - - foreach (QString fileName, pluginsDir.entryList(QDir::Files)) - { - //qWarning("file dialog path: %s",qPrintable(fileName)); - QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); - QObject *plugin = loader.instance(); - if (loader.isLoaded()) - qDebug("FileDialog: plugin loaded - %s", qPrintable(fileName)); - else - qDebug("FileDialog: %s",qPrintable(loader.errorString())); - - FileDialogFactory *fct = 0; - if (plugin) - fct = qobject_cast(plugin); - - if (fct) - if (!registerFactory(fct)) - qDebug("Warning: Plugin with name %s is already registered...", - qPrintable(fct->name())); - } -} - -bool FileDialog::registerFactory(FileDialogFactory *f) -{ - QString name = f->name(); - if (!factories.contains(name)) - { - factories.insert(name,f); - return true; - } - return false; -} - -QString FileDialog::m_current_factory = QString(); - -FileDialog* FileDialog::instance() -{ - //qWarning("INSTANCE"); - if(_instance && _instance->modal()) - { - delete _instance; - _instance = 0; - } - - if(factories.isEmpty()) - { - registerBuiltinFactories(); - registerExternalFactories(); - } - - QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); - QString f_dialogName = - settings.value("FileDialog",QtFileDialogFactory::QtFileDialogFactoryName).toString(); - - QStringList names = factories.keys(); - - if(m_current_factory != f_dialogName || !_instance) - { - if(_instance) - delete _instance; - - qWarning("%s\t%s",qPrintable(m_current_factory),qPrintable(f_dialogName)); - foreach(QString name,names) - { - if(name == f_dialogName) - { - _instance = factories[name]->create(); - m_current_factory = f_dialogName; - } - } - - if(!_instance) - _instance = factories[QtFileDialogFactory::QtFileDialogFactoryName]->create(); - } - //else if(!_instance->modal()) - //return _instance; - // _instance->raise(); - - return _instance; - -} - -FileDialog* FileDialog::defaultInstance() -{ - if(_instance) - { - delete _instance; - _instance = 0; - } - - if(factories.isEmpty()) - { - registerBuiltinFactories(); - registerExternalFactories(); - } - - _instance = factories[QtFileDialogFactory::QtFileDialogFactoryName]->create(); - - return _instance; -} - -QStringList FileDialog::registeredFactories() -{ - if(factories.isEmpty()) - { - registerBuiltinFactories(); - registerExternalFactories(); - } - return factories.keys(); -} - - -void FileDialog::popup(QObject* o,const QString& d,Mode m,const QStringList& f) -{ -// qWarning("void FileDialog::popup(QObject* o,const QString& d,Mode m,const QStringList& f)"); - instance()->init(o); - instance()->raise(d,m,f); -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - -QtFileDialog::~QtFileDialog() -{ - qWarning("QtFileDialog::~QtFileDialog()"); -} - -QString QtFileDialog::existingDirectory(QWidget * parent, const QString & caption, const QString & dir) -{ - return QFileDialog::getExistingDirectory(parent,caption,dir,QFileDialog::DontResolveSymlinks | QFileDialog::ShowDirsOnly); -} - -QString QtFileDialog::openFileName(QWidget * parent,const QString & caption,const QString & dir,const QString & filter, - QString * selectedFilter) -{ - return QFileDialog::getOpenFileName(parent,caption,dir,filter,selectedFilter); -} - -QStringList QtFileDialog::openFileNames(QWidget * parent, const QString & caption , const QString & dir , - const QString & filter, QString * selectedFilter) -{ - return QFileDialog::getOpenFileNames(parent,caption,dir,filter,selectedFilter); -} - - QString QtFileDialog::saveFileName ( QWidget * parent, const QString & caption, - const QString & dir, const QString & filter, QString * selectedFilter) -{ - return QFileDialog::getSaveFileName(parent,caption,dir,filter,selectedFilter); -} - - - - - - -FileDialog* QtFileDialogFactory::create() -{ - return new QtFileDialog(); -} - -QString QtFileDialogFactory::name() -{ - return QtFileDialogFactoryName; -} - -QString QtFileDialogFactory::QtFileDialogFactoryName = "Qt File Dialog"; - - diff --git a/src/filedialog.h b/src/filedialog.h deleted file mode 100644 index 8e82e98b7..000000000 --- a/src/filedialog.h +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef FILEDIALOG_H -#define FILEDIALOG_H - -#include -#include - -#include -#include - -#define interface struct - -interface FileDialogFactory; - - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////// FILE DIALOG ////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -class FileDialog : public QObject -{ -Q_OBJECT - public: - enum Mode{AddFiles,AddDirs,SaveFiles}; - static QString getExistingDirectory( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(),bool = FALSE); - static QString getOpenFileName(QWidget * parent = 0,const QString & caption = QString(),const QString & dir = QString(),const QString & filter = QString(), - QString * selectedFilter = 0,bool = FALSE); - static QStringList getOpenFileNames( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), - const QString & filter = QString(), QString * selectedFilter = 0,bool = FALSE); - static QString getSaveFileName ( QWidget * parent = 0, const QString & caption = QString(), - const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0,bool = FALSE); - static QStringList registeredFactories(); - - static bool isModal(); - static void popup(QObject* ,const QString& = QString(),Mode = AddFiles,const QStringList& nameFilters = QStringList()); - signals: - void filesAdded(const QStringList&); - protected: - FileDialog(); - virtual QString existingDirectory( QWidget* , const QString& , const QString& ); - virtual QString openFileName( QWidget* ,const QString& ,const QString& ,const QString& , QString* ); - virtual QStringList openFileNames( QWidget* , const QString& , const QString& ,const QString& , QString* ); - virtual QString saveFileName ( QWidget* , const QString& ,const QString& , const QString& , QString* ); - virtual bool modal()const{ return TRUE;} - virtual ~FileDialog(){;} - virtual void init(QObject*); - virtual void raise(const QString& = QString(),Mode = AddFiles,const QStringList& = QStringList()){;} - - static bool registerFactory(FileDialogFactory*); - public: - static void registerBuiltinFactories(); - static void registerExternalFactories(); - protected: - static FileDialog* instance(); - static FileDialog* defaultInstance(); - private: - static QMap factories; - static FileDialog* _instance; - static QString m_current_factory; - bool m_initialized; -}; - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - - - -interface FileDialogFactory -{ - virtual FileDialog* create() = 0; - virtual QString name() = 0; - virtual ~FileDialogFactory(){;} -}; - -Q_DECLARE_INTERFACE(FileDialogFactory, "FileDialogFactory/1.0"); - - -//////////////////////////////////////////// QT FILE DIALOG //////////////////////////////////////////////////////////////////// - -class QtFileDialog : public FileDialog -{ - public: - virtual ~QtFileDialog(); - virtual QString existingDirectory(QWidget * parent , const QString & , const QString & dir); - virtual QString openFileName(QWidget * parent,const QString & caption,const QString & dir,const QString & filter, - QString * selectedFilter); - virtual QStringList openFileNames(QWidget * parent, const QString & caption , const QString & dir , - const QString & filter, QString * selectedFilter); - virtual QString saveFileName ( QWidget * parent, const QString & caption, - const QString & dir, const QString & filter, QString * selectedFilter); -}; - - -class QtFileDialogFactory : public QObject, public FileDialogFactory -{ - Q_OBJECT - Q_INTERFACES(FileDialogFactory); - public: - virtual FileDialog* create(); - virtual QString name(); - virtual ~QtFileDialogFactory(){;} - static QString QtFileDialogFactoryName; -}; - - -#endif - - diff --git a/src/fileloader.cpp b/src/fileloader.cpp deleted file mode 100644 index fda8efdc1..000000000 --- a/src/fileloader.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include - -#include "fileloader.h" -#include "mediafile.h" - -FileLoader::FileLoader(QObject *parent) - : QThread(parent),m_files_to_load(),m_directory() -{ - m_filters = Decoder::nameFilters(); - m_finished = false; -} - - -FileLoader::~FileLoader() -{ - qWarning("FileLoader::~FileLoader()"); -} - - -void FileLoader::addFiles(const QStringList &files) -{ - if (files.isEmpty ()) - return; - - foreach(QString s, files) - { - if (Decoder::supports(s)) - emit newMediaFile(new MediaFile(s)); - if(m_finished) return; - } -} - - -void FileLoader::addDirectory(const QString& s) -{ - QDir dir(s); - dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); - dir.setSorting(QDir::Name); - QFileInfoList l = dir.entryInfoList(m_filters); - for (int i = 0; i < l.size(); ++i) - { - QFileInfo fileInfo = l.at(i); - QString suff = fileInfo.completeSuffix(); - list << fileInfo; - - if (Decoder::supports(fileInfo.absoluteFilePath ())) - emit newMediaFile(new MediaFile(fileInfo.absoluteFilePath ())); - if(m_finished) return; - } - dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); - dir.setSorting(QDir::Name); - l.clear(); - l = dir.entryInfoList(); - if (l.size() > 0) - for (int i = 0; i < l.size(); ++i) - { - QFileInfo fileInfo = l.at(i); - addDirectory(fileInfo.absoluteFilePath ()); - if(m_finished) return; - } -} - - -void FileLoader::run() -{ - if(!m_files_to_load.isEmpty()) - addFiles(m_files_to_load); - else if(!m_directory.isEmpty()) - addDirectory(m_directory); -} - - - -void FileLoader::setFilesToLoad(const QStringList & l) -{ - m_files_to_load = l; - m_directory = QString(); -} - -void FileLoader::setDirectoryToLoad(const QString & d) -{ - m_directory = d; - m_files_to_load.clear(); -} - -void FileLoader::finish() -{ - m_finished = true; -} diff --git a/src/fileloader.h b/src/fileloader.h deleted file mode 100644 index c23d1ed35..000000000 --- a/src/fileloader.h +++ /dev/null @@ -1,72 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef FILELOADER_H -#define FILELOADER_H - -#include -#include -#include - -class MediaFile; - -/*! - * This class represents fileloader object that - * processes file list in separate thread and emits - * \b newMediaFile(MediaFile*) signal for every newly - * created media file. - @author Ilya Kotov -*/ -class FileLoader : public QThread -{ -Q_OBJECT -public: - FileLoader(QObject *parent = 0); - - ~FileLoader(); - virtual void run(); - - /*! - * Call this method when you want to notify the thread about finishing - */ - void finish(); - - /*! - * Sets filelist to load( directory to load will be cleaned ) - */ - void setFilesToLoad(const QStringList&); - - /*! - * Sets directory to load( filelist to load will be cleaned ) - */ - void setDirectoryToLoad(const QString&); -signals: - void newMediaFile(MediaFile*); -protected: - void addFiles(const QStringList &files); - void addDirectory(const QString& s); -private: - QFileInfoList list; - QStringList m_filters; - QStringList m_files_to_load; - QString m_directory; - bool m_finished; -}; - -#endif diff --git a/src/html/about_cs.html b/src/html/about_cs.html deleted file mode 100644 index 84bd2b42a..000000000 --- a/src/html/about_cs.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - Qt-based Multimedia Player - -
-

- Qt-based Multimedia Player (Qmmp) -

-
-

- Qmmp je přehrávač zvuku založený na knihovně Qt. -

-

- Klíčové vlastnosti: -

-
    -
  • - podpora témat programu Winamp; -
  • -
  • - podpora zásuvných modulů (plugin); -
  • -
  • - podpora MPEG1 layer 1/2/3; -
  • -
  • - podpora Ogg-Vorbis; -
  • -
  • - podpora FLAC; -
  • -
  • - podpora Musepack; -
  • -
  • - podpora WMA; -
  • -
  • - zvukový výstup ALSA; -
  • -
  • - zvukový výstup JACK. -
  • -
-

- Požadavky: -

- diff --git a/src/html/about_en.html b/src/html/about_en.html deleted file mode 100644 index d03691cf6..000000000 --- a/src/html/about_en.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - Qt-based Multimedia Player - -
-

- Qt-based Multimedia Player (Qmmp) -

-
-

- This program is an audio-player, written with help of Qt library. -

-

- Main opportunities: -

-
    -
  • - unpacked winamp skins support; -
  • -
  • - plugins support; -
  • -
  • - MPEG1 layer 1/2/3 support; -
  • -
  • - Ogg Vorbis support; -
  • -
  • - native FLAC support; -
  • -
  • - Musepack support; -
  • -
  • - WMA support; -
  • -
  • - ALSA sound output; -
  • -
  • - JACK sound output. -
  • -
-

- Requirements: -

- diff --git a/src/html/about_ru.html b/src/html/about_ru.html deleted file mode 100644 index 26e5b9906..000000000 --- a/src/html/about_ru.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - Qt-based Multimedia Player - -
-

- Qt-based Multimedia Player (Qmmp) -

-
-

- Данная программа является аудио-плеером, написанным с использованием библиотеки Qt. Программа имеет интерфейс, аналогичный winamp или xmms. -

-

- Основные возможности программы: -

-
    -
  • - поддержка тем winamp в распакованном виде; -
  • -
  • - поддержка модулей (плагинов); -
  • -
  • - поддержка файлов MPEG1 layer 1/2/3; -
  • -
  • - поддержка файлов Ogg Vorbis; -
  • -
  • - поддержка файлов Native FLAC; -
  • -
  • - поддержка файлов Musepack; -
  • -
  • - поддержка файлов WMA; -
  • -
  • - вывод звука через ALSA; -
  • -
  • - вывод звука через Jack. -
  • -
-

- Для работы необходимы: -

-
    -
  • - операционная система GNU Linux; -
  • -
  • - Qt версии >= 4.2; -
  • -
  • - MAD; -
  • -
  • - Ogg Vorbis; -
  • -
  • - FLAC версии >= 1.1.3; -
  • -
  • - ALSA версии >= 1.0.1; -
  • -
  • - TagLib версии >= 1.4. -
  • -
  • - libmpcdec версии >= 1.2.6 -
  • -
  • - Jack версии >= 0.102.5 -
  • -
  • - FFmpeg версии >= 0.4.9-pre1 -
  • -
diff --git a/src/html/about_zh_CN.html b/src/html/about_zh_CN.html deleted file mode 100644 index eadc7f78d..000000000 --- a/src/html/about_zh_CN.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - 基于Qt的多媒体播放器 - -
-

- 基于Qt的多媒体播放器(Qmmp)。 -

-
-

- 此程序是一个音乐播放器,程序的编写基于Qt库。 -

-

- 主要功能: -

-
    -
  • - 未压缩的winamp皮肤支持; -
  • -
  • - 插件支持; -
  • -
  • - MPEG1 1/2/3 层支持; -
  • -
  • - Ogg Vorbis 支持; -
  • -
  • - native FLAC 支持; -
  • -
  • - Musepack 支持; -
  • -
  • - WMA 支持; -
  • -
  • - ALSA 声音输出; -
  • -
  • - JACK 声音输出。 -
  • -
-

- 要求: -

- diff --git a/src/html/authors_cs.txt b/src/html/authors_cs.txt deleted file mode 100644 index 89d585c24..000000000 --- a/src/html/authors_cs.txt +++ /dev/null @@ -1,12 +0,0 @@ -Vývojáři programu: - - Илья Котов (Ilja Kotov) (nápad a základní kód) - Владимир Кузнецов (Vladimír Kuzněcov) (vzhled a mnoho vylepšení) - -Vývojáři zásuvných modulů: - - Юрий Журавлёв (Jurij Žuravljov) (jack plugin) - -Český překlad: - - Karel Volný diff --git a/src/html/authors_en.txt b/src/html/authors_en.txt deleted file mode 100644 index 6c11ebd5e..000000000 --- a/src/html/authors_en.txt +++ /dev/null @@ -1,12 +0,0 @@ -Core Developers: - - Ilya Kotov (idea and base code) - Vladimir Kuznetsov (look&feel and many improvements) - -Plugin Developers: - - Yuriy Zhuravlev (jack plugin) - -Turkish translation: - - Mustafa GUNAY diff --git a/src/html/authors_ru.txt b/src/html/authors_ru.txt deleted file mode 100644 index b95c3887e..000000000 --- a/src/html/authors_ru.txt +++ /dev/null @@ -1,9 +0,0 @@ -Разработчики ядра: - - Владимир Кузнецов (внешний вид и множество улучшений) - Илья Котов (идея и основной код) - -Разработчики модулей: - - Юрий Журавлёв (модуль jack) - diff --git a/src/html/authors_zh_CN.txt b/src/html/authors_zh_CN.txt deleted file mode 100644 index f2d8892fd..000000000 --- a/src/html/authors_zh_CN.txt +++ /dev/null @@ -1,16 +0,0 @@ -核心开发: - - Ilya Kotov (idea and base code) - Vladimir Kuznetsov (look&feel and many improvements) - -插件开发: - - Yuriy Zhuravlev (jack plugin) - -土耳其语翻译: - - Mustafa GUNAY - -简体中文翻译: - - 李红昆 \ No newline at end of file diff --git a/src/html/thanks_cs.txt b/src/html/thanks_cs.txt deleted file mode 100644 index 9bc0388da..000000000 --- a/src/html/thanks_cs.txt +++ /dev/null @@ -1,3 +0,0 @@ -Poděkování patří: - - Вадим Калинников (Vadim Kalinnikov) (hosting projektu) diff --git a/src/html/thanks_en.txt b/src/html/thanks_en.txt deleted file mode 100644 index 3ed2fe5d5..000000000 --- a/src/html/thanks_en.txt +++ /dev/null @@ -1,3 +0,0 @@ -Thanks to: - - Vadim Kalinnikov (project hosting) diff --git a/src/html/thanks_ru.txt b/src/html/thanks_ru.txt deleted file mode 100644 index 79acc177d..000000000 --- a/src/html/thanks_ru.txt +++ /dev/null @@ -1,3 +0,0 @@ -Благодарности: - - Вадиму Калинникову (хотстинг проекта) diff --git a/src/html/thanks_zh_CN.txt b/src/html/thanks_zh_CN.txt deleted file mode 100644 index 505d05c72..000000000 --- a/src/html/thanks_zh_CN.txt +++ /dev/null @@ -1,3 +0,0 @@ -感谢: - - Vadim Kalinnikov (project hosting) diff --git a/src/images/advanced.png b/src/images/advanced.png deleted file mode 100644 index beb0071b4..000000000 Binary files a/src/images/advanced.png and /dev/null differ diff --git a/src/images/images.qrc b/src/images/images.qrc deleted file mode 100644 index 8dcc2efe2..000000000 --- a/src/images/images.qrc +++ /dev/null @@ -1,14 +0,0 @@ - - - - play.png - pause.png - stop.png - qmmp.xpm - interface.png - playlist.png - advanced.png - plugins.png - logo-qmmp.png - - diff --git a/src/images/interface.png b/src/images/interface.png deleted file mode 100644 index 0277801c1..000000000 Binary files a/src/images/interface.png and /dev/null differ diff --git a/src/images/logo-qmmp.png b/src/images/logo-qmmp.png deleted file mode 100644 index 7a4d6ded4..000000000 Binary files a/src/images/logo-qmmp.png and /dev/null differ diff --git a/src/images/pause.png b/src/images/pause.png deleted file mode 100644 index 096371d82..000000000 Binary files a/src/images/pause.png and /dev/null differ diff --git a/src/images/play.png b/src/images/play.png deleted file mode 100644 index 5a4aee976..000000000 Binary files a/src/images/play.png and /dev/null differ diff --git a/src/images/playlist.png b/src/images/playlist.png deleted file mode 100644 index 0cff0ddcb..000000000 Binary files a/src/images/playlist.png and /dev/null differ diff --git a/src/images/plugins.png b/src/images/plugins.png deleted file mode 100644 index b08dcac3f..000000000 Binary files a/src/images/plugins.png and /dev/null differ diff --git a/src/images/qmmp.xpm b/src/images/qmmp.xpm deleted file mode 100644 index 85ea94fc1..000000000 --- a/src/images/qmmp.xpm +++ /dev/null @@ -1,278 +0,0 @@ -/* XPM */ -static char *trayicon[]={ -"32 32 243 2", -"#N c None", -"Qt c None", -".# c #000000", -".a c #050d16", -".U c #060e16", -".L c #06101b", -"a9 c #091725", -"b. c #0a0b11", -"bU c #0b1826", -".c c #0c2034", -"bt c #0d1823", -"be c #0d2034", -"bb c #0f0f0f", -".A c #0f253c", -"a7 c #11263d", -".n c #112a45", -"a6 c #12273d", -"aL c #122f4c", -"bV c #131e29", -"bi c #141b23", -"bg c #14212e", -".b c #16385b", -".i c #16385c", -"#L c #191b2b", -"bW c #1a2b3e", -".d c #1a4169", -"aY c #1a416b", -"bm c #1a426b", -"aB c #1b1d2e", -"aZ c #1b1d2f", -".o c #1c1c1c", -"bl c #1c436b", -"aH c #1d436b", -"ah c #1e1f25", -"at c #1e4b7a", -"#o c #1f2236", -"#K c #1f272f", -"bO c #1f2e3e", -"aK c #1f4c7b", -"bk c #202a35", -"bh c #202e3e", -"au c #212331", -"as c #215489", -"a8 c #21548a", -".R c #223952", -"br c #233242", -"#J c #24303e", -".3 c #253647", -".T c #27507b", -".e c #292929", -"#O c #292a30", -"aM c #2967a7", -".x c #2968a9", -"bN c #2a598a", -"aJ c #2c69a9", -"ar c #2d71b7", -"ap c #2d71b8", -".M c #2e2e2e", -"bs c #2f4d6c", -"#w c #2f547b", -"#B c #303030", -"ag c #303453", -"bI c #30353a", -"bc c #30465d", -"bf c #307ac7", -"bP c #314253", -".K c #317bc7", -"#I c #323e4b", -"#p c #333333", -"#8 c #34353d", -"aq c #3484d6", -"aA c #3484d7", -"az c #35404c", -"#d c #363636", -"aN c #373b5e", -"bu c #387ec8", -".4 c #393939", -"a4 c #39414a", -"aI c #3a87d7", -"af c #3b3b3b", -"#j c #3b699a", -".V c #3c3c3c", -"#A c #3c4046", -"bn c #3c6a9a", -".m c #3c95f2", -".l c #3c95f3", -".k c #3c96f4", -".j c #3c96f5", -".z c #3c97f5", -".y c #3c97f6", -"bJ c #3f4954", -"aX c #3f99f6", -"bD c #408ad7", -".J c #419af6", -"aT c #4284c8", -"aW c #459cf6", -"bd c #46688c", -"#X c #474a60", -".I c #479df6", -"## c #48719b", -"bT c #4887c8", -"ba c #494949", -"aU c #4a97e7", -"bE c #4b81b9", -".S c #4b89c9", -"aV c #4b9ff6", -".1 c #4d4d4d", -".p c #545454", -"ay c #555555", -"#M c #555b91", -".2 c #57789c", -"#. c #585d61", -"a5 c #5897d9", -"bC c #59a6f7", -"bM c #5aa6f7", -".f c #606060", -"#G c #616161", -"bv c #62abf7", -"aC c #636785", -"#v c #646464", -"aF c #676767", -"bj c #6a8aac", -"bS c #6bb0f8", -"#a c #6f94bb", -"bB c #6fb2f8", -"aO c #707175", -"bL c #70b2f8", -"#b c #71879d", -"bo c #72b4f8", -"#6 c #747474", -"aR c #757575", -"#7 c #777777", -"bQ c #7798bb", -"#x c #77b6f8", -"#W c #787878", -"#t c #797979", -"#k c #7ab8f8", -".0 c #7b7b7b", -"ai c #7b7f9f", -"bF c #7bb9f8", -".h c #7e7e7e", -"#i c #808080", -"by c #808f9d", -"aG c #828282", -"#F c #838383", -"bR c #83bdf9", -".Q c #848484", -"av c #8487a4", -"#5 c #858585", -"bz c #86a8cb", -"ao c #878787", -"#9 c #878aa2", -"ac c #888888", -"bA c #89c0f9", -"#2 c #8a8a8a", -"bp c #8ac1f9", -".w c #8b8b8b", -".q c #8c8c8c", -"#3 c #8d8d8d", -"#H c #8e8e8e", -"#n c #90979e", -"#U c #919191", -"#Z c #9396ac", -"aS c #969696", -"bw c #96c7fa", -"#4 c #989898", -"bG c #98c8fa", -"ad c #9a9a9a", -"#T c #9b9b9b", -".g c #9c9c9c", -"#e c #9d9d9d", -"#y c #9dcafa", -"ae c #9f9f9f", -"#c c #9fbddc", -"aE c #a0a0a0", -"bH c #a1bedc", -".9 c #a2a2a2", -"a. c #a2a3ad", -"#l c #a3cefa", -"aD c #a4a4a4", -"#Y c #a4a5ad", -"#u c #a5a5a5", -"aw c #a7a7a7", -"al c #a8a8a8", -"#g c #a9a9a9", -"bK c #a9d1fb", -"bq c #aacaeb", -"#h c #acacac", -"am c #afafaf", -"#Q c #afb1bd", -"#1 c #b0b0b0", -".Z c #b1b1b1", -".8 c #b3b3b3", -"#P c #b3b3b9", -"ak c #b4b4b4", -"bx c #b5d7fb", -"#r c #b9b9b9", -"aj c #bababa", -"ax c #bbbbbb", -"a# c #bebebe", -"an c #bfbfbf", -".B c #c0c0c0", -".r c #c2c2c2", -"#R c #c2c3cb", -".6 c #c5c5c5", -"#z c #c5e0fc", -"aa c #c7c7c7", -".Y c #c8c8c8", -"#0 c #c9c9c9", -"#C c #cacaca", -"aP c #cbcbcb", -"#S c #cccccc", -"#E c #cecece", -"b# c #cfcfcf", -".X c #d0d0d0", -".7 c #d1d1d1", -"ab c #d2d2d2", -"#m c #d2e7fc", -"#q c #d5d5d5", -"#f c #d6d6d6", -"#D c #d6d7db", -"aQ c #d7d7d7", -"#s c #d9d9d9", -".t c #dbdbdb", -".s c #dcdcdc", -".5 c #dddddd", -".F c #dedede", -".E c #e0e0e0", -".D c #e1e1e1", -".C c #e3e3e3", -".u c #e5e5e5", -".G c #e6e6e6", -".P c #e7e7e7", -"#V c #eaeaea", -".v c #ebebeb", -".H c #ececec", -".O c #ededed", -"a3 c #eeeeee", -"a0 c #efefef", -"a2 c #f0f0f0", -"a1 c #f1f1f1", -".W c #f7f7f7", -".N c #f9f9f9", -"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQtQtQt.#.#QtQtQtQtQt.a.b.#.c.dQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQt.#.#.e.f.g.h.#QtQtQtQt.i.j.k.l.m.nQtQtQtQtQt", -"QtQtQtQtQtQtQt.#.o.p.q.r.s.t.u.v.w.#QtQtQt.x.y.z.k.k.AQtQtQtQtQt", -"QtQtQtQtQtQt.#.B.u.C.D.E.F.s.s.G.H.q.#Qt.#.I.J.K.c.#.LQtQtQtQtQt", -"QtQtQtQtQtQt.M.N.O.u.C.D.E.F.s.s.P.O.Q.#.R.S.T.UQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQt.V.W.N.O.u.C.F.X.r.Y.X.Z.0.1.2.3QtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQt.4.H.W.N.5.6.7.s.8.9#.###a#b#c.#QtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQt#d.D.H.W.Y#e#f#g#h#i#j#k#l#m#n#oQtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQt#p#q.D.H.X#r#s#t#u#v#w#x#y#z#AQtQtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQt#B#C#q#D#E#s.t#F#G#H.w#I#J#K#L#MQt#NQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQt#O#P#Q#R#S.s.F.r#T#U.w.F#V#WQt#MQtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQt#X#Y#Z#C#0.F#1#2#3#4#5#6.O#7Qt#MQtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQt#8#9a.a#aaabac.E.8adae.1.Eaf.##oQtagQtQtQtQtQtQtQtQt", -"QtQtQtQtQt#Nahaiajak.6al#5am#2an.q.paoap.zaqarasat.A.AQtQtQtQtQt", -"QtQtQtQtQtQtauavan#r.6#i#eawanaxay#4azaAapap.z.j.k.k.l.#QtQtQtQt", -"QtQtQtQtQtQtaBaC.ra##SaD.0aE#3ayaFaGaHaIaJaK.iaLaLataMQtQtQtQtQt", -"QtQtQtQtQtQtQtaNaOa#aPaQaR.1.paS.G.waTaUaVaWaX.y.y.zaYQtQtQtQtQt", -"QtQtQtQtQt#NQtQtaZaF#E#5a0a1a2a3ana4a5.#.#a6a7aKa8.za9QtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtb.#2.Hb#.Qbabb.#bcbdQtQtQtQtQtbebfQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQt.#.#.#.#bgbhbibjbkQtQtQtQtQtblbmQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQt.#bnbobp#lbq.#Qt.#brbsbtbua9QtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQt.#bv#kbwbxbyQt.#bzbAbBbCbD.#QtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQt.#bEbFbGbHbIQtbJbKbpbLbMbNQtQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQtQt.#bObP.#QtQt.#bQbRbSbTbUQtQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.#bVbW.#QtQtQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", -"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt"}; diff --git a/src/images/stop.png b/src/images/stop.png deleted file mode 100644 index 637137f59..000000000 Binary files a/src/images/stop.png and /dev/null differ diff --git a/src/inlines.h b/src/inlines.h deleted file mode 100644 index 3efccf0de..000000000 --- a/src/inlines.h +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright (c) 2000-2001 Brad Hughes -// -// Use, modification and distribution is allowed without limitation, -// warranty, or liability of any kind. -// - -#ifndef INLINES_H -#define INLINES_H - -#include "fft.h" - -// *fast* convenience functions -static inline void -calc_freq(short* dest, short *src) -{ - static fft_state *state = NULL; - float tmp_out[257]; - int i; - - if (!state) - state = fft_init(); - - fft_perform(src, tmp_out, state); - - for (i = 0; i < 256; i++) - dest[i] = ((int) sqrt(tmp_out[i + 1])) >> 8; -} - -static inline void -calc_mono_freq(short dest[2][256], short src[2][512], int nch) -{ - int i; - short *d, *sl, *sr, tmp[512]; - - if (nch == 1) - calc_freq(dest[0], src[0]); - else - { - d = tmp; - sl = src[0]; - sr = src[1]; - for (i = 0; i < 512; i++) - { - *(d++) = (*(sl++) + *(sr++)) >> 1; - } - calc_freq(dest[0], tmp); - } -} - -static inline void stereo16_from_stereopcm8(register short *l, - register short *r, - register uchar *c, - long cnt) -{ - while (cnt >= 4l) - { - l[0] = c[0]; - r[0] = c[1]; - l[1] = c[2]; - r[1] = c[3]; - l[2] = c[4]; - r[2] = c[5]; - l[3] = c[6]; - r[3] = c[7]; - l += 4; - r += 4; - c += 8; - cnt -= 4l; - } - - if (cnt > 0l) - { - l[0] = c[0]; - r[0] = c[1]; - if (cnt > 1l) - { - l[1] = c[2]; - r[1] = c[3]; - if (cnt > 2l) - { - l[2] = c[4]; - r[2] = c[5]; - } - } - } -} - - -static inline void stereo16_from_stereopcm16(register short *l, - register short *r, - register short *s, - long cnt) -{ - while (cnt >= 4l) - { - l[0] = s[0]; - r[0] = s[1]; - l[1] = s[2]; - r[1] = s[3]; - l[2] = s[4]; - r[2] = s[5]; - l[3] = s[6]; - r[3] = s[7]; - l += 4; - r += 4; - s += 8; - cnt -= 4l; - } - - if (cnt > 0l) - { - l[0] = s[0]; - r[0] = s[1]; - if (cnt > 1l) - { - l[1] = s[2]; - r[1] = s[3]; - if (cnt > 2l) - { - l[2] = s[4]; - r[2] = s[5]; - } - } - } -} - - -static inline void mono16_from_monopcm8(register short *l, - register uchar *c, - long cnt) -{ - while (cnt >= 4l) - { - l[0] = c[0]; - l[1] = c[1]; - l[2] = c[2]; - l[3] = c[3]; - l += 4; - c += 4; - cnt -= 4l; - } - - if (cnt > 0l) - { - l[0] = c[0]; - if (cnt > 1l) - { - l[1] = c[1]; - if (cnt > 2l) - { - l[2] = c[2]; - } - } - } -} - - -static inline void mono16_from_monopcm16(register short *l, - register short *s, - long cnt) -{ - while (cnt >= 4l) - { - l[0] = s[0]; - l[1] = s[1]; - l[2] = s[2]; - l[3] = s[3]; - l += 4; - s += 4; - cnt -= 4l; - } - - if (cnt > 0l) - { - l[0] = s[0]; - if (cnt > 1l) - { - l[1] = s[1]; - if (cnt > 2l) - { - l[2] = s[2]; - } - } - } -} - - -static inline void fast_short_set(register short *p, - short v, - long c) -{ - while (c >= 4l) - { - p[0] = v; - p[1] = v; - p[2] = v; - p[3] = v; - p += 4; - c -= 4l; - } - - if (c > 0l) - { - p[0] = v; - if (c > 1l) - { - p[1] = v; - if (c > 2l) - { - p[2] = v; - } - } - } -} - -#ifdef FFTW -static inline void fast_real_set(register fftw_real *p, - fftw_real v, - long c) -{ - while (c >= 4l) - { - p[0] = v; - p[1] = v; - p[2] = v; - p[3] = v; - p += 4; - c -= 4l; - } - - if (c > 0l) - { - p[0] = v; - if (c > 1l) - { - p[1] = v; - if (c > 2l) - { - p[2] = v; - } - } - } -} - -static inline void fast_complex_set(register fftw_complex *p, - fftw_complex v, - long c) -{ - while (c >= 4l) - { - p[0] = v; - p[1] = v; - p[2] = v; - p[3] = v; - p += 4; - c -= 4l; - } - - if (c > 0l) - { - p[0] = v; - if (c > 1l) - { - p[1] = v; - if (c > 2l) - { - p[2] = v; - } - } - } -} - - -static inline void fast_real_set_from_short(register fftw_real *d, - register short *s, - long c) -{ - while (c >= 4l) - { - d[0] = fftw_real(s[0]); - d[1] = fftw_real(s[1]); - d[2] = fftw_real(s[2]); - d[3] = fftw_real(s[3]); - d += 4; - s += 4; - c -= 4l; - } - - if (c > 0l) - { - d[0] = fftw_real(s[0]); - if (c > 1l) - { - d[1] = fftw_real(s[1]); - if (c > 2l) - { - d[2] = fftw_real(s[2]); - } - } - } -} - -static inline void fast_complex_set_from_short(register fftw_complex *d, - register short *s, - long c) -{ - while (c >= 4l) - { - d[0].re = fftw_real(s[0]); - d[0].im = 0; - d[1].re = fftw_real(s[1]); - d[1].im = 0; - d[2].re = fftw_real(s[2]); - d[2].im = 0; - d[3].re = fftw_real(s[3]); - d[3].im = 0; - d += 4; - s += 4; - c -= 4l; - } - - if (c > 0l) - { - d[0].re = fftw_real(s[0]); - d[0].im = 0; - if (c > 1l) - { - d[1].re = fftw_real(s[1]); - d[1].im = 0; - if (c > 2l) - { - d[2].re = fftw_real(s[2]); - d[2].im = 0; - } - } - } -} - - -static inline void fast_real_avg_from_shorts(register fftw_real *d, - register short *s1, - register short *s2, - long c) -{ - fftw_real t0, t1, t2, t3; - while (c >= 4l) - { - t0 = (s1[0] + s2[0]) / 2; - t1 = (s1[1] + s2[1]) / 2; - t2 = (s1[2] + s2[2]) / 2; - t3 = (s1[3] + s2[3]) / 2; - d[0] = t0; - d[1] = t1; - d[2] = t2; - d[3] = t3; - d += 4; - s1 += 4; - s2 += 4; - c -= 4l; - } - - if (c > 0l) - { - d[0] = fftw_real((s1[0] + s2[0]) / 2); - if (c > 1l) - { - d[1] = fftw_real((s1[1] + s2[1]) / 2); - if (c > 2l) - { - d[2] = fftw_real((s1[2] + s2[2]) / 2); - } - } - } -} - -static inline void fast_complex_avg_from_shorts(register fftw_complex *d, - register short *s1, - register short *s2, - long c) -{ - fftw_real t0, t1, t2, t3; - while (c >= 4l) - { - t0 = (s1[0] + s2[0]) / 2; - t1 = (s1[1] + s2[1]) / 2; - t2 = (s1[2] + s2[2]) / 2; - t3 = (s1[3] + s2[3]) / 2; - d[0].re = t0; - d[0].im = 0; - d[1].re = t1; - d[1].im = 0; - d[2].re = t2; - d[2].im = 0; - d[3].re = t3; - d[3].im = 0; - d += 4; - s1 += 4; - s2 += 4; - c -= 4l; - } - - if (c > 0l) - { - d[0].re = fftw_real((s1[0] + s2[0]) / 2); - d[0].im = 0; - if (c > 1l) - { - d[1].re = fftw_real((s1[1] + s2[1]) / 2); - d[1].im = 0; - if (c > 2l) - { - d[2].re = fftw_real((s1[2] + s2[2]) / 2); - d[2].im = 0; - } - } - } -} - - -static inline fftw_complex fftw_complex_from_real( fftw_real re ) -{ - fftw_complex c; - - c.re = re; - c.im = 0; - - return c; -} - -static inline void fast_reals_set(register fftw_real *p1, - register fftw_real *p2, - fftw_real v, - long c) -{ - while (c >= 4l) - { - p1[0] = v; - p1[1] = v; - p1[2] = v; - p1[3] = v; - p2[0] = v; - p2[1] = v; - p2[2] = v; - p2[3] = v; - p1 += 4; - p2 += 4; - c -= 4l; - } - - if (c > 0l) - { - p1[0] = v; - p2[0] = v; - if (c > 1l) - { - p1[1] = v; - p2[1] = v; - if (c > 2l) - { - p1[2] = v; - p2[2] = v; - } - } - } -} - -static inline void fast_complex_set(register fftw_complex *p1, - register fftw_complex *p2, - fftw_complex v, - long c) -{ - while (c >= 4l) - { - p1[0] = v; - p1[1] = v; - p1[2] = v; - p1[3] = v; - p2[0] = v; - p2[1] = v; - p2[2] = v; - p2[3] = v; - p1 += 4; - p2 += 4; - c -= 4l; - } - - if (c > 0l) - { - p1[0] = v; - p2[0] = v; - if (c > 1l) - { - p1[1] = v; - p2[1] = v; - if (c > 2l) - { - p1[2] = v; - p2[2] = v; - } - } - } -} -#endif // FFTW - -#endif // INLINES_H diff --git a/src/jumptotrackdialog.cpp b/src/jumptotrackdialog.cpp deleted file mode 100644 index bcd0f308c..000000000 --- a/src/jumptotrackdialog.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "jumptotrackdialog.h" -#include "playlistmodel.h" - -#include -#include -#include -#include - -JumpToTrackDialog::JumpToTrackDialog(QWidget* parent, Qt::WFlags fl) -: QDialog( parent, fl ) -{ - setupUi(this); - setAttribute(Qt::WA_QuitOnClose, FALSE); - m_playListModel = 0; - m_listModel = new QStringListModel(this); - - m_proxyModel = new QSortFilterProxyModel; - m_proxyModel->setDynamicSortFilter(true); - m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); - m_proxyModel->setSourceModel(m_listModel); - songsListView->setModel(m_proxyModel); - - connect(songsListView,SIGNAL(doubleClicked(const QModelIndex &)), - this,SLOT(jumpTo(const QModelIndex&))); - - - connect(songsListView->selectionModel(), - SIGNAL(currentRowChanged(const QModelIndex&,const QModelIndex&)), - this,SLOT(queueUnqueue(const QModelIndex&,const QModelIndex&))); - - new QShortcut(QKeySequence("Q"),this,SLOT(on_queuePushButton_clicked())); - new QShortcut(QKeySequence("J"),this,SLOT(on_jumpToPushButton_clicked())); - new QShortcut(QKeySequence("F5"),this,SLOT(on_refreshPushButton_clicked())); -} - -JumpToTrackDialog::~JumpToTrackDialog() -{ -} - - -void JumpToTrackDialog::on_closePushButton_clicked() -{ - hide(); -} - -void JumpToTrackDialog::on_refreshPushButton_clicked() -{ - refresh(); -} - -void JumpToTrackDialog::on_queuePushButton_clicked() -{ - QModelIndexList mi_list = songsListView->selectionModel()->selectedRows(); - if(!mi_list.isEmpty()) - { - int selected = (m_proxyModel->mapToSource(mi_list.at(0))).row(); - m_playListModel->setQueued(m_playListModel->item(selected)); - if(m_playListModel->isQueued(m_playListModel->item(selected))) - queuePushButton->setText(tr("Unqueue")); - else - queuePushButton->setText(tr("Queue")); - } -} - -void JumpToTrackDialog::on_jumpToPushButton_clicked() -{ - QModelIndexList mi_list = songsListView->selectionModel()->selectedRows(); - if(!mi_list.isEmpty()) - { - jumpTo(mi_list.at(0)); - } -} - -void JumpToTrackDialog::refresh() -{ - filterLineEdit->clear(); - QStringList titles = m_playListModel->getTitles(0,m_playListModel->count()); - m_listModel->setStringList(titles); - filterLineEdit->setFocus(); -} - -void JumpToTrackDialog::setModel(PlayListModel * model) -{ - m_playListModel = model; -} - -void JumpToTrackDialog::on_filterLineEdit_textChanged(const QString &str) -{ - m_proxyModel->setFilterFixedString(str); -} - -void JumpToTrackDialog::jumpTo(const QModelIndex & index) -{ - int selected = (m_proxyModel->mapToSource(index)).row(); - m_playListModel->setCurrent(selected); - emit playRequest(); -} - -void JumpToTrackDialog::queueUnqueue(const QModelIndex& curr,const QModelIndex&) -{ - int row = m_proxyModel->mapToSource(curr).row(); - if(m_playListModel->isQueued(m_playListModel->item(row))) - queuePushButton->setText(tr("Unqueue")); - else - queuePushButton->setText(tr("Queue")); -} - - diff --git a/src/jumptotrackdialog.h b/src/jumptotrackdialog.h deleted file mode 100644 index cfe629693..000000000 --- a/src/jumptotrackdialog.h +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ - -#ifndef JUMPTOTRACKDIALOG_H -#define JUMPTOTRACKDIALOG_H - -#include -#include "ui_jumptotrackdialog.h" - -/** - @author Vladimir Kuznetsov - */ - -class QStringListModel; -class PlayListModel; -class QSortFilterProxyModel; - - -class JumpToTrackDialog : public QDialog, private Ui::JumpToTrackDialog -{ - Q_OBJECT - -public: - JumpToTrackDialog(QWidget* parent = 0, Qt::WFlags fl = 0 ); - ~JumpToTrackDialog(); - void setModel(PlayListModel* model); - void refresh(); -protected slots: - void on_closePushButton_clicked(); - void on_refreshPushButton_clicked(); - void on_queuePushButton_clicked(); - void on_jumpToPushButton_clicked(); - void on_filterLineEdit_textChanged(const QString&); - void jumpTo(const QModelIndex&); - void queueUnqueue(const QModelIndex&,const QModelIndex&); -signals: - void playRequest(); -private: - PlayListModel* m_playListModel; - QStringListModel* m_listModel; - QSortFilterProxyModel* m_proxyModel; -}; - -#endif - diff --git a/src/jumptotrackdialog.ui b/src/jumptotrackdialog.ui deleted file mode 100644 index 1418c54fd..000000000 --- a/src/jumptotrackdialog.ui +++ /dev/null @@ -1,110 +0,0 @@ - - JumpToTrackDialog - - - - 0 - 0 - 487 - 315 - - - - Jump To Track - - - - 9 - - - 6 - - - - - 0 - - - 6 - - - - - Filter - - - - - - - - - - - - QAbstractItemView::NoEditTriggers - - - true - - - QAbstractItemView::SelectRows - - - - - - - 0 - - - 6 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Queue - - - - - - - Refresh - - - - - - - Jump To - - - - - - - Close - - - - - - - - - - diff --git a/src/keyboardmanager.cpp b/src/keyboardmanager.cpp deleted file mode 100644 index 5ad32fee7..000000000 --- a/src/keyboardmanager.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - - -#include - -#include "playlist.h" -#include "playlistmodel.h" -#include "listwidget.h" -#include "keyboardmanager.h" -#include "mainwindow.h" - - -KeyboardManager::KeyboardManager ( PlayList* pl ) -{ - m_playlist = pl; -} - -bool KeyboardManager::handleKeyPress ( QKeyEvent* ke ) -{ - bool handled = TRUE; - switch ( ke->key() ) - { - case Qt::Key_Up: - keyUp ( ke ); - break; - case Qt::Key_Down: - keyDown ( ke ); - break; - case Qt::Key_PageUp: - keyPgUp ( ke ); - break; - case Qt::Key_PageDown: - keyPgDown ( ke ); - break; - case Qt::Key_Enter: - case Qt::Key_Return: - keyEnter ( ke ); - default: - handled = FALSE; - } - return handled; -} - -bool KeyboardManager::handleKeyRelease ( QKeyEvent* ) -{ - return FALSE; -} - - - -void KeyboardManager::setModel ( PlayListModel *m ) -{ - m_playListModel = m; -} - -void KeyboardManager::keyUp ( QKeyEvent * ke ) -{ - QList rows = m_playListModel->getSelectedRows(); - ListWidget* list_widget = m_playlist->listWidget(); - - if ( rows.count() > 0 ) - { - if(rows[0] == 0 && rows.count() == 1) - return; - - if ( ! ( ke->modifiers() & Qt::ShiftModifier || ke->modifiers() & Qt::AltModifier ) ) - { - m_playListModel->clearSelection(); - list_widget->setAnchorRow(-1); - } - - bool select_top = false; - int first_visible = list_widget->firstVisibleRow(); - int last_visible = list_widget->visibleRows() + first_visible - 1; - foreach ( int i, rows ) - { - if ( i > last_visible || i < first_visible ) - { - select_top = true; - break; - } - } - - if ( !select_top || ke->modifiers() & Qt::ShiftModifier || ke->modifiers() & Qt::AltModifier ) - { - if ( ke->modifiers() == Qt::AltModifier ) - { - m_playListModel->moveItems ( rows[0],rows[0] - 1 ); - list_widget->setAnchorRow ( list_widget->getAnchorRow() - 1 ); - } - else - { - if ( rows.last() > list_widget->getAnchorRow() && ke->modifiers() & Qt::ShiftModifier ) - { - m_playListModel->setSelected ( rows.last(),false ); - } - else if ( rows[0] > 0 ) - { - m_playListModel->setSelected ( rows[0] - 1,true ); - } - else - { - m_playListModel->setSelected ( rows[0],true ); - if(list_widget->getAnchorRow() == -1) - list_widget->setAnchorRow(rows[0]); - } - - if ( ! ( ke->modifiers() & Qt::ShiftModifier ) && rows[0] > 0 ) - list_widget->setAnchorRow ( rows[0] - 1 ); - } - } - else - { - m_playListModel->setSelected ( list_widget->firstVisibleRow(),true ); - list_widget->setAnchorRow(list_widget->firstVisibleRow()); - } - - rows = m_playListModel->getSelectedRows(); - - if ( rows[0] < list_widget->firstVisibleRow() && list_widget->firstVisibleRow() > 0 ) - { - int r = rows.last() > list_widget->getAnchorRow() ? rows.last(): rows.first(); - if(ke->modifiers() & Qt::ShiftModifier && (r >= list_widget->firstVisibleRow() )) - ; - else - list_widget->scroll ( list_widget->firstVisibleRow() - 1 ); - } - } - else - { - //if(list_widget->getAnchorRow() == -1) - list_widget->setAnchorRow(list_widget->firstVisibleRow()); - m_playListModel->setSelected ( list_widget->firstVisibleRow(),true ); - } -} - -void KeyboardManager::keyDown ( QKeyEvent * ke ) -{ - QList rows = m_playListModel->getSelectedRows(); - ListWidget* list_widget = m_playlist->listWidget(); - //qWarning("count: %d",rows.count()); - if ( rows.count() > 0 ) - { - if ( ! ( ke->modifiers() & Qt::ShiftModifier || ke->modifiers() & Qt::AltModifier ) ) - { - m_playListModel->clearSelection(); - list_widget->setAnchorRow(-1); - } - - bool select_top = false; - int first_visible = list_widget->firstVisibleRow(); - int last_visible = list_widget->visibleRows() + first_visible - 1; - foreach ( int i, rows ) - { - if ( i > last_visible || i < first_visible ) - { - select_top = true; - break; - } - } - - if ( !select_top || ke->modifiers() & Qt::ShiftModifier || ke->modifiers() & Qt::AltModifier ) - { - if ( ke->modifiers() == Qt::AltModifier ) - { - m_playListModel->moveItems ( rows.last(),rows.last() + 1 ); - list_widget->setAnchorRow ( list_widget->getAnchorRow() + 1 ); - } - else - { - //qWarning("list_widget %d",list_widget->getAnchorRow()); - //qWarning("model count: %d rows.last(): %d",m_playListModel->count(),rows.last()); - if ( rows[0] < list_widget->getAnchorRow() && ke->modifiers() & Qt::ShiftModifier ) - m_playListModel->setSelected ( rows[0],false ); - else if ( rows.last() < m_playListModel->count() - 1 ) - { - m_playListModel->setSelected ( rows.last() + 1,true ); - } - else - { - m_playListModel->setSelected ( rows.last(),true ); - if(list_widget->getAnchorRow() == -1) - list_widget->setAnchorRow(rows.last()); - } - - if ( ! ( ke->modifiers() & Qt::ShiftModifier ) && rows.last() < m_playListModel->count() - 1 ) - list_widget->setAnchorRow ( rows.last() + 1 ); - } - } - else - { - m_playListModel->setSelected ( list_widget->firstVisibleRow(),true ); - list_widget->setAnchorRow(list_widget->firstVisibleRow()); - } - - rows = m_playListModel->getSelectedRows(); - - if ( !rows.isEmpty() && rows.last() >= list_widget->visibleRows() + list_widget->firstVisibleRow() ) - { - int r = rows.first() < list_widget->getAnchorRow() ? rows.first(): rows.last(); - if(ke->modifiers() & Qt::ShiftModifier && - (r < list_widget->firstVisibleRow() + list_widget->visibleRows() )) - ; - else - list_widget->scroll ( list_widget->firstVisibleRow() + 1 ); - } - } - else - { - m_playListModel->setSelected ( list_widget->firstVisibleRow(),true ); - //if(list_widget->getAnchorRow() == -1) - list_widget->setAnchorRow(list_widget->firstVisibleRow()); - } -} - -void KeyboardManager::keyPgUp ( QKeyEvent * ) -{ - ListWidget* list_widget = m_playlist->listWidget(); - int page_size = list_widget->visibleRows(); - int offset= ( list_widget->firstVisibleRow()-page_size >= 0 ) ?list_widget->firstVisibleRow()-page_size:0; - list_widget->scroll ( offset ); -} - -void KeyboardManager::keyPgDown ( QKeyEvent * ) -{ - ListWidget* list_widget = m_playlist->listWidget(); - int page_size = list_widget->visibleRows(); - int offset = ( list_widget->firstVisibleRow() +page_size < m_playListModel->count() ) ? - list_widget->firstVisibleRow() +page_size:m_playListModel->count() - 1; - list_widget->scroll ( offset ); -} - -void KeyboardManager::keyEnter ( QKeyEvent * ) -{ - QList rows = m_playListModel->getSelectedRows(); - MainWindow* mw = qobject_cast ( m_playlist->parentWidget() ); - if ( mw && rows.count() > 0 ) - { - m_playListModel->setCurrent ( rows[0] ); - mw->replay(); - } -} diff --git a/src/keyboardmanager.h b/src/keyboardmanager.h deleted file mode 100644 index 2b33b5ef9..000000000 --- a/src/keyboardmanager.h +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ - - -#ifndef _KEYBOARDMANAGER_H -#define _KEYBOARDMANAGER_H - -class PlayList; -class PlayListModel; -class QKeyEvent; - - -/*! - * Class \b KeyboardManager represents key handler object that processes - * all key events passed to the \b PlayList - * @author Vladimir Kuznetsov - */ -class KeyboardManager -{ - public: - /*! - * Constructor. Takes \b PlayList object as an argument. - */ - KeyboardManager ( PlayList* ); - - /*! - * Handles key press events from \b PlayList object. Returns \b TRUE - * if the key was handled, otherwise \b FALSE. - */ - bool handleKeyPress ( QKeyEvent* ); - - /*! - * Handles key release events from \b PlayList object. Returns \b TRUE - * if the key was handled, otherwise \b FALSE. - */ - bool handleKeyRelease ( QKeyEvent* ); - - /*! - * Inits the \b KeyboardManager object with data model. - */ - void setModel ( PlayListModel* ); - protected: - void keyUp ( QKeyEvent* ke ); - void keyDown ( QKeyEvent* ke ); - void keyPgUp ( QKeyEvent* ke ); - void keyPgDown ( QKeyEvent* ke ); - void keyEnter ( QKeyEvent* ke ); - private: - PlayList* m_playlist; - PlayListModel* m_playListModel; -}; - -#endif - diff --git a/src/listwidget.cpp b/src/listwidget.cpp deleted file mode 100644 index fb2173b33..000000000 --- a/src/listwidget.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mediafile.h" -#include "textscroller.h" -#include "listwidget.h" -#include "skin.h" -#include "playlistmodel.h" -#include "playlist.h" - -#define INVALID_ROW -1 - -ListWidget::ListWidget(QWidget *parent) - : QWidget(parent) -{ - m_update = FALSE; - m_skin = Skin::getPointer(); - loadColors(); - setWindowFlags(Qt::FramelessWindowHint); - m_menu = new QMenu(this); - m_scroll_direction = NONE; - m_prev_y = 0; - m_anchor_row = INVALID_ROW; - - m_first = 0; - m_rows = 0; - m_scroll = FALSE; - m_select_on_release = FALSE; - readSettings(); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); - setAcceptDrops(true); -} - - -ListWidget::~ListWidget() -{} - -void ListWidget::readSettings() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - QString fontname = settings.value("PlayList/Font","").toString(); - if (fontname.isEmpty ()) - fontname = QFont("Helvetica [Cronyx]", 10).toString(); - m_font.fromString(fontname); - - if (m_update) - { - delete m_metrics; - m_metrics = new QFontMetrics(m_font); - m_rows = (height() - 10) / m_metrics->ascent (); - updateList(); - } - else - { - m_update = TRUE; - m_metrics = new QFontMetrics(m_font); - } -} - -void ListWidget::loadColors() -{ - m_normal.setNamedColor(m_skin->getPLValue("normal")); - m_current.setNamedColor(m_skin->getPLValue("current")); - m_normal_bg.setNamedColor(m_skin->getPLValue("normalbg")); - m_selected_bg.setNamedColor(m_skin->getPLValue("selectedbg")); -} - -void ListWidget::paintEvent(QPaintEvent *) -{ - - QPainter m_painter(this); - //m_painter.setPen(Qt::white); - m_painter.setFont(m_font); - m_painter.setBrush(QBrush(m_normal_bg)); - m_painter.drawRect(-1,-1,width()+1,height()+1); - - - - for (int i=0; iisSelected(i + m_first)) - { - m_painter.setBrush(QBrush(m_selected_bg)); - m_painter.setPen(m_selected_bg); - m_painter.drawRect ( 6, 15+(i-1)*m_metrics->ascent(), - width() - 10, m_metrics->ascent()); - } - - if (m_model->currentRow() == i + m_first) - m_painter.setPen(m_current); - else - m_painter.setPen(m_normal); //243,58 - - m_painter.drawText(10,14+i*m_metrics->ascent(),m_titles.at(i)); - - if (m_model->isQueued(m_model->item(i + m_first))) - { - QString queue_string = "|" + - QString::number(1 + m_model->queuedIndex(m_model->item(m_first + i))) + "|"; - - int old_size = m_font.pointSize(); - m_font.setPointSize(old_size - 1 ); - m_painter.setFont(m_font); - - m_painter.drawText(width() - 10 - m_metrics->width(queue_string) - m_metrics->width(m_times.at(i)), 12+i*m_metrics->ascent (), queue_string); - - m_font.setPointSize(old_size); - m_painter.setFont(m_font); - - - m_painter.setBrush(QBrush(Qt::transparent)); - //m_painter.drawRect(width() - 10 - m_metrics->width(queue_string) - m_metrics->width(m_times.at(i)), - // /*14+*/i*m_metrics->ascent () + 3,10,12); - m_painter.setBrush(QBrush(m_normal_bg)); - } - - - m_painter.drawText(width() - 7 - m_metrics->width(m_times.at(i)), - 14+i*m_metrics->ascent (), m_times.at(i)); - - } - -} - -void ListWidget::mouseDoubleClickEvent (QMouseEvent *e) -{ - int y = e->y(); - int row = rowAt(y); - if (INVALID_ROW != row) - { - m_model->setCurrent(row); - emit selectionChanged(); - update(); - } -} - - -void ListWidget::mousePressEvent(QMouseEvent *e) -{ - m_scroll = TRUE; - int y = e->y(); - int row = rowAt(y); - - if (INVALID_ROW != row && m_model->count() > row) - { - if (!(Qt::ControlModifier & e->modifiers () || - Qt::ShiftModifier & e->modifiers () || - m_model->isSelected(row))) - m_model->clearSelection(); - - if (m_model->isSelected(row) && (e->modifiers() == Qt::NoModifier)) - m_select_on_release = TRUE; - - //qWarning("m_prev_clicked_row: %d",m_prev_clicked_row); - - m_pressed_row = row; - if ((Qt::ShiftModifier & e->modifiers())) - { - - if (m_pressed_row > m_anchor_row) - { - //int upper_selected = m_model->firstSelectedUpper(m_anchor_row); - //if (INVALID_ROW != upper_selected) - //{ - /*for (int j = upper_selected;j < m_anchor_row;j++) - { - m_model->setSelected(j, false); - }*/ - m_model->clearSelection(); - for (int j = m_anchor_row;j <= m_pressed_row;j++) - { - m_model->setSelected(j, true); - } - //} - } - else - { - m_model->clearSelection(); - for (int j = m_anchor_row;j >= m_pressed_row;j--) - { - m_model->setSelected(j, true); - } - } - - /* - int upper_selected = m_model->firstSelectedUpper(row); - int lower_selected = m_model->firstSelectedLower(row); - if (INVALID_ROW != upper_selected) - { - for (int j = upper_selected;j <= row;j++) - { - m_model->setSelected(j, true); - } - } - else if (INVALID_ROW != lower_selected) - { - for (int j = row;j <= lower_selected;j++) - { - m_model->setSelected(j, true); - } - } - else - m_model->setSelected(row, true); - */ - } - else - { - if (!m_model->isSelected(row) || (Qt::ControlModifier & e->modifiers())) - m_model->setSelected(row, !m_model->isSelected(row)); - } - - if (m_model->getSelection(m_pressed_row).count() == 1) - m_anchor_row = m_pressed_row; - //qWarning("m_anchor_row: %d",m_anchor_row); - - update(); - } - QWidget::mousePressEvent(e); -} - -void ListWidget::resizeEvent(QResizeEvent *e) -{ - m_rows = (e->size().height() - 10) / m_metrics->ascent (); - - m_scroll = TRUE; - - updateList(); - QWidget::resizeEvent(e); -} - -void ListWidget::wheelEvent (QWheelEvent *e) -{ - if (m_model->count() <= m_rows) - return; - if ((m_first == 0 && e->delta() > 0) || - ((m_first == m_model->count() - m_rows) && e->delta() < 0)) - return; - m_first -= e->delta()/40; //40*3 TODO: add step to config - if (m_first < 0) - m_first = 0; - - if (m_first > m_model->count() - m_rows) - m_first = m_model->count() - m_rows; - - m_scroll = FALSE; - updateList(); -} - -void ListWidget::updateList() -{ - if (m_model->count() < (m_rows+m_first+1) && m_rows< m_model->count()) - { - m_first = m_model->count() - m_rows; - } - if (m_model->count() < m_rows + 1) - { - m_first = 0; - emit positionChanged(0,0); - } - else - { - //int pos = m_first*99/(m_model->count() - m_rows); - //emit positionChanged(pos); - emit positionChanged(m_first, m_model->count() - m_rows); - } - if (m_model->count() <= m_first) - { - m_first = 0; - emit positionChanged(0, qMax(0, m_model->count() - m_rows)); - } - - m_titles = m_model->getTitles(m_first, m_rows ); - m_times = m_model->getTimes(m_first, m_rows ); - m_scroll = FALSE; - //add numbers - for (int i = 0; i < m_titles.size(); ++i) - { - QString title = m_titles.at(i); - m_titles.replace(i, title.prepend(QString("%1").arg(m_first+i+1)+". ")); - - } - if (m_model->currentItem()) - { - TextScroller::getPointer()->setText("*** "+m_model->currentItem()->title()); - parentWidget()->parentWidget()->setWindowTitle(m_model->currentItem()->title()); - } - cut(); - update(); -} - -void ListWidget::setModel(PlayListModel *model) -{ - m_model = model; - connect (m_model, SIGNAL(listChanged()), SLOT(updateList())); - connect (m_model, SIGNAL(currentChanged()), SLOT(recenterCurrent())); - updateList(); -} - -void ListWidget::scroll(int sc) -{ - if (m_model->count() <= m_rows) - return; - m_first = sc; //*(m_model->count() - m_rows)/99; - m_scroll = TRUE; - updateList(); -} - -void ListWidget::cut() -{ - bool cut; - for (int i=0; iisQueued(m_model->item(i + m_first))) - { - int index = m_model->queuedIndex(m_model->item(m_first + i)); - QString queue_string = "|"+QString::number(index)+"|"; - queue_number_space = m_metrics->width(queue_string); - } - while ( m_metrics->width(m_titles.at(i)) > (this->width() - 54 - queue_number_space)) - { - cut = TRUE; - name = m_titles.at(i); - m_titles.replace(i, name.left(name.length()-1) ); - } - if (cut) - { - m_titles.replace(i, name.left(name.length()-3).trimmed()+"..."); - - } - } -} - -void ListWidget::updateSkin() -{ - loadColors(); - update(); -} - -void ListWidget::dragEnterEvent(QDragEnterEvent *event) -{ - if (event->mimeData()->hasFormat("text/uri-list")) - event->acceptProposedAction(); -} - - -void ListWidget::dropEvent(QDropEvent *event) -{ - if (event->mimeData()->hasUrls()) - { - QList list_urls = event->mimeData()->urls(); - event->acceptProposedAction(); - QApplication::restoreOverrideCursor(); - - foreach(QUrl u,list_urls) - { - QString add_string = u.toString(QUrl::RemoveScheme); - if (!add_string.isEmpty()) - processFileInfo(QFileInfo(add_string)); - } - } - -} - -void ListWidget::processFileInfo(const QFileInfo& info) -{ - if (info.isDir()) - { - m_model->addDirectory(info.absoluteFilePath()); - } - else - { - m_model->addFile(info.absoluteFilePath()); - } -} - -void ListWidget::mouseMoveEvent(QMouseEvent *e) -{ - m_scroll = true; - if (m_prev_y > e->y()) - m_scroll_direction = TOP; - else if (m_prev_y < e->y()) - m_scroll_direction = DOWN; - else - m_scroll_direction = NONE; - - int row = rowAt(e->y()); - - if (INVALID_ROW != row) - { - SimpleSelection sel = m_model->getSelection(m_pressed_row); - if ((sel.m_top == 0 && m_scroll_direction == TOP) && sel.count() > 1 || - (sel.m_bottom == m_model->count() - 1 && m_scroll_direction == DOWN && sel.count() > 1) - ) - return; - - if (row + 1 == m_first + m_rows && m_scroll_direction == DOWN) - (m_first + m_rows < m_model->count() ) ? m_first ++ : m_first; - else if (row == m_first && m_scroll_direction == TOP) - (m_first > 0) ? m_first -- : 0; - - m_model->moveItems(m_pressed_row,row); - m_prev_y = e->y(); - m_scroll = false; - m_pressed_row = row; - } -} - -void ListWidget::mouseReleaseEvent(QMouseEvent *e) -{ - if (FALSE != m_select_on_release) - { - m_model->clearSelection(); - m_model->setSelected(m_pressed_row,true); - //if(e->modifiers() != Qt::ShiftModifier) - m_anchor_row = m_pressed_row; - m_select_on_release = FALSE; - } - m_pressed_row = INVALID_ROW; - m_scroll_direction = NONE; - QWidget::mouseReleaseEvent(e); -} - -int ListWidget::rowAt( int y) const -{ - for (int i = 0; i < qMin(m_rows, m_model->count() - m_first); ++i ) - { - if ((y >= 2+i*m_metrics->ascent())&&(y < 2+(i+1)*m_metrics->ascent())) - return m_first + i; - } - return INVALID_ROW; -} - - -void ListWidget::contextMenuEvent(QContextMenuEvent * event) -{ - if (menu()) - menu()->exec(event->globalPos()); -} - -void ListWidget::recenterCurrent() -{ - if (!m_scroll) - { - if (m_first + m_rows < m_model->currentRow() + 1) - m_first = qMin(m_model->count() - m_rows, - m_model->currentRow() - m_rows/2 + 1); - else if (m_first > m_model->currentRow()) - m_first = qMax (m_model->currentRow() - m_rows/2 + 1, 0); - } -} - - diff --git a/src/listwidget.h b/src/listwidget.h deleted file mode 100644 index 2f20a3bf8..000000000 --- a/src/listwidget.h +++ /dev/null @@ -1,126 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef LISTWIDGET_H -#define LISTWIDGET_H - -#include -#include -#include - -/** - @author Ilya Kotov -*/ -class QFont; -class QFontMetrics; -class QMenu; -class QAction; - -class PlayList; -class PlayListModel; -class Skin; -class MediaFile; - -class ListWidget : public QWidget -{ - Q_OBJECT -public: - ListWidget(QWidget *parent = 0); - - ~ListWidget(); - - void setModel(PlayListModel *); - void readSettings(); - /*! - * Returns count of currently visible rows. - */ - int visibleRows()const{return m_rows;} - - /*! - * Returns number of first visible row. - */ - int firstVisibleRow()const{return m_first;} - - int getAnchorRow()const{return m_anchor_row;} - - void setAnchorRow(int r){m_anchor_row = r;} - -public slots: - void updateList(); - void scroll(int); //0-99 - void recenterCurrent(); - - QMenu *menu() - { - return m_menu; - }; - -signals: - void selectionChanged(); - void positionChanged(int, int); //current position, maximum value - -protected: - void paintEvent(QPaintEvent *); - void mouseDoubleClickEvent(QMouseEvent *); - void mousePressEvent(QMouseEvent *); - void mouseMoveEvent(QMouseEvent *); - void mouseReleaseEvent(QMouseEvent *); - void resizeEvent(QResizeEvent *); - void wheelEvent(QWheelEvent *); - int rowAt(int)const; - void dragEnterEvent(QDragEnterEvent *event); - void dropEvent(QDropEvent *event); - void contextMenuEvent ( QContextMenuEvent * event ); - -private slots: - void updateSkin(); - -private: - void cut(); - void loadColors(); - void processFileInfo(const QFileInfo&); - bool m_update; - bool m_scroll; - int m_pressed_row; - QMenu *m_menu; - PlayListModel *m_model; - int m_rows, m_first; - QList m_titles; - QList m_times; - PlayList *m_pl; - QFont m_font; - QFontMetrics *m_metrics; - Skin *m_skin; - QColor m_normal, m_current, m_normal_bg, m_selected_bg; - int m_anchor_row; - - enum ScrollDirection - { - NONE = 0,TOP,DOWN - }; - - /*! - * Scroll direction that is preforming in current moment. - */ - ScrollDirection m_scroll_direction; - int m_prev_y; - bool m_select_on_release; -}; - -#endif diff --git a/src/logscale.cpp b/src/logscale.cpp deleted file mode 100644 index 921004fd9..000000000 --- a/src/logscale.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2000-2001 Brad Hughes -// -// Use, modification and distribution is allowed without limitation, -// warranty, or liability of any kind. -// - -#include "logscale.h" - -#include -#include - - -LogScale::LogScale(int maxscale, int maxrange) - : indices(0), s(0), r(0) -{ - setMax(maxscale, maxrange); -} - - -LogScale::~LogScale() -{ - if (indices) - delete [] indices; -} - - -void LogScale::setMax(int maxscale, int maxrange) -{ - if (maxscale == 0 || maxrange == 0) - return; - - s = maxscale; - r = maxrange; - - if (indices) - delete [] indices; - - double alpha; - int i, scaled; - double domain = double(maxscale), - range = double(maxrange), - x = 1.0, - dx = 1.0, - y = 0.0, - yy = 0.0, - t = 0.0, - e4 = double(1.0E-8); - - indices = new int[maxrange]; - for (i = 0; i < maxrange; i++) - indices[i] = 0; - - // initialize log scale - while (fabs(dx) > e4) { - t = log((domain + x) / x); - y = (x * t) - range; - yy = t - (domain / (x + domain)); - dx = y / yy; - x -= dx; - } - - alpha = x; - for (i = 1; i < (int) domain; i++) { - scaled = (int) floor(0.5 + (alpha * log((double(i) + alpha) / alpha))); - if (indices[scaled - 1] < i) - indices[scaled - 1] = i; - } -} - - -int LogScale::operator[](int index) -{ - return indices[index]; -} diff --git a/src/logscale.h b/src/logscale.h deleted file mode 100644 index d74d25207..000000000 --- a/src/logscale.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) 2000-2001 Brad Hughes -// -// Use, modification and distribution is allowed without limitation, -// warranty, or liability of any kind. -// - -#ifndef __logscale_h -#define __logscale_h - - -class LogScale -{ -public: - LogScale(int = 0, int = 0); - ~LogScale(); - - int scale() const { return s; } - int range() const { return r; } - - void setMax(int, int); - - int operator[](int); - - -private: - int *indices; - int s, r; -}; - - -#endif // __logscale_h diff --git a/src/mainvisual.cpp b/src/mainvisual.cpp deleted file mode 100644 index 5bdcbf5cb..000000000 --- a/src/mainvisual.cpp +++ /dev/null @@ -1,628 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "skin.h" -#include "fft.h" -#include "inlines.h" -#include "mainvisual.h" - - -MainVisual *MainVisual::pointer = 0; - -MainVisual *MainVisual::getPointer() -{ - if ( !pointer ) - qFatal ( "MainVisual: this object not created!" ); - return pointer; -} - -MainVisual::MainVisual (QWidget *parent) - : Visual (parent), m_vis (0), m_playing (FALSE) -{ - m_draw = TRUE; - m_skin = Skin::getPointer(); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSettings())); - resize(75,20); - m_pixmap = QPixmap (75,20); - m_timer = new QTimer (this); - connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout())); - m_nodes.clear(); - createMenu(); - readSettings(); - pointer = this; -} - -MainVisual::~MainVisual() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - if (m_vis) - { - settings.setValue("Visualization/type",m_vis->name()); - delete m_vis; - m_vis = 0; - } - else - settings.setValue("Visualization/type", "None"); - settings.setValue("Visualization/rate", 1000/m_timer->interval()); - while (!m_nodes.isEmpty()) - delete m_nodes.takeFirst(); -} - -void MainVisual::setVisual (VisualBase *newvis) -{ - m_timer->stop(); - if (m_vis) - delete m_vis; - m_vis = newvis; - if (m_vis) - m_timer->start(); - else - { - m_pixmap.fill (Qt::transparent); - update(); - } -} - -void MainVisual::clear() -{ - while (!m_nodes.isEmpty()) - delete m_nodes.takeFirst(); - if (m_vis) - m_vis->clear(); - update(); -} - -void MainVisual::add ( Buffer *b, unsigned long w, int c, int p ) -{ - if (!m_timer->isActive () || !m_vis) - return; - long len = b->nbytes, cnt; - short *l = 0, *r = 0; - - len /= c; - len /= ( p / 8 ); - if ( len > 512 ) - len = 512; - cnt = len; - - if ( c == 2 ) - { - l = new short[len]; - r = new short[len]; - - if ( p == 8 ) - stereo16_from_stereopcm8 ( l, r, b->data, cnt ); - else if ( p == 16 ) - stereo16_from_stereopcm16 ( l, r, ( short * ) b->data, cnt ); - } - else if ( c == 1 ) - { - l = new short[len]; - - if ( p == 8 ) - mono16_from_monopcm8 ( l, b->data, cnt ); - else if ( p == 16 ) - mono16_from_monopcm16 ( l, ( short * ) b->data, cnt ); - } - else - len = 0; - - m_nodes.append ( new VisualNode ( l, r, len, w ) ); -} - -void MainVisual::timeout() -{ - VisualNode *node = 0; - - if ( /*playing &&*/ output()) - { - //output()->mutex()->lock (); - //long olat = output()->latency(); - //long owrt = output()->written(); - //output()->mutex()->unlock(); - - //long synctime = owrt < olat ? 0 : owrt - olat; - - mutex()->lock (); - VisualNode *prev = 0; - while ((!m_nodes.isEmpty())) - { - node = m_nodes.first(); - /*if ( node->offset > synctime ) - break;*/ - - if ( prev ) - delete prev; - m_nodes.removeFirst(); - - prev = node; - - } - mutex()->unlock(); - node = prev; - } - - if (m_vis) - m_vis->process ( node ); - delete node; - - if ( m_vis ) - { - if (m_draw) - drawBackGround(); - m_draw = FALSE; - m_pixmap = m_bg; - QPainter p(&m_pixmap); - m_vis->draw (&p); - } - else - m_pixmap.fill("Red"); - update(); -} - -void MainVisual::paintEvent ( QPaintEvent * ) -{ - QPainter painter ( this ); - painter.drawPixmap ( 0,0,m_pixmap ); -} - -void MainVisual::hideEvent ( QHideEvent *) -{ - m_timer->stop(); -} - -void MainVisual::showEvent ( QShowEvent *) -{ - if (m_vis) - m_timer->start(); -} - -void MainVisual::mousePressEvent (QMouseEvent *e) -{ - if (e->button() == Qt::RightButton) - m_menu->exec(e->globalPos()); - else - { - if (!m_vis) - setVisual(new mainvisual::Analyzer); - else if (m_vis->name() == "Analyzer") - setVisual(new mainvisual::Scope); - else if (m_vis->name() == "Scope") - setVisual(0); - - QString str = "Off"; - if (m_vis) - str = m_vis->name(); - foreach(QAction *act, m_visModeGroup->actions ()) - if (str == act->data().toString()) - { - act->setChecked(TRUE); - break; - } - } -} - -void MainVisual::drawBackGround() -{ - m_bg = QPixmap (75,20); - QPainter painter(&m_bg); - for (int x = 0; x < 75; x += 2) - { - painter.setPen(m_skin->getVisColor(0)); - painter.drawLine(x + 1, 0, x + 1, 20); - for (int y = 0; y < 20; y +=2) - { - painter.setPen(m_skin->getVisColor(0)); - painter.drawPoint(x,y); - painter.setPen(m_skin->getVisColor(1)); - painter.drawPoint(x,y + 1); - } - } -} - -void MainVisual::updateSettings() -{ - drawBackGround(); - m_pixmap = m_bg; - update(); - QAction *act = m_fpsGroup->checkedAction (); - if (act) - m_timer->setInterval (1000/act->data().toInt()); - else - m_timer->setInterval (40); - - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - act = m_peaksFalloffGroup->checkedAction (); - if (act) - settings.setValue("Visualization/peaks_falloff", act->data().toInt()); - else - settings.setValue("Visualization/peaks_falloff", 3); - - act = m_analyzerFalloffGroup->checkedAction (); - if (act) - settings.setValue("Visualization/analyzer_falloff", act->data().toInt()); - else - settings.setValue("Visualization/analyzer_falloff", 3); - - settings.setValue("Visualization/show_peaks", m_peaksAction->isChecked()); - - act = m_analyzerModeGroup->checkedAction(); - if (act) - settings.setValue("Visualization/analyzer_mode", act->data().toInt()); - else - settings.setValue("Visualization/analyzer_mode", 0); - - act = m_analyzerTypeGroup->checkedAction(); - if (act) - settings.setValue("Visualization/analyzer_type", act->data().toInt()); - else - settings.setValue("Visualization/analyzer_type", 1); - - act = m_visModeGroup->checkedAction (); - QString visName; - if (act) - visName = act->data().toString(); - else - visName == "Off"; - - if (visName == "Analyzer") - setVisual(new mainvisual::Analyzer); - else if (visName == "Scope") - setVisual(new mainvisual::Scope); - else - setVisual(0); - -} - -void MainVisual::createMenu() -{ - m_menu = new QMenu (this); - connect(m_menu, SIGNAL(triggered (QAction *)),SLOT(updateSettings())); - QMenu *visMode = m_menu->addMenu(tr("Visualization Mode")); - m_visModeGroup = new QActionGroup(this); - m_visModeGroup->setExclusive(TRUE); - m_visModeGroup->addAction(tr("Analyzer"))->setData("Analyzer"); - m_visModeGroup->addAction(tr("Scope"))->setData("Scope"); - m_visModeGroup->addAction(tr("Off"))->setData("Off"); - foreach(QAction *act, m_visModeGroup->actions ()) - { - act->setCheckable(TRUE); - visMode->addAction(act); - } - - QMenu *analyzerMode = m_menu->addMenu(tr("Analyzer Mode")); - m_analyzerModeGroup = new QActionGroup(this); - m_analyzerTypeGroup = new QActionGroup(this); - m_analyzerModeGroup->addAction(tr("Normal"))->setData(0); - m_analyzerModeGroup->addAction(tr("Fire"))->setData(1); - m_analyzerModeGroup->addAction(tr("Vertical Lines"))->setData(2); - m_analyzerTypeGroup->addAction(tr("Lines"))->setData(0); - m_analyzerTypeGroup->addAction(tr("Bars"))->setData(1); - foreach(QAction *act, m_analyzerModeGroup->actions ()) - { - act->setCheckable(TRUE); - analyzerMode->addAction(act); - } - analyzerMode->addSeparator (); - foreach(QAction *act, m_analyzerTypeGroup->actions ()) - { - act->setCheckable(TRUE); - analyzerMode->addAction(act); - } - analyzerMode->addSeparator (); - m_peaksAction = analyzerMode->addAction(tr("Peaks")); - m_peaksAction->setCheckable(TRUE); - - - QMenu *refreshRate = m_menu->addMenu(tr("Refresh Rate")); - m_fpsGroup = new QActionGroup(this); - m_fpsGroup->setExclusive(TRUE); - m_fpsGroup->addAction(tr("50 fps"))->setData(50); - m_fpsGroup->addAction(tr("25 fps"))->setData(25); - m_fpsGroup->addAction(tr("10 fps"))->setData(10); - m_fpsGroup->addAction(tr("5 fps"))->setData(5); - foreach(QAction *act, m_fpsGroup->actions ()) - { - act->setCheckable(TRUE); - refreshRate->addAction(act); - } - - QMenu *analyzerFalloff = m_menu->addMenu(tr("Analyzer Falloff")); - m_analyzerFalloffGroup = new QActionGroup(this); - m_analyzerFalloffGroup->setExclusive(TRUE); - m_analyzerFalloffGroup->addAction(tr("Slowest"))->setData(1); - m_analyzerFalloffGroup->addAction(tr("Slow"))->setData(2); - m_analyzerFalloffGroup->addAction(tr("Medium"))->setData(3); - m_analyzerFalloffGroup->addAction(tr("Fast"))->setData(4); - m_analyzerFalloffGroup->addAction(tr("Fastest"))->setData(5); - foreach(QAction *act, m_analyzerFalloffGroup->actions ()) - { - act->setCheckable(TRUE); - analyzerFalloff->addAction(act); - } - - QMenu *peaksFalloff = m_menu->addMenu(tr("Peaks Falloff")); - m_peaksFalloffGroup = new QActionGroup(this); - m_peaksFalloffGroup->setExclusive(TRUE); - m_peaksFalloffGroup->addAction(tr("Slowest"))->setData(1); - m_peaksFalloffGroup->addAction(tr("Slow"))->setData(2); - m_peaksFalloffGroup->addAction(tr("Medium"))->setData(3); - m_peaksFalloffGroup->addAction(tr("Fast"))->setData(4); - m_peaksFalloffGroup->addAction(tr("Fastest"))->setData(5); - foreach(QAction *act, m_peaksFalloffGroup->actions ()) - { - act->setCheckable(TRUE); - peaksFalloff->addAction(act); - } - update(); -} - - -void MainVisual::readSettings() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - - QString name = settings.value("Visualization/type","Analyzer").toString(); - m_visModeGroup->actions ()[0]->setChecked(TRUE); - foreach(QAction *act, m_visModeGroup->actions ()) - if (name == act->data().toString()) - act->setChecked(TRUE); - - m_peaksAction->setChecked( - settings.value("Visualization/show_peaks", TRUE).toBool()); - - int fps = settings.value("Visualization/rate", 25).toInt(); - m_fpsGroup->actions ()[1]->setChecked(TRUE); - foreach(QAction *act, m_fpsGroup->actions ()) - if (fps == act->data().toInt()) - act->setChecked(TRUE); - - int mode = settings.value("Visualization/analyzer_mode", 0).toInt(); - m_analyzerModeGroup->actions ()[0]->setChecked(TRUE); - foreach(QAction *act, m_analyzerModeGroup->actions ()) - if (mode == act->data().toInt()) - act->setChecked(TRUE); - - int type = settings.value("Visualization/analyzer_type", 1).toInt(); - m_analyzerTypeGroup->actions ()[1]->setChecked(TRUE); - foreach(QAction *act, m_analyzerTypeGroup->actions ()) - if (type == act->data().toInt()) - act->setChecked(TRUE); - - int speed = settings.value("Visualization/peaks_falloff", 3).toInt(); - m_peaksFalloffGroup->actions ()[2]->setChecked(TRUE); - foreach(QAction *act, m_peaksFalloffGroup->actions ()) - if (speed == act->data().toInt()) - act->setChecked(TRUE); - - speed = settings.value("Visualization/analyzer_falloff", 3).toInt(); - m_analyzerFalloffGroup->actions ()[2]->setChecked(TRUE); - foreach(QAction *act, m_analyzerFalloffGroup->actions ()) - if (speed == act->data().toInt()) - act->setChecked(TRUE); - - updateSettings(); -} - -using namespace mainvisual; - -Analyzer::Analyzer() - : m_analyzerBarWidth ( 4 ), m_fps ( 20 ) -{ - m_size = QSize(75,20); - clear(); - m_skin = Skin::getPointer(); - - double peaks_speed[] = { 0.05, 0.1, 0.2, 0.4, 0.8 }; - double analyzer_speed[] = { 1.2, 1.8, 2.2, 2.8, 2.4 }; - - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - m_peaks_falloff = - peaks_speed[settings.value("Visualization/peaks_falloff", 3).toInt()-1]; - m_analyzer_falloff = - analyzer_speed[settings.value("Visualization/analyzer_falloff", 3).toInt()-1]; - m_show_peaks = settings.value("Visualization/show_peaks", TRUE).toBool(); - - m_lines = settings.value("Visualization/analyzer_type", 1).toInt() == 0; - m_mode = settings.value("Visualization/analyzer_mode", 0).toInt(); -} - -Analyzer::~Analyzer() -{} - -void Analyzer::clear() -{ - for ( int i = 0; i< 75; ++i ) - { - m_intern_vis_data[i] = 0; - m_peaks[i] = 0; - } -} - -bool Analyzer::process ( VisualNode *node ) -{ - static fft_state *state = 0; - if ( !state ) - state = fft_init(); - short dest[256]; - - const int xscale_long[] = - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55, 56, 57, 58, 61, 66, 71, 76, 81, 87, 93, 100, 107, - 114, 122, 131, 140, 150, 161, 172, 184, 255 - }; - - const int xscale_short[] = - { - 0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 15, 20, 27, - 36, 47, 62, 82, 107, 141, 184, 255 - }; - - if ( node ) - { - //i = node->length; - calc_freq ( dest, node->left ); - } - else - return FALSE; - const double y_scale = 3.60673760222; /* 20.0 / log(256) */ - int max = m_lines ? 75 : 19, y, j; - - for ( int i = 0; i < max; i++ ) - { - if (m_lines) - for ( j = xscale_long[i], y = 0; j < xscale_long[i + 1]; j++ ) - { - if ( dest[j] > y ) - y = dest[j]; - } - else - for ( j = xscale_short[i], y = 0; j < xscale_short[i + 1]; j++ ) - { - if ( dest[j] > y ) - y = dest[j]; - } - y >>= 7; - int magnitude = 0; - if ( y != 0 ) - { - magnitude = int(log (y) * y_scale); - if ( magnitude > 15 ) - magnitude = 15; - if ( magnitude < 0 ) - magnitude = 0; - } - - m_intern_vis_data[i] -= m_analyzer_falloff; - m_intern_vis_data[i] = magnitude > m_intern_vis_data[i] - ? magnitude : m_intern_vis_data[i]; - if (m_show_peaks) - { - m_peaks[i] -= m_peaks_falloff; - m_peaks[i] = magnitude > m_peaks[i] - ? magnitude : m_peaks[i]; - } - } - return TRUE; -} - -void Analyzer::draw ( QPainter *p) -{ - if (m_lines) - for ( int j = 0; j < 75; ++j ) - { - for ( int i = 0; i <= m_intern_vis_data[j]; ++i ) - { - if (m_mode == 0) - p->setPen (m_skin->getVisColor (18-i)); - else if (m_mode == 1) - p->setPen (m_skin->getVisColor (3+(int(m_intern_vis_data[j])-i))); - else - p->setPen (m_skin->getVisColor (18-int(m_intern_vis_data[j]))); - p->drawPoint (j, m_size.height()-i); - } - p->setPen (m_skin->getVisColor (23)); - if (m_show_peaks) - p->drawPoint (j, m_size.height()-int(m_peaks[j])); - } - else - for (int j = 0; j < 19; ++j) - { - for (int i = 0; i <= m_intern_vis_data[j]; ++i) - { - if (m_mode == 0) - p->setPen (m_skin->getVisColor (18-i)); - else if (m_mode == 1) - p->setPen (m_skin->getVisColor (3+(int(m_intern_vis_data[j])-i))); - else - p->setPen (m_skin->getVisColor (18-int(m_intern_vis_data[j]))); - p->drawLine (j*4,m_size.height()-i, (j+1)*4-2,m_size.height()-i); - } - p->setPen (m_skin->getVisColor (23)); - if (m_show_peaks) - p->drawLine (j*4,m_size.height()-int(m_peaks[j]), - (j+1) *4-2,m_size.height()-int(m_peaks[j])); - } -} - -Scope::Scope() -{ - clear(); - m_skin = Skin::getPointer(); -} - -void Scope::clear() -{ - for (int i = 0; i< 75; ++i) - m_intern_vis_data[i] = 7; -} - -Scope::~Scope() -{} - -bool Scope::process(VisualNode *node) -{ - if (!node) - return FALSE; - - int step = (node->length << 8)/74; - int pos = 0; - - for (int i = 0; i < 75; ++i) - { - pos += step; - m_intern_vis_data[i] = (node->left[pos >> 8] >> 12); - - if (m_intern_vis_data[i] > 5) - m_intern_vis_data[i] = 5; - else if (m_intern_vis_data[i] < -5) - m_intern_vis_data[i] = -5; - } - return TRUE; -} - -void Scope::draw(QPainter *p) -{ - for ( int i = 0; i<73; ++i ) - { - int h1 = 10 - m_intern_vis_data[i]; - int h2 = 10 - m_intern_vis_data[i+1]; - if (h1 > h2) - qSwap(h1, h2); - p->setPen (m_skin->getVisColor(19 + (10 - h2)/2 )); - p->drawLine(i, h1, i, h2); - } - for ( int i = 0; i< 75; ++i ) - m_intern_vis_data[i] = 0; -} diff --git a/src/mainvisual.h b/src/mainvisual.h deleted file mode 100644 index 5c5b76256..000000000 --- a/src/mainvisual.h +++ /dev/null @@ -1,172 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef MAINVISUAL_H -#define MAINVISUAL_H - -#include -#include -#include -#include - -#include "logscale.h" - -class QSettings; -class QTimer; -class QMenu; -class QActionGroup; - -class Buffer; - - -class VisualNode -{ -public: - VisualNode(short *l, short *r, unsigned long n, unsigned long o) - : left(l), right(r), length(n), offset(o) - { - // left and right are allocated and then passed to this class - // the code that allocated left and right should give up all ownership - } - - ~VisualNode() - { - delete [] left; - delete [] right; - } - - short *left, *right; - long length, offset; -}; - -class VisualBase -{ -public: - virtual ~VisualBase() - {}; - virtual void clear() = 0; - virtual bool process(VisualNode *node) = 0; - virtual void draw(QPainter *) = 0; - virtual const QString name() = 0; -}; - -class Skin; - -class MainVisual : public Visual -{ - Q_OBJECT - -public: - MainVisual( QWidget *parent = 0); - virtual ~MainVisual(); - - static MainVisual *getPointer(); - - void setVisual( VisualBase *newvis ); - - void add(Buffer *, unsigned long, int, int); - void clear(); - void paintEvent(QPaintEvent *); - -protected: - virtual void hideEvent (QHideEvent *); - virtual void showEvent (QShowEvent *); - virtual void mousePressEvent (QMouseEvent *); - -public slots: - void timeout(); - -private slots: - void updateSettings(); - -private: - void drawBackGround(); - void createMenu(); - void readSettings(); - static MainVisual *pointer; - VisualBase *m_vis; - QPixmap m_pixmap; - QPixmap m_bg; - QList m_nodes; - QTimer *m_timer; - bool m_playing; - bool m_draw; - Skin *m_skin; - //menu and actions - QMenu *m_menu; - //action groups - QActionGroup *m_visModeGroup; - QActionGroup *m_fpsGroup; - QActionGroup *m_peaksFalloffGroup; - QActionGroup *m_analyzerFalloffGroup; - QActionGroup *m_analyzerModeGroup; - QActionGroup *m_analyzerTypeGroup; - QAction *m_peaksAction; -}; - -namespace mainvisual -{ -class Analyzer : public VisualBase -{ -public: - Analyzer(); - virtual ~Analyzer(); - - void clear(); - bool process(VisualNode *node); - void draw(QPainter *p); - const QString name() - { - return "Analyzer"; - }; - -private: - QSize m_size; - int m_analyzerBarWidth, m_fps; - double m_intern_vis_data[75]; - double m_peaks[75]; - double m_peaks_falloff; - double m_analyzer_falloff; - bool m_show_peaks; - bool m_lines; - int m_mode; - Skin *m_skin; -}; - -class Scope : public VisualBase -{ -public: - Scope(); - virtual ~Scope(); - - void clear(); - bool process(VisualNode *node); - void draw(QPainter *p); - const QString name() - { - return "Scope"; - }; - -private: - int m_intern_vis_data[75]; - Skin *m_skin; -}; -} - -#endif diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp deleted file mode 100644 index 2d54df4d3..000000000 --- a/src/mainwindow.cpp +++ /dev/null @@ -1,819 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include -#include - -#include - -#include - -#include "textscroller.h" -#include "mainwindow.h" -#include "constants.h" -#include "fileloader.h" -#include "skin.h" -#include "playlist.h" -#include "playlistmodel.h" -#include "configdialog.h" -#include "dock.h" -#include "eqwidget.h" -#include "mainvisual.h" -#include "playlistformat.h" -#include "jumptotrackdialog.h" -#include "aboutdialog.h" -#include -#include "filedialog.h" -#include "listwidget.h" -#include "visualmenu.h" - -#define KEY_OFFSET 10 - -MainWindow::MainWindow(const QStringList& args, QWidget *parent) - : QMainWindow(parent) -{ - m_vis = 0; - seeking = FALSE; - m_update = FALSE; - m_paused = FALSE; - m_elapsed = 0; - - setWindowIcon( QIcon(":/qmmp.xpm") ); - - m_skin = new Skin(this); - Dock *dock = new Dock(this); - dock->setMainWidget(this); - - setWindowFlags(Qt::FramelessWindowHint); - setFixedSize (275,116); - - display = new MainDisplay(this); - setCentralWidget(display); - display->show(); - display->setFocus (); - - m_playlistName = tr("Default"); - - m_playlist = new PlayList(this); - - connect (m_playlist,SIGNAL(next()),SLOT(next())); - connect (m_playlist,SIGNAL(prev()),SLOT(previous())); - connect (m_playlist,SIGNAL(play()),SLOT(play())); - connect (m_playlist,SIGNAL(pause()),SLOT(pause())); - connect (m_playlist,SIGNAL(stop()),SLOT(stop())); - connect (m_playlist,SIGNAL(eject()),SLOT(addFile())); - - connect (m_playlist,SIGNAL(newPlaylist()),SLOT(newPlaylist())); - connect (m_playlist,SIGNAL(loadPlaylist()),SLOT(loadPlaylist())); - connect (m_playlist,SIGNAL(savePlaylist()),SLOT(savePlaylist())); - - m_playListModel = new PlayListModel(this); - - connect(display,SIGNAL(shuffleToggled(bool)),m_playListModel,SLOT(prepareForShufflePlaying(bool))); - connect(display,SIGNAL(repeatableToggled(bool)),m_playListModel,SLOT(prepareForRepeatablePlaying(bool))); - - dock->addWidget(m_playlist); - - m_equalizer = new EqWidget(this); - dock->addWidget(m_equalizer); - connect(m_equalizer, SIGNAL(valueChanged()), SLOT(updateEQ())); - - m_playlist->setModel(m_playListModel); - - m_jumpDialog = new JumpToTrackDialog(this); - m_jumpDialog->setModel(m_playListModel); - connect(m_jumpDialog,SIGNAL(playRequest()),this,SLOT(play())); - m_jumpDialog->hide(); - - createActions(); - - m_core = new SoundCore(this); - m_titlebar = new TitleBar(this); - m_titlebar->move(0,0); - m_titlebar->show(); - m_titlebar->setActive(TRUE); - - m_tray = new QSystemTrayIcon( this ); - m_tray->setIcon ( QIcon(":/stop.png") ); - m_tray->setContextMenu( m_mainMenu ); - connect(m_tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason))); - - readSettings(); - dock->updateDock(); - - display->setEQ(m_equalizer); - display->setPL(m_playlist); - - m_vis = MainVisual::getPointer(); - - m_core->addVisualization(m_vis); - m_core->showVisualization(this); - - connect(m_core, SIGNAL(outputStateChanged(const OutputState&)), - SLOT(showOutputState(const OutputState&))); - connect(m_core, SIGNAL(decoderStateChanged(const DecoderState&)), - SLOT(showDecoderState(const DecoderState&))); - connect(m_core, SIGNAL(titleChanged(const QString&)), - SLOT(changeTitle(const QString&))); - - connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); - updateEQ(); - updateSkin(); - - FileDialog::registerBuiltinFactories(); - FileDialog::registerExternalFactories(); - - m_playListModel->readSettings(); - char buf[PATH_MAX + 1]; - QString cwd = QString::fromLocal8Bit(getcwd(buf,PATH_MAX)); - processCommandArgs(args,cwd); -} - - -MainWindow::~MainWindow() -{ - stop(); -} - -void MainWindow::play() -{ - m_playListModel->doCurrentVisibleRequest(); - - if (m_core->isPaused()) - { - pause(); - return; - } - stop(); - if (m_playListModel->count() == 0) - return; - - m_equalizer->loadPreset(m_playListModel->currentItem()->fileName()); - m_playListModel->currentItem()->updateTags(); - m_playlist->listWidget()->updateList(); - QString s = m_playListModel->currentItem()->path(); - if (s.isEmpty()) - return; - if (m_core->play(s)) - { - display->setTime(0); - display->setMaxTime(m_core->length()); - } - else - { - //find out the reason why the playback failed - switch ((int) m_core->error()) - { - case SoundCore::OutputError: - { - stop(); - return; //unrecovable error in output, so abort playing - } - case SoundCore::DecoderError: - { - //error in decoder, so we should try to play next song - qApp->processEvents(); - if (!m_playListModel->isEmptyQueue()) - { - m_playListModel->setCurrentToQueued(); - } - else if (!m_playListModel->next()) - { - stop(); - display->hideTimeDisplay(); - return; - } - m_playlist->update(); - play(); - break; - } - } - } -} - -void MainWindow::replay() -{ - stop(); - play(); -} - -void MainWindow::seek(int pos) -{ - if (!seeking) - m_core->seek(pos); -} - - -void MainWindow::forward() -{ - seek(m_elapsed + KEY_OFFSET); -} - -void MainWindow::backward() -{ - seek(qMax(0,m_elapsed - KEY_OFFSET)); -} - -void MainWindow::setVolume(int volume, int balance) -{ - m_core->setVolume(volume-qMax(balance,0)*volume/100, - volume+qMin(balance,0)*volume/100); -} - -void MainWindow::pause(void) -{ - m_core->pause(); -} - -void MainWindow::stop() -{ - display->setTime(0); - m_core->stop(); -} -void MainWindow::next() -{ - if (!m_playListModel->isEmptyQueue()) - { - m_playListModel->setCurrentToQueued(); - } - else if (!m_playListModel->next()) - { - stop(); - display->hideTimeDisplay(); - return; - } - m_playlist->update(); - if (m_core->isInitialized()) - { - stop(); - m_elapsed = 0; - play(); - } - else - display->hideTimeDisplay(); -} -void MainWindow::previous() -{ - if (!m_playListModel->previous()) - { - display->hideTimeDisplay(); - return; - } - - m_playlist->update(); - if (m_core->isInitialized()) - { - stop(); - play(); - } - else - display->hideTimeDisplay(); -} - -void MainWindow::updateEQ() -{ - int b[10]; - for (int i=0; i<10; ++i) - b[i] = m_equalizer->gain(i); - m_core->setEQ(b, m_equalizer->preamp()); - m_core->setEQEnabled(m_equalizer->isEQEnabled()); -} - -void MainWindow::showOutputState(const OutputState &st) - -{ - if (seeking) - return; - - display->setInfo(st); - m_playlist->setInfo(st, m_core->length(), m_playListModel->totalLength()); - m_titlebar->setInfo(st); - m_equalizer->setInfo(st); - switch ((int) st.type()) - { - case OutputState::Playing: - { - m_tray->setIcon ( QIcon(":/play.png") ); - if (m_showMessage && m_playListModel->currentItem()) - m_tray->showMessage ( tr("Now Playing"), - m_playListModel->currentItem()->title(), - QSystemTrayIcon::Information, m_messageDelay ); - if (m_showToolTip && m_playListModel->currentItem()) - m_tray->setToolTip (m_playListModel->currentItem()->title()); - break; - } - case OutputState::Paused: - { - m_tray->setIcon ( QIcon(":/pause.png") ); - break; - } - case OutputState::Stopped: - { - m_tray->setIcon ( QIcon(":/stop.png") ); - break; - } - case OutputState::Info: - { - m_elapsed = st.elapsedSeconds(); - } - } - -} -void MainWindow::showDecoderState(const DecoderState &st) -{ - switch ((int) st.type()) - { - case DecoderState::Finished: - { - next(); - break; - } - case DecoderState::Info: - { - qDebug("file info:"); - qDebug("ARTIST = %s", qPrintable(st.tag()->artist())); - qDebug("TITLE = %s", qPrintable(st.tag()->title())); - qDebug("ALBUM = %s", qPrintable(st.tag()->album())); - qDebug("COMMENT = %s", qPrintable(st.tag()->comment())); - qDebug("GENRE = %s", qPrintable(st.tag()->genre())); - qDebug("YEAR = %d", st.tag()->year()); - qDebug("TRACK = %d", st.tag()->track()); - qDebug("LENGTH = %d", st.tag()->length()); - - m_playlist->currentItem()->updateTags(st.tag()); - m_playlist->listWidget()->updateList(); - break; - } - } -} - -void MainWindow::changeTitle(const QString &title) -{ - m_playlist->currentItem()->changeTitle(title); - m_playlist->listWidget()->updateList(); -} - -void MainWindow::closeEvent ( QCloseEvent *) -{ - writeSettings(); - m_playlist->close(); - m_equalizer->close(); - QApplication::quit (); -} - -void MainWindow::addDir() -{ - /* - QString s = QFileDialog::getExistingDirectory( - this, - tr("Choose a directory"), - m_lastDir, - QFileDialog::DontResolveSymlinks | QFileDialog::ShowDirsOnly); - - if (s.isEmpty()) - return; - m_playListModel->addDirectory(s); - m_lastDir = s+"../"; - */ - if (FileDialog::isModal()) - { - qWarning("void MainWindow::addDir()"); - QString s = FileDialog::getExistingDirectory(this,tr("Choose a directory"),m_lastDir); - - if (s.isEmpty()) - return; - m_playListModel->addDirectory(s); - m_lastDir = s+"../"; - } - else - FileDialog::popup(m_playListModel,m_lastDir,FileDialog::AddDirs,Decoder::nameFilters()); -} - -void MainWindow::addFile() -{ - /* - QStringList files = QFileDialog::getOpenFileNames( - this, - tr("Select one or more files to open"), - m_lastDir, - Decoder::filter()); - if (files.isEmpty ()) - return; - - // foreach(QString s, files) - // m_playListModel->load(new MediaFile(s)); - - m_playListModel->addFiles(files); - m_lastDir = files.at(0); - */ - - - if (FileDialog::isModal()) - { - QStringList files = FileDialog::getOpenFileNames( - this, - tr("Select one or more files to open"), - m_lastDir, - Decoder::filter()); - if (files.isEmpty ()) - return; - /* - foreach(QString s, files) - m_playListModel->load(new MediaFile(s)); - */ - m_playListModel->addFiles(files); - m_lastDir = files.at(0); - } - else - FileDialog::popup(m_playListModel,m_lastDir,FileDialog::AddFiles,Decoder::nameFilters()); - -} - -void MainWindow::clear() -{ - m_playListModel->clear(); -} - -void MainWindow::startSeek() -{ - seeking = TRUE; -} - -void MainWindow::endSeek() -{ - seeking = FALSE; -} - -void MainWindow::changeEvent (QEvent * event) -{ - if (event->type() == QEvent::ActivationChange) - { - m_titlebar->setActive(isActiveWindow()); - } -} - -void MainWindow::readSettings() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - if (!m_update) - { - settings.beginGroup("MainWindow"); - //geometry - move(settings.value("pos", QPoint(100, 100)).toPoint()); - //last directory - m_lastDir = settings.value("last_dir","/").toString(); - settings.endGroup(); - show(); - //visibility - m_playlist->setVisible(settings.value("Playlist/visible",TRUE).toBool()); - m_equalizer->setVisible(settings.value("Equalizer/visible",TRUE).toBool()); - bool val = settings.value("Playlist/repeatable",FALSE).toBool(); - - // Repeat/Shuffle - m_playListModel->prepareForRepeatablePlaying(val); - display->setIsRepeatable(val); - val = settings.value("Playlist/shuffle",FALSE).toBool(); - display->setIsShuffle(val); - m_playListModel->prepareForShufflePlaying(val); - - // Playlist name - m_playlistName = settings.value("Playlist/playlist_name","Default").toString(); - - m_update = TRUE; - } - //tray - settings.beginGroup("Tray"); - m_tray->setVisible(settings.value("enabled",TRUE).toBool()); - m_showMessage = settings.value("show_message",TRUE).toBool(); - m_messageDelay = settings.value("message_delay",2000).toInt(); - m_showToolTip = settings.value("show_tooltip", FALSE).toBool(); - m_hide_on_titlebar_close = settings.value("hide_on_close",FALSE).toBool(); - if (!m_showToolTip) - m_tray->setToolTip(QString()); - settings.endGroup(); - -} - -void MainWindow::writeSettings() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - settings.beginGroup("MainWindow"); - //geometry - settings.setValue("pos", this->pos()); - //last directory - settings.setValue("last_dir",m_lastDir); - settings.endGroup(); - - // Repeat/Shuffle - settings.beginGroup("Playlist"); - settings.setValue("repeatable",display->isRepeatable()); - settings.setValue("shuffle",display->isShuffle()); - - // Playlist name - settings.setValue("playlist_name",m_playlistName); - settings.endGroup(); -} - -void MainWindow::showSettings() -{ - m_confDialog = new ConfigDialog(this); - if (m_confDialog->exec() == QDialog::Accepted) - { - readSettings(); - m_playlist->readSettings(); - TextScroller::getPointer()->readSettings(); - m_core->updateConfig(); - m_visMenu->updateActions(); - } - delete m_confDialog; -} - -void MainWindow::toggleVisibility() -{ - if (isHidden()) - { - show(); - m_playlist->setVisible(display->isPlaylistVisible()); - m_equalizer->setVisible(display->isEqualizerVisible()); - if (isMinimized()) - { - if (isMaximized()) - showMaximized(); - else - showNormal(); - } - raise(); - activateWindow(); - } - else - { - hide(); - if (m_playlist->isVisible()) - m_playlist->hide(); - if (m_equalizer->isVisible()) - m_equalizer->hide(); - } -} - -void MainWindow::trayActivated(QSystemTrayIcon::ActivationReason reason) -{ - if (reason == QSystemTrayIcon::Trigger) - toggleVisibility(); -} - -void MainWindow::createActions() -{ - m_mainMenu = new QMenu(this); - m_mainMenu->addAction(tr("&Play"),this, SLOT(play()), tr("X")); - m_mainMenu->addAction(tr("&Pause"),this, SLOT(pause()), tr("C")); - m_mainMenu->addAction(tr("&Stop"),this, SLOT(stop()), tr("V")); - m_mainMenu->addAction(tr("&Previous"),this, SLOT(previous()), tr("Z")); - m_mainMenu->addAction(tr("&Next"),this, SLOT(next()), tr("B")); - m_mainMenu->addAction(tr("&Queue"),m_playListModel, SLOT(addToQueue()), tr("Q")); - m_mainMenu->addSeparator(); - m_mainMenu->addAction(tr("&Jump To File"),this, SLOT(jumpToFile()), tr("J")); - m_mainMenu->addSeparator(); - m_visMenu = new VisualMenu(this); - m_mainMenu->addMenu(m_visMenu); - - m_mainMenu->addSeparator(); - m_mainMenu->addAction(tr("&Settings"),this, SLOT(showSettings()), tr("Ctrl+P")); - m_mainMenu->addSeparator(); - m_mainMenu->addAction(tr("&About"),this, SLOT(about())); - Dock::getPointer()->addActions(m_mainMenu->actions()); - m_mainMenu->addSeparator(); - m_mainMenu->addAction(tr("&Exit"),this, SLOT(close ()), tr("Ctrl+Q")); - - QAction* forward = new QAction(this); - forward->setShortcut(QKeySequence(Qt::Key_Right)); - connect(forward,SIGNAL(triggered(bool)),this,SLOT(forward())); - QAction* backward = new QAction(this); - backward->setShortcut(QKeySequence(Qt::Key_Left)); - connect(backward,SIGNAL(triggered(bool)),this,SLOT(backward())); - - Dock::getPointer()->addActions( QList() << forward << backward ); - Dock::getPointer()->addActions(m_mainMenu->actions()); -} - - -void MainWindow::about() -{ - AboutDialog dlg(this); - dlg.exec(); -} - -QMenu* MainWindow::menu() -{ - return m_mainMenu; -} - -void MainWindow::updateSkin() -{ - clearMask(); - m_equalizer->clearMask(); - /*qt bug workarround */ - setMask(QRegion(0,0,275,116)); - m_equalizer->setMask(QRegion(0,0,275,116)); - update(); - m_equalizer->update(); - - QRegion region = m_skin->getMWRegion(); - if (!region.isEmpty()) - setMask(region); - - region = m_skin->getPLRegion(); - if (!region.isEmpty()) - m_equalizer->setMask(region); -} - -void MainWindow::newPlaylist() -{ - m_playListModel->clear(); - m_playlistName = tr("Default"); -} - -void MainWindow::loadPlaylist() -{ - QStringList l; - QList p_list = m_playListModel->registeredPlaylistFormats(); - if (!p_list.isEmpty()) - { - foreach(PlaylistFormat* fmt,p_list) - l << fmt->getExtensions(); - - QString mask = tr("Playlist Files")+" (" + l.join(" *.").prepend("*.") + ")"; - if (FileDialog::isModal()) - { - //qWarning("Modal"); - QString f_name = FileDialog::getOpenFileName(this,tr("Open Playlist"),m_lastDir,mask); - if (!f_name.isEmpty()) - { - m_playListModel->loadPlaylist(f_name); - m_playlistName = QFileInfo(f_name).baseName(); - } - m_lastDir = QFileInfo(f_name).absoluteDir().path(); - } - else //FileDialog::popup(m_playListModel,m_lastDir,FileDialog::AddFiles,Decoder::nameFilters()); - // TODO: implement playlist loading with nonmodal dialogs - // For now we'll use default dialog - { - //qWarning("Modal"); - QString f_name = FileDialog::getOpenFileName(this,tr("Open Playlist"),m_lastDir,mask,0,true); - if (!f_name.isEmpty()) - { - m_playListModel->loadPlaylist(f_name); - m_playlistName = QFileInfo(f_name).baseName(); - } - m_lastDir = QFileInfo(f_name).absoluteDir().path(); - } - } - else - { - //qWarning("Non Modal"); - qWarning("Error: There is no registered playlist parsers"); - } -} - -void MainWindow::savePlaylist() -{ - QStringList l; - QList p_list = m_playListModel->registeredPlaylistFormats(); - if (!p_list.isEmpty()) - { - foreach(PlaylistFormat* fmt,p_list) - l << fmt->getExtensions(); - - QString mask = tr("Playlist Files")+" (" + l.join(" *.").prepend("*.") + ")"; - if (FileDialog::isModal()) - { - QString f_name = FileDialog::getSaveFileName(this, tr("Save Playlist"),m_lastDir + "/" + - m_playlistName + "." + l[0],mask); - - if (!f_name.isEmpty()) - { - m_playListModel->savePlaylist(f_name); - m_playlistName = QFileInfo(f_name).baseName(); - } - m_lastDir = QFileInfo(f_name).absoluteDir().path(); - } - else // TODO: implement saving playlists with nonmodal dialogs - // For now we'll use default dialog - { - QString f_name = FileDialog::getSaveFileName(this, tr("Save Playlist"),m_lastDir + "/" + - m_playlistName + "." + l[0],mask,0,true); - - if (!f_name.isEmpty()) - { - m_playListModel->savePlaylist(f_name); - m_playlistName = QFileInfo(f_name).baseName(); - } - m_lastDir = QFileInfo(f_name).absoluteDir().path(); - } - } - else - qWarning("Error: There is no registered playlist parsers"); -} - -void MainWindow::setFileList(const QStringList & l) -{ - if (!m_playListModel->setFileList(l)) - addFile(); -} - -void MainWindow::playPause() -{ - if (m_core->isInitialized()) - pause(); - else - play(); -} - -bool MainWindow::processCommandArgs(const QStringList &slist,const QString& cwd) -{ - if (slist.count() > 0) - { - QString str = slist[0]; - if (str.startsWith("--")) // is it a command? - { - if (str == "--play") - play(); - else if (str == "--stop") - { - stop(); - display->hideTimeDisplay(); - } - else if (str == "--pause") - pause(); - else if (str == "--next") - { - next(); - if(!m_core->isInitialized()) - play(); - } - else if (str == "--previous") - { - previous(); - if(!m_core->isInitialized()) - play(); - } - else if (str == "--play-pause") - playPause(); - else - return false; - } - else// maybe it is a list of files or dirs - { - QStringList full_path_list; - foreach(QString s,slist) - { - if (s.left(1) == "/") //is it absolute path? - full_path_list << s; - else - full_path_list << cwd + "/" + s; - } - setFileList(full_path_list); - } - } - return true; -} - -void MainWindow::jumpToFile() -{ - if (m_jumpDialog->isHidden()) - { - m_jumpDialog->show(); - m_jumpDialog->refresh(); - } -} - -void MainWindow::handleCloseRequest() -{ - if (m_hide_on_titlebar_close && m_tray->isVisible()) - toggleVisibility(); - else - QApplication::closeAllWindows(); -} - -void MainWindow::addUrl( ) -{ - AddUrlDialog::popup(this,m_playListModel); -} diff --git a/src/mainwindow.h b/src/mainwindow.h deleted file mode 100644 index 97caed52a..000000000 --- a/src/mainwindow.h +++ /dev/null @@ -1,140 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include - -#include "output.h" -#include "decoder.h" -#include "display.h" -#include "mediafile.h" -#include "decoderfactory.h" -#include "titlebar.h" - -/** - @author Ilya Kotov -*/ -class PlayList; -class PlayListModel; -class ConfigDialog; -class EqWidget; -class MainVisual; -class Skin; -class SoundCore; -class JumpToTrackDialog; -class VisualMenu; - -class QMenu; -class QKeyEvent; - - - -class MainWindow : public QMainWindow -{ - Q_OBJECT -public: - MainWindow(const QStringList& args, QWidget *parent); - - ~MainWindow(); - - PlayList *getPLPointer() - { - return m_playlist; - } - - void seek(int); - QMenu* menu(); - void setVolume(int volume, int balance); - - bool processCommandArgs(const QStringList &slist,const QString& cwd); - -public slots: - void previous(); - void play(); - void pause(); - void playPause(); - void stop(); - void next(); - void replay(); - - void newPlaylist(); - void loadPlaylist(); - void savePlaylist(); - - void setFileList(const QStringList&); - -protected: - virtual void closeEvent ( QCloseEvent *); - virtual void changeEvent ( QEvent * event ); - -private slots: - void showOutputState(const OutputState&); - void showDecoderState(const DecoderState&); - void changeTitle(const QString&); - void clear(); - void startSeek(); - void endSeek(); - void showSettings(); - void addDir(); - void addFile(); - void addUrl(); - void updateEQ(); - void updateSkin(); - void forward(); - void backward(); - void jumpToFile(); - void toggleVisibility(); - void trayActivated(QSystemTrayIcon::ActivationReason); - void about(); - void handleCloseRequest(); - -private: - void readSettings(); - void writeSettings(); - void createActions(); - bool seeking; - SoundCore *m_core; - QMenu *m_mainMenu; - MainDisplay *display; - PlayList *m_playlist; - PlayListModel *m_playListModel; - TitleBar *m_titlebar; - ConfigDialog *m_confDialog; - int m_preamp; - EqWidget *m_equalizer; - MainVisual *m_vis; - QString m_lastDir; - QSystemTrayIcon *m_tray; - bool m_update; - bool m_showMessage; - int m_messageDelay; - bool m_paused; - bool m_showToolTip; - Skin *m_skin; - QString m_playlistName; - JumpToTrackDialog* m_jumpDialog; - bool m_hide_on_titlebar_close; - int m_elapsed; - VisualMenu *m_visMenu; -}; - -#endif diff --git a/src/mediafile.cpp b/src/mediafile.cpp deleted file mode 100644 index 24b6ce174..000000000 --- a/src/mediafile.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include - -#include - -#include "mediafile.h" - -MediaFile::MediaFile(const QString& path) : m_flag(FREE) -{ - m_selected = FALSE; - m_current = FALSE; - m_path = path; - m_tag = 0; - - QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); - m_use_meta = settings.value ("PlayList/load_metadata", TRUE).toBool(); - //format - m_format = settings.value("PlayList/title_format", "%p - %t").toString(); - if (m_use_meta && !path.startsWith("http://")) - { - m_tag = Decoder::createTag(path); - readMetadata(); - } - else - m_title = m_path.startsWith("http://") ? m_path: m_path.section('/',-1); -} - - -MediaFile::~MediaFile() -{ - if (m_tag) - delete m_tag; -} - -const QString MediaFile::path()const -{ - return m_path; -} -const QString MediaFile::fileName() const -{ - return m_path.section('/',-1); -} - -const QString MediaFile::title() const -{ - return m_title; -} - -int MediaFile::length() const -{ - if (m_tag) - return m_tag->length(); - else - return 0; -} - -void MediaFile::setSelected(bool yes) -{ - m_selected = yes; -} - -bool MediaFile::isSelected() const -{ - return m_selected; -} - -uint MediaFile::year() const -{ - return m_year; -} - -bool MediaFile::isCurrent() -{ - return m_current; -} - -void MediaFile::setCurrent(bool cur) -{ - m_current = cur; -} - -void MediaFile::updateTags(const FileTag *tag) -{ - if (m_tag) - { - delete m_tag; - m_tag = 0; - } - if (!tag->isEmpty()) - m_tag = new FileTag(*tag); - readMetadata(); -} - -void MediaFile::updateTags() -{ - if (m_path.startsWith("http://")) - return; - if (m_tag) - { - delete m_tag; - m_tag = 0; - } - m_tag = Decoder::createTag(m_path); - readMetadata(); -} - -void MediaFile::readMetadata() -{ - if (m_use_meta && m_tag && !m_tag->isEmpty()) - { - m_year = m_tag->year(); - m_title = m_format; - m_title.replace("%p",m_tag->artist()); - m_title.replace("%a",m_tag->album()); - m_title.replace("%t",m_tag->title()); - m_title.replace("%n",QString("%1").arg(m_tag->track())); - m_title.replace("%g",m_tag->genre ()); - m_title.replace("%f",m_path.section('/',-1)); - m_title.replace("%F",m_path); - //m_title.replace("%d",); - m_title.replace("%y",QString("%1").arg(m_tag->year ())); - //m_title.replace("%c",); - } - else - m_title = m_path.startsWith("http://") ? m_path: m_path.section('/',-1); -} - -void MediaFile::changeTitle(const QString &newtitle) -{ - m_title = newtitle; -} - -void MediaFile::setFlag(FLAGS f) -{ - m_flag = f; -} - - -MediaFile::FLAGS MediaFile::flag() const -{ - return m_flag; -} - diff --git a/src/mediafile.h b/src/mediafile.h deleted file mode 100644 index 7adab6603..000000000 --- a/src/mediafile.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef MEDIAFILE_H -#define MEDIAFILE_H - -#include - -class FileTag; -/** - @author Ilya Kotov -*/ - - -class MediaFile -{ -public: - /*! - * Current state of media file. - * FREE - instance is free and may be deleted - * EDITING - instance is currently busy in some kind of operation(tags editing etc.) - * and can't be deleted at the moment. Set flag SCHEDULED_FOR_DELETION for it - * instead of delete operator call. - */ - enum FLAGS{FREE = 0,EDITING,SCHEDULED_FOR_DELETION}; - - MediaFile() : m_flag(FREE) - {}; - MediaFile(const QString&); - - ~MediaFile(); - - const QString path()const; - const QString title()const; - const QString fileName()const; - uint year()const; - int length()const; - void setSelected(bool); - bool isSelected()const; - bool isCurrent(); - void setCurrent(bool); - void updateTags(const FileTag*); - void updateTags(); - void changeTitle(const QString&); - FLAGS flag()const; - void setFlag(FLAGS); - -private: - void readMetadata(); - QString m_path; - QString m_title; - uint m_year; - FileTag *m_tag; - bool m_selected; - bool m_current; - bool m_use_meta; - QString m_format; - FLAGS m_flag; - -}; - -#endif diff --git a/src/monostereo.cpp b/src/monostereo.cpp deleted file mode 100644 index 659fec7be..000000000 --- a/src/monostereo.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include - -#include "skin.h" -#include "monostereo.h" - -MonoStereo::MonoStereo ( QWidget *parent ) - : PixmapWidget ( parent ) -{ - m_skin = Skin::getPointer(); - m_pixmap = QPixmap ( 54,12 ); - setChannels ( 0 ); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); -} - - -MonoStereo::~MonoStereo() -{} - -void MonoStereo::setChannels ( int c ) -{ - m_channels = c; - QPainter paint ( &m_pixmap ); - switch ( ( int ) c ) - { - case 0: - { - paint.drawPixmap ( 0,0,m_skin->getMSPart ( Skin::MONO_I ) ); - paint.drawPixmap ( 27,0,m_skin->getMSPart ( Skin::STEREO_I ) ); - break; - } - case 1: - { - paint.drawPixmap ( 0,0,m_skin->getMSPart ( Skin::MONO_A ) ); - paint.drawPixmap ( 27,0,m_skin->getMSPart ( Skin::STEREO_I ) ); - break; - } - } - if ( c > 1 ) - { - paint.drawPixmap ( 0,0,m_skin->getMSPart ( Skin::MONO_I ) ); - paint.drawPixmap ( 27,0,m_skin->getMSPart ( Skin::STEREO_A ) ); - } - setPixmap ( m_pixmap ); -} - -void MonoStereo::updateSkin() -{ - setChannels ( m_channels ); -} diff --git a/src/monostereo.h b/src/monostereo.h deleted file mode 100644 index be1419c5c..000000000 --- a/src/monostereo.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef MONOSTEREO_H -#define MONOSTEREO_H - -#include - -/** - @author Ilya Kotov -*/ -class Skin; - -class MonoStereo : public PixmapWidget -{ -Q_OBJECT -public: - MonoStereo(QWidget *parent = 0); - - ~MonoStereo(); - - void setChannels(int); - -private slots: - void updateSkin(); - -private: - Skin *m_skin; - QPixmap m_pixmap; - int m_channels; - -}; - -#endif diff --git a/src/mp3player.cpp b/src/mp3player.cpp deleted file mode 100644 index cf6b27535..000000000 --- a/src/mp3player.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ - - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include - -#include "mainwindow.h" -#include "playlist.h" -#include "qmmpstarter.h" - -int main(int argc, char *argv[]) -{ - QApplication a (argc, argv ); - QTranslator translator; - QString locale = QLocale::system().name(); - translator.load(QString(":/qmmp_") + locale); - a.installTranslator(&translator); - - QMMPStarter starter(argc,argv); - Q_UNUSED(starter) - - return a.exec(); -} diff --git a/src/number.cpp b/src/number.cpp deleted file mode 100644 index 9f127965e..000000000 --- a/src/number.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "number.h" -#include "skin.h" - -Number::Number(QWidget *parent) - : PixmapWidget(parent) -{ - m_skin = Skin::getPointer(); - //TODO default value?? - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); -} - - -Number::~Number() -{ -} - -void Number::setValue(int n) -{ - setPixmap(m_skin->getNumber(n)); - m_value = n; -} - -void Number::updateSkin(void) -{ - setValue(m_value); -} diff --git a/src/number.h b/src/number.h deleted file mode 100644 index 1c89f71d4..000000000 --- a/src/number.h +++ /dev/null @@ -1,49 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef NUMBER_H -#define NUMBER_H - -#include "pixmapwidget.h" - -/** - @author Ilya Kotov -*/ -class Skin; - -class Number : public PixmapWidget -{ -Q_OBJECT -public: - Number(QWidget *parent = 0); - - ~Number(); - - void setValue(int); - -private slots: - void updateSkin(void); - -private: - Skin *m_skin; - int m_value; - -}; - -#endif diff --git a/src/pixmapwidget.cpp b/src/pixmapwidget.cpp deleted file mode 100644 index a0f4ff7fd..000000000 --- a/src/pixmapwidget.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include - -#include "pixmapwidget.h" - -PixmapWidget::PixmapWidget(QWidget *parent) - : QWidget(parent) -{} - - -PixmapWidget::~PixmapWidget() -{} - -void PixmapWidget::setPixmap(const QPixmap pixmap) -{ - m_pixmap = pixmap; - resize(m_pixmap.size()); - update(); -} - -void PixmapWidget::paintEvent ( QPaintEvent *) -{ - QPainter paint(this); - paint.drawPixmap(0,0, m_pixmap); -} - diff --git a/src/pixmapwidget.h b/src/pixmapwidget.h deleted file mode 100644 index 24d34260e..000000000 --- a/src/pixmapwidget.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef PIXMAPWIDGET_H -#define PIXMAPWIDGET_H - -#include - -/** - @author Ilya Kotov -*/ -class QPixmap; - -class PixmapWidget : public QWidget -{ -Q_OBJECT -public: - PixmapWidget(QWidget *parent = 0); - - ~PixmapWidget(); - - virtual void setPixmap(const QPixmap); - -protected: - void paintEvent ( QPaintEvent * event ); - -private: - QPixmap m_pixmap; - - - -}; - -#endif diff --git a/src/playlist.cpp b/src/playlist.cpp deleted file mode 100644 index 282463ef0..000000000 --- a/src/playlist.cpp +++ /dev/null @@ -1,471 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include -#include -#include -#include - -#include "dock.h" -#include "fileloader.h" -#include "playlist.h" -#include "skin.h" -#include "listwidget.h" -#include "button.h" -#include "mediafile.h" -#include "playlistmodel.h" -#include "playlisttitlebar.h" -#include "playlistslider.h" -#include "pixmapwidget.h" -#include "symboldisplay.h" -#include "playlistcontrol.h" -#include "keyboardmanager.h" -#include - -PlayList::PlayList ( QWidget *parent ) - : QWidget ( parent ) -{ - setWindowFlags ( Qt::Dialog | Qt::FramelessWindowHint ); - - m_update = FALSE; - m_resize = FALSE; - m_anchor_row = -1; - - createMenus(); - - - resize ( 275,116 ); - setMinimumSize ( 275,116 ); - setBaseSize ( 275,116 ); - m_listWidget = new ListWidget ( this ); - m_listWidget->show(); - m_listWidget->setGeometry ( 12,20,243,58 ); - - m_plslider = new PlayListSlider ( this ); - m_plslider->show(); - - setSizeIncrement ( 25,29 ); - m_skin = Skin::getPointer(); - - m_buttonAdd = new Button ( this,Skin::PL_BT_ADD,Skin::PL_BT_ADD ); - m_buttonAdd->move ( 11,86 ); - m_buttonSub = new Button ( this,Skin::PL_BT_SUB,Skin::PL_BT_SUB ); - m_buttonSub->move ( 40,86 ); - m_selectButton = new Button ( this,Skin::PL_BT_SEL,Skin::PL_BT_SEL ); - m_selectButton->move ( 70,86 ); - m_sortButton= new Button ( this,Skin::PL_BT_SORT,Skin::PL_BT_SORT ); - m_sortButton->move ( 99,86 ); - m_playlistButton = new Button ( this,Skin::PL_BT_LST,Skin::PL_BT_LST ); - - m_pl_control = new PlaylistControl ( this ); - m_pl_control->move ( 0,0 ); - m_pl_control->show(); - - m_length_totalLength = new SymbolDisplay ( this,14 ); - m_length_totalLength->setAlignment ( Qt::AlignLeft ); - m_length_totalLength -> show(); - - m_current_time = new SymbolDisplay ( this,6 ); - m_current_time->show(); - - m_keyboardManager = new KeyboardManager ( this ); - - connect ( m_listWidget, SIGNAL ( selectionChanged() ), parent, SLOT ( replay() ) ); - - connect ( m_plslider, SIGNAL ( sliderMoved ( int ) ), m_listWidget, SLOT ( scroll ( int ) ) ); - connect ( m_listWidget, SIGNAL ( positionChanged ( int, int ) ), m_plslider, - SLOT ( setPos ( int, int ) ) ); - connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT ( update() ) ); - connect ( m_buttonAdd, SIGNAL ( clicked() ), SLOT ( showAddMenu() ) ); - connect ( m_buttonSub, SIGNAL ( clicked() ), SLOT ( showSubMenu() ) ); - connect ( m_selectButton, SIGNAL ( clicked() ), SLOT ( showSelectMenu() ) ); - connect ( m_sortButton, SIGNAL ( clicked() ), SLOT ( showSortMenu() ) ); - connect ( m_playlistButton, SIGNAL ( clicked() ), SLOT ( showPlaylistMenu() ) ); - - connect ( m_pl_control, SIGNAL ( nextClicked() ), SIGNAL ( next() ) ); - connect ( m_pl_control, SIGNAL ( previousClicked() ), SIGNAL ( prev() ) ); - connect ( m_pl_control, SIGNAL ( playClicked() ), SIGNAL ( play() ) ); - connect ( m_pl_control, SIGNAL ( pauseClicked() ), SIGNAL ( pause() ) ); - connect ( m_pl_control, SIGNAL ( stopClicked() ), SIGNAL ( stop() ) ); - connect ( m_pl_control, SIGNAL ( ejectClicked() ), SIGNAL ( eject() ) ); - m_titleBar = new PlayListTitleBar ( this ); - m_titleBar->move ( 0,0 ); - readSettings(); -} - - -PlayList::~PlayList() -{} - -void PlayList::createMenus() -{ - m_addMenu = new QMenu ( this ); - m_subMenu = new QMenu ( this ); - m_selectMenu = new QMenu ( this ); - m_sortMenu = new QMenu ( this ); - m_playlistMenu = new QMenu ( this ); -} - -void PlayList::createActions() -{ //add menu - QAction *addFileAct = new QAction ( tr ( "&Add File" ),this ); - addFileAct->setShortcut ( tr ( "F" ) ); - m_addMenu->addAction ( addFileAct ); - connect ( addFileAct, SIGNAL ( triggered() ), parent(), SLOT ( addFile () ) ); - m_actions << addFileAct; - - QAction *addDirAct = new QAction ( tr ( "&Add Directory" ),this ); - addDirAct->setShortcut ( tr ( "D" ) ); - m_addMenu->addAction ( addDirAct ); - connect ( addDirAct, SIGNAL ( triggered() ), parent(), SLOT ( addDir () ) ); - m_actions << addDirAct; - - QAction *addUrlAct = new QAction ( tr ( "&Add Url" ),this ); - addUrlAct->setShortcut ( tr ( "U" ) ); - m_addMenu->addAction ( addUrlAct ); - connect ( addUrlAct, SIGNAL ( triggered() ), parent(), SLOT ( addUrl () ) ); - m_actions << addUrlAct; - - //remove menu - QAction *remSelAct = new QAction ( tr ( "&Remove Selected" ),this ); - remSelAct->setShortcut ( tr ( "Del" ) ); - m_subMenu->addAction ( remSelAct ); - connect ( remSelAct, SIGNAL ( triggered() ), - m_playListModel, SLOT ( removeSelected () ) ); - this->addAction ( remSelAct ); - - QAction *remAllAct = new QAction ( tr ( "&Remove All" ),this ); - //remAllAct->setShortcut(tr("D")); FIXME: add correct shortcat - m_subMenu->addAction ( remAllAct ); - connect ( remAllAct, SIGNAL ( triggered() ), m_playListModel, SLOT ( clear () ) ); - m_actions << remAllAct; - - QAction *remUnselAct = new QAction ( tr ( "&Remove Unselected" ),this ); - m_subMenu->addAction ( remUnselAct ); - connect ( remUnselAct, SIGNAL ( triggered() ), - m_playListModel, SLOT ( removeUnselected () ) ); - - //listwidget menu - QAction *detailsAct = new QAction ( tr ( "&View Track Details" ),this ); - detailsAct->setShortcut ( tr ( "Alt+I" ) ); - m_listWidget->menu()->addAction ( detailsAct ); - connect ( detailsAct, SIGNAL ( triggered() ), m_playListModel, SLOT ( showDetails () ) ); - - // sort menu - m_sortMenu->addAction ( detailsAct ); - m_sortMenu->addSeparator(); - - QMenu* sort_mode_menu = new QMenu ( tr ( "Sort List" ),m_sortMenu ); - - QSignalMapper* signalMapper = new QSignalMapper ( this ); - QAction* titleAct = sort_mode_menu->addAction ( tr ( "By Title" ) ); - connect ( titleAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); - signalMapper->setMapping ( titleAct, PlayListModel::TITLE ); - - QAction* nameAct = sort_mode_menu->addAction ( tr ( "By Filename" ) ); - connect ( nameAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); - signalMapper->setMapping ( nameAct, PlayListModel::FILENAME ); - - QAction* pathnameAct = sort_mode_menu->addAction ( tr ( "By Path + Filename" ) ); - connect ( pathnameAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); - signalMapper->setMapping ( pathnameAct, PlayListModel::PATH_AND_FILENAME ); - - QAction* dateAct = sort_mode_menu->addAction ( tr ( "By Date" ) ); - connect ( dateAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); - signalMapper->setMapping ( dateAct, PlayListModel::DATE ); - - connect ( signalMapper, SIGNAL ( mapped ( int ) ), - m_playListModel, SLOT ( sort ( int ) ) ); - - m_sortMenu->addMenu ( sort_mode_menu ); - - sort_mode_menu = new QMenu ( tr ( "Sort Selection" ),m_sortMenu ); - signalMapper = new QSignalMapper ( this ); - titleAct = sort_mode_menu->addAction ( tr ( "By Title" ) ); - connect ( titleAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); - signalMapper->setMapping ( titleAct, PlayListModel::TITLE ); - - nameAct = sort_mode_menu->addAction ( tr ( "By Filename" ) ); - connect ( nameAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); - signalMapper->setMapping ( nameAct, PlayListModel::FILENAME ); - - pathnameAct = sort_mode_menu->addAction ( tr ( "By Path + Filename" ) ); - connect ( pathnameAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); - signalMapper->setMapping ( pathnameAct, PlayListModel::PATH_AND_FILENAME ); - - dateAct = sort_mode_menu->addAction ( tr ( "By Date" ) ); - connect ( dateAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); - signalMapper->setMapping ( dateAct, PlayListModel::DATE ); - - connect ( signalMapper, SIGNAL ( mapped ( int ) ), - m_playListModel, SLOT ( sortSelection ( int ) ) ); - - m_sortMenu->addMenu ( sort_mode_menu ); - - m_sortMenu->addSeparator(); - m_sortMenu->addAction ( tr ( "Randomize List" ),m_playListModel,SLOT ( randomizeList() ) ); - m_sortMenu->addAction ( tr ( "Reverse List" ),m_playListModel,SLOT ( reverseList() ) ); - - m_listWidget->menu()->addSeparator(); - m_listWidget->menu()->addActions ( m_subMenu->actions() ); - m_actions << detailsAct; - - //select menu - QAction *invSelAct = new QAction ( tr ( "Invert Selection" ),this ); - m_selectMenu->addAction ( invSelAct ); - connect ( invSelAct, SIGNAL ( triggered() ), - m_playListModel, SLOT ( invertSelection () ) ); - - m_selectMenu->addSeparator(); - - QAction *selNoneAct = new QAction ( tr ( "&Select None" ),this ); - //selNoneAct->setShortcut(tr("Ctrl+Shift+A")); - m_selectMenu->addAction ( selNoneAct ); - connect ( selNoneAct, SIGNAL ( triggered() ), - m_playListModel, SLOT ( clearSelection () ) ); - this->addAction ( selNoneAct ); - - QAction *selAllAct = new QAction ( tr ( "&Select All" ),this ); - selAllAct->setShortcut ( tr ( "Ctrl+A" ) ); - m_selectMenu->addAction ( selAllAct ); - connect ( selAllAct, SIGNAL ( triggered() ), - m_playListModel, SLOT ( selectAll () ) ); - this->addAction ( selAllAct ); - -// Playlist Menu - QAction *newListAct = new QAction ( tr ( "&New List" ),this ); - newListAct->setShortcut ( tr ( "Shift+N" ) ); - m_actions << newListAct; - m_playlistMenu->addAction ( newListAct ); - connect ( newListAct, SIGNAL ( triggered() ), this, SIGNAL ( newPlaylist() ) ); - m_playlistMenu->addSeparator(); - - QAction *loadListAct = new QAction ( tr ( "&Load List" ),this ); - loadListAct->setShortcut ( tr ( "O" ) ); - m_playlistMenu->addAction ( loadListAct ); - connect ( loadListAct, SIGNAL ( triggered() ), this, SIGNAL ( loadPlaylist() ) ); - - QAction *saveListAct = new QAction ( tr ( "&Save List" ),this ); - saveListAct->setShortcut ( tr ( "Shift+S" ) ); - m_playlistMenu->addAction ( saveListAct ); - connect ( saveListAct, SIGNAL ( triggered() ), this, SIGNAL ( savePlaylist() ) ); - this->addActions ( m_playlistMenu->actions() ); - - Dock::getPointer()->addActions ( m_actions ); -} - -void PlayList::closeEvent ( QCloseEvent* ) -{ - writeSettings(); -} - -void PlayList::paintEvent ( QPaintEvent * ) -{ - int m_sx = ( width()-275 ) /25; - int m_sy = ( height()-116 ) /29; - drawPixmap ( m_sx, m_sy ); -} - -void PlayList::drawPixmap ( int sx, int sy ) -{ - QPainter paint; - paint.begin ( this ); - paint.drawPixmap ( 0,20,m_skin->getPlPart ( Skin::PL_LFILL ) ); - for ( int i = 1; igetPlPart ( Skin::PL_LFILL ) ); - } - paint.drawPixmap ( 0,78+29*sy,m_skin->getPlPart ( Skin::PL_LSBAR ) ); - for ( int i = 0; igetPlPart ( Skin::PL_SFILL1 ) ); - } - - paint.drawPixmap ( 125+sx*25,78+sy*29,m_skin->getPlPart ( Skin::PL_RSBAR ) ); - paint.end(); - -} - -void PlayList::resizeEvent ( QResizeEvent *e ) -{ - int sx = ( e->size().width()-275 ) /25; - int sy = ( e->size().height()-116 ) /29; - if (sx < 0 || sy < 0) - return; - - m_titleBar->resize ( 275+25*sx,20 ); - m_plslider->resize ( 20,58+sy*29 ); - - m_listWidget->resize ( 243+25*sx,58+29*sy ); - - m_buttonAdd->move ( 11,86+29*sy ); - m_buttonSub->move ( 40,86+29*sy ); - m_selectButton->move ( 70,86+29*sy ); - m_sortButton->move ( 99,86+29*sy ); - - m_pl_control->move ( 128+sx*25,100+29*sy ); - m_playlistButton->move ( 228+sx*25,86+29*sy ); - - m_length_totalLength -> move ( 131+sx*25,88+29*sy ); - m_current_time->move ( 190+sx*25,101+29*sy ); - - m_plslider->move ( 255+sx*25,20 ); -} -void PlayList::mousePressEvent ( QMouseEvent *e ) -{ - m_pos = e->pos (); - if ( ( m_pos.x() > width()-25 ) && ( m_pos.y() > height()-25 ) ) - { - m_resize = TRUE; - setCursor ( Qt::SizeFDiagCursor ); - } - else - m_resize = FALSE; -} -void PlayList::mouseMoveEvent ( QMouseEvent *e ) -{ - if ( m_resize ) - { - resize ( e->x() +25, e->y() +25 ); - //usleep(32000); - } -} -void PlayList::mouseReleaseEvent ( QMouseEvent * ) -{ - setCursor ( Qt::ArrowCursor ); - /*if (m_resize) - m_listWidget->updateList();*/ - m_resize = FALSE; - Dock::getPointer()->updateDock(); -} -void PlayList::setModel ( PlayListModel *model ) -{ - m_playListModel = model; - m_listWidget->setModel (model); - m_keyboardManager->setModel (model); - m_titleBar->setModel (model); - createActions(); -} - -void PlayList::changeEvent ( QEvent * event ) -{ - if ( event->type() == QEvent::ActivationChange ) - { - m_titleBar->setActive ( isActiveWindow() ); - } -} - -void PlayList::readSettings() -{ - if ( m_update ) - { - m_listWidget->readSettings(); - m_titleBar->readSettings(); - } - else - { - QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); - settings.beginGroup ( "PlayList" ); - //position - move ( settings.value ("pos", QPoint ( 100, 332 ) ).toPoint()); - settings.endGroup(); - m_update = TRUE; - } - -} - -void PlayList::writeSettings() -{ - QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); - settings.beginGroup ( "PlayList" ); - //position - settings.setValue ( "pos", this->pos() ); - settings.endGroup(); -} - -void PlayList::showAddMenu() -{ - m_addMenu->exec ( m_buttonAdd->mapToGlobal ( QPoint ( 0,0 ) ) ); -} - -void PlayList::showSubMenu() -{ - m_subMenu->exec ( m_buttonSub->mapToGlobal ( QPoint ( 0,0 ) ) ); -} - -void PlayList::showSelectMenu() -{ - m_selectMenu->exec ( m_selectButton->mapToGlobal ( QPoint ( 0,0 ) ) ); -} - -void PlayList::showSortMenu() -{ - m_sortMenu->exec ( m_sortButton->mapToGlobal ( QPoint ( 0,0 ) ) ); -} - - - -QString PlayList::formatTime ( int sec ) -{ - int minutes = sec / 60; - int seconds = sec % 60; - - QString str_minutes = QString::number ( minutes ); - QString str_seconds = QString::number ( seconds ); - - if ( minutes < 10 ) str_minutes.prepend ( "0" ); - if ( seconds < 10 ) str_seconds.prepend ( "0" ); - - return str_minutes + ":" + str_seconds; -} - -void PlayList::setInfo (const OutputState &st,int length_current, int length_total) -{ - if ( st.type() == OutputState::Info ) - { - m_current_time->display ( formatTime ( st.elapsedSeconds() ) ); - m_current_time->update(); - - QString str_length = formatTime ( length_current ) + "/" + formatTime ( length_total ); - m_length_totalLength->display ( str_length ); - m_length_totalLength->update(); - } -} - -MediaFile *PlayList::currentItem() -{ - if ( m_playListModel ) - return m_playListModel->currentItem(); - else - return 0; -} - -void PlayList::showPlaylistMenu() -{ - m_playlistMenu->exec ( m_playlistButton->mapToGlobal ( QPoint ( 0,0 ) ) ); -} - -void PlayList::keyPressEvent ( QKeyEvent *ke ) -{ - if ( m_keyboardManager->handleKeyPress ( ke ) ) - update(); -} diff --git a/src/playlist.h b/src/playlist.h deleted file mode 100644 index 4e8bdc1f8..000000000 --- a/src/playlist.h +++ /dev/null @@ -1,124 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef PLAYLIST_H -#define PLAYLIST_H - -#include - -class KeyboardManager; - -/** - @author Ilya Kotov -*/ - -class QMenu; - -class Skin; -class ListWidget; -class MediaFile; -class Button; -class PlayListModel; -class PlayListTitleBar; -class PlayListSlider; -class MainWindow; -class SymbolDisplay; -class OutputState; -class PixmapWidget; -class PlaylistControl; - -class PlayList : public QWidget -{ - Q_OBJECT - public: - PlayList ( QWidget *parent = 0 ); - - ~PlayList(); - void load ( MediaFile * ); - void setModel ( PlayListModel * ); - void readSettings(); - void setInfo ( const OutputState &,int,int ); - MediaFile *currentItem(); - ListWidget* listWidget() const{return m_listWidget;} - - signals: - void play(); - void next(); - void prev(); - void pause(); - void stop(); - void eject(); - void loadPlaylist(); - void savePlaylist(); - void newPlaylist(); - void closed(); - - private slots: - void showAddMenu(); - void showSubMenu(); - void showSelectMenu(); - void showSortMenu(); - void showPlaylistMenu(); - - - private: - QString formatTime ( int sec ); - void drawPixmap ( int, int ); - void writeSettings(); - void createMenus(); - void createActions(); - QMenu *m_addMenu; - QMenu *m_subMenu; - QMenu *m_selectMenu; - QMenu *m_sortMenu; - QMenu *m_playlistMenu; - Button *m_buttonAdd; - Button *m_buttonSub; - Button *m_selectButton; - Button *m_sortButton; - Button* m_playlistButton; - - PlaylistControl* m_pl_control; - SymbolDisplay* m_length_totalLength; - SymbolDisplay* m_current_time; - - Skin *m_skin; - ListWidget *m_listWidget; - PlayListModel *m_playListModel; - PlayListTitleBar *m_titleBar; - PlayListSlider *m_plslider; - QList m_actions; - QPoint m_pos; - bool m_resize; - bool m_update; - int m_anchor_row; - KeyboardManager* m_keyboardManager; - - protected: - virtual void paintEvent ( QPaintEvent * ); - virtual void resizeEvent ( QResizeEvent * ); - virtual void mouseMoveEvent ( QMouseEvent * ); - virtual void mousePressEvent ( QMouseEvent * ); - virtual void mouseReleaseEvent ( QMouseEvent * ); - virtual void changeEvent ( QEvent* ); - virtual void closeEvent ( QCloseEvent* ); - virtual void keyPressEvent ( QKeyEvent* ); -}; - -#endif diff --git a/src/playlistcontrol.cpp b/src/playlistcontrol.cpp deleted file mode 100644 index 8f111fe4e..000000000 --- a/src/playlistcontrol.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include - -#include "playlistcontrol.h" -#include "skin.h" - -PlaylistControl::PlaylistControl(QWidget* parent) : PixmapWidget(parent) -{ - m_skin = Skin::getPointer(); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(update())); -} - -void PlaylistControl::paintEvent(QPaintEvent *) -{ - QPainter painter(this); - painter.drawPixmap(0,0,m_skin->getPlPart(Skin::PL_CONTROL)); -} - -void PlaylistControl::mouseReleaseEvent(QMouseEvent *me) -{ - QPoint pt = me->pos(); - if(QRect(4,1,7,7).contains(pt)) - emit previousClicked(); - else if(QRect(12,1,7,7).contains(pt)) - emit playClicked(); - else if(QRect(21,1,7,7).contains(pt)) - emit pauseClicked(); - else if(QRect(31,1,7,7).contains(pt)) - emit stopClicked(); - else if(QRect(40,1,7,7).contains(pt)) - emit nextClicked(); - else if(QRect(49,1,7,7).contains(pt)) - emit ejectClicked(); -} diff --git a/src/playlistcontrol.h b/src/playlistcontrol.h deleted file mode 100644 index 26c3871d4..000000000 --- a/src/playlistcontrol.h +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ - - /** - @author Vladimir Kuznetsov - */ - -#ifndef _PALYLISTCONTROL_H -#define _PALYLISTCONTROL_H - -#include "pixmapwidget.h" - -class PaintEvent; -class Skin; -class QMouseEvent; - -class PlaylistControl : public PixmapWidget -{ -Q_OBJECT -public: - PlaylistControl(QWidget* parent = 0); - void paintEvent(QPaintEvent*); - void mouseReleaseEvent(QMouseEvent*); -signals: - void previousClicked(); - void nextClicked(); - void pauseClicked(); - void playClicked(); - void stopClicked(); - void ejectClicked(); -protected: - Skin* m_skin; -}; - -#endif diff --git a/src/playlistformat.cpp b/src/playlistformat.cpp deleted file mode 100644 index 505805c88..000000000 --- a/src/playlistformat.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2006 by Ilya Kotov * -* forkotov02@hotmail.ru * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License for more details. * -* * -* You should have received a copy of the GNU General Public License * -* along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -#ifndef XSPF_PLUGIN - #include - #include - #include - #include "version.h" -#endif - -#include "playlistformat.h" - -#include "mediafile.h" - -bool PLSPlaylistFormat::hasFormat(const QString & f) -{ - foreach(QString s,m_supported_formats) - if(f == s) - return true; - - return false; -} - -QStringList PLSPlaylistFormat::getExtensions() const -{ - return m_supported_formats; -} - -PLSPlaylistFormat::PLSPlaylistFormat() -{ - m_supported_formats << "pls"; -} - -QString PLSPlaylistFormat::name() const -{ - return "PLSPlaylistFormat"; -} - - -QStringList PLSPlaylistFormat::decode(const QString & contents) -{ - QStringList out; - QStringList splitted = contents.split("\n"); - if(!splitted.isEmpty()) - { - if(splitted.takeAt(0).toLower().contains("[playlist]")) - { - foreach(QString str, splitted) - { - if(str.startsWith("File")) - { - QString unverified = str.remove(0,str.indexOf(QChar('=')) + 1); - if(QFileInfo(unverified).exists()) - out << QFileInfo(unverified).absoluteFilePath(); - else - qWarning("File %s does not exist",unverified.toLocal8Bit().data()); - } - } - return out; - } - } - else - qWarning("Error parsing PLS format"); - - return QStringList(); -} - -QString PLSPlaylistFormat::encode(const QList< MediaFile * > & contents) -{ - QStringList out; - out << QString("[playlist]"); - int counter = 1; - foreach(MediaFile* f,contents) - { - QString begin = "File" + QString::number(counter) + "="; - out.append(begin + f->path()); - begin = "Title" + QString::number(counter) + "="; - out.append(begin + f->title()); - begin = "Length" + QString::number(counter) + "="; - out.append(begin + QString::number(f->length())); - counter ++; - } - out << "NumberOfEntries=" + QString::number(contents.count()); - return out.join("\n"); -} - - - - -bool M3UPlaylistFormat::hasFormat(const QString & f) -{ - foreach(QString s,m_supported_formats) - if(f == s) - return true; - - return false; -} - -QStringList M3UPlaylistFormat::getExtensions() const -{ - return m_supported_formats; -} - -M3UPlaylistFormat::M3UPlaylistFormat() -{ - m_supported_formats << "m3u"; -} - -QStringList M3UPlaylistFormat::decode(const QString & contents) -{ - QStringList out; - QStringList splitted = contents.split("\n"); - if(!splitted.isEmpty()) - { - if(splitted.takeAt(0).contains("#EXTM3U")) - { - foreach(QString str, splitted) - { - if(str.startsWith("#EXTINF:")) - ;//TODO: Let's skip it for now... - else if(QFileInfo(str).exists()) - out << QFileInfo(str).absoluteFilePath(); - else - qWarning("File %s does not exist",str.toLocal8Bit().data()); - } - return out; - } - } - else - qWarning("Error parsing M3U format"); - - return QStringList(); -} - -QString M3UPlaylistFormat::encode(const QList< MediaFile * > & contents) -{ - QStringList out; - out << QString("#EXTM3U"); - foreach(MediaFile* f,contents) - { - QString info = "#EXTINF:" + QString::number(f->length()) + "," + f->title(); - out.append(info); - out.append(f->path()); - } - return out.join("\n"); -} - -QString M3UPlaylistFormat::name() const -{ - return "M3UPlaylistFormat"; -} - -#ifndef XSPF_PLUGIN - -// Needs more work - it's better use libSpiff there and put it as plugin. - -QStringList XSPFPlaylistFormat::decode(const QString & contents) -{ - QStringList out; - QDomDocument doc; - QString errorMsg; - int errorCol; - int errorRow; - bool ok = doc.setContent(contents, &errorMsg, &errorRow, &errorCol); - - if(!ok) - qDebug("Parse Error: %s\tRow:%d\tCol%d", - qPrintable(errorMsg), errorRow, errorCol ); - - QDomElement rootElement = doc.firstChildElement("playlist"); - if(rootElement.isNull()) - qWarning("Error parsing XSPF: can't find 'playlist' element"); - - QDomElement tracklistElement = rootElement.firstChildElement("trackList"); - if(tracklistElement.isNull()) - qWarning("Error parsing XSPF: can't find 'trackList' element"); - - QDomElement child = tracklistElement.firstChildElement("track"); - - while (!child.isNull()) - { - QString str = QUrl(child.firstChildElement("location").text()).toString(QUrl::RemoveScheme); - out << str; - child = child.nextSiblingElement(); - } - - return out; -} - -// Needs more work - it's better use libSpiff there and put it as plugin. - -QString XSPFPlaylistFormat::encode(const QList< MediaFile * > & files) -{ - QDomDocument doc; - QDomElement root = doc.createElement("playlist"); - root.setAttribute("version",QString("1")); - root.setAttribute("xmlns",QString("http://xspf.org/ns/0")); - - QDomElement creator = doc.createElement("creator"); - QDomText text = doc.createTextNode("qmmp-" + QString(QMMP_STR_VERSION)); - creator.appendChild(text); - root.appendChild(creator); - - QDomElement tracklist = doc.createElement("trackList"); - - int counter = 1; - foreach(MediaFile* f,files) - { - QDomElement track = doc.createElement("track"); - - QDomElement ch = doc.createElement("location"); - QDomText text = doc.createTextNode(/*QString("file://") + */QFileInfo(f->path()).absoluteFilePath()); - ch.appendChild(text); - track.appendChild(ch); - - ch = doc.createElement("title"); - text = doc.createTextNode(f->title()); - ch.appendChild(text); - track.appendChild(ch); - - ch = doc.createElement("trackNum"); - text = doc.createTextNode(QString::number(counter)); - ch.appendChild(text); - track.appendChild(ch); - - ch = doc.createElement("year"); - text = doc.createTextNode(QString::number(f->year())); - ch.appendChild(text); - track.appendChild(ch); - - tracklist.appendChild(track); - counter ++; - } - - root.appendChild(tracklist); - doc.appendChild( root ); - QString xml_header("\n"); - return doc.toString().prepend(xml_header); -} - -XSPFPlaylistFormat::XSPFPlaylistFormat() -{ - m_supported_formats << "xspf"; -} - -bool XSPFPlaylistFormat::hasFormat(const QString & f) -{ - foreach(QString s,m_supported_formats) - if(f == s) - return true; - - return false; -} - -QStringList XSPFPlaylistFormat::getExtensions() const -{ - return m_supported_formats; -} - - -QString XSPFPlaylistFormat::name() const -{ - return "XSPFPlaylistFormat"; -} - -#endif - - - - diff --git a/src/playlistformat.h b/src/playlistformat.h deleted file mode 100644 index 70af82764..000000000 --- a/src/playlistformat.h +++ /dev/null @@ -1,120 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ - -#ifndef _PALYLISTFORMAT_H -#define _PALYLISTFORMAT_H -#include - - -class MediaFile; -/*! - * Abstract interface for playlist formats. - * - * @author Vladimir Kuznetsov - */ -class PlaylistFormat -{ -public: - virtual ~PlaylistFormat(){;} - /*! - * Takes raw contents of playlist file, should return string list of - * ready file pathes to fill the playlist. - */ - virtual QStringList decode(const QString& contents) = 0; - - /*! - * Takes the list of MediaFile objects, should return string of - * encoded playlist file - */ - virtual QString encode(const QList& contents) = 0; - - /*! - * Returns list of file extensions that current format supports - */ - virtual QStringList getExtensions()const = 0; - - /*! - * Verifies is the \b ext file extension supported by current playlist format. - */ - virtual bool hasFormat(const QString& ext) = 0; - - /// Unique name of playlist format. - virtual QString name()const = 0; -}; - -Q_DECLARE_INTERFACE(PlaylistFormat,"PlaylistFormatInterface/1.0"); - -/*! - * Class for PLS playlist format parsing - */ -class PLSPlaylistFormat : public PlaylistFormat -{ -public: - PLSPlaylistFormat(); - virtual QStringList getExtensions()const; - virtual bool hasFormat(const QString&); - virtual QStringList decode(const QString& contents); - virtual QString encode(const QList& contents); - virtual QString name()const; -protected: - QStringList m_supported_formats; - -}; - - - -/*! - * Class for M3U playlist format parsing - */ -class M3UPlaylistFormat : public PlaylistFormat -{ - public: - M3UPlaylistFormat(); - virtual QStringList getExtensions()const; - virtual bool hasFormat(const QString&); - virtual QStringList decode(const QString& contents); - virtual QString encode(const QList& contents); - virtual QString name()const; -protected: - QStringList m_supported_formats; -}; - - -// Format below is made also as plugin - experimental. To enable it -// uncomment 'CONFIG += XSPF_PLUGIN' line in qmmp.pri -#ifndef XSPF_PLUGIN -/*! - * Class for XSPF playlist format parsing - */ -class XSPFPlaylistFormat : public PlaylistFormat -{ - public: - XSPFPlaylistFormat(); - virtual QStringList getExtensions()const; - virtual bool hasFormat(const QString&); - virtual QStringList decode(const QString& contents); - virtual QString encode(const QList& contents); - virtual QString name()const; - protected: - QStringList m_supported_formats; -}; -#endif - -#endif diff --git a/src/playlistmodel.cpp b/src/playlistmodel.cpp deleted file mode 100644 index 196608438..000000000 --- a/src/playlistmodel.cpp +++ /dev/null @@ -1,899 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "fileloader.h" -#include "playlistmodel.h" -#include "mediafile.h" -#include "playlistformat.h" -#include "playstate.h" - -#include - -#define INVALID_ROW -1 - -TagUpdater::TagUpdater(QObject* o,MediaFile* f):m_observable(o),m_file(f) -{ - m_file->setFlag(MediaFile::EDITING); - connect (m_observable, SIGNAL(destroyed (QObject * )),SLOT(updateTag())); - connect (m_observable, SIGNAL(destroyed (QObject * )),SLOT(deleteLater())); -} - -void TagUpdater::updateTag() -{ - if(m_file->flag() == MediaFile::SCHEDULED_FOR_DELETION) - { - delete m_file; - m_file = NULL; - } - else - { - m_file->updateTags(); - m_file->setFlag(MediaFile::FREE); - } -} - - -PlayListModel::PlayListModel ( QObject *parent ) - : QObject ( parent ) , m_selection() -{ - qsrand(time(0)); - m_total_length = 0; - m_current = 0; - m_block_update_signals = false; - is_repeatable_list = false; - m_play_state = new NormalPlayState(this); - //readSettings(); - - registerPlaylistFormat( new PLSPlaylistFormat); - registerPlaylistFormat( new M3UPlaylistFormat); -#ifndef XSPF_PLUGIN - registerPlaylistFormat( new XSPFPlaylistFormat); -#endif - loadExternalPlaylistFormats(); -} - -PlayListModel::~PlayListModel() -{ - writeSettings(); - clear(); - delete m_play_state; - qDeleteAll(m_registered_pl_formats); - - foreach(GuardedFileLoader l,m_running_loaders) - { - if (!l.isNull()) - { - l->finish(); - l->wait(); - } - } -} - -void PlayListModel::load ( MediaFile *file ) -{ - if (m_files.isEmpty()) - m_currentItem = file; - - m_total_length += file->length(); - m_files << file; - - //if (!m_block_update_signals) - emit listChanged(); -} - -int PlayListModel::count() -{ - return m_files.size(); -} - -MediaFile* PlayListModel::currentItem() -{ - if ( m_files.isEmpty() ) - return 0; - else - return m_files.at ( qMin(m_files.size() - 1, m_current)); -} - -int PlayListModel::currentRow() -{ - return m_current; -} - -bool PlayListModel::setCurrent ( int c ) -{ - if ( c > count()-1 || c < 0) - return FALSE; - m_current = c; - m_currentItem = m_files.at(c); - emit currentChanged(); - emit listChanged(); - return TRUE; -} - - -bool PlayListModel::next() -{ - if (isFileLoaderRunning()) - m_play_state->prepare(); - - return m_play_state->next(); -} - -bool PlayListModel::previous() -{ - if (isFileLoaderRunning()) - m_play_state->prepare(); - - return m_play_state->previous();//) -} - -void PlayListModel::clear() -{ - foreach(GuardedFileLoader l,m_running_loaders) - { - if (!l.isNull()) - { - l->finish(); - l->wait(); - } - } - - m_running_loaders.clear(); - - m_current = 0; - while ( !m_files.isEmpty() ) - { - MediaFile* mf = m_files.takeFirst(); - - if(mf->flag() == MediaFile::FREE) - { - delete mf; - } - else if(mf->flag() == MediaFile::EDITING) - { - mf->setFlag(MediaFile::SCHEDULED_FOR_DELETION); - } - } - - m_total_length = 0; - m_play_state->resetState(); - emit listChanged(); -} - -void PlayListModel::clearSelection() -{ - for ( int i = 0; isetSelected ( FALSE ); - emit listChanged(); -} - -QList PlayListModel::getTitles ( int b,int l ) -{ - QList m_titles; - for ( int i = b; ( i < b + l ) && ( i < m_files.size() ); ++i ) - m_titles << m_files.at ( i )->title(); - return m_titles; -} - -QList PlayListModel::getTimes ( int b,int l ) -{ - QList m_times; - for ( int i = b; ( i < b + l ) && ( i < m_files.size() ); ++i ) - m_times << QString ( "%1" ).arg ( m_files.at ( i )->length() /60 ) +":" - +QString ( "%1" ).arg ( m_files.at ( i )->length() %60/10 ) + - QString ( "%1" ).arg ( m_files.at ( i )->length() %60%10 ); - return m_times; -} - -bool PlayListModel::isSelected ( int row ) -{ - if (m_files.count() > row && row >= 0) - return m_files.at ( row )->isSelected(); - - return false; -} - -void PlayListModel::setSelected ( int row, bool yes ) -{ - if (m_files.count() > row && row >= 0) - m_files.at ( row )->setSelected ( yes ); -} - -void PlayListModel::removeSelected() -{ - removeSelection(false); -} - -void PlayListModel::removeUnselected() -{ - removeSelection(true); -} - -void PlayListModel::removeSelection(bool inverted) -{ - int i = 0; - - int select_after_delete = -1; - - while ( !m_files.isEmpty() && iisSelected() ^ inverted ) - { - MediaFile* f = m_files.takeAt ( i ); - m_total_length -= f->length(); - if (m_total_length < 0) - m_total_length = 0; - - if(f->flag() == MediaFile::FREE) - { - delete f; - f = NULL; - } - else if(f->flag() == MediaFile::EDITING) - f->setFlag(MediaFile::SCHEDULED_FOR_DELETION); - - select_after_delete = i; - - if ( m_current >= i && m_current!=0 ) - m_current--; - } - else - i++; - } - - if (!m_files.isEmpty()) - m_currentItem = m_files.at(m_current); - - if (select_after_delete >= m_files.count()) - select_after_delete = m_files.count() - 1; - - setSelected(select_after_delete,true); - - m_play_state->prepare(); - - emit listChanged(); -} - -void PlayListModel::invertSelection() -{ - for ( int i = 0; isetSelected ( !m_files.at ( i )->isSelected() ); - emit listChanged(); -} - -void PlayListModel::selectAll() -{ - for ( int i = 0; isetSelected ( TRUE ); - emit listChanged(); -} - -void PlayListModel::showDetails() -{ - for ( int i = 0; iisSelected() ) - { - DecoderFactory *fact = Decoder::findByPath ( m_files.at ( i )->path() ); - if ( fact ) - { - QObject* o = fact->showDetails ( 0, m_files.at ( i )->path() ); - if(o) - { - TagUpdater *updater = new TagUpdater(o,m_files.at(i)); - m_editing_files.append(m_files.at(i)); - connect (updater, SIGNAL(destroyed (QObject * )),SIGNAL(listChanged())); - } - } - - return; - } - } - -} - - -void PlayListModel::readSettings() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - m_current = settings.value("Playlist/current",0).toInt(); - - QFile file ( QDir::homePath() +"/.qmmp/playlist.txt" ); - file.open ( QIODevice::ReadOnly ); - - QStringList files; - QByteArray line; - m_files.clear(); - - while (!file.atEnd ()) - { - line = file.readLine(); - files << QString::fromUtf8 ( line ).trimmed (); - } - - file.close (); - - if(m_current > files.count() - 1) - m_current = 0; - - int preload = (files.count() < 100) ? files.count() : 100; - - for (int i = 0;i < preload;i++) - { - load(new MediaFile(files.takeAt(0))); - } - - if (files.isEmpty()) - { - doCurrentVisibleRequest (); - return; - } - - FileLoader* f_loader = createFileLoader(); - connect(f_loader, SIGNAL(finished ()), SLOT(doCurrentVisibleRequest ())); - - f_loader->setFilesToLoad(files); - //f_loader->start(QThread::IdlePriority); - QTimer::singleShot(1000,f_loader,SLOT(start())); - //m_play_state->prepare(); -} - -void PlayListModel::writeSettings() -{ - QFile file ( QDir::homePath() +"/.qmmp/playlist.txt" ); - file.open ( QIODevice::WriteOnly ); - foreach ( MediaFile* m, m_files ) - file.write ( m->path().toUtf8 () +"\n" ); - file.close (); - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - settings.setValue("Playlist/current", m_current); -} - -void PlayListModel::addFile(const QString& path) -{ - if (path.isEmpty ()) - return; - if (path.startsWith("http://")) - load(new MediaFile(path)); - else if (Decoder::supports(path)) - load(new MediaFile(path)); - - m_play_state->prepare(); -} - -FileLoader * PlayListModel::createFileLoader() -{ - FileLoader* f_loader = new FileLoader(this); -// f_loader->setStackSize(20 * 1024 * 1024); - m_running_loaders << f_loader; - connect(f_loader,SIGNAL(newMediaFile(MediaFile*)),this,SLOT(load(MediaFile*)),Qt::QueuedConnection); - connect(f_loader,SIGNAL(finished()),this,SLOT(preparePlayState())); - connect(f_loader,SIGNAL(finished()),f_loader,SLOT(deleteLater())); - return f_loader; -} - -void PlayListModel::addFiles(const QStringList &files) -{ - FileLoader* f_loader = createFileLoader(); - f_loader->setFilesToLoad(files); - f_loader->start(QThread::IdlePriority); -} - -void PlayListModel::addDirectory(const QString& s) -{ - FileLoader* f_loader = createFileLoader(); - f_loader->setDirectoryToLoad(s); - f_loader->start(QThread::IdlePriority); -} - -void PlayListModel::addFileList(const QStringList &l) -{ -// qWarning("void// PlayListModel::addFileList(const QStringList &l)"); - foreach(QString str,l) - { - QFileInfo f_info(str); - if (f_info.exists()) - { - if (f_info.isDir()) - addDirectory(str); - else - addFile(str); - } - // Do processing the rest of events to avoid GUI freezing - QApplication::processEvents(QEventLoop::AllEvents,10); - } -} - -bool PlayListModel::setFileList(const QStringList & l) -{ - bool model_cleared = FALSE; - foreach(QString str,l) - { - QFileInfo f_info(str); - if (f_info.exists()) - { - if (!model_cleared) - { - clear(); - model_cleared = TRUE; - } - if (f_info.isDir()) - addDirectory(str); - else - addFile(str); - } - // Do processing the rest of events to avoid GUI freezing - QApplication::processEvents(QEventLoop::AllEvents,10); - } - - return model_cleared; -} - -int PlayListModel::firstSelectedUpper(int row) -{ - for (int i = row - 1;i >= 0;i--) - { - if (isSelected(i)) - return i; - } - return -1; -} - -int PlayListModel::firstSelectedLower(int row) -{ - for (int i = row + 1;i < count() ;i++) - { - if (isSelected(i)) - return i; - } - return -1; -} - -void PlayListModel::moveItems( int from, int to ) -{ - // Get rid of useless work - if (from == to) - return; - - QList selected_rows = getSelectedRows(); - - if (! (bottommostInSelection(from) == INVALID_ROW || - from == INVALID_ROW || - topmostInSelection(from) == INVALID_ROW) - ) - { - if (from > to) - foreach(int i, selected_rows) - if (i + to - from < 0) - break; - else - m_files.move(i,i + to - from); - else - for (int i = selected_rows.count() - 1; i >= 0; i--) - if (selected_rows[i] + to -from >= m_files.count()) - break; - else - m_files.move(selected_rows[i],selected_rows[i] + to - from); - - m_current = m_files.indexOf(m_currentItem); - - emit listChanged(); - } -} - - - -int PlayListModel::topmostInSelection( int row) -{ - if ( row == 0) - return 0; - - for (int i = row - 1;i >= 0;i--) - { - if (isSelected(i)) - continue; - else - return i + 1; - } - return 0; -} - -int PlayListModel::bottommostInSelection( int row ) -{ - if (row >= m_files.count() - 1) - return row; - - for (int i = row + 1;i < count() ;i++) - { - if (isSelected(i)) - continue; - else - return i - 1; - } - return count() - 1; -} - -const SimpleSelection& PlayListModel::getSelection(int row ) -{ - m_selection.m_top = topmostInSelection( row ); - m_selection.m_anchor = row; - m_selection.m_bottom = bottommostInSelection( row ); - m_selection.m_selected_rows = getSelectedRows(); - return m_selection; -} - -QList PlayListModel::getSelectedRows() const -{ - QListselected_rows; - for (int i = 0;iisSelected()) - { - selected_rows.append(i); - } - } - return selected_rows; -} - -QList< MediaFile * > PlayListModel::getSelectedItems() const -{ - QListselected_items; - for (int i = 0;iisSelected()) - { - selected_items.append(m_files[i]); - } - } - return selected_items; -} - -void PlayListModel::addToQueue() -{ - QList selected_items = getSelectedItems(); - foreach(MediaFile* file,selected_items) - {/* - if (isQueued(file)) - m_queued_songs.removeAt(m_queued_songs.indexOf(file)); - else - m_queued_songs.append(file); - */ - setQueued(file); - } - emit listChanged(); -} - -void PlayListModel::setQueued(MediaFile* file) -{ - if (isQueued(file)) - m_queued_songs.removeAt(m_queued_songs.indexOf(file)); - else - m_queued_songs.append(file); - - emit listChanged(); -} - -bool PlayListModel::isQueued(MediaFile* f) const -{ - return m_queued_songs.contains(f); -} - -void PlayListModel::setCurrentToQueued() -{ - setCurrent(row(m_queued_songs.at(0))); - m_queued_songs.pop_front(); -} - -bool PlayListModel::isEmptyQueue() const -{ - return m_queued_songs.isEmpty(); -} - -void PlayListModel::randomizeList() -{ - for (int i = 0;i < m_files.size();i++) - m_files.swap(qrand()%m_files.size(),qrand()%m_files.size()); - - m_current = m_files.indexOf(m_currentItem); - emit listChanged(); -} - -void PlayListModel::reverseList() -{ - for (int i = 0;i < m_files.size()/2;i++) - m_files.swap(i,m_files.size() - i - 1); - - m_current = m_files.indexOf(m_currentItem); - emit listChanged(); -} - -////===============THE BEGINNING OF SORT IMPLEMENTATION =======================//// - -// First we'll implement bundle of static compare procedures -// to sort items in different ways -static bool _titleLessComparator(MediaFile* s1,MediaFile* s2) -{ - return s1->title() < s2->title(); -} - -static bool _titleGreaterComparator(MediaFile* s1,MediaFile* s2) -{ - return s1->title() > s2->title(); -} - -static bool _pathAndFilenameLessComparator(MediaFile* s1,MediaFile* s2) -{ - return s1->path() < s2->path(); -} - -static bool _pathAndFilenameGreaterComparator(MediaFile* s1,MediaFile* s2) -{ - return s1->path() > s2->path(); -} - -static bool _filenameLessComparator(MediaFile* s1,MediaFile* s2) -{ - QFileInfo i_s1(s1->path()); - QFileInfo i_s2(s2->path()); - return i_s1.baseName() < i_s2.baseName(); -} - -static bool _filenameGreaterComparator(MediaFile* s1,MediaFile* s2) -{ - QFileInfo i_s1(s1->path()); - QFileInfo i_s2(s2->path()); - return i_s1.baseName() > i_s2.baseName(); -} - -static bool _dateLessComparator(MediaFile* s1,MediaFile* s2) -{ - return s1->year() < s2->year(); -} - -static bool _dateGreaterComparator(MediaFile* s1,MediaFile* s2) -{ - return s1->year() > s2->year(); -} - -// This is main sort method -void PlayListModel::doSort(int sort_mode,QList& list_to_sort) -{ - QList::iterator begin; - QList::iterator end; - - begin = list_to_sort.begin(); - end = list_to_sort.end(); - - bool (*compareLessFunc)(MediaFile*,MediaFile*) = 0; - bool (*compareGreaterFunc)(MediaFile*,MediaFile*) = 0; - - switch (sort_mode) - { - case TITLE: - compareLessFunc = _titleLessComparator; - compareGreaterFunc = _titleGreaterComparator; - break; - case FILENAME: - compareLessFunc = _filenameLessComparator; - compareGreaterFunc = _filenameGreaterComparator; - break; - case PATH_AND_FILENAME: - compareLessFunc = _pathAndFilenameLessComparator; - compareGreaterFunc = _pathAndFilenameGreaterComparator; - break; - case DATE: - compareLessFunc = _dateLessComparator; - compareGreaterFunc = _dateGreaterComparator; - break; - //qWarning("TODO Sort by Date: %s\t%d",__FILE__,__LINE__); - default: - compareLessFunc = _titleLessComparator; - compareGreaterFunc = _titleGreaterComparator; - } - - static bool sorted_asc = false; - if (!sorted_asc) - { - qSort(begin,end,compareLessFunc); - sorted_asc = true; - } - else - { - qSort(begin,end,compareGreaterFunc); - sorted_asc = false; - } - - m_current = m_files.indexOf(m_currentItem); -} - -void PlayListModel::sortSelection(int mode) -{ - QListselected_items = getSelectedItems(); - QListselected_rows = getSelectedRows(); - - doSort(mode,selected_items); - - for (int i = 0;i < selected_rows.count();i++) - m_files.replace(selected_rows[i],selected_items[i]); - - m_current = m_files.indexOf(m_currentItem); - emit listChanged(); -} - -void PlayListModel::sort(int mode) -{ - doSort(mode,m_files); - emit listChanged(); -} - -////=============== THE END OF SORT IMPLEMENTATION =======================//// - -void PlayListModel::prepareForShufflePlaying(bool val) -{ - if (m_play_state) - delete m_play_state; - - if (val) - m_play_state = new ShufflePlayState(this); - else - m_play_state = new NormalPlayState(this); - -} - -void PlayListModel::prepareForRepeatablePlaying(bool val) -{ - is_repeatable_list = val; -} - -void PlayListModel::doCurrentVisibleRequest() -{ - emit currentChanged(); - emit listChanged(); -} - -void PlayListModel::setUpdatesEnabled(bool yes) -{ - if (yes) - { - m_block_update_signals = false; - emit listChanged(); - } - else - { - m_block_update_signals = true; - } -} - -void PlayListModel::loadPlaylist(const QString & f_name) -{ - - foreach(PlaylistFormat* prs,m_registered_pl_formats.values()) - { - if (prs->hasFormat(QFileInfo(f_name).completeSuffix().toLower())) - { - QFile file(f_name); - if (file.open(QIODevice::ReadOnly)) - { - clear(); - addFiles(prs->decode(QTextStream(&file).readAll())); - file.close(); - } - else - qWarning("Error opening %s",f_name.toLocal8Bit().data()); - } - } -} - -void PlayListModel::savePlaylist(const QString & f_name) -{ - foreach(PlaylistFormat* prs,m_registered_pl_formats.values()) - { - if (prs->hasFormat(QFileInfo(f_name).completeSuffix().toLower())) - { - QFile file(f_name); - if (file.open(QIODevice::WriteOnly)) - { - QTextStream ts(&file); - ts << prs->encode(m_files); - file.close(); - } - else - qWarning("Error opening %s",f_name.toLocal8Bit().data()); - } - } -} - - -void PlayListModel::loadExternalPlaylistFormats() -{ - QDir pluginsDir (QDir::homePath()+"/.qmmp/plugins/PlaylistFormats"); - //pluginsDir.cdUp(); - //pluginsDir.cd("plugins/PlaylistFormats"); - foreach (QString fileName, pluginsDir.entryList(QDir::Files)) - { - QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); - QObject *plugin = loader.instance(); - if (loader.isLoaded()) - qDebug("PlaylistFormat: plugin loaded - %s", qPrintable(fileName)); - - PlaylistFormat *fmt = 0; - if (plugin) - fmt = qobject_cast(plugin); - - if (fmt) - if (!registerPlaylistFormat(fmt)) - qDebug("Warning: Plugin with name %s is already registered...", - qPrintable(fmt->name())); - } -} - -bool PlayListModel::registerPlaylistFormat(PlaylistFormat* p) -{ - QString name = p->name(); - if (!m_registered_pl_formats.contains(name)) - { - m_registered_pl_formats.insert(name,p); - return true; - } - return false; -} - -bool PlayListModel::isFileLoaderRunning() const -{ - foreach(FileLoader* l,m_running_loaders) - if (l && l->isRunning()) - return TRUE; - - return FALSE; -} - -void PlayListModel::preparePlayState() -{ - m_play_state->prepare(); -} - - - - - - - - - - - - - - diff --git a/src/playlistmodel.h b/src/playlistmodel.h deleted file mode 100644 index b3ac19c04..000000000 --- a/src/playlistmodel.h +++ /dev/null @@ -1,377 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef PLAYLISTMODEL_H -#define PLAYLISTMODEL_H - -#include -#include -#include -#include -#include -#include - -//#include "fileloader.h" -class FileLoader; - -/** - @author Ilya Kotov -*/ - -class MediaFile; -class PlayState; -class PlaylistFormat; -class PlayListModel; - -struct SimpleSelection -{ - SimpleSelection() - { - ; - } - inline bool isValid()const - { - return (m_bottom != -1) && (m_anchor != -1) && (m_top != -1); - } - inline void dump()const - { - qWarning("top: %d\tbotom: %d\tanchor: %d",m_top,m_bottom,m_anchor); - } - inline int count()const - { - return m_bottom - m_top + 1; - } - int m_bottom; - int m_top; - int m_anchor; - QListm_selected_rows; -}; - -/*! - * Helper class used for tags update after details dialog closing. - * @author Vladimir Kuznetsov - */ -class TagUpdater : public QObject -{ - Q_OBJECT - QObject* m_observable; - MediaFile* m_file; -public: - TagUpdater(QObject* o,MediaFile* f); -protected slots: - void updateTag(); -}; - - -class PlayListModel : public QObject -{ - Q_OBJECT -public: - PlayListModel(QObject *parent = 0); - - ~PlayListModel(); - - int count(); - MediaFile* currentItem(); - int row(MediaFile* f)const - { - return m_files.indexOf(f); - } - MediaFile* item(int row)const - { - return m_files.at(row); - } - int currentRow(); - bool setCurrent (int); - bool isSelected(int); - void setSelected(int, bool); - - bool next(); - bool previous(); - - QList getTitles(int,int); - QList getTimes(int,int); - - void moveItems(int from,int to); - - /*! - * Returns \b true if \b f file is in play queue, else return \b false - */ - bool isQueued(MediaFile* f) const; - - bool isRepeatableList()const - { - return is_repeatable_list; - } - - /*! - * Sets current song to the file that is nex in queue, if queue is empty - does nothing - */ - void setCurrentToQueued(); - - /*! - * Returns \b true if play queue is empty,otherwise - \b false. - */ - bool isEmptyQueue()const; - - /*! - * Returns index of \b f file in queue.e - */ - int queuedIndex(MediaFile* f)const - { - return m_queued_songs.indexOf(f); - } - - /*! - * Returns current selection(playlist can contain a lot of selections, - * this method returns selection which \b row belongs to) - */ - const SimpleSelection& getSelection(int row); - - /*! - * Returns vector with selected rows indexes. - */ - QList getSelectedRows()const; - /*! - * Returns vector of \b MediaFile pointers that are selected. - */ - QList getSelectedItems()const; - - QList items()const - { - return m_files; - } - - /*! - * Returns number of first item that selected upper the \b row item. - */ - int firstSelectedUpper(int row); - - /*! - * Returns number of first item that selected lower the \b row item. - */ - int firstSelectedLower(int row); - - /*! - * Returns total lenght in seconds of all songs. - */ - int totalLength()const - { - return m_total_length; - } - - /*! - * Registers playlist format parser. - */ - bool registerPlaylistFormat(PlaylistFormat* p); - - /*! - * Checks and loads external playlist format plugins - */ - void loadExternalPlaylistFormats(); - - /*! - * Returns vector of reistered format parsers. - */ - const QList registeredPlaylistFormats()const - { - return m_registered_pl_formats.values(); - } - - const QStringList registeredPlaylistFormatNames()const - { - return m_registered_pl_formats.keys(); - } - - /*! - * Loads playlist with \b f_name name. - */ - void loadPlaylist(const QString& f_name); - - /*! - * Saves current songs to the playlist with \b f_name name. - */ - void savePlaylist(const QString& f_name); - - /*! - * Enum of available sort modes - */ - enum SortMode - { - TITLE,FILENAME,PATH_AND_FILENAME,DATE - }; - -signals: - void listChanged(); - void currentChanged(); - -public slots: - void load(MediaFile *); - void clear(); - void clearSelection(); - void removeSelected(); - void removeUnselected(); - void invertSelection(); - void selectAll(); - void showDetails(); - void doCurrentVisibleRequest(); - - void addFile(const QString&); - - /*! - * Adds the list \b l of files to the model. - */ - void addFiles(const QStringList& l); - - /*! - * Adds \b dir to the model. - */ - void addDirectory(const QString& dir); - - /*! - * Loads list of files (regular files or directories), - * returns \b TRUE if at least one file has been successfully loaded, - * otherwise \b FALSE - */ - bool setFileList(const QStringList&); - - void addFileList(const QStringList &l); - - void randomizeList(); - void reverseList(); - - /*! - * Prepares model for shuffle playing. \b yes parameter is true - model iterates in shuffle mode. - */ - void prepareForShufflePlaying(bool yes); - - /*! - * Prepares model for shuffle playing. \b yes parameter is true - model iterates in repeat mode. - */ - void prepareForRepeatablePlaying(bool); - - /*! - * Sorts selected items in \b mode sort mode. - */ - void sortSelection(int mode); - - /*! - * Sorts items in \b mode sort mode. - */ - void sort(int mode); - - /*! - * Adds selected items to play queue. - */ - void addToQueue(); - - /*! - * Sets \b f media file to queue. - */ - void setQueued(MediaFile* f); - - void preparePlayState(); - -private: - - /*! - * This internal method performs sorting of \b list_to_sort list of items. - */ - void doSort(int mode,QList& list_to_sort); - /*! - * Returns topmost row in current selection - */ - int topmostInSelection(int); - - /*! - * Returns bottommost row in current selection - */ - int bottommostInSelection(int); - - /*! - * Creates and initializes file loader object. - */ - FileLoader* createFileLoader(); - - - /*! - * Is someone of file loaders is running? - */ - bool isFileLoaderRunning()const; - - /*! - * Removes items from model. If \b inverted is \b false - - * selected items will be removed, else - unselected. - */ - void removeSelection(bool inverted = false); - -private: - - QList m_files; - QList m_editing_files; - MediaFile* m_currentItem; - - int m_current; - void readSettings(); - void writeSettings(); - - void setUpdatesEnabled(bool); - - bool updatesEnabled()const - { - return !m_block_update_signals; - } - - /*! - * This flyweight object represents current selection. - */ - SimpleSelection m_selection; - - /*! - * Songs in play queue. - */ - QListm_queued_songs; - - QMap m_registered_pl_formats; - - /*! - * Is playlist repeatable? - */ - bool is_repeatable_list; - - /// Current playing state (Normal or Shuffle) - PlayState* m_play_state; - - bool m_block_update_signals; - - int m_total_length; - - typedef QPointer GuardedFileLoader; - - /*! Vector of currently running file loaders. - * All loaders are automatically sheduled for deletion - * when finished. - */ - QVector m_running_loaders; - - friend class MainWindow; -}; - - -#endif diff --git a/src/playlistslider.cpp b/src/playlistslider.cpp deleted file mode 100644 index 098b3bcee..000000000 --- a/src/playlistslider.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include - -#include "skin.h" -#include "playlistslider.h" -#include "pixmapwidget.h" - -PlayListSlider::PlayListSlider(QWidget *parent) - : QWidget(parent) -{ - m_skin = Skin::getPointer(); - - m_moving = FALSE; - m_pressed = FALSE; - m_min = 0; - m_max = 0; - m_value = 0; - pos = 0; - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); -} - - -PlayListSlider::~PlayListSlider() -{} - -void PlayListSlider::paintEvent(QPaintEvent *) -{ - int sy = (height()-58)/29; - int p=int(ceil(double(m_value-m_min)*(height()-18)/(m_max-m_min))); - QPainter paint(this); - paint.drawPixmap(0,0,m_skin->getPlPart(Skin::PL_RFILL)); - paint.drawPixmap(0,29,m_skin->getPlPart(Skin::PL_RFILL)); - - for (int i = 0; igetPlPart(Skin::PL_RFILL)); - } - if (m_pressed) - paint.drawPixmap(5,p,m_skin->getButton(Skin::PL_BT_SCROLL_P)); - else - paint.drawPixmap(5,p,m_skin->getButton(Skin::PL_BT_SCROLL_N)); - m_pos = p; -} - -void PlayListSlider::mousePressEvent(QMouseEvent *e) -{ - - m_moving = TRUE; - press_pos = e->y(); - if (m_posy() && e->y()y()-m_pos; - } - else - { - m_value = convert(qMax(qMin(height()-18,e->y()-9),0)); - press_pos = 9; - if (m_value!=m_old) - { - emit sliderMoved(m_value); - m_old = m_value; - //qDebug ("%d",m_value); - } - } - m_pressed = TRUE; - update(); -} - -void PlayListSlider::mouseReleaseEvent(QMouseEvent*) -{ - m_moving = FALSE; - m_pressed = FALSE; - update(); -} - -void PlayListSlider::mouseMoveEvent(QMouseEvent* e) -{ - if (m_moving) - { - int po = e->y(); - po = po - press_pos; - - if (0<=po && po<=height()-18) - { - m_value = convert(po); - update(); - if (m_value!=m_old) - { - - m_old = m_value; - emit sliderMoved(m_value); - } - } - } -} - -void PlayListSlider::setPos(int p, int max) -{ - m_max = max; - m_value = p; - if(m_moving) - return; - update(); -} - -void PlayListSlider::updateSkin() -{ - update(); -} - -int PlayListSlider::convert(int p) -{ - return int(floor(double(m_max-m_min)*(p)/(height()-18)+m_min)); -} - diff --git a/src/playlistslider.h b/src/playlistslider.h deleted file mode 100644 index a8eb45c66..000000000 --- a/src/playlistslider.h +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef PLAYLISTSLIDER_H -#define PLAYLISTSLIDER_H - -#include - -class Skin; -class PixmapWidget; -/** - @author Ilya Kotov -*/ -class PlayListSlider : public QWidget -{ -Q_OBJECT -public: - PlayListSlider(QWidget *parent = 0); - - ~PlayListSlider(); - -public slots: - void setPos(int pos, int max); - -signals: - void sliderMoved (int); - -private slots: - void updateSkin(); - -private: - Skin *m_skin; - PixmapWidget *m_scroll; - int m_old; - bool m_moving, m_pressed; - int press_pos; - int m_min, m_max, m_value, pos, m_pos; - int convert(int); // value = convert(position); - -protected: - void paintEvent(QPaintEvent*); - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); -}; - -#endif diff --git a/src/playlisttitlebar.cpp b/src/playlisttitlebar.cpp deleted file mode 100644 index a583065ca..000000000 --- a/src/playlisttitlebar.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include - -#include "dock.h" -#include "button.h" -#include "playlistmodel.h" -#include "playlisttitlebar.h" -#include "skin.h" - -PlayListTitleBar::PlayListTitleBar(QWidget *parent) - : PixmapWidget(parent) -{ - m_active = FALSE; - m_resize = FALSE; - m_shade2 = 0; - m_model = 0; - m_shaded = FALSE; - m_align = FALSE; - m_skin = Skin::getPointer(); - setSizeIncrement(25,1); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); - m_pl = qobject_cast(parent); - m_mw = qobject_cast(m_pl->parent()); - - m_close = new Button(this,Skin::PL_BT_CLOSE_N, Skin::PL_BT_CLOSE_P); - connect (m_close, SIGNAL(clicked()), m_pl, SIGNAL(closed())); - m_close->move(264,3); - m_shade = new Button(this, Skin::PL_BT_SHADE1_N, Skin::PL_BT_SHADE1_P); - connect(m_shade, SIGNAL(clicked()), SLOT(shade())); - m_shade->move(255,3); - resize(275,20); - setMinimumWidth(275); - readSettings(); - QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); - m_pl->resize (settings.value ("PlayList/size", QSize (275, 116)).toSize()); - if (settings.value ("PlayList/shaded", FALSE).toBool()) - shade(); - resize(m_pl->width(),height()); - m_align = TRUE; -} - - -PlayListTitleBar::~PlayListTitleBar() -{ - QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); - settings.setValue ("PlayList/size", QSize (m_pl->width(), m_shaded ? m_height:m_pl->height())); - settings.setValue ("PlayList/shaded", m_shaded); -} - -void PlayListTitleBar::drawPixmap(int sx) -{ - m_close->move(264+sx*25,3); - m_shade->move(255+sx*25,3); - if (m_shade2) - m_shade2->move(255+sx*25,3); - QPixmap pixmap(275+sx*25,20); - pixmap.fill("black"); - QPainter paint; - paint.begin(&pixmap); - if (m_shaded) - { - paint.drawPixmap(0,0,m_skin->getPlPart(Skin::PL_TITLEBAR_SHADED2)); - for (int i = 1; igetPlPart(Skin::PL_TFILL_SHADED)); - } - } - - if (m_active) - { - if (m_shaded) - { - m_shade2->show(); - paint.drawPixmap(225+sx*25,0,m_skin->getPlPart(Skin::PL_TITLEBAR_SHADED1_A)); - } - else - { - paint.drawPixmap(0,0,m_skin->getPlPart(Skin::PL_CORNER_UL_A)); - for (int i = 1; igetPlPart(Skin::PL_TFILL1_A)); - } - paint.drawPixmap(100-12+12*sx,0,m_skin->getPlPart(Skin::PL_TITLEBAR_A)); - paint.drawPixmap(250+sx*25,0,m_skin->getPlPart(Skin::PL_CORNER_UR_A)); - m_close->show(); - m_shade->show(); - } - } - else - { - if (m_shaded) - { - m_shade2->hide(); - paint.drawPixmap(275-50+sx*25,0,m_skin->getPlPart(Skin::PL_TITLEBAR_SHADED1_I)); - } - else - { - paint.drawPixmap(0,0,m_skin->getPlPart(Skin::PL_CORNER_UL_I)); - for (int i = 1; igetPlPart(Skin::PL_TFILL1_I)); - } - paint.drawPixmap(100-12+12*sx,0,m_skin->getPlPart(Skin::PL_TITLEBAR_I)); - paint.drawPixmap(250+sx*25,0,m_skin->getPlPart(Skin::PL_CORNER_UR_I)); - m_close->hide(); - m_shade->hide(); - } - } - if (m_shaded) - { - //draw text background - for (int i = 0; i < 47 + sx*5; ++i) - { - paint.drawPixmap(8+i*5,2,m_skin->getLetter(' ')); - paint.drawPixmap(8+i*5,6,m_skin->getLetter(' ')); - } - //draw text - paint.setFont(m_font); - paint.setPen(QString(m_skin->getPLValue("normal"))); - paint.drawText(9, 11, m_truncatedText); - } - paint.end(); - setPixmap(pixmap); -} - -void PlayListTitleBar::resizeEvent(QResizeEvent *e) -{ - truncate(); - drawPixmap((e->size().width()-275)/25); -} - -void PlayListTitleBar::mousePressEvent(QMouseEvent* event) -{ - switch ((int) event->button ()) - { - case Qt::LeftButton: - { - pos = event->pos(); - - if (m_shaded && (width() - 30) < pos.x() && pos.x() < (width() - 22)) - { - m_resize = TRUE; - m_pl->setCursor (Qt::SizeHorCursor); - } - - - break; - } - case Qt::RightButton: - { - m_mw->menu()->exec(event->globalPos()); - } - } -} - -void PlayListTitleBar::mouseReleaseEvent(QMouseEvent*) -{ - Dock::getPointer()->updateDock(); - m_resize = FALSE; - m_pl->setCursor (Qt::ArrowCursor); -} - -void PlayListTitleBar::mouseMoveEvent(QMouseEvent* event) -{ - QPoint npos = (event->globalPos()-pos); - QPoint oldpos = npos; - if (m_shaded && m_resize) - { - m_pl->resize((event->x() + 25), m_pl->height()); - resize((event->x() + 25), height()); - } - else - Dock::getPointer()->move(m_pl, npos); -} - -void PlayListTitleBar::setActive(bool a) -{ - m_active = a; - drawPixmap((width()-275)/25); -} - - -void PlayListTitleBar::setModel(PlayListModel *model) -{ - m_model = model; - connect (m_model, SIGNAL(listChanged()), SLOT(showCurrent())); -} - -void PlayListTitleBar::readSettings() -{ - QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); - QString fontname = settings.value("PlayList/Font","").toString(); - if (fontname.isEmpty ()) - fontname = QFont("Helvetica [Cronyx]", 8).toString(); - m_font.fromString(fontname); - m_font.setPointSize(8); -} - -void PlayListTitleBar::updateSkin() -{ - drawPixmap((width()-275)/25); -} - -void PlayListTitleBar::shade() -{ - m_shaded = !m_shaded; - - if (m_shaded) - { - m_height = m_pl->height(); - m_pl->setFixedHeight(14); - m_shade->hide(); - m_shade2 = new Button(this, Skin::PL_BT_SHADE2_N, Skin::PL_BT_SHADE2_P); - m_shade2->move(254,3); - connect(m_shade2, SIGNAL(clicked()), SLOT(shade())); - m_shade2->show(); - } - else - { - m_pl->setMinimumSize (275,116); - m_pl->setMaximumSize (10000,10000); - m_pl->resize(width(),m_height); - delete m_shade2; - m_shade2 = 0; - m_shade->show(); - } - showCurrent(); - update(); - if (m_align) - Dock::getPointer()->align(m_pl, m_shaded? -m_height+14: m_height-14); -} - -void PlayListTitleBar::showCurrent() -{ - if (m_model) - { - MediaFile* info = m_model->currentItem(); - if (info) - { - m_text = QString("%1. ").arg(m_model->currentRow()+1); - m_text.append(info->title()); - m_text.append(QString(" (%1:%2)").arg(info->length()/60).arg(info->length()%60)); - } - else - m_text.clear(); - } - truncate(); - drawPixmap((width()-275)/25); -} - -void PlayListTitleBar::truncate() -{ - m_truncatedText = m_text; - QFontMetrics metrics(m_font); - bool truncate = FALSE; - while (metrics.width(m_truncatedText) > (this->width() - 35)) - { - truncate = TRUE; - m_truncatedText = m_truncatedText.left(m_truncatedText.length()-1); - } - if (truncate) - m_truncatedText = m_truncatedText.left(m_truncatedText.length()-3).trimmed()+"..."; -} diff --git a/src/playlisttitlebar.h b/src/playlisttitlebar.h deleted file mode 100644 index f50018371..000000000 --- a/src/playlisttitlebar.h +++ /dev/null @@ -1,78 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef PLAYLISTTITLEBAR_H -#define PLAYLISTTITLEBAR_H - -#include "playlist.h" -#include "pixmapwidget.h" -#include "mainwindow.h" - -/** - @author Ilya Kotov -*/ -class Skin; -class MainWindow; -class Button; -class PlayListModel; - -class PlayListTitleBar : public PixmapWidget -{ -Q_OBJECT -public: - PlayListTitleBar(QWidget *parent = 0); - - ~PlayListTitleBar(); - - void setActive(bool); - void setModel(PlayListModel *model); - void readSettings(); - -private slots: - void updateSkin(); - void shade(); - void showCurrent(); - -private: - void drawPixmap(int); - void truncate(); - Skin *m_skin; - QPoint pos; - bool m_active; - PlayList* m_pl; - MainWindow* m_mw; - Button* m_close; - Button* m_shade; - Button* m_shade2; - bool m_shaded; - bool m_align, m_resize; - int m_height; - PlayListModel* m_model; - QString m_text; - QString m_truncatedText; - QFont m_font; - -protected: - void resizeEvent(QResizeEvent*); - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); -}; - -#endif diff --git a/src/playstate.cpp b/src/playstate.cpp deleted file mode 100644 index 373619574..000000000 --- a/src/playstate.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -ShufflePlayState::ShufflePlayState(PlayListModel * model) : PlayState(model) -{ - prepare(); -} - -bool ShufflePlayState::next() -{ - int itm_count = m_model->items().count(); - - if (itm_count > 0) - { - if (m_shuffled_current >= m_shuffled_indexes.count() -1 ) - { - if (!m_model->isRepeatableList()) - return FALSE; - else - prepare(); - } - - if (m_shuffled_current < m_shuffled_indexes.count() - 1)m_shuffled_current++; - - return m_model->setCurrent(m_shuffled_indexes.at(m_shuffled_current)); - } - return FALSE; -} - -bool ShufflePlayState::previous() -{ - int itm_count = m_model->items().count(); - - if (itm_count > 0) - { - if (m_shuffled_current <= 0) - { - if (!m_model->isRepeatableList()) - return FALSE; - else - { - prepare(); - m_shuffled_current = m_shuffled_indexes.count() - 1; - } - } - - if (itm_count > 1) m_shuffled_current --; - - m_model->setCurrent(m_shuffled_indexes.at(m_shuffled_current)); - return TRUE; - } - return FALSE; -} - -void ShufflePlayState::prepare() -{ - resetState(); - for (int i = 0;i < m_model->items().count();i++) - { - if (i != m_model->currentRow()) - m_shuffled_indexes << i; - } - - for (int i = 0;i < m_shuffled_indexes.count();i++) - m_shuffled_indexes.swap(qrand()%m_shuffled_indexes.size(),qrand()%m_shuffled_indexes.size()); - - m_shuffled_indexes.prepend(m_model->currentRow()); -} - -void ShufflePlayState::resetState() -{ - m_shuffled_indexes.clear(); - m_shuffled_current = 0; -} - - - - - -NormalPlayState::NormalPlayState(PlayListModel * model) : PlayState(model) -{} - - -bool NormalPlayState::next() -{ - int itm_count = m_model->items().count(); - - if (itm_count > 0) - { - if ( m_model->currentRow() == itm_count - 1) - { - if (m_model->isRepeatableList()) - return m_model->setCurrent(0); - else - return FALSE; - } - return m_model->setCurrent(m_model->currentRow() + 1); - } - else - return FALSE; -} - -bool NormalPlayState::previous() -{ - int itm_count = m_model->items().count(); - - if (itm_count > 0) - { - if ( m_model->currentRow() < 1 && !m_model->isRepeatableList()) - return FALSE; - else if (m_model->setCurrent(m_model->currentRow() - 1)) - return TRUE; - else if (m_model->isRepeatableList()) - return m_model->setCurrent(m_model->items().count() - 1); - } - - return FALSE; -} - diff --git a/src/playstate.h b/src/playstate.h deleted file mode 100644 index e4af7fa6f..000000000 --- a/src/playstate.h +++ /dev/null @@ -1,109 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ - -#ifndef _PLAYSTATE_H -#define _PLAYSTATE_H - -/** - @author Vladimir Kuznetsov - */ - -#include - -/*! - * Abstract class that represents data model playing states - */ -class PlayState -{ -public: - /*! Makes single step forward through songs list. - * If the step has done returns \b true, otherwise \b false - */ - virtual bool next() = 0; - - /*! Makes single step back through songs list. - * If the step has done returns \b true, otherwise \b false - */ - virtual bool previous() = 0; - - /*! - * Service method, resets state to it's defaults. - */ - virtual void resetState() - { - ; - }; - - /*! - * Service method, can be used for state initializing. - */ - virtual void prepare() - { - ; - } - virtual ~PlayState() - { - ; - } - PlayState(PlayListModel* model) : m_model(model) - { - ; - } -protected: - - /// Data model - PlayListModel* m_model; -}; - -/*! - * Represents normal playing state. - * @author Vladimir Kuznetsov - */ -class NormalPlayState : public PlayState -{ -public: - virtual bool next(); - virtual bool previous(); - NormalPlayState(PlayListModel* model); -}; - -/*! - * Represents shuffle playing state. - * @author Vladimir Kuznetsov - */ -class ShufflePlayState : public PlayState -{ -public: - virtual bool next(); - virtual bool previous(); - virtual void prepare(); - ShufflePlayState(PlayListModel* model); - virtual void resetState(); -private: - - /// Current shuffled index. - int m_shuffled_current; - - /// List of indexes used for shuffled playing. - QList m_shuffled_indexes; -}; - - -#endif diff --git a/src/playstatus.cpp b/src/playstatus.cpp deleted file mode 100644 index 913199c4f..000000000 --- a/src/playstatus.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "skin.h" -#include "playstatus.h" - -PlayStatus::PlayStatus ( QWidget *parent ) - : PixmapWidget ( parent ) -{ - m_skin = Skin::getPointer(); - setStatus ( STOP ); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); -} - - -PlayStatus::~PlayStatus() -{} - -void PlayStatus::setStatus ( Type st ) -{ - m_status = st; - switch ( ( uint ) st ) - { - case PLAY: - { - setPixmap ( m_skin->getItem ( Skin::PLAY )); - break; - } - case STOP: - { - setPixmap ( m_skin->getItem ( Skin::STOP )); - break; - } - case PAUSE: - { - setPixmap ( m_skin->getItem ( Skin::PAUSE )); - break; - } - } -} - -void PlayStatus::updateSkin() -{ - setStatus ( m_status ); -} - - diff --git a/src/playstatus.h b/src/playstatus.h deleted file mode 100644 index b050de1ca..000000000 --- a/src/playstatus.h +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef PLAYSTATUS_H -#define PLAYSTATUS_H - -#include - -/** - @author Ilya Kotov -*/ -class Skin; - -class PlayStatus : public PixmapWidget -{ -Q_OBJECT -public: - PlayStatus(QWidget *parent = 0); - - ~PlayStatus(); - - enum Type - { - PLAY, - STOP, - PAUSE, - }; - -void setStatus(Type); - -private slots: - void updateSkin(); - -private: - Skin *m_skin; - Type m_status; -}; - -#endif diff --git a/src/pluginitem.cpp b/src/pluginitem.cpp deleted file mode 100644 index fc32f8ab8..000000000 --- a/src/pluginitem.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "pluginitem.h" - -/*Input*/ -InputPluginItem::InputPluginItem(QObject *parent, DecoderFactory *fact, - const QString &filePath) - : QObject(parent) -{ - m_fileName = filePath.section('/',-1); - m_factory = fact; -} - -InputPluginItem::~InputPluginItem() -{} - -bool InputPluginItem::isSelected() -{ - QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); - QStringList blacklist = settings.value("Decoder/disabled_plugins").toStringList(); - return !blacklist.contains(m_fileName); -} - -DecoderFactory* InputPluginItem::factory() -{ - return m_factory; -} - -void InputPluginItem::setSelected(bool select) -{ - QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); - QStringList blacklist = settings.value("Decoder/disabled_plugins").toStringList(); - if (select) - blacklist.removeAll (m_fileName); - else - blacklist.append (m_fileName); - settings.setValue("Decoder/disabled_plugins", blacklist); -} - -/*Output*/ -OutputPluginItem::OutputPluginItem(QObject *parent, OutputFactory *fact, - const QString &filePath): QObject(parent) -{ - m_fileName = filePath.section('/',-1); - m_factory = fact; -} - - -OutputPluginItem::~OutputPluginItem() -{} - -void OutputPluginItem::select() -{ - QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); - settings.setValue("Output/plugin_file", m_fileName); -} - -bool OutputPluginItem::isSelected() -{ - QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); - return m_fileName == settings.value("Output/plugin_file","libalsa.so").toString(); -} - -OutputFactory *OutputPluginItem::factory() -{ - return m_factory; -} - -/*Visual*/ -VisualPluginItem::VisualPluginItem(QObject *parent, VisualFactory *fact, - const QString &filePath): QObject(parent) -{ - m_fileName = filePath.section('/',-1); - m_factory = fact; -} - - -VisualPluginItem::~VisualPluginItem() -{} - -void VisualPluginItem::select(bool on) -{ - if(on) - SoundCore::instance()->addVisual(m_factory, 0); - else - SoundCore::instance()->removeVisual(m_factory); -} - -bool VisualPluginItem::isSelected() -{ - return Visual::isEnabled(m_factory); -} - -VisualFactory *VisualPluginItem::factory() -{ - return m_factory; -} - -/*Effect*/ -EffectPluginItem::EffectPluginItem(QObject *parent, EffectFactory *fact, - const QString &filePath): QObject(parent) -{ - m_fileName = filePath.section('/',-1); - m_factory = fact; -} - - -EffectPluginItem::~EffectPluginItem() -{} - -void EffectPluginItem::select(bool on) -{ - Effect::setEnabled(m_factory, on); -} - -bool EffectPluginItem::isSelected() -{ - return Effect::isEnabled(m_factory); -} - -EffectFactory *EffectPluginItem::factory() -{ - return m_factory; -} diff --git a/src/pluginitem.h b/src/pluginitem.h deleted file mode 100644 index 11798ee25..000000000 --- a/src/pluginitem.h +++ /dev/null @@ -1,112 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef PLUGINITEM_H -#define PLUGINITEM_H - -#include - -/** - @author Ilya Kotov -*/ - -class DecoderFactory; -class OutputFactory; -class VisualFactory; -class EffectFactory; - -class InputPluginItem : public QObject -{ - Q_OBJECT -public: - InputPluginItem(QObject *parent, DecoderFactory *fact, const QString &filePath); - - ~InputPluginItem(); - - bool isSelected(); - DecoderFactory * factory(); - -public slots: - void setSelected(bool); - -private: - QString m_fileName; - DecoderFactory *m_factory; - -}; - -class OutputPluginItem : public QObject -{ - Q_OBJECT -public: - OutputPluginItem(QObject *parent, OutputFactory *fact, const QString &filePath); - - ~OutputPluginItem(); - - bool isSelected(); - OutputFactory * factory(); - -public slots: - void select(); - -private: - QString m_fileName; - OutputFactory *m_factory; - -}; - -class VisualPluginItem : public QObject -{ - Q_OBJECT -public: - VisualPluginItem(QObject *parent, VisualFactory *fact, const QString &filePath); - - ~VisualPluginItem(); - - bool isSelected(); - VisualFactory * factory(); - -public slots: - void select(bool); - -private: - QString m_fileName; - VisualFactory *m_factory; -}; - -class EffectPluginItem : public QObject -{ - Q_OBJECT -public: - EffectPluginItem(QObject *parent, EffectFactory *fact, const QString &filePath); - - ~EffectPluginItem(); - - bool isSelected(); - EffectFactory * factory(); - -public slots: - void select(bool); - -private: - QString m_fileName; - EffectFactory *m_factory; -}; - -#endif diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt new file mode 100644 index 000000000..42382b5cd --- /dev/null +++ b/src/plugins/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(Input) +add_subdirectory(Output) +add_subdirectory(Visual) +add_subdirectory(Effect) \ No newline at end of file diff --git a/src/plugins/Effect/CMakeLists.txt b/src/plugins/Effect/CMakeLists.txt new file mode 100644 index 000000000..a777010b9 --- /dev/null +++ b/src/plugins/Effect/CMakeLists.txt @@ -0,0 +1,8 @@ +SET(USE_SRC TRUE CACHE BOOL "enable/disable SRC plugin") + +IF(USE_SRC) +MESSAGE( STATUS "SRC ON") +add_subdirectory(srconverter) +ELSE(USE_SRC) +MESSAGE( STATUS "SRC OFF") +ENDIF(USE_SRC) diff --git a/src/plugins/Effect/Effect.pro b/src/plugins/Effect/Effect.pro new file mode 100644 index 000000000..b03c8a598 --- /dev/null +++ b/src/plugins/Effect/Effect.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS += srconverter + diff --git a/src/plugins/Effect/srconverter/CMakeLists.txt b/src/plugins/Effect/srconverter/CMakeLists.txt new file mode 100644 index 000000000..ef95abf79 --- /dev/null +++ b/src/plugins/Effect/srconverter/CMakeLists.txt @@ -0,0 +1,76 @@ +project(libsrconverter) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +PKGCONFIG(samplerate SAMPLERATE_INCLUDE_DIR SAMPLERATE_LINK_DIR SAMPLERATE_LINK_FLAGS SAMPLERATE_CFLAGS) + +IF(NOT SAMPLERATE_LINK_FLAGS) + SET(SAMPLERATE_LINK_FLAGS -lsamplerate) +ENDIF(NOT SAMPLERATE_LINK_FLAGS) + +include_directories(${SAMPLERATE_INCLUDE_DIR}) +link_directories(${SAMPLERATE_LINK_DIR}) + +ADD_DEFINITIONS(${SAMPLERATE_CFLAGS}) + +SET(libsrconverter_SRCS + srconverter.cpp + settingsdialog.cpp + effectsrconverterfactory.cpp +) + +SET(libsrconverter_MOC_HDRS + srconverter.h + settingsdialog.h + effectsrconverterfactory.h +) + +#SET(libsrconverter_RCCS translations/translations.qrc) + +#QT4_ADD_RESOURCES(libsrconverter_RCC_SRCS ${libsrconverter_RCCS}) + +QT4_WRAP_CPP(libsrconverter_MOC_SRCS ${libsrconverter_MOC_HDRS}) + +# user interface + + +SET(libsrconverter_UIS + settingsdialog.ui +) + +QT4_WRAP_UI(libsrconverter_UIS_H ${libsrconverter_UIS}) +# Don't forget to include output directory, otherwise +# the UI file won't be wrapped! +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(srconverter SHARED ${libsrconverter_SRCS} ${libsrconverter_MOC_SRCS} ${libsrconverter_UIS_H} + ${libsrconverter_RCC_SRCS}) +target_link_libraries(srconverter ${QT_LIBRARIES} -lqmmp ${SAMPLERATE_LINK_FLAGS}) +install(TARGETS srconverter DESTINATION ${LIB_DIR}/qmmp/Effect) + diff --git a/src/plugins/Effect/srconverter/effectsrconverterfactory.cpp b/src/plugins/Effect/srconverter/effectsrconverterfactory.cpp new file mode 100644 index 000000000..bd4f93c1b --- /dev/null +++ b/src/plugins/Effect/srconverter/effectsrconverterfactory.cpp @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "settingsdialog.h" +#include "effectsrconverterfactory.h" +#include "srconverter.h" + +const EffectProperties EffectSRConverterFactory::properties() const +{ + EffectProperties properties; + properties.name = tr("SRC Plugin"); + return properties; +}; + +Effect *EffectSRConverterFactory::create(QObject *parent) +{ + return new SRConverter(parent); +}; + +void EffectSRConverterFactory::showSettings(QWidget *parent) +{ + SettingsDialog *s = new SettingsDialog(parent); + s ->show(); +}; + +void EffectSRConverterFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About Sample Rate Converter Plugin"), + tr("Qmmp Sample Rate Converter Plugin")+"\n"+ + tr("Writen by: Ilya Kotov ")); +}; + +QTranslator *EffectSRConverterFactory::createTranslator(QObject *parent) +{ + return 0; +}; + +Q_EXPORT_PLUGIN(EffectSRConverterFactory) diff --git a/src/plugins/Effect/srconverter/effectsrconverterfactory.h b/src/plugins/Effect/srconverter/effectsrconverterfactory.h new file mode 100644 index 000000000..4112a3af5 --- /dev/null +++ b/src/plugins/Effect/srconverter/effectsrconverterfactory.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef EFFECTSRCONVERTERFACTORY_H +#define EFFECTSRCONVERTERFACTORY_H + + +#include + +#include +#include + +/** + @author Ilya Kotov +*/ +class EffectSRConverterFactory : public QObject, public EffectFactory +{ +Q_OBJECT +Q_INTERFACES(EffectFactory); + +public: + const EffectProperties properties() const; + Effect *create(QObject *parent); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); +}; + + +#endif diff --git a/src/plugins/Effect/srconverter/settingsdialog.cpp b/src/plugins/Effect/srconverter/settingsdialog.cpp new file mode 100644 index 000000000..d4e017bba --- /dev/null +++ b/src/plugins/Effect/srconverter/settingsdialog.cpp @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "settingsdialog.h" + +SettingsDialog::SettingsDialog(QWidget *parent) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, TRUE); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + ui.srSpinBox->setValue(settings.value("SRC/sample_rate",48000).toInt()); + ui.engineComboBox->setCurrentIndex(settings.value("SRC/engine", 0).toInt()); + connect (ui.okButton, SIGNAL(clicked()),SLOT(writeSettings())); +} + + +SettingsDialog::~SettingsDialog() +{ +} + +void SettingsDialog::writeSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.setValue("SRC/sample_rate",ui.srSpinBox->value()); + settings.setValue("SRC/engine", ui.engineComboBox->currentIndex()); + accept(); +} diff --git a/src/plugins/Effect/srconverter/settingsdialog.h b/src/plugins/Effect/srconverter/settingsdialog.h new file mode 100644 index 000000000..b7c466477 --- /dev/null +++ b/src/plugins/Effect/srconverter/settingsdialog.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include + +#include "ui_settingsdialog.h" + +/** + @author Ilya Kotov +*/ +class SettingsDialog : public QDialog +{ +Q_OBJECT +public: + SettingsDialog(QWidget *parent = 0); + + ~SettingsDialog(); + +private slots: + void writeSettings(); + +private: + Ui::SettingsDialog ui; + +}; + +#endif diff --git a/src/plugins/Effect/srconverter/settingsdialog.ui b/src/plugins/Effect/srconverter/settingsdialog.ui new file mode 100644 index 000000000..e837c9cf0 --- /dev/null +++ b/src/plugins/Effect/srconverter/settingsdialog.ui @@ -0,0 +1,124 @@ + + SettingsDialog + + + + 0 + 0 + 357 + 107 + + + + Sample Rate Converter Plugin Settings + + + + + + Sample Rate (Hz): + + + + + + + 96000 + + + 100 + + + 48000 + + + + + + + Interpolation Engine: + + + + + + + + Best Sinc Interpolation + + + + + Medium Sinc Interpolation + + + + + Fastest Sinc Interpolation + + + + + ZOH Interpolation + + + + + Linear Interpolation + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + &OK + + + + + + + &Cancel + + + + + + + + + + + cancelButton + clicked() + SettingsDialog + reject() + + + 302 + 88 + + + 42 + 69 + + + + + diff --git a/src/plugins/Effect/srconverter/srconverter.cpp b/src/plugins/Effect/srconverter/srconverter.cpp new file mode 100644 index 000000000..0e733c8c4 --- /dev/null +++ b/src/plugins/Effect/srconverter/srconverter.cpp @@ -0,0 +1,125 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include "srconverter.h" + +SRConverter::SRConverter(QObject* parent) : Effect(parent) +{ + m_isSrcAlloc = FALSE; + int converter_type_array[] = {SRC_SINC_BEST_QUALITY, SRC_SINC_MEDIUM_QUALITY, SRC_SINC_FASTEST, + SRC_ZERO_ORDER_HOLD, SRC_LINEAR}; + m_srcIn = 0; + m_srcOut = 0; + m_src_state = 0; + m_srcError = 0; + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + m_overSamplingFs = settings.value("SRC/sample_rate",48000).toInt(); + m_converter_type = converter_type_array[settings.value("SRC/engine", 0).toInt()]; +} + +SRConverter::~SRConverter() +{ + src_reset (m_src_state) ; + freeSRC(); + m_src_data.data_in = 0; + m_src_data.data_out = 0; + m_src_data.end_of_input = 0; + m_src_data.input_frames = 0; + m_src_data.output_frames = 0; + if (m_isSrcAlloc) + { + free(m_srcIn); + free(m_srcOut); + free(m_wOut); + m_isSrcAlloc = FALSE; + } +} + +const ulong SRConverter::process(char *in_data, const ulong size, char **out_data) +{ + if (m_isSrcAlloc) + { + free(m_srcIn); + free(m_srcOut); + free(m_wOut); + m_isSrcAlloc = FALSE; + } + ulong wbytes = 0; + + if (m_src_state && size > 0) + { + int lrLength = size/2; + int overLrLength= (int)floor(lrLength*(m_src_data.src_ratio+1)); + m_srcIn = (float*) malloc(sizeof(float)*lrLength); + m_srcOut = (float*) malloc(sizeof(float)*overLrLength); + m_wOut = (short int*) malloc(sizeof(short int)*overLrLength); + src_short_to_float_array((short int*)in_data, m_srcIn, lrLength); + m_isSrcAlloc = TRUE; + m_src_data.data_in = m_srcIn; + m_src_data.data_out = m_srcOut; + m_src_data.end_of_input = 0; + m_src_data.input_frames = lrLength/2; + m_src_data.output_frames = overLrLength/2; + if ((m_srcError = src_process(m_src_state, &m_src_data)) > 0) + { + qWarning("SRConverter: src_process(): %s\n", src_strerror(m_srcError)); + } + else + { + src_float_to_short_array(m_srcOut, m_wOut, m_src_data.output_frames_gen*2); + wbytes = m_src_data.output_frames_gen*4; + *out_data = new char[wbytes]; + memcpy(*out_data, (char*) m_wOut, wbytes); + } + } + return wbytes; +} + +void SRConverter::configure(ulong freq, int chan, int res) +{ + Effect::configure(freq, chan, res); + freeSRC(); + uint rate = freq; + { + m_src_state = src_new(m_converter_type, 2, &m_srcError); + if (m_src_state) + { + m_src_data.src_ratio = (float)m_overSamplingFs/(float)rate; + rate = m_overSamplingFs; + } + else + qDebug("SRConverter: src_new(): %s", src_strerror(m_srcError)); + } +} + +const ulong SRConverter::frequency() +{ + return m_overSamplingFs; +} + +void SRConverter::freeSRC() +{ + if (m_src_state != NULL) + m_src_state = src_delete(m_src_state); +} diff --git a/src/plugins/Effect/srconverter/srconverter.h b/src/plugins/Effect/srconverter/srconverter.h new file mode 100644 index 000000000..8c6dcb6d3 --- /dev/null +++ b/src/plugins/Effect/srconverter/srconverter.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SRCONVERTER_H +#define SRCONVERTER_H + +#include + +extern "C" +{ +#include +} + +/** + @author Ilya Kotov +*/ + +class SRConverter : public Effect +{ + Q_OBJECT +public: + SRConverter(QObject *parent = 0); + + virtual ~SRConverter(); + + const ulong process(char *in_data, const ulong size, char **out_data); + void configure(ulong freq, int chan, int res); + const ulong frequency(); + +private: + void freeSRC(); + SRC_STATE *m_src_state; + SRC_DATA m_src_data; + int m_overSamplingFs; + int m_srcError; + int m_converter_type; + bool m_isSrcAlloc; + float *m_srcIn, *m_srcOut; + short *m_wOut; + ulong m_freq; +}; + +#endif diff --git a/src/plugins/Effect/srconverter/srconverter.pro b/src/plugins/Effect/srconverter/srconverter.pro new file mode 100644 index 000000000..af20c1e92 --- /dev/null +++ b/src/plugins/Effect/srconverter/srconverter.pro @@ -0,0 +1,34 @@ +include(../../plugins.pri) + +HEADERS += srconverter.h \ + effectsrconverterfactory.h \ + settingsdialog.h + +SOURCES += srconverter.cpp \ + effectsrconverterfactory.cpp \ + settingsdialog.cpp + +TARGET=$$PLUGINS_PREFIX/Effect/srconverter +QMAKE_CLEAN =$$PLUGINS_PREFIX/Effect/libsrconverter.so +INCLUDEPATH += ../../../qmmp +CONFIG += release \ +warn_on \ +plugin \ +link_pkgconfig + +PKGCONFIG += samplerate +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmp -L/usr/lib -I/usr/include + +#TRANSLATIONS = translations/ffmpeg_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty(LIB_DIR){ + LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/Effect +INSTALLS += target + +FORMS += settingsdialog.ui + diff --git a/src/plugins/General/General.pro b/src/plugins/General/General.pro new file mode 100644 index 000000000..11f567452 --- /dev/null +++ b/src/plugins/General/General.pro @@ -0,0 +1,4 @@ +SUBDIRS += statusicon \ + scrobbler \ + dbuscontrol +TEMPLATE = subdirs diff --git a/src/plugins/General/dbuscontrol/dbusadaptor.cpp b/src/plugins/General/dbuscontrol/dbusadaptor.cpp new file mode 100644 index 000000000..77ace9208 --- /dev/null +++ b/src/plugins/General/dbuscontrol/dbusadaptor.cpp @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "dbusadaptor.h" + +DBUSAdaptor::DBUSAdaptor(QObject *parent) + : QDBusAbstractAdaptor(parent) +{ + setAutoRelaySignals(TRUE); +} + +DBUSAdaptor::~DBUSAdaptor() +{ +} + +void DBUSAdaptor::play() +{ + QMetaObject::invokeMethod(parent(), "play"); +} + +void DBUSAdaptor::stop() +{ + QMetaObject::invokeMethod(parent(), "stop"); +} + +void DBUSAdaptor::next() +{ + QMetaObject::invokeMethod(parent(), "next"); +} + +void DBUSAdaptor::previous() +{ + QMetaObject::invokeMethod(parent(), "previous"); +} + +void DBUSAdaptor::pause() +{ + QMetaObject::invokeMethod(parent(), "pause"); +} + +void DBUSAdaptor::exit() +{ + QMetaObject::invokeMethod(parent(), "exit"); +} + + diff --git a/src/plugins/General/dbuscontrol/dbusadaptor.h b/src/plugins/General/dbuscontrol/dbusadaptor.h new file mode 100644 index 000000000..43294e753 --- /dev/null +++ b/src/plugins/General/dbuscontrol/dbusadaptor.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DBUSADAPTOR_H +#define DBUSADAPTOR_H + +#include + +/** + @author Ilya Kotov +*/ +class DBUSAdaptor : public QDBusAbstractAdaptor +{ +Q_OBJECT +Q_CLASSINFO("D-Bus Interface", "org.qmmp.dbus") +public: + DBUSAdaptor(QObject *parent = 0); + + ~DBUSAdaptor(); + +public slots: + void play(); + void stop(); + void next(); + void previous(); + void pause(); + void exit(); + +}; + +#endif diff --git a/src/plugins/General/dbuscontrol/dbuscontrol.cpp b/src/plugins/General/dbuscontrol/dbuscontrol.cpp new file mode 100644 index 000000000..1133cec7a --- /dev/null +++ b/src/plugins/General/dbuscontrol/dbuscontrol.cpp @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "dbusadaptor.h" +#include "dbuscontrol.h" + +DBUSControl::DBUSControl(QObject *parent) + : General(parent) +{ + new DBUSAdaptor(this); + QDBusConnection connection = QDBusConnection::sessionBus(); + connection.registerObject("/Qmmp", this); + connection.registerService("org.qmmp.dbus"); +} + + +DBUSControl::~DBUSControl() +{} + +void DBUSControl::setState(const uint &state) +{ + switch ((uint) state) + { + case General::Playing: + { + //m_tray->setIcon(QIcon(":/tray_play.png")); + break; + } + case General::Paused: + { + //m_tray->setIcon(QIcon(":/tray_pause.png")); + break; + } + case General::Stopped: + { + //m_tray->setIcon(QIcon(":/tray_stop.png")); + break; + } + } +} + +void DBUSControl::setSongInfo(const SongInfo &song) +{ +} diff --git a/src/plugins/General/dbuscontrol/dbuscontrol.h b/src/plugins/General/dbuscontrol/dbuscontrol.h new file mode 100644 index 000000000..2d5f3c91a --- /dev/null +++ b/src/plugins/General/dbuscontrol/dbuscontrol.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef STATUSICON_H +#define STATUSICON_H + + +#include + +/** + @author Ilya Kotov +*/ + +class DBUSControl : public General +{ +Q_OBJECT +public: + DBUSControl(QObject *parent = 0); + + ~DBUSControl(); + + void setState(const uint& state); + void setSongInfo(const SongInfo &song); + +}; + +#endif diff --git a/src/plugins/General/dbuscontrol/dbuscontrol.pro b/src/plugins/General/dbuscontrol/dbuscontrol.pro new file mode 100644 index 000000000..4ad8e047b --- /dev/null +++ b/src/plugins/General/dbuscontrol/dbuscontrol.pro @@ -0,0 +1,39 @@ +include(../../plugins.pri) + +CONFIG += release \ +warn_on \ +plugin \ + lib \ + qdbus + +TARGET=$$PLUGINS_PREFIX/General/dbuscontrol +QMAKE_CLEAN =$$PLUGINS_PREFIX/General/libdbuscontrol.so + +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib + +#TRANSLATIONS = translations/ffmpeg_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty(LIB_DIR){ + LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/General +INSTALLS += target +#FORMS += settingsdialog.ui + +#RESOURCES += images/images.qrc + + +HEADERS += dbuscontrolfactory.h \ + dbuscontrol.h \ + dbusadaptor.h + +SOURCES += dbuscontrolfactory.cpp \ + dbuscontrol.cpp \ + dbusadaptor.cpp + +INCLUDEPATH += ../../../../src + +LIBS += -lqmmpui + diff --git a/src/plugins/General/dbuscontrol/dbuscontrolfactory.cpp b/src/plugins/General/dbuscontrol/dbuscontrolfactory.cpp new file mode 100644 index 000000000..922962c67 --- /dev/null +++ b/src/plugins/General/dbuscontrol/dbuscontrolfactory.cpp @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "dbuscontrol.h" +#include "dbuscontrolfactory.h" + +const GeneralProperties DBUSControlFactory::properties() const +{ + GeneralProperties properties; + properties.name = tr("D-Bus Plugin"); + properties.hasAbout = TRUE; + properties.hasSettings = FALSE; + return properties; +} + +General *DBUSControlFactory::create(QObject *parent) +{ + return new DBUSControl(parent); +} + +void DBUSControlFactory::showSettings(QWidget *) +{} + +void DBUSControlFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About D-Bus Plugin"), + tr("Qmmp D-Bus Plugin")+"\n"+ + tr("Writen by: Ilya Kotov ")); +} + +QTranslator *DBUSControlFactory::createTranslator(QObject *parent) +{ + return 0; +} + +Q_EXPORT_PLUGIN(DBUSControlFactory) diff --git a/src/plugins/General/dbuscontrol/dbuscontrolfactory.h b/src/plugins/General/dbuscontrol/dbuscontrolfactory.h new file mode 100644 index 000000000..98121edec --- /dev/null +++ b/src/plugins/General/dbuscontrol/dbuscontrolfactory.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef STATUSICONFACTORY_H +#define STATUSICONFACTORY_H + +/** + @author Ilya Kotov +*/ +#include +#include + +#include +#include + +class DBUSControlFactory : public QObject, public GeneralFactory +{ +Q_OBJECT +Q_INTERFACES(GeneralFactory); +public: + const GeneralProperties properties() const; + General *create(QObject *parent); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); + +}; + +#endif diff --git a/src/plugins/General/scrobbler/scrobbler.cpp b/src/plugins/General/scrobbler/scrobbler.cpp new file mode 100644 index 000000000..7713161b7 --- /dev/null +++ b/src/plugins/General/scrobbler/scrobbler.cpp @@ -0,0 +1,259 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scrobbler.h" + +#define SCROBBLER_HS_URL "post.audioscrobbler.com" +#define PROTOCOL_VER "1.2" +#define CLIENT_ID "qmm" +#define CLIENT_VER "0.1" + +Scrobbler::Scrobbler(QObject *parent) + : General(parent) +{ + m_http = new QHttp(this); + m_http->setHost(SCROBBLER_HS_URL, 80); + m_state = General::Stopped; + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("Scrobbler"); + m_login = settings.value("login").toString(); + m_passw = settings.value("password").toString(); + settings.endGroup(); + m_disabled = m_login.isEmpty() || m_passw.isEmpty(); + m_passw = QString(QCryptographicHash::hash(m_passw.toAscii(), QCryptographicHash::Md5).toHex()); + connect(m_http, SIGNAL(requestFinished (int, bool)), SLOT(processResponse(int, bool))); + connect(m_http, SIGNAL(readyRead (const QHttpResponseHeader&)), + SLOT(readResponse(const QHttpResponseHeader&))); + m_time = new QTime(); + m_submitedSongs = 0; + m_handshakeid = 0; + m_submitid = 0; + if (!m_disabled) + handshake(); + //TODO proxy support +} + + +Scrobbler::~Scrobbler() +{ + delete m_time; +} + +void Scrobbler::setState(const uint &state) +{ + m_state = state; + if (m_disabled) + return; + switch ((uint) state) + { + case General::Playing: + { + m_start_ts = time(NULL); + m_time->restart(); + if (!isReady() && m_handshakeid == 0) + handshake(); + break; + } + case General::Paused: + { + break; + } + case General::Stopped: + { + if (!m_song.isEmpty() + && ((m_time->elapsed ()/1000 > 240) + || (m_time->elapsed ()/1000 > int(m_song.length()/2))) + && (m_time->elapsed ()/1000 > 60)) + { + m_songCache << m_song; + m_timeStamps << m_start_ts; + } + + m_song.clear(); + if (m_songCache.isEmpty()) + break; + + if (m_http->error() != QHttp::NoError) + m_http->clearPendingRequests (); + + if (isReady() && m_submitid == 0) + { + submit(); + } + break; + } + } +} + +void Scrobbler::setSongInfo(const SongInfo &song) +{ + if (m_state == General::Playing + && !song.title().isEmpty() //skip empty tags + && !song.artist().isEmpty() + && !song.isStream() //skip stream + && !song.artist().contains("&") //skip tags with special symbols + && !song.title().contains("&") + && !song.album().contains("&") + && !song.artist().contains("=") + && !song.title().contains("=") + && !song.album().contains("=")) + { + m_song = song; + } +} + +void Scrobbler::processResponse(int id, bool error) +{ + if (error) + { + qWarning("Scrobbler: %s", qPrintable(m_http->errorString ())); + //TODO hard failure handling + + if (id == m_submitid) + m_submitid = 0; + else if (id == m_handshakeid) + m_handshakeid = 0; + return; + } + QString str(m_array); + QStringList strlist = str.split("\n"); + + if (id == m_handshakeid) + { + m_handshakeid = 0; + if (!strlist[0].contains("OK") || strlist.size() < 4) + { + qWarning("Scrobbler: handshake phase error: %s", qPrintable(strlist[0])); + //TODO badtime handling + return; + } + if (strlist.size() > 3) //process handshake response + { + qDebug("Scrobbler: reading handshake response"); + qDebug("Scrobbler: Session ID: %s",qPrintable(strlist[1])); + qDebug("Scrobbler: Now-Playing URL: %s",qPrintable(strlist[2])); + qDebug("Scrobbler: Submission URL: %s",qPrintable(strlist[3])); + m_submitUrl = strlist[3]; + m_session = strlist[1]; + return; + } + } + else if (id == m_submitid) + { + m_submitid = 0; + if (!strlist[0].contains("OK")) + { + qWarning("Scrobbler: submit error: %s", qPrintable(strlist[0])); + //TODO badsession handling + return; + } + qWarning("Scrobbler: submited %d song(s)", m_submitedSongs); + while (m_submitedSongs) + { + m_submitedSongs--; + m_timeStamps.removeFirst (); + m_songCache.removeFirst (); + } + } + m_array.clear(); +} + +void Scrobbler::readResponse(const QHttpResponseHeader &header) +{ + if (header.statusCode () != 200) + { + qWarning("Scrobbler: error: %s",qPrintable(header.reasonPhrase ())); + //TODO Failure Handling + return; + } + m_array = m_http->readAll(); +} + +void Scrobbler::handshake() +{ + qDebug("Scrobbler::handshake()"); + time_t ts = time(NULL); + qDebug("Scrobbler: current time stamp %ld",ts); + QString auth_tmp = QString("%1%2").arg(m_passw).arg(ts); + QByteArray auth = QCryptographicHash::hash(auth_tmp.toAscii (), QCryptographicHash::Md5); + auth = auth.toHex(); + + QString url = QString("%1?hs=true&p=%2&c=%3&v=%4&u=%5&t=%6&a=%7") + .arg("/") + .arg(PROTOCOL_VER) + .arg(CLIENT_ID) + .arg(CLIENT_VER) + .arg(m_login) + .arg(ts) + .arg(QString(auth)); + + qDebug("Scrobbler: request url: %s",qPrintable(url)); + m_http->setHost(SCROBBLER_HS_URL, 80); + m_handshakeid = m_http->get(url); +} + +void Scrobbler::submit() +{ + qDebug("Scrobbler::submit()"); + if (m_songCache.isEmpty()) + return; + m_submitedSongs = m_songCache.size(); + QString body = QString("s=%1").arg(m_session); + for (int i = 0; i < qMin(m_songCache.size(), 25); ++i) + { + SongInfo info = m_songCache[i]; + body += QString("&a[%9]=%1&t[%9]=%2&i[%9]=%3&o[%9]=%4&r[%9]=%5&l[%9]=%6&b[%9]=%7&n[%9]=%8&m[%9]=") + .arg(info.artist()) + .arg(info.title()) + .arg( m_timeStamps[i]) + .arg("P") + .arg("") + .arg(info.length()) + .arg(info.album()) + .arg(info.track()) + .arg(i); + } + QUrl url(m_submitUrl); + m_http->setHost(url.host(), url.port()); + QHttpRequestHeader header("POST", url.path()); + header.setContentType("application/x-www-form-urlencoded"); + header.setValue("User-Agent","iScrobbler/1.5.1qmmp-plugins/0.2"); + header.setValue("Host",url.host()); + header.setValue("Accept", "*/*"); + header.setContentLength(QUrl::toPercentEncoding(body,":/[]&=").size()); + qDebug("Scrobbler: submit request header"); + qDebug(qPrintable(header.toString())); + qDebug("*****************************"); + m_submitid = m_http->request(header, QUrl::toPercentEncoding(body,":/[]&=")); +} + +bool Scrobbler::isReady() +{ + return !m_submitUrl.isEmpty() && !m_session.isEmpty(); +} diff --git a/src/plugins/General/scrobbler/scrobbler.h b/src/plugins/General/scrobbler/scrobbler.h new file mode 100644 index 000000000..25faa13fd --- /dev/null +++ b/src/plugins/General/scrobbler/scrobbler.h @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SCROBBLER_H +#define SCROBBLER_H + +#include +#include +#include + +class QHttp; +class QTime; + + + +/** + @author Ilya Kotov +*/ + +class Scrobbler : public General +{ +Q_OBJECT +public: + Scrobbler(QObject *parent = 0); + + ~Scrobbler(); + + void setState(const uint& state); + void setSongInfo(const SongInfo &song); + +private slots: + void processResponse(int, bool); + void processResponseHeader(const QHttpResponseHeader &); + void readResponse(const QHttpResponseHeader&); + +private: + void handshake(); + void submit(); + bool isReady(); + time_t m_start_ts; + SongInfo m_song; + QHttp *m_http; + uint m_state; + QString m_login; + QString m_passw; + QString m_submitUrl; + QString m_session; + QList m_timeStamps; + QList m_songCache; + QTime* m_time; + int m_submitedSongs; + int m_handshakeid; + int m_submitid; + QByteArray m_array; + bool m_disabled; + +}; + +#endif diff --git a/src/plugins/General/scrobbler/scrobbler.pro b/src/plugins/General/scrobbler/scrobbler.pro new file mode 100644 index 000000000..787cb9f37 --- /dev/null +++ b/src/plugins/General/scrobbler/scrobbler.pro @@ -0,0 +1,41 @@ +include(../../plugins.pri) + +CONFIG += release \ + warn_on \ + plugin + +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib + +TARGET=$$PLUGINS_PREFIX/General/scrobbler +QMAKE_CLEAN =$$PLUGINS_PREFIX/General/libscrobbler.so + + +#TRANSLATIONS = translations/ffmpeg_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty(LIB_DIR){ + LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/General +INSTALLS += target +#FORMS += settingsdialog.ui + +#RESOURCES += images/images.qrc + + +HEADERS += scrobblerfactory.h \ + scrobbler.h \ + settingsdialog.h +SOURCES += scrobblerfactory.cpp \ + scrobbler.cpp \ + settingsdialog.cpp +QT += network + + +INCLUDEPATH += ../../../ + +LIBS += -lqmmpui + +FORMS += settingsdialog.ui + diff --git a/src/plugins/General/scrobbler/scrobblerfactory.cpp b/src/plugins/General/scrobbler/scrobblerfactory.cpp new file mode 100644 index 000000000..77bbb0f2b --- /dev/null +++ b/src/plugins/General/scrobbler/scrobblerfactory.cpp @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "scrobbler.h" +#include "settingsdialog.h" +#include "scrobblerfactory.h" + +const GeneralProperties ScrobblerFactory::properties() const +{ + GeneralProperties properties; + properties.name = tr("Scrobbler Plugin"); + properties.hasAbout = TRUE; + properties.hasSettings = TRUE; + return properties; +} + +General *ScrobblerFactory::create(QObject *parent) +{ + return new Scrobbler(parent); +} + +void ScrobblerFactory::showSettings(QWidget *parent) +{ + SettingsDialog *dialog = new SettingsDialog(parent); + dialog->show(); +} + +void ScrobblerFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About Scrobbler Plugin"), + tr("Qmmp AudioScrobbler Plugin")+"\n"+ + tr("Writen by: Ilya Kotov ")); +} + +QTranslator *ScrobblerFactory::createTranslator(QObject *parent) +{ + return 0; +} + +Q_EXPORT_PLUGIN(ScrobblerFactory) diff --git a/src/plugins/General/scrobbler/scrobblerfactory.h b/src/plugins/General/scrobbler/scrobblerfactory.h new file mode 100644 index 000000000..240749714 --- /dev/null +++ b/src/plugins/General/scrobbler/scrobblerfactory.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SCROBBLERFACTORY_H +#define SCROBBLERFACTORY_H + +/** + @author Ilya Kotov +*/ +#include +#include + +#include +#include + +class ScrobblerFactory : public QObject, public GeneralFactory +{ +Q_OBJECT +Q_INTERFACES(GeneralFactory); +public: + const GeneralProperties properties() const; + General *create(QObject *parent); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); + +}; + +#endif diff --git a/src/plugins/General/scrobbler/settingsdialog.cpp b/src/plugins/General/scrobbler/settingsdialog.cpp new file mode 100644 index 000000000..8dc2dfe22 --- /dev/null +++ b/src/plugins/General/scrobbler/settingsdialog.cpp @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "settingsdialog.h" + +SettingsDialog::SettingsDialog(QWidget *parent) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("Scrobbler"); + ui.userLineEdit->setText(settings.value("login").toString()); + ui.passwordLineEdit->setText(settings.value("password").toString()); + settings.endGroup(); + connect(ui.okButton, SIGNAL(clicked()), SLOT(writeSettings())); +} + + +SettingsDialog::~SettingsDialog() +{} + +void SettingsDialog::writeSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("Scrobbler"); + settings.setValue("login",ui.userLineEdit->text()); + settings.setValue("password",ui.passwordLineEdit->text()); + settings.endGroup(); + accept(); +} diff --git a/src/plugins/General/scrobbler/settingsdialog.h b/src/plugins/General/scrobbler/settingsdialog.h new file mode 100644 index 000000000..0d5b21d52 --- /dev/null +++ b/src/plugins/General/scrobbler/settingsdialog.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include + + +#include "ui_settingsdialog.h" + +/** + @author Ilya Kotov +*/ +class SettingsDialog : public QDialog +{ +Q_OBJECT +public: + SettingsDialog(QWidget *parent = 0); + + ~SettingsDialog(); + + +private slots: + void writeSettings(); + +private: + Ui::SettingsDialog ui; + +}; + +#endif diff --git a/src/plugins/General/scrobbler/settingsdialog.ui b/src/plugins/General/scrobbler/settingsdialog.ui new file mode 100644 index 000000000..ec446bba2 --- /dev/null +++ b/src/plugins/General/scrobbler/settingsdialog.ui @@ -0,0 +1,92 @@ + + SettingsDialog + + + + 0 + 0 + 250 + 123 + + + + Scrobbler Plugin Settings + + + + + + User name: + + + + + + + + + + Password: + + + + + + + QLineEdit::Password + + + + + + + + + Qt::Horizontal + + + + 61 + 20 + + + + + + + + OK + + + + + + + Cansel + + + + + + + + + + + canselButton + clicked() + SettingsDialog + reject() + + + 204 + 90 + + + 26 + 102 + + + + + diff --git a/src/plugins/General/statusicon/images/images.qrc b/src/plugins/General/statusicon/images/images.qrc new file mode 100644 index 000000000..b072b1d73 --- /dev/null +++ b/src/plugins/General/statusicon/images/images.qrc @@ -0,0 +1,8 @@ + + + + tray_play.png + tray_pause.png + tray_stop.png + + diff --git a/src/plugins/General/statusicon/images/tray_pause.png b/src/plugins/General/statusicon/images/tray_pause.png new file mode 100644 index 000000000..dfed3deb1 Binary files /dev/null and b/src/plugins/General/statusicon/images/tray_pause.png differ diff --git a/src/plugins/General/statusicon/images/tray_play.png b/src/plugins/General/statusicon/images/tray_play.png new file mode 100644 index 000000000..4d0f9099c Binary files /dev/null and b/src/plugins/General/statusicon/images/tray_play.png differ diff --git a/src/plugins/General/statusicon/images/tray_stop.png b/src/plugins/General/statusicon/images/tray_stop.png new file mode 100644 index 000000000..9e894d9eb Binary files /dev/null and b/src/plugins/General/statusicon/images/tray_stop.png differ diff --git a/src/plugins/General/statusicon/settingsdialog.cpp b/src/plugins/General/statusicon/settingsdialog.cpp new file mode 100644 index 000000000..7cb6bb1e5 --- /dev/null +++ b/src/plugins/General/statusicon/settingsdialog.cpp @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "settingsdialog.h" + +SettingsDialog::SettingsDialog(QWidget *parent) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("Tray"); + ui.messageCheckBox->setChecked(settings.value("show_message",TRUE).toBool()); + ui.messageDelaySpinBox->setValue(settings.value("message_delay", 2000).toInt()); + ui.toolTipCheckBox->setChecked(settings.value("show_tooltip",FALSE).toBool()); + ui.hideToTrayRadioButton->setChecked(settings.value("hide_on_close", FALSE).toBool()); + settings.endGroup(); + connect(ui.okButton, SIGNAL(clicked()), SLOT(writeSettings())); +} + + +SettingsDialog::~SettingsDialog() +{} + +void SettingsDialog::writeSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("Tray"); + settings.setValue ("show_message", ui.messageCheckBox->isChecked()); + settings.setValue ("message_delay", ui.messageDelaySpinBox->value()); + settings.setValue ("show_tooltip", ui.toolTipCheckBox->isChecked()); + settings.setValue ("hide_on_close", ui.hideToTrayRadioButton->isChecked()); + settings.endGroup(); + accept(); +} diff --git a/src/plugins/General/statusicon/settingsdialog.h b/src/plugins/General/statusicon/settingsdialog.h new file mode 100644 index 000000000..0d5b21d52 --- /dev/null +++ b/src/plugins/General/statusicon/settingsdialog.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include + + +#include "ui_settingsdialog.h" + +/** + @author Ilya Kotov +*/ +class SettingsDialog : public QDialog +{ +Q_OBJECT +public: + SettingsDialog(QWidget *parent = 0); + + ~SettingsDialog(); + + +private slots: + void writeSettings(); + +private: + Ui::SettingsDialog ui; + +}; + +#endif diff --git a/src/plugins/General/statusicon/settingsdialog.ui b/src/plugins/General/statusicon/settingsdialog.ui new file mode 100644 index 000000000..126fcce7a --- /dev/null +++ b/src/plugins/General/statusicon/settingsdialog.ui @@ -0,0 +1,173 @@ + + SettingsDialog + + + + 0 + 0 + 267 + 285 + + + + Status Icon Plugin Settings + + + + + + Tray Icon + + + + + + Show message + + + + + + + Show tooltip + + + + + + + Message delay, ms: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 100 + + + 10000 + + + 100 + + + 1000 + + + + + + + + + + Action On Close + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Hide to tray + + + + + + + Quit + + + true + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 131 + 31 + + + + + + + + OK + + + + + + + Cancel + + + + + + + + + + + cancelButton + clicked() + SettingsDialog + reject() + + + 336 + 210 + + + 179 + 224 + + + + + diff --git a/src/plugins/General/statusicon/statusicon.cpp b/src/plugins/General/statusicon/statusicon.cpp new file mode 100644 index 000000000..59225d028 --- /dev/null +++ b/src/plugins/General/statusicon/statusicon.cpp @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include "statusicon.h" + +StatusIcon::StatusIcon(QObject *parent) + : General(parent) +{ + m_tray = new QSystemTrayIcon(this); + connect(m_tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason))); + m_tray->setIcon ( QIcon(":/tray_stop.png")); + m_tray->show(); + QMenu *menu = new QMenu(qobject_cast(parent)); + menu->addAction(tr("Play"), this, SLOT(play())); + menu->addAction(tr("Pause"), this, SLOT(pause())); + menu->addAction(tr("Stop"), this, SLOT(stop())); + menu->addAction(tr("Next"), this, SLOT(next())); + menu->addAction(tr("Previous"), this, SLOT(previous())); + menu->addSeparator(); + menu->addAction(tr("Exit"), this, SLOT(exit())); + m_tray->setContextMenu(menu); + + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("Tray"); + m_showMessage = settings.value("show_message",TRUE).toBool(); + m_messageDelay = settings.value("message_delay", 2000).toInt(); + m_showTooltip = settings.value("show_tooltip",FALSE).toBool(); + m_hideToTray = settings.value("hide_on_close", FALSE).toBool(); + settings.endGroup(); + m_enabled = FALSE; + QTimer::singleShot(200, this, SLOT(enable())); + +} + + +StatusIcon::~StatusIcon() +{} + +void StatusIcon::setState(const uint &state) +{ + switch ((uint) state) + { + case General::Playing: + { + m_tray->setIcon(QIcon(":/tray_play.png")); + break; + } + case General::Paused: + { + m_tray->setIcon(QIcon(":/tray_pause.png")); + break; + } + case General::Stopped: + { + m_tray->setIcon(QIcon(":/tray_stop.png")); + break; + } + } +} + +void StatusIcon::setSongInfo(const SongInfo &song) +{ + if(!m_enabled) + return; + QString message = song.artist() + " - " +song.title(); + if (song.artist().isEmpty()) + message = song.title(); + if (song.title().isEmpty()) + message = song.artist(); + if (m_showMessage) + m_tray->showMessage (tr("Now Playing"), message, + QSystemTrayIcon::Information, m_messageDelay); + if (m_showTooltip) + m_tray->setToolTip(message); +} + +void StatusIcon::trayActivated(QSystemTrayIcon::ActivationReason reason) +{ + if (reason == QSystemTrayIcon::Trigger) + toggleVisibility(); +} + +void StatusIcon::enable() +{ + m_enabled = TRUE; +} diff --git a/src/plugins/General/statusicon/statusicon.h b/src/plugins/General/statusicon/statusicon.h new file mode 100644 index 000000000..fae20422d --- /dev/null +++ b/src/plugins/General/statusicon/statusicon.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef STATUSICON_H +#define STATUSICON_H + +#include + +#include + + + +/** + @author Ilya Kotov +*/ + +class StatusIcon : public General +{ +Q_OBJECT +public: + StatusIcon(QObject *parent = 0); + + ~StatusIcon(); + + void setState(const uint& state); + void setSongInfo(const SongInfo &song); + +private slots: + void trayActivated(QSystemTrayIcon::ActivationReason); + void enable(); + +private: + QSystemTrayIcon *m_tray; + bool m_showMessage; + bool m_showTooltip; + bool m_hideToTray; + bool m_enabled; + int m_messageDelay; + +}; + +#endif diff --git a/src/plugins/General/statusicon/statusicon.pro b/src/plugins/General/statusicon/statusicon.pro new file mode 100644 index 000000000..01408d1c8 --- /dev/null +++ b/src/plugins/General/statusicon/statusicon.pro @@ -0,0 +1,36 @@ +include(../../plugins.pri) + +INCLUDEPATH += ../../../../src +CONFIG += release \ +warn_on \ +plugin + +TARGET=$$PLUGINS_PREFIX/General/statusicon +QMAKE_CLEAN =$$PLUGINS_PREFIX/General/libstatusicon.so + + +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmpui + +#TRANSLATIONS = translations/ffmpeg_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty(LIB_DIR){ + LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/General +INSTALLS += target +#FORMS += settingsdialog.ui + +RESOURCES += images/images.qrc + + +HEADERS += statusiconfactory.h \ +statusicon.h \ + settingsdialog.h +SOURCES += statusiconfactory.cpp \ +statusicon.cpp \ + settingsdialog.cpp +FORMS += settingsdialog.ui + diff --git a/src/plugins/General/statusicon/statusiconfactory.cpp b/src/plugins/General/statusicon/statusiconfactory.cpp new file mode 100644 index 000000000..1d3beaa0b --- /dev/null +++ b/src/plugins/General/statusicon/statusiconfactory.cpp @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "statusicon.h" +#include "settingsdialog.h" +#include "statusiconfactory.h" + +const GeneralProperties StatusIconFactory::properties() const +{ + GeneralProperties properties; + properties.name = tr("Status Icon Plugin"); + properties.hasAbout = TRUE; + properties.hasSettings = TRUE; + return properties; +} + +General *StatusIconFactory::create(QObject *parent) +{ + return new StatusIcon(parent); +} + +void StatusIconFactory::showSettings(QWidget *parent) +{ + SettingsDialog *s = new SettingsDialog(parent); + s->show(); +} + +void StatusIconFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About Scrobbler Plugin"), + tr("Qmmp Status Icon Plugin")+"\n"+ + tr("Writen by: Ilya Kotov ")); +} + +QTranslator *StatusIconFactory::createTranslator(QObject *parent) +{ + return 0; +} + +Q_EXPORT_PLUGIN(StatusIconFactory) diff --git a/src/plugins/General/statusicon/statusiconfactory.h b/src/plugins/General/statusicon/statusiconfactory.h new file mode 100644 index 000000000..b09fb1ef1 --- /dev/null +++ b/src/plugins/General/statusicon/statusiconfactory.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef STATUSICONFACTORY_H +#define STATUSICONFACTORY_H + +/** + @author Ilya Kotov +*/ +#include +#include + +#include +#include + +class StatusIconFactory : public QObject, public GeneralFactory +{ +Q_OBJECT +Q_INTERFACES(GeneralFactory); +public: + const GeneralProperties properties() const; + General *create(QObject *parent); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); + +}; + +#endif diff --git a/src/plugins/Input/CMakeLists.txt b/src/plugins/Input/CMakeLists.txt new file mode 100644 index 000000000..8114bc092 --- /dev/null +++ b/src/plugins/Input/CMakeLists.txt @@ -0,0 +1,49 @@ + +SET(USE_MAD TRUE CACHE BOOL "enable/disable mad plugin") +SET(USE_FLAC TRUE CACHE BOOL "enable/disable flac plugin") +SET(USE_VORBIS TRUE CACHE BOOL "enable/disable ogg vorbis plugin") +SET(USE_FFMPEG TRUE CACHE BOOL "enable/disable ffmpeg plugin") +SET(USE_MPC TRUE CACHE BOOL "enable/disable mpc plugin") +SET(USE_SNDFILE TRUE CACHE BOOL "enable/disable sndfile plugin") + +IF(USE_MAD) +MESSAGE( STATUS "MAD ON") +add_subdirectory(mad) +ELSE(USE_MAD) +MESSAGE( STATUS "MAD OFF") +ENDIF(USE_MAD) + +IF(USE_FLAC) +MESSAGE( STATUS "FLAC ON") +add_subdirectory(flac) +ELSE(USE_FLAC) +MESSAGE( STATUS "FLAC OFF") +ENDIF(USE_FLAC) + +IF(USE_VORBIS) +MESSAGE( STATUS "VORBIS ON") +add_subdirectory(vorbis) +ELSE(USE_VORBIS) +MESSAGE( STATUS "VORBIS OFF") +ENDIF(USE_VORBIS) + +IF(USE_FFMPEG) +MESSAGE( STATUS "FFMPEG ON") +add_subdirectory(ffmpeg) +ELSE(USE_FFMPEG) +MESSAGE( STATUS "FFMPEG OFF") +ENDIF(USE_FFMPEG) + +IF(USE_MPC) +MESSAGE( STATUS "MPC ON") +add_subdirectory(mpc) +ELSE(USE_MPC) +MESSAGE( STATUS "MPC OFF") +ENDIF(USE_MPC) + +IF(USE_SNDFILE) +MESSAGE( STATUS "SNDFILE ON") +add_subdirectory(sndfile) +ELSE(USE_SNDFILE) +MESSAGE( STATUS "SNDFILE OFF") +ENDIF(USE_SNDFILE) diff --git a/src/plugins/Input/Input.pro b/src/plugins/Input/Input.pro new file mode 100644 index 000000000..e180229cc --- /dev/null +++ b/src/plugins/Input/Input.pro @@ -0,0 +1,26 @@ +include(../../../qmmp.pri) + +SUBDIRS += mad vorbis sndfile +TEMPLATE = subdirs + +contains(CONFIG, MUSEPACK_PLUGIN){ + SUBDIRS += mpc + message(***************************) + message(* Musepack plugin enabled *) + message(***************************) +} + +contains(CONFIG, FLAC_PLUGIN){ + SUBDIRS += flac + message(***********************) + message(* FLAC plugin enabled *) + message(***********************) +} + +contains(CONFIG, FFMPEG_PLUGIN){ + SUBDIRS += ffmpeg + message(*************************) + message(* FFMPEG plugin enabled *) + message(*************************) +} + diff --git a/src/plugins/Input/ffmpeg/CMakeLists.txt b/src/plugins/Input/ffmpeg/CMakeLists.txt new file mode 100644 index 000000000..1ca0d4b7a --- /dev/null +++ b/src/plugins/Input/ffmpeg/CMakeLists.txt @@ -0,0 +1,94 @@ +project(libffmpeg) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) +# fixes ffmpeg defines +ADD_DEFINITIONS(-D__STDC_CONSTANT_MACROS) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +# libffmpeg and taglib +PKGCONFIG(libavcodec LIBAVCODEC_INCLUDE_DIR LIBAVCODEC_LINK_DIR LIBAVCODEC_LINK_FLAGS LIBAVCODEC_CFLAGS) +PKGCONFIG(libavformat LIBAVFORMAT_INCLUDE_DIR LIBAVFORMAT_LINK_DIR LIBAVFORMAT_LINK_FLAGS LIBAVFORMAT_CFLAGS) +PKGCONFIG(taglib TAGLIB_INCLUDE_DIR TAGLIB_LINK_DIR TAGLIB_LINK_FLAGS TAGLIB_CFLAGS) + +IF(NOT LIBAVCODEC_LINK_FLAGS) + SET(LIBAVCODEC_LINK_FLAGS -lavcodec) +ENDIF(NOT LIBAVCODEC_LINK_FLAGS) + +IF(NOT LIBAVFORMAT_LINK_FLAGS) + SET(LIBAVFORMAT_LINK_FLAGS -lavformat) +ENDIF(NOT LIBAVFORMAT_LINK_FLAGS) + +IF(NOT TAGLIB_LINK_FLAGS) + SET(TAGLIB_LINK_FLAGS -ltag) + SET(TAGLIB_INCLUDE_DIR /usr/include/taglib) + SET(TAGLIB_CFLAGS -I/usr/include/taglib) +ENDIF(NOT TAGLIB_LINK_FLAGS) + +include_directories(${FLAC_INCLUDE_DIR} ${TAGLIB_INCLUDE_DIR}) +link_directories(${FLAC_LINK_DIR} ${TAGLIB_LINK_DIR}) + +ADD_DEFINITIONS(${LIBAVCODEC_CFLAGS}) +ADD_DEFINITIONS(${LIBAVFORMAT_CFLAGS}) +ADD_DEFINITIONS(${TAGLIB_CFLAGS}) + + +SET(libffmpeg_SRCS + decoder_ffmpeg.cpp + decoderffmpegfactory.cpp + detailsdialog.cpp +) + +SET(libffmpeg_MOC_HDRS + decoderffmpegfactory.h + decoder_ffmpeg.h + detailsdialog.h +) + +SET(libffmpeg_RCCS translations/translations.qrc) + +QT4_ADD_RESOURCES(libffmpeg_RCC_SRCS ${libffmpeg_RCCS}) + +QT4_WRAP_CPP(libffmpeg_MOC_SRCS ${libffmpeg_MOC_HDRS}) + +# user interface + + +SET(libffmpeg_UIS + detailsdialog.ui +) + +QT4_WRAP_UI(libffmpeg_UIS_H ${libffmpeg_UIS}) +# Don't forget to include output directory, otherwise +# the UI file won't be wrapped! +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(ffmpeg SHARED ${libffmpeg_SRCS} ${libffmpeg_MOC_SRCS} ${libffmpeg_UIS_H} + ${libffmpeg_RCC_SRCS}) +target_link_libraries(ffmpeg ${QT_LIBRARIES} -lqmmp ${LIBAVCODEC_LINK_FLAGS} ${LIBAVFORMAT_LINK_FLAGS} ${TAGLIB_LINK_FLAGS} ${TAGLIB_CFLAGS}) +install(TARGETS ffmpeg DESTINATION ${LIB_DIR}/qmmp/Input PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) + diff --git a/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp b/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp new file mode 100644 index 000000000..095f818e7 --- /dev/null +++ b/src/plugins/Input/ffmpeg/decoder_ffmpeg.cpp @@ -0,0 +1,342 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "constants.h" +#include "buffer.h" +#include "output.h" +#include "recycler.h" + +#include "decoder_ffmpeg.h" + +// Decoder class + +DecoderFFmpeg::DecoderFFmpeg(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o) + : Decoder(parent, d, i, o) +{ + inited = FALSE; + user_stop = FALSE; + stat = 0; + output_buf = 0; + output_bytes = 0; + output_at = 0; + bks = 0; + done = FALSE; + finish = FALSE; + freq = 0; + bitrate = 0; + seekTime = -1.0; + totalTime = 0.0; + chan = 0; + output_size = 0; + ic = 0; + wma_outbuf = 0; +} + + +DecoderFFmpeg::~DecoderFFmpeg() +{ + deinit(); + if (wma_outbuf) + { + delete [] wma_outbuf; + wma_outbuf = 0; + } + if (output_buf) + delete [] output_buf; + output_buf = 0; + + if (ic) + av_close_input_file(ic); +} + + +void DecoderFFmpeg::stop() +{ + user_stop = TRUE; +} + + +void DecoderFFmpeg::flush(bool final) +{ + ulong min = final ? 0 : bks; + + while ((! done && ! finish) && output_bytes > min) + { + output()->recycler()->mutex()->lock (); + + while ((! done && ! finish) && output()->recycler()->full()) + { + mutex()->unlock(); + + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + + mutex()->lock (); + done = user_stop; + } + + if (user_stop || finish) + { + inited = FALSE; + done = TRUE; + } + else + { + output_bytes -= produceSound(output_buf, output_bytes, bitrate, chan); + output_size += bks; + output_at = output_bytes; + } + + if (output()->recycler()->full()) + { + output()->recycler()->cond()->wakeOne(); + } + + output()->recycler()->mutex()->unlock(); + } +} + + +bool DecoderFFmpeg::initialize() +{ + bks = blockSize(); + inited = user_stop = done = finish = FALSE; + freq = bitrate = 0; + stat = chan = 0; + output_size = 0; + seekTime = -1.0; + totalTime = 0.0; + + + if (! input()) + { + error("DecoderFFmpeg: cannot initialize. No input."); + + return FALSE; + } + + if (! output_buf) + output_buf = new char[globalBufferSize]; + output_at = 0; + output_bytes = 0; + + if (! input()) + { + error("DecoderFFmpeg: cannot initialize. No input."); + + return FALSE; + } + + if (! output_buf) + output_buf = new char[globalBufferSize]; + output_at = 0; + output_bytes = 0; + + QString filename = qobject_cast(input())->fileName (); + input()->close(); + avcodec_init(); + avcodec_register_all(); + av_register_all(); + + AVCodec *codec; + if (av_open_input_file(&ic, filename.toLocal8Bit(), NULL,0, NULL) < 0) + { + qDebug("DecoderFFmpeg: cannot open input file"); + return FALSE; + } + for (wma_idx = 0; wma_idx < ic->nb_streams; wma_idx++) + { + c = ic->streams[wma_idx]->codec; + if (c->codec_type == CODEC_TYPE_AUDIO) break; + } + + av_find_stream_info(ic); + + codec = avcodec_find_decoder(c->codec_id); + + if (!codec) return FALSE; + if (avcodec_open(c, codec) < 0) + return FALSE; + + totalTime = ic->duration/AV_TIME_BASE; + + configure(c->sample_rate, c->channels, 16, c->bit_rate); + + bitrate = c->bit_rate; + chan = c->channels; + wma_outbuf = new uint8_t[AVCODEC_MAX_AUDIO_FRAME_SIZE*sizeof(int16_t)]; + inited = TRUE; + qDebug("DecoderFFmpeg: initialize succes"); + return TRUE; +} + + +double DecoderFFmpeg::lengthInSeconds() +{ + if (! inited) + return 0; + + return totalTime; +} + + +void DecoderFFmpeg::seek(double pos) +{ + seekTime = pos; +} + + +void DecoderFFmpeg::deinit() +{ + inited = user_stop = done = finish = FALSE; + freq = bitrate = 0; + stat = chan = 0; + output_size = 0; +} + +void DecoderFFmpeg::run() +{ +// mpc_uint32_t vbrAcc = 0; +// mpc_uint32_t vbrUpd = 0; + uint8_t *inbuf_ptr; + int out_size, size; + AVPacket pkt; + + mutex()->lock (); + + if (! inited) + { + mutex()->unlock(); + + return; + } + stat = DecoderState::Decoding; + mutex()->unlock(); + { + dispatch(DecoderState ((DecoderState::Type) stat)); + } + + while (! done && ! finish) + { + mutex()->lock (); + // decode + + if (seekTime >= 0.0) + { + int64_t timestamp; + timestamp = int64_t(seekTime)*AV_TIME_BASE; + if (ic->start_time != AV_NOPTS_VALUE) + timestamp += ic->start_time; + av_seek_frame(ic, -1, timestamp, AVSEEK_FLAG_BACKWARD); + avcodec_flush_buffers(c); + seekTime = -1.0; + } + + int l = 0; + if (av_read_frame(ic, &pkt) < 0) + { + finish = TRUE; + goto end; + } + size = pkt.size; + inbuf_ptr = pkt.data; + + out_size = 0; + + while (size > 0) + { + out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*sizeof(int16_t); + l = avcodec_decode_audio2(c, (int16_t *)(wma_outbuf), &out_size, inbuf_ptr, size); + + if(l < 0) + goto end; + ffmpeg_out(out_size); + size -= l; + inbuf_ptr += l; + if (pkt.data) + av_free_packet(&pkt); + } + bitrate = c->bit_rate/1024; +end: + if (finish) + { + flush(TRUE); + + if (output()) + { + output()->recycler()->mutex()->lock (); + // end of stream + while (! output()->recycler()->empty() && ! user_stop) + { + output()->recycler()->cond()->wakeOne(); + mutex()->unlock(); + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + mutex()->lock (); + } + output()->recycler()->mutex()->unlock(); + } + + done = TRUE; + if (! user_stop) + { + finish = TRUE; + } + } + + mutex()->unlock(); + + } + + mutex()->lock (); + + if (finish) + stat = DecoderState::Finished; + else if (user_stop) + stat = DecoderState::Stopped; + + mutex()->unlock(); + + { + dispatch(DecoderState ((DecoderState::Type) stat)); + } + + deinit(); +} + +void DecoderFFmpeg::ffmpeg_out(int size) +{ + if (size == 0) + return; + int at = 0; + int to_copy = 0; + while (size > 0 && !user_stop) + { + to_copy = qMin(int(globalBufferSize - output_at), int(size) ); + memmove ( (char *) (output_buf + output_at), wma_outbuf + at, to_copy); + at += to_copy; + size -= to_copy; + output_at += to_copy; + output_bytes += to_copy; + if (output()) + flush(); + } +} diff --git a/src/plugins/Input/ffmpeg/decoder_ffmpeg.h b/src/plugins/Input/ffmpeg/decoder_ffmpeg.h new file mode 100644 index 000000000..956e5f32b --- /dev/null +++ b/src/plugins/Input/ffmpeg/decoder_ffmpeg.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef __decoder_ffmeg_h +#define __decoder_ffmeg_h + +extern "C"{ +#include +#include +} +#include "decoder.h" + +class DecoderFFmpeg : public Decoder +{ +public: + DecoderFFmpeg(QObject *, DecoderFactory *, QIODevice *, Output *); + virtual ~DecoderFFmpeg(); + + // Standard Decoder API + bool initialize(); + double lengthInSeconds(); + void seek(double); + void stop(); + + // Equalizer + bool isEQSupported() const { return FALSE; } + void setEQEnabled(bool) { ; } + void setEQGain(int) { ; } + void setEQBands(int[10]) { ; } + + +private: + // thread run function + void run(); + // helper functions + void flush(bool = FALSE); + void deinit(); + void ffmpeg_out(int size); + + bool inited, user_stop; + int stat; + + // output buffer + char *output_buf; + ulong output_bytes, output_at; + + AVFormatContext *ic; + AVCodecContext *c; + uint wma_st_buff, wma_idx, wma_idx2; + uint8_t *wma_outbuf; + + unsigned int bks; + bool done, finish; + long freq, bitrate; + int chan; + unsigned long output_size; + double totalTime, seekTime; +}; + + +#endif // __decoder_ffmpeg_h diff --git a/src/plugins/Input/ffmpeg/decoderffmpegfactory.cpp b/src/plugins/Input/ffmpeg/decoderffmpegfactory.cpp new file mode 100644 index 000000000..789635a15 --- /dev/null +++ b/src/plugins/Input/ffmpeg/decoderffmpegfactory.cpp @@ -0,0 +1,93 @@ +#include + +extern "C"{ +#include +#include +} + +#include "detailsdialog.h" +#include "decoder_ffmpeg.h" +#include "decoderffmpegfactory.h" + + +// DecoderFFmpegFactory + +bool DecoderFFmpegFactory::supports(const QString &source) const +{ + + return (source.right(4).toLower() == ".wma" || source.right(4).toLower() == ".wav"); +} + +bool DecoderFFmpegFactory::canDecode(QIODevice *) const +{ + return FALSE; +} + +const DecoderProperties DecoderFFmpegFactory::properties() const +{ + DecoderProperties properties; + properties.name = tr("WMA Files"); + properties.filter = "*.wma *.wav"; + properties.description = tr("WMA Files"); + //properties.contentType = ""; + properties.hasAbout = TRUE; + properties.hasSettings = FALSE; + return properties; +} + +Decoder *DecoderFFmpegFactory::create(QObject *parent, QIODevice *input, + Output *output) +{ + return new DecoderFFmpeg(parent, this, input, output); +} + +FileTag *DecoderFFmpegFactory::createTag(const QString &source) +{ + FileTag *ftag = new FileTag(); + avcodec_init(); + avcodec_register_all(); + av_register_all(); + AVFormatContext *in; + + if (av_open_input_file(&in, source.toLocal8Bit(), NULL,0, NULL) < 0) + return ftag; + av_find_stream_info(in); + ftag->setValue(FileTag::ALBUM, QString::fromUtf8(in->album).trimmed()); + ftag->setValue(FileTag::ARTIST, QString::fromUtf8(in->author).trimmed()); + ftag->setValue(FileTag::COMMENT, QString::fromUtf8(in->comment).trimmed()); + ftag->setValue(FileTag::GENRE, QString::fromUtf8(in->genre).trimmed()); + ftag->setValue(FileTag::TITLE, QString::fromUtf8(in->title).trimmed()); + ftag->setValue(FileTag::YEAR, in->year); + ftag->setValue(FileTag::TRACK, in->track); + ftag->setValue(FileTag::LENGTH ,int(in->duration/AV_TIME_BASE)); + av_close_input_file(in); + return ftag; +} + +QObject* DecoderFFmpegFactory::showDetails(QWidget *parent, const QString &path) +{ + DetailsDialog *d = new DetailsDialog(parent, path); + d -> show(); + return d; +} + +void DecoderFFmpegFactory::showSettings(QWidget *) +{} + +void DecoderFFmpegFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About FFmpeg Audio Plugin"), + tr("Qmmp FFmpeg Audio Plugin")+"\n"+ + tr("Suppored formats: WMA")+"\n"+ + tr("Writen by: Ilya Kotov ")); +} + +QTranslator *DecoderFFmpegFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/ffmpeg_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(DecoderFFmpegFactory) diff --git a/src/plugins/Input/ffmpeg/decoderffmpegfactory.h b/src/plugins/Input/ffmpeg/decoderffmpegfactory.h new file mode 100644 index 000000000..16b6de1dd --- /dev/null +++ b/src/plugins/Input/ffmpeg/decoderffmpegfactory.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DECODERFFMPEGFACTORY_H +#define DECODERFFMPEGFACTORY_H + +#include +#include +#include +#include + +#include +#include +#include +#include + + + + +class DecoderFFmpegFactory : public QObject, + DecoderFactory +{ +Q_OBJECT +Q_INTERFACES(DecoderFactory); + +public: + bool supports(const QString &source) const; + bool canDecode(QIODevice *input) const; + const DecoderProperties properties() const; + Decoder *create(QObject *, QIODevice *, Output *); + FileTag *createTag(const QString &source); + QObject* showDetails(QWidget *parent, const QString &path); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); +}; + +#endif diff --git a/src/plugins/Input/ffmpeg/detailsdialog.cpp b/src/plugins/Input/ffmpeg/detailsdialog.cpp new file mode 100644 index 000000000..076cd6872 --- /dev/null +++ b/src/plugins/Input/ffmpeg/detailsdialog.cpp @@ -0,0 +1,103 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +extern "C" +{ +#include +#include +} +#include + +#include "detailsdialog.h" + +DetailsDialog::DetailsDialog(QWidget *parent, const QString &path) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + m_path = path; + setWindowTitle (path.section('/',-1)); + path.section('/',-1); + + ui.pathLineEdit->setText(m_path); + if(QFile::exists(m_path)) + loadInfo(); +} + + +DetailsDialog::~DetailsDialog() +{} + +void DetailsDialog::loadInfo() +{ + AVFormatContext *in; + avcodec_init(); + avcodec_register_all(); + av_register_all(); + if (av_open_input_file(&in, m_path.toLocal8Bit(), NULL,0, NULL) < 0) + return; + av_find_stream_info(in); + QString string = QString::fromUtf8(in->title).trimmed(); + ui.titleLineEdit->setText(string); + string = QString::fromUtf8(in->author).trimmed(); + ui.artistLineEdit->setText(string); + string = QString::fromUtf8(in->album).trimmed(); + ui.albumLineEdit->setText(string); + string = QString::fromUtf8(in->comment).trimmed(); + ui.commentLineEdit->setText(string); + string = QString("%1").arg(in->year); + ui.yearLineEdit->setText(string); + string = QString("%1").arg(in->track); + ui.trackLineEdit->setText(string); + string = QString::fromUtf8(in->genre).trimmed(); + ui.genreLineEdit->setText(string); + + QString text; + text = QString("%1").arg(int(in->duration/AV_TIME_BASE)/60); + text +=":"+QString("%1").arg(int(in->duration/AV_TIME_BASE)%60,2,10,QChar('0')); + ui.lengthLabel->setText(text); + + + text = QString("%1").arg(in->file_size/1024)+" "+tr("KB"); + ui.fileSizeLabel->setText(text); + text = QString("%1").arg(in->bit_rate/1000); + ui.bitrateLabel->setText(text+" "+tr("kbps")); + + AVCodecContext *c = 0; + uint wma_idx; + + for (wma_idx = 0; wma_idx < in->nb_streams; wma_idx++) + { + c = in->streams[wma_idx]->codec; + if (c->codec_type == CODEC_TYPE_AUDIO) break; + } + + if (c) + { + text = QString("%1").arg(c->sample_rate); + ui.sampleRateLabel->setText(text+" "+tr("Hz")); + text = QString("%1").arg(c->channels); + ui.channelsLabel->setText(text); + } + + av_close_input_file(in); +} + + diff --git a/src/plugins/Input/ffmpeg/detailsdialog.h b/src/plugins/Input/ffmpeg/detailsdialog.h new file mode 100644 index 000000000..258a1bd21 --- /dev/null +++ b/src/plugins/Input/ffmpeg/detailsdialog.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DETAILSDIALOG_H +#define DETAILSDIALOG_H + +#include + +#include "ui_detailsdialog.h" + +/** + @author Ilya Kotov +*/ +class DetailsDialog : public QDialog +{ +Q_OBJECT +public: + DetailsDialog(QWidget *parent = 0, const QString &path = 0); + + ~DetailsDialog(); + +private: + void loadInfo(); + Ui::DetailsDialog ui; + QString m_path; + +}; + +#endif diff --git a/src/plugins/Input/ffmpeg/detailsdialog.ui b/src/plugins/Input/ffmpeg/detailsdialog.ui new file mode 100644 index 000000000..70ed57052 --- /dev/null +++ b/src/plugins/Input/ffmpeg/detailsdialog.ui @@ -0,0 +1,332 @@ + + DetailsDialog + + + + 0 + 0 + 449 + 375 + + + + Details + + + + 9 + + + 6 + + + + + + 175 + 16 + + + + ASF Info + + + + 9 + + + 6 + + + + + - + + + + + + + Qt::LeftToRight + + + - + + + + + + + Bitrate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + File size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::LeftToRight + + + Channels: + + + Qt::PlainText + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Sample rate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Length: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Qt::Vertical + + + + 74 + 151 + + + + + + + + + + + + 5 + 5 + 0 + 0 + + + + WMA Tag + + + + 8 + + + 6 + + + + + false + + + Save + + + + + + + + + + Track number: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Year: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Genre: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Comment: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Album: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Artist: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Title: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 111 + 20 + + + + + + + + Close + + + + + + + File path: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + true + + + + + + + + + pushButton_3 + clicked() + DetailsDialog + close() + + + 623 + 353 + + + 539 + 352 + + + + + diff --git a/src/plugins/Input/ffmpeg/ffmpeg.pro b/src/plugins/Input/ffmpeg/ffmpeg.pro new file mode 100644 index 000000000..7de7c7d5b --- /dev/null +++ b/src/plugins/Input/ffmpeg/ffmpeg.pro @@ -0,0 +1,35 @@ +include(../../plugins.pri) + +FORMS += detailsdialog.ui +HEADERS += decoderffmpegfactory.h \ + detailsdialog.h \ + decoder_ffmpeg.h +SOURCES += detailsdialog.cpp \ + decoder_ffmpeg.cpp \ + decoderffmpegfactory.cpp + + +QMAKE_CLEAN = ../libffmpeg.so + +TARGET=$$PLUGINS_PREFIX/Input/ffmpeg +QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libffmpeg.so + + +INCLUDEPATH += ../../../qmmp +CONFIG += release \ +warn_on \ +plugin \ +link_pkgconfig +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmp -L/usr/lib -I/usr/include +DEFINES += __STDC_CONSTANT_MACROS +PKGCONFIG += libavcodec libavformat +#TRANSLATIONS = translations/ffmpeg_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/Input +INSTALLS += target diff --git a/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_cs.ts b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_cs.ts new file mode 100644 index 000000000..8f686a145 --- /dev/null +++ b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_cs.ts @@ -0,0 +1,150 @@ + + + + + DecoderFFmpegFactory + + + WMA Files + Soubory WMA + + + + About FFmpeg Audio Plugin + O pluginu FFmpeg + + + + Qmmp FFmpeg Audio Plugin + Vstupní plugin Qmmp FFmpeg + + + + Suppored formats: WMA + Podporované formáty: WMA + + + + Writen by: Ilya Kotov <forkotov02@hotmail.ru> + Autor: Ilja Kotov <forkotov02@hotmail.ru> + + + + FFmpeg Plugin + Plugin FFmpeg + + + + DetailsDialog + + + kbps + kbps + + + + Hz + Hz + + + + KB + KB + + + + Details + Podrobnosti + + + + File size: + Velikost souboru: + + + + - + - + + + + Sample rate: + Vzorkovací frakvence: + + + + Save + Uložit + + + + Track number: + Číslo stopy: + + + + Year: + Rok: + + + + Genre: + Žánr: + + + + Comment: + Komentář: + + + + Album: + Album: + + + + Artist: + Umělec: + + + + Title: + Název: + + + + Close + Zavřít + + + + File path: + Cesta k souboru: + + + + Length: + Délka: + + + + Channels: + Počet kanálů: + + + + Bitrate: + Datový tok: + + + + ASF Info + Informace ASF + + + + WMA Tag + WMA tag + + + diff --git a/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.qm b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.qm new file mode 100644 index 000000000..68ceb6f8b Binary files /dev/null and b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.qm differ diff --git a/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.ts b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.ts new file mode 100644 index 000000000..a65f434f2 --- /dev/null +++ b/src/plugins/Input/ffmpeg/translations/ffmpeg_plugin_ru.ts @@ -0,0 +1,149 @@ + + + + DecoderFFmpegFactory + + + FFmpeg Plugin + Модуль FFmpeg + + + + WMA Files + Файлы WMA + + + + About FFmpeg Audio Plugin + Об аудио-модуле FFmpeg + + + + Qmmp FFmpeg Audio Plugin + Аудио-модуль FFmpeg для Qmmp + + + + Suppored formats: WMA + Поддерживаемые форматы: WMA + + + + Writen by: Ilya Kotov <forkotov02@hotmail.ru> + Разработчик: Илья Котов <forkotov02@hotmail.ru> + + + + DetailsDialog + + + KB + Кб + + + + Hz + Гц + + + + ASF Info + Информация ASF + + + + - + + + + + Bitrate: + Битовая частота: + + + + File size: + Размер файла: + + + + Channels: + Каналов: + + + + Sample rate: + Дискретизация: + + + + Length: + Длительность: + + + + WMA Tag + WMA-тег + + + + Save + Сохранить + + + + Track number: + Номер трека: + + + + Year: + Год: + + + + Genre: + Жанр: + + + + Comment: + Комментарий: + + + + Album: + Альбом: + + + + Artist: + Исполнитель: + + + + Title: + Название: + + + + Close + Закрыть + + + + File path: + Путь к файлу: + + + + kbps + Кб/с + + + + Details + Информация + + + diff --git a/src/plugins/Input/ffmpeg/translations/translations.qrc b/src/plugins/Input/ffmpeg/translations/translations.qrc new file mode 100644 index 000000000..5e15f321d --- /dev/null +++ b/src/plugins/Input/ffmpeg/translations/translations.qrc @@ -0,0 +1,6 @@ + + + + ffmpeg_plugin_ru.qm + + diff --git a/src/plugins/Input/flac/CMakeLists.txt b/src/plugins/Input/flac/CMakeLists.txt new file mode 100644 index 000000000..24041608c --- /dev/null +++ b/src/plugins/Input/flac/CMakeLists.txt @@ -0,0 +1,86 @@ +project(libflac) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +# libflac and taglib +PKGCONFIG(flac FLAC_INCLUDE_DIR FLAC_LINK_DIR FLAC_LINK_FLAGS FLAC_CFLAGS) +PKGCONFIG(taglib TAGLIB_INCLUDE_DIR TAGLIB_LINK_DIR TAGLIB_LINK_FLAGS TAGLIB_CFLAGS) + +IF(NOT FLAC_LINK_FLAGS) + SET(FLAC_LINK_FLAGS -lFLAC) +ENDIF(NOT FLAC_LINK_FLAGS) + +IF(NOT TAGLIB_LINK_FLAGS) + SET(TAGLIB_LINK_FLAGS -ltag) + SET(TAGLIB_INCLUDE_DIR /usr/include/taglib) + SET(TAGLIB_CFLAGS -I/usr/include/taglib) +ENDIF(NOT TAGLIB_LINK_FLAGS) + +include_directories(${FLAC_INCLUDE_DIR} ${TAGLIB_INCLUDE_DIR}) +link_directories(${FLAC_LINK_DIR} ${TAGLIB_LINK_DIR}) + +ADD_DEFINITIONS(${FLAC_CFLAGS}) +ADD_DEFINITIONS(${TAGLIB_CFLAGS}) + + +SET(libflac_SRCS + decoder_flac.cpp + decoderflacfactory.cpp + detailsdialog.cpp +) + +SET(libflac_MOC_HDRS + decoderflacfactory.h + decoder_flac.h + detailsdialog.h +) + +SET(libflac_RCCS translations/translations.qrc) + +QT4_ADD_RESOURCES(libflac_RCC_SRCS ${libflac_RCCS}) + +QT4_WRAP_CPP(libflac_MOC_SRCS ${libflac_MOC_HDRS}) + +# user interface + + +SET(libflac_UIS + detailsdialog.ui +) + +QT4_WRAP_UI(libflac_UIS_H ${libflac_UIS}) +# Don't forget to include output directory, otherwise +# the UI file won't be wrapped! +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(flac SHARED ${libflac_SRCS} ${libflac_MOC_SRCS} ${libflac_UIS_H} + ${libflac_RCC_SRCS}) +target_link_libraries(flac ${QT_LIBRARIES} -lqmmp ${FLAC_LINK_FLAGS} ${FLAC_CFLAGS} ${TAGLIB_LINK_FLAGS} ${TAGLIB_CFLAGS}) +install(TARGETS flac DESTINATION ${LIB_DIR}/qmmp/Input PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) + diff --git a/src/plugins/Input/flac/decoder_flac.cpp b/src/plugins/Input/flac/decoder_flac.cpp new file mode 100644 index 000000000..b2a895bca --- /dev/null +++ b/src/plugins/Input/flac/decoder_flac.cpp @@ -0,0 +1,567 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +#include "constants.h" +#include "buffer.h" +#include "output.h" +#include "recycler.h" + +#include +#include +#include +#include "decoder_flac.h" + + + +static size_t pack_pcm_signed (FLAC__byte *data, + const FLAC__int32 * const input[], + unsigned wide_samples, + unsigned channels, unsigned bps) +{ + FLAC__byte * const start = data; + FLAC__int32 sample; + const FLAC__int32 *input_; + unsigned samples, channel; + unsigned bytes_per_sample; + unsigned incr; + + if (bps == 24) + bps = 32; /* we encode to 32-bit words */ + bytes_per_sample = bps / 8; + incr = bytes_per_sample * channels; + + for (channel = 0; channel < channels; channel++) + { + samples = wide_samples; + data = start + bytes_per_sample * channel; + input_ = input[channel]; + + while (samples--) + { + sample = *input_++; + + switch (bps) + { + case 8: + data[0] = sample; + break; + case 16: + data[1] = (FLAC__byte)(sample >> 8); + data[0] = (FLAC__byte)sample; + break; + case 32: + data[3] = (FLAC__byte)(sample >> 16); + data[2] = (FLAC__byte)(sample >> 8); + data[1] = (FLAC__byte)sample; + data[0] = 0; + break; + } + + data += incr; + } + } + + return wide_samples * channels * bytes_per_sample; +} + +static int flac_decode (void *void_data, char *buf, int buf_len) /*, + struct sound_params *sound_params)*/ +{ + //struct flac_data *data = (struct flac_data *)void_data; + DecoderFLAC *dflac = (DecoderFLAC *) void_data; + unsigned to_copy; + int bytes_per_sample; + FLAC__uint64 decode_position; + + bytes_per_sample = dflac->data()->bits_per_sample / 8; + + /*switch (bytes_per_sample) { + case 1: + sound_params->fmt = SFMT_S8; + break; + case 2: + sound_params->fmt = SFMT_S16 | SFMT_LE; + break; + case 3: + sound_params->fmt = SFMT_S32 | SFMT_LE; + break; + } + + sound_params->rate = data->sample_rate; + sound_params->channels = data->channels;*/ + + //decoder_error_clear (&data->error); + + if (!dflac->data()->sample_buffer_fill) + { + + if (FLAC__stream_decoder_get_state(dflac->data()->decoder) + == FLAC__STREAM_DECODER_END_OF_STREAM) + { + return 0; + } + + if (!FLAC__stream_decoder_process_single( + dflac->data()->decoder)) + { + return 0; + } + + /* Count the bitrate */ + if (!FLAC__stream_decoder_get_decode_position( + dflac->data()->decoder, &decode_position)) + decode_position = 0; + if (decode_position > dflac->data()->last_decode_position) + { + int bytes_per_sec = bytes_per_sample * dflac->data()->sample_rate + * dflac->data()->channels; + + dflac->data()->bitrate = int(((float)decode_position - + dflac->data()->last_decode_position) * 8.0 * + bytes_per_sec / + dflac->data()->sample_buffer_fill / 1000); + } + + dflac->data()->last_decode_position = decode_position; + } + + to_copy = qMin((unsigned)buf_len, dflac->data()->sample_buffer_fill); + memcpy (buf, dflac->data()->sample_buffer, to_copy); + memmove (dflac->data()->sample_buffer, + dflac->data()->sample_buffer + to_copy, + dflac->data()->sample_buffer_fill - to_copy); + dflac->data()->sample_buffer_fill -= to_copy; + return to_copy; +} + + +static FLAC__StreamDecoderReadStatus +flac_callback_read (const FLAC__StreamDecoder *, FLAC__byte buffer[], + size_t *bytes, void *client_data) +{ + DecoderFLAC *dflac = (DecoderFLAC *) client_data; + qint64 res; + + res = dflac->input()->read((char *)buffer, *bytes); + + if (res > 0) + { + *bytes = res; + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; + } + if (res == 0) + { + *bytes = res; + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + } + + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + +} + +static FLAC__StreamDecoderWriteStatus +flac_callback_write (const FLAC__StreamDecoder *, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) +{ + DecoderFLAC *dflac = (DecoderFLAC *) client_data; + const unsigned wide_samples = frame->header.blocksize; + + if (dflac->data()->abort) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + + + dflac->data()->sample_buffer_fill = pack_pcm_signed ( + dflac->data()->sample_buffer, + buffer, wide_samples, + dflac->data()->channels, + dflac->data()->bits_per_sample); + + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +static FLAC__StreamDecoderTellStatus +flac_callback_tell (const FLAC__StreamDecoder *, FLAC__uint64 *offset, void *client_data) +{ + DecoderFLAC *dflac = (DecoderFLAC *) client_data; + *offset = dflac->input()->pos (); + return FLAC__STREAM_DECODER_TELL_STATUS_OK; +} + +static FLAC__StreamDecoderSeekStatus +flac_callback_seek (const FLAC__StreamDecoder *, FLAC__uint64 offset, void *client_data) +{ + DecoderFLAC *dflac = (DecoderFLAC *) client_data; + + return dflac->input()->seek(offset) + ? FLAC__STREAM_DECODER_SEEK_STATUS_OK + : FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; +} + +static FLAC__StreamDecoderLengthStatus +flac_callback_length (const FLAC__StreamDecoder *, FLAC__uint64 *stream_length, void *client_data) +{ + DecoderFLAC *dflac = (DecoderFLAC *) client_data; + *stream_length = dflac->input()->size(); + return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; +} + +static void +flac_callback_metadata (const FLAC__StreamDecoder *, const FLAC__StreamMetadata *metadata, void *client_data) +{ + DecoderFLAC *dflac = (DecoderFLAC *) client_data; + + if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) + { + qDebug ("DecoderFLAC: getting metadata info"); + + dflac->data()->total_samples = + (unsigned)(metadata->data.stream_info.total_samples + & 0xffffffff); + dflac->data()->bits_per_sample = + metadata->data.stream_info.bits_per_sample; + dflac->data()->channels = metadata->data.stream_info.channels; + dflac->data()->sample_rate = metadata->data.stream_info.sample_rate; + dflac->data()->length = dflac->data()->total_samples / dflac->data()->sample_rate; + } +} + +static FLAC__bool +flac_callback_eof (const FLAC__StreamDecoder *, void *) +{ + return FALSE; +} + +static void +flac_callback_error (const FLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus status, void *client_data) +{} + +// Decoder class + +DecoderFLAC::DecoderFLAC(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o) + : Decoder(parent, d, i, o) +{ + inited = FALSE; + user_stop = FALSE; + stat = 0; + output_buf = 0; + output_bytes = 0; + output_at = 0; + bks = 0; + done = FALSE; + finish = FALSE; + len = 0; + freq = 0; + bitrate = 0; + seekTime = -1.0; + totalTime = 0.0; + chan = 0; + output_size = 0; + m_data = 0; + + + + +} + + +DecoderFLAC::~DecoderFLAC() +{ + deinit(); + if (data()) + { + if (data()->decoder) + FLAC__stream_decoder_delete (data()->decoder); + delete data(); + m_data = 0; + } + + if (output_buf) + delete [] output_buf; + output_buf = 0; +} + + +void DecoderFLAC::stop() +{ + user_stop = TRUE; +} + + +void DecoderFLAC::flush(bool final) +{ + //qDebug("DecoderFLAC: flush()"); + ulong min = final ? 0 : bks; + + while ((! done && ! finish) && output_bytes > min) + { + output()->recycler()->mutex()->lock(); + + while ((! done && ! finish) && output()->recycler()->full()) + { + mutex()->unlock(); + + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + + mutex()->lock(); + done = user_stop; + } + + if (user_stop || finish) + { + inited = FALSE; + done = TRUE; + } + else + { + output_bytes -= produceSound(output_buf, output_bytes, bitrate, chan); + output_size += bks; + output_at = output_bytes; + } + + if (output()->recycler()->full()) + { + output()->recycler()->cond()->wakeOne(); + } + + output()->recycler()->mutex()->unlock(); + } +} + + +bool DecoderFLAC::initialize() +{ + bks = blockSize(); + inited = user_stop = done = finish = FALSE; + len = freq = bitrate = 0; + stat = chan = 0; + output_size = 0; + seekTime = -1.0; + totalTime = 0.0; + + + if (! input()) + { + error("DecoderFLAC: cannot initialize. No input."); + + return FALSE; + } + + if (! output_buf) + output_buf = new char[globalBufferSize]; + output_at = 0; + output_bytes = 0; + + if (! input()->isOpen()) + { + if (! input()->open(QIODevice::ReadOnly)) + { + + return FALSE; + } + } + + + if (! input()) + { + error("DecoderFLAC: cannot initialize. No input."); + + return FALSE; + } + + if (! output_buf) + output_buf = new char[globalBufferSize]; + output_at = 0; + output_bytes = 0; + + if (! input()->isOpen()) + { + if (! input()->open(QIODevice::ReadOnly)) + { + return FALSE; + } + } + if (!m_data) + { + m_data = new flac_data; + m_data->decoder = NULL; + } + + m_data->bitrate = -1; + m_data->abort = 0; + m_data->sample_buffer_fill = 0; + m_data->last_decode_position = 0; + if (!m_data->decoder) + { + qDebug("DecoderFLAC: creating FLAC__StreamDecoder"); + m_data->decoder = FLAC__stream_decoder_new (); + } + qDebug("DecoderFLAC: setting callbacks"); + if (FLAC__stream_decoder_init_stream( + m_data->decoder, + flac_callback_read, + flac_callback_seek, + flac_callback_tell, + flac_callback_length, + flac_callback_eof, + flac_callback_write, + flac_callback_metadata, + flac_callback_error, + this) != FLAC__STREAM_DECODER_INIT_STATUS_OK) + { + data()->ok = 0; + return FALSE; + } + + if (!FLAC__stream_decoder_process_until_end_of_metadata( + data()->decoder)) + { + data()->ok = 0; + return FALSE; + } + chan = data()->channels; + configure(data()->sample_rate, data()->channels, 16, bitrate); + totalTime = data()->length; + + inited = TRUE; + qDebug("DecoderFLAC: initialize succes"); + return TRUE; +} + + +double DecoderFLAC::lengthInSeconds() +{ + if (! inited) + return 0; + + return totalTime; +} + + +void DecoderFLAC::seek(double pos) +{ + seekTime = pos; +} + + +void DecoderFLAC::deinit() +{ + if(data()) + FLAC__stream_decoder_finish (data()->decoder); + inited = user_stop = done = finish = FALSE; + len = freq = bitrate = 0; + stat = chan = 0; + output_size = 0; +} + +void DecoderFLAC::run() +{ + mutex()->lock (); + + if (! inited) + { + mutex()->unlock(); + + return; + } + stat = DecoderState::Decoding; + mutex()->unlock(); + { + dispatch(DecoderState ((DecoderState::Type) stat)); + } + + while (! done && ! finish) + { + mutex()->lock (); + // decode + + if (seekTime >= 0.0) + { + FLAC__uint64 target_sample; + + target_sample = (FLAC__uint64)((seekTime/(double)data()->length) * + (double)data()->total_samples); + + FLAC__stream_decoder_seek_absolute(data()->decoder, + target_sample); + seekTime = -1.0; + } + len = flac_decode (this, (char *) (output_buf + output_at), bks); + + if (len > 0) + { + bitrate = data()->bitrate; + output_at += len; + output_bytes += len; + + if (output()) + flush(); + + } + else if (len == 0) + { + flush(TRUE); + + if (output()) + { + output()->recycler()->mutex()->lock (); + // end of stream + while (! output()->recycler()->empty() && ! user_stop) + { + output()->recycler()->cond()->wakeOne(); + mutex()->unlock(); + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + mutex()->lock (); + } + output()->recycler()->mutex()->unlock(); + } + + done = TRUE; + if (! user_stop) + { + finish = TRUE; + } + } + else + { + // error in read + error("DecoderFLAC: Error while decoding stream, File appears to be " + "corrupted"); + + finish = TRUE; + } + + mutex()->unlock(); + } + + mutex()->lock (); + + if (finish) + stat = DecoderState::Finished; + else if (user_stop) + stat = DecoderState::Stopped; + + mutex()->unlock(); + + { + dispatch(DecoderState ((DecoderState::Type) stat)); + } + + deinit(); +} diff --git a/src/plugins/Input/flac/decoder_flac.h b/src/plugins/Input/flac/decoder_flac.h new file mode 100644 index 000000000..4c85176ed --- /dev/null +++ b/src/plugins/Input/flac/decoder_flac.h @@ -0,0 +1,124 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef __decoder_flac_h +#define __decoder_flac_h + +class DecoderOgg; + +#include "decoder.h" + +#include + +#define MAX_SUPPORTED_CHANNELS 2 + +#define SAMPLES_PER_WRITE 512 +#define SAMPLE_BUFFER_SIZE ((FLAC__MAX_BLOCK_SIZE + SAMPLES_PER_WRITE) * MAX_SUPPORTED_CHANNELS * (32/8)) + +struct flac_data +{ + //FLAC__SeekableStreamDecoder *decoder; + FLAC__StreamDecoder *decoder; + struct io_stream *stream; + int bitrate; + int abort; /* abort playing (due to an error) */ + + unsigned length; + unsigned total_samples; + + FLAC__byte sample_buffer[SAMPLE_BUFFER_SIZE]; + unsigned sample_buffer_fill; + + /* sound parameters */ + unsigned bits_per_sample; + unsigned sample_rate; + unsigned channels; + + FLAC__uint64 last_decode_position; + + int ok; /* was this stream successfully opened? */ + //struct decoder_error error; +}; + +class DecoderFLAC : public Decoder +{ +public: + DecoderFLAC(QObject *, DecoderFactory *, QIODevice *, Output *); + virtual ~DecoderFLAC(); + + // Standard Decoder API + bool initialize(); + double lengthInSeconds(); + void seek(double); + void stop(); + + // Equalizer + bool isEQSupported() const + { + return FALSE; + } + void setEQEnabled(bool) + { + ; + } + void setEQGain(int) + { + ; + } + void setEQBands(int[10]) + { + ; + } + + struct flac_data *data() + { + return m_data; + } + + +private: + // thread run function + void run(); + struct flac_data *m_data; + // helper functions + void flush(bool = FALSE); + void deinit(); + + bool inited, user_stop; + int stat; + + // output buffer + char *output_buf; + ulong output_bytes, output_at; + + // FLAC Decoder + //FLAC__SeekableStreamDecoder *m_flacDecoder; + FLAC__StreamDecoder *m_flacDecoder; + + unsigned int bks; + bool done, finish; + long len, freq, bitrate; + int chan; + unsigned long output_size; + double totalTime, seekTime; +}; + + +#endif // __decoder_flac_h diff --git a/src/plugins/Input/flac/decoderflacfactory.cpp b/src/plugins/Input/flac/decoderflacfactory.cpp new file mode 100644 index 000000000..5abb60b39 --- /dev/null +++ b/src/plugins/Input/flac/decoderflacfactory.cpp @@ -0,0 +1,95 @@ +#include +#include +#include + +#include "detailsdialog.h" +#include "decoder_flac.h" +#include "decoderflacfactory.h" + + +// DecoderFLACFactory + +bool DecoderFLACFactory::supports(const QString &source) const +{ + + return (source.right(5).toLower() == ".flac"); +} + +bool DecoderFLACFactory::canDecode(QIODevice *input) const +{ + return FALSE; +} + +const DecoderProperties DecoderFLACFactory::properties() const +{ + DecoderProperties properties; + properties.name = tr("FLAC Plugin"); + properties.filter = "*.flac"; + properties.description = tr("FLAC Files"); + //properties.contentType = ; + properties.hasAbout = TRUE; + properties.hasSettings = FALSE; + return properties; +} + +Decoder *DecoderFLACFactory::create(QObject *parent, QIODevice *input, + Output *output) +{ + return new DecoderFLAC(parent, this, input, output); +} + +FileTag *DecoderFLACFactory::createTag(const QString &source) +{ + FileTag *ftag = new FileTag(); + + TagLib::FileRef fileRef(source.toLocal8Bit ()); + TagLib::Tag *tag = fileRef.tag(); + + if (tag && !tag->isEmpty()) + { + ftag->setValue(FileTag::ALBUM, + QString::fromUtf8(tag->album().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::ARTIST, + QString::fromUtf8(tag->artist().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::COMMENT, + QString::fromUtf8(tag->comment().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::GENRE, + QString::fromUtf8(tag->genre().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::TITLE, + QString::fromUtf8(tag->title().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::YEAR, tag->year()); + ftag->setValue(FileTag::TRACK, tag->track()); + } + + if (fileRef.audioProperties()) + ftag->setValue(FileTag::LENGTH, fileRef.audioProperties()->length()); + + return ftag; +} + +QObject* DecoderFLACFactory::showDetails(QWidget *parent, const QString &path) +{ + DetailsDialog *d = new DetailsDialog(parent, path); + d -> show(); + return d; +} + +void DecoderFLACFactory::showSettings(QWidget *) +{} + +void DecoderFLACFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About FLAC Audio Plugin"), + tr("Qmmp FLAC Audio Plugin")+"\n"+ + tr("Writen by: Ilya Kotov ")); +} + +QTranslator *DecoderFLACFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/flac_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(DecoderFLACFactory) diff --git a/src/plugins/Input/flac/decoderflacfactory.h b/src/plugins/Input/flac/decoderflacfactory.h new file mode 100644 index 000000000..586bc3b33 --- /dev/null +++ b/src/plugins/Input/flac/decoderflacfactory.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DECODERFLACFACTORY_H +#define DECODERFLACFACTORY_H + +#include +#include +#include +#include + +#include +#include +#include +#include + + + + +class DecoderFLACFactory : public QObject, + DecoderFactory +{ +Q_OBJECT +Q_INTERFACES(DecoderFactory); + +public: + bool supports(const QString &source) const; + bool canDecode(QIODevice *input) const; + const DecoderProperties properties() const; + Decoder *create(QObject *, QIODevice *, Output *); + FileTag *createTag(const QString &source); + QObject* showDetails(QWidget *parent, const QString &path); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); +}; + +#endif diff --git a/src/plugins/Input/flac/detailsdialog.cpp b/src/plugins/Input/flac/detailsdialog.cpp new file mode 100644 index 000000000..2826b6cdb --- /dev/null +++ b/src/plugins/Input/flac/detailsdialog.cpp @@ -0,0 +1,118 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include +#include + +#include "detailsdialog.h" + +#define QStringToTString_qt4(s) TagLib::String(s.toUtf8().constData(), TagLib::String::UTF8) + +DetailsDialog::DetailsDialog(QWidget *parent, const QString &path) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + m_path = path; + setWindowTitle (path.section('/',-1)); + path.section('/',-1); + ui.pathLineEdit->setText(m_path); + if (QFile::exists(m_path)) + { + loadFLACInfo(); + loadTag(); + } +} + + +DetailsDialog::~DetailsDialog() +{} + +void DetailsDialog::loadFLACInfo() +{ + TagLib::FLAC::File f (m_path.toLocal8Bit()); + //l.label + //ui. f.audioProperties()->level(); + QString text; + text = QString("%1").arg(f.audioProperties()->length()/60); + text +=":"+QString("%1").arg(f.audioProperties()->length()%60,2,10,QChar('0')); + ui.lengthLabel->setText(text); + text = QString("%1").arg(f.audioProperties()->sampleRate()); + ui.sampleRateLabel->setText(text+" "+tr("Hz")); + text = QString("%1").arg(f.audioProperties()->channels()); + ui.channelsLabel->setText(text); + text = QString("%1").arg(f.audioProperties()->bitrate()); + ui.bitrateLabel->setText(text+" "+tr("kbps")); + text = QString("%1").arg(f.audioProperties()->sampleWidth()); + ui.sampleWidthLabel->setText(text+" "+tr("bits")); + text = QString("%1 "+tr("KB")).arg(f.length()/1024); + ui.fileSizeLabel->setText(text); + +} + +void DetailsDialog::loadTag() +{ + TagLib::FileRef f (m_path.toLocal8Bit()); + + if (f.tag()) + { //TODO: load codec name from config + + TagLib::String title = f.tag()->title(); + TagLib::String artist = f.tag()->artist(); + TagLib::String album = f.tag()->album(); + TagLib::String comment = f.tag()->comment(); + TagLib::String genre = f.tag()->genre(); + QString string = QString::fromUtf8(title.toCString(TRUE)).trimmed(); + ui.titleLineEdit->setText(string); + string = QString::fromUtf8(artist.toCString(TRUE)).trimmed(); + ui.artistLineEdit->setText(string); + string = QString::fromUtf8(album.toCString(TRUE)).trimmed(); + ui.albumLineEdit->setText(string); + string = QString::fromUtf8(comment.toCString(TRUE)).trimmed(); + ui.commentLineEdit->setText(string); + string = QString("%1").arg(f.tag()->year()); + ui.yearLineEdit->setText(string); + string = QString("%1").arg(f.tag()->track()); + ui.trackLineEdit->setText(string); + string = QString::fromUtf8(genre.toCString(TRUE)).trimmed(); + ui.genreLineEdit->setText(string); + } + QFileInfo info(m_path); + ui.saveButton->setEnabled(info.isWritable()); + connect(ui.saveButton, SIGNAL(clicked()), SLOT(saveTag())); +} + +void DetailsDialog::saveTag() +{ + TagLib::FileRef f (m_path.toLocal8Bit()); + + f.tag()->setTitle(QStringToTString_qt4(ui.titleLineEdit->text())); + f.tag()->setArtist(QStringToTString_qt4(ui.artistLineEdit->text())); + f.tag()->setAlbum(QStringToTString_qt4(ui.albumLineEdit->text())); + f.tag()->setComment(QStringToTString_qt4(ui.commentLineEdit->text())); + f.tag()->setGenre(QStringToTString_qt4(ui.genreLineEdit->text())); + f.tag()->setYear(ui.yearLineEdit->text().toUInt()); + f.tag()->setTrack(ui.trackLineEdit->text().toUInt()); + + f.save(); +} diff --git a/src/plugins/Input/flac/detailsdialog.h b/src/plugins/Input/flac/detailsdialog.h new file mode 100644 index 000000000..80c17544c --- /dev/null +++ b/src/plugins/Input/flac/detailsdialog.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DETAILSDIALOG_H +#define DETAILSDIALOG_H + +#include + +#include "ui_detailsdialog.h" + +/** + @author Ilya Kotov +*/ +class DetailsDialog : public QDialog +{ +Q_OBJECT +public: + DetailsDialog(QWidget *parent = 0, const QString &path = 0); + + ~DetailsDialog(); + +private slots: + void saveTag(); + +private: + void loadFLACInfo(); + void loadTag(); + Ui::DetailsDialog ui; + QString m_path; + +}; + +#endif diff --git a/src/plugins/Input/flac/detailsdialog.ui b/src/plugins/Input/flac/detailsdialog.ui new file mode 100644 index 000000000..5ea739953 --- /dev/null +++ b/src/plugins/Input/flac/detailsdialog.ui @@ -0,0 +1,349 @@ + + DetailsDialog + + + + 0 + 0 + 449 + 375 + + + + Details + + + + 8 + + + 6 + + + + + + 175 + 16 + + + + FLAC Info + + + + 8 + + + 6 + + + + + Qt::Vertical + + + + 74 + 151 + + + + + + + + - + + + + + + + Length: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Sample rate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Qt::LeftToRight + + + Channels: + + + Qt::PlainText + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + File size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Bitrate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::LeftToRight + + + - + + + + + + + - + + + + + + + Sample width: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + + + + true + + + + + + + File path: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Close + + + + + + + Qt::Horizontal + + + + 111 + 20 + + + + + + + + + 5 + 5 + 0 + 0 + + + + FLAC Tag + + + + 8 + + + 6 + + + + + false + + + Save + + + + + + + + + + Track number: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Year: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Genre: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Comment: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Album: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Artist: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Title: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + + + + + + + + + + + + pushButton_3 + clicked() + DetailsDialog + close() + + + 623 + 353 + + + 539 + 352 + + + + + diff --git a/src/plugins/Input/flac/flac.pro b/src/plugins/Input/flac/flac.pro new file mode 100644 index 000000000..4ab46c296 --- /dev/null +++ b/src/plugins/Input/flac/flac.pro @@ -0,0 +1,36 @@ +# ???? ?????? ? KDevelop ?????????? qmake. +# ------------------------------------------- +# ?????????? ???????????? ???????? ???????? ???????: ./Plugins/Input/flac +# ???? - ??????????: + +include(../../plugins.pri) + +FORMS += detailsdialog.ui +HEADERS += decoderflacfactory.h \ + decoder_flac.h \ + detailsdialog.h +SOURCES += decoder_flac.cpp \ + decoderflacfactory.cpp \ + detailsdialog.cpp + +TARGET=$$PLUGINS_PREFIX/Input/flac +QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libflac.so + +INCLUDEPATH += ../../../qmmp +CONFIG += release \ +warn_on \ +plugin \ +link_pkgconfig +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmp -L/usr/lib -I/usr/include +PKGCONFIG += taglib flac +#TRANSLATIONS = translations/flac_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/Input +INSTALLS += target + diff --git a/src/plugins/Input/flac/translations/flac_plugin_ru.qm b/src/plugins/Input/flac/translations/flac_plugin_ru.qm new file mode 100644 index 000000000..fbd97d091 Binary files /dev/null and b/src/plugins/Input/flac/translations/flac_plugin_ru.qm differ diff --git a/src/plugins/Input/flac/translations/flac_plugin_ru.ts b/src/plugins/Input/flac/translations/flac_plugin_ru.ts new file mode 100644 index 000000000..a1e9b98b7 --- /dev/null +++ b/src/plugins/Input/flac/translations/flac_plugin_ru.ts @@ -0,0 +1,154 @@ + + + + DecoderFLACFactory + + + FLAC Plugin + Модуль FLAC + + + + FLAC Files + Файлы FLAC + + + + About FLAC Audio Plugin + Об аудио-модуле FLAC + + + + Qmmp FLAC Audio Plugin + Аудио-модуль FLAC для Qmmp + + + + Writen by: Ilya Kotov <forkotov02@hotmail.ru> + Разработчик: Илья Котов <forkotov02@hotmail.ru> + + + + DetailsDialog + + + Hz + Гц + + + + bits + бит + + + + FLAC Info + Информация FLAC + + + + - + + + + + Length: + Длительность: + + + + Sample rate: + Частота сэмплов: + + + + Channels: + Каналов: + + + + File size: + Размер файла: + + + + Bitrate: + Битовая частота: + + + + Sample width: + Ширина кадра: + + + + File path: + Путь к файлу: + + + + Close + Закрыть + + + + FLAC Tag + FLAC-тег + + + + Save + Сохранить + + + + Track number: + Номер трека: + + + + Year: + Год: + + + + Genre: + Жанр: + + + + Comment: + Комментарий: + + + + Album: + Альбом: + + + + Artist: + Исполнитель: + + + + Title: + Название: + + + + kbps + Кб/с + + + + KB + Кб + + + + Details + Информация + + + diff --git a/src/plugins/Input/flac/translations/translations.qrc b/src/plugins/Input/flac/translations/translations.qrc new file mode 100644 index 000000000..cd630dfce --- /dev/null +++ b/src/plugins/Input/flac/translations/translations.qrc @@ -0,0 +1,6 @@ + + + + flac_plugin_ru.qm + + diff --git a/src/plugins/Input/mad/CMakeLists.txt b/src/plugins/Input/mad/CMakeLists.txt new file mode 100644 index 000000000..3e4dfa9d0 --- /dev/null +++ b/src/plugins/Input/mad/CMakeLists.txt @@ -0,0 +1,90 @@ +project(libmad) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +# libmad and taglib +PKGCONFIG(mad MAD_INCLUDE_DIR MAD_LINK_DIR MAD_LINK_FLAGS MAD_CFLAGS) +PKGCONFIG(taglib TAGLIB_INCLUDE_DIR TAGLIB_LINK_DIR TAGLIB_LINK_FLAGS TAGLIB_CFLAGS) + +IF(NOT MAD_LINK_FLAGS) + MESSAGE("Can not find mad.pc") + SET(MAD_LINK_FLAGS -lmad) +ENDIF(NOT MAD_LINK_FLAGS) + +IF(NOT TAGLIB_LINK_FLAGS) + SET(TAGLIB_LINK_FLAGS -ltag) + SET(TAGLIB_INCLUDE_DIR /usr/include/taglib) + SET(TAGLIB_CFLAGS -I/usr/include/taglib) +ENDIF(NOT TAGLIB_LINK_FLAGS) + +include_directories(${MAD_INCLUDE_DIR} ${TAGLIB_INCLUDE_DIR}) +link_directories(${MAD_LINK_DIR} ${TAGLIB_LINK_DIR}) + +#ADD_DEFINITIONS(${MAD_CFLAGS}) +ADD_DEFINITIONS(${TAGLIB_CFLAGS}) + + +SET(libmad_SRCS + decoder_mad.cpp + decodermadfactory.cpp + detailsdialog.cpp + settingsdialog.cpp +) + +SET(libmad_MOC_HDRS + settingsdialog.h + decodermadfactory.h + decoder_mad.h + detailsdialog.h +) + +SET(libmad_RCCS translations/translations.qrc) + +QT4_ADD_RESOURCES(libmad_RCC_SRCS ${libmad_RCCS}) + +QT4_WRAP_CPP(libmad_MOC_SRCS ${libmad_MOC_HDRS}) + +# user interface + + +SET(libmad_UIS + detailsdialog.ui + settingsdialog.ui +) + +QT4_WRAP_UI(libmad_UIS_H ${libmad_UIS}) +# Don't forget to include output directory, otherwise +# the UI file won't be wrapped! +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(mad SHARED ${libmad_SRCS} ${libmad_MOC_SRCS} ${libmad_UIS_H} + ${libmad_RCC_SRCS}) + +target_link_libraries(mad ${QT_LIBRARIES} -lqmmp ${MAD_LINK_FLAGS} ${TAGLIB_LINK_FLAGS} ${TAGLIB_CFLAGS}) +install(TARGETS mad DESTINATION ${LIB_DIR}/qmmp/Input PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) diff --git a/src/plugins/Input/mad/decoder_mad.cpp b/src/plugins/Input/mad/decoder_mad.cpp new file mode 100644 index 000000000..6b4c2569a --- /dev/null +++ b/src/plugins/Input/mad/decoder_mad.cpp @@ -0,0 +1,572 @@ +#include + +#include "decoder_mad.h" +#include "constants.h" +#include "buffer.h" +#include "output.h" + +#include +#include + +# define XING_MAGIC (('X' << 24) | ('i' << 16) | ('n' << 8) | 'g') + + +DecoderMAD::DecoderMAD(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o) + : Decoder(parent, d, i, o) +{ + inited = false; + user_stop = false; + done = false; + finish = false; + derror = false; + eof = false; + useeq = false; + totalTime = 0.; + seekTime = -1.; + channels = 0; + bks = 0; + bitrate = 0; + freq = 0; + len = 0; + input_buf = 0; + input_bytes = 0; + output_buf = 0; + output_bytes = 0; + output_at = 0; + output_size = 0; +} + +DecoderMAD::~DecoderMAD() +{ + wait(); + deinit(); + mutex()->lock(); + if (input_buf) + { + qDebug("DecoderMAD: deleting input_buf"); + delete [] input_buf; + } + input_buf = 0; + + if (output_buf) + { + qDebug("DecoderMAD: deleting output_buf"); + delete [] output_buf; + } + output_buf = 0; + mutex()->unlock(); +} + +bool DecoderMAD::initialize() +{ + bks = blockSize(); + + inited = false; + user_stop = false; + done = false; + finish = false; + derror = false; + eof = false; + totalTime = 0.; + seekTime = -1.; + channels = 0; + bitrate = 0; + freq = 0; + len = 0; + input_bytes = 0; + output_bytes = 0; + output_at = 0; + output_size = 0; + + if (! input()) + { + error("DecoderMAD: cannot initialize. No input."); + return FALSE; + } + + if (! input_buf) + input_buf = new char[globalBufferSize]; + + if (! output_buf) + output_buf = new char[globalBufferSize]; + + if (! input()->isOpen()) + { + if (! input()->open(QIODevice::ReadOnly)) + { + error("DecoderMAD: Failed to open input. Error " + + QString::number(input()->isOpen()) + "."); + return FALSE; + } + } + + mad_stream_init(&stream); + mad_frame_init(&frame); + mad_synth_init(&synth); + + if (! findHeader()) + { + qDebug("DecoderMAD: Cannot find a valid MPEG header."); + return FALSE; + } + configure(freq, channels, 16, bitrate); + + inited = TRUE; + return TRUE; +} + + +void DecoderMAD::deinit() +{ + if(!inited) + return; + + mad_synth_finish(&synth); + mad_frame_finish(&frame); + mad_stream_finish(&stream); + + inited = false; + user_stop = false; + done = false; + finish = false; + derror = false; + eof = false; + useeq = false; + totalTime = 0.; + seekTime = -1.; + channels = 0; + bks = 0; + bitrate = 0; + freq = 0; + len = 0; + input_bytes = 0; + output_bytes = 0; + output_at = 0; + output_size = 0; +} + +bool DecoderMAD::findXingHeader(struct mad_bitptr ptr, unsigned int bitlen) +{ + if (bitlen < 64 || mad_bit_read(&ptr, 32) != XING_MAGIC) + goto fail; + + xing.flags = mad_bit_read(&ptr, 32); + bitlen -= 64; + + if (xing.flags & XING_FRAMES) + { + if (bitlen < 32) + goto fail; + + xing.frames = mad_bit_read(&ptr, 32); + bitlen -= 32; + } + + if (xing.flags & XING_BYTES) + { + if (bitlen < 32) + goto fail; + + xing.bytes = mad_bit_read(&ptr, 32); + bitlen -= 32; + } + + if (xing.flags & XING_TOC) + { + int i; + + if (bitlen < 800) + goto fail; + + for (i = 0; i < 100; ++i) + xing.toc[i] = mad_bit_read(&ptr, 8); + + bitlen -= 800; + } + + if (xing.flags & XING_SCALE) + { + if (bitlen < 32) + goto fail; + + xing.scale = mad_bit_read(&ptr, 32); + bitlen -= 32; + } + + return true; + +fail: + xing.flags = 0; + xing.frames = 0; + xing.bytes = 0; + xing.scale = 0; + return false; +} + +bool DecoderMAD::findHeader() +{ + bool result = false; + int count = 0; + + while (1) + { + if (input_bytes < globalBufferSize) + { + int bytes = input()->read(input_buf + input_bytes, + globalBufferSize - input_bytes); + if (bytes <= 0) + { + if (bytes == -1) + result = false; + ; + break; + } + input_bytes += bytes; + } + + mad_stream_buffer(&stream, (unsigned char *) input_buf, input_bytes); + + bool done = false; + while (! done) + { + if (mad_frame_decode(&frame, &stream) != -1) + done = true; + else if (!MAD_RECOVERABLE(stream.error)) + { + qWarning("DecoderMAD: Can't decode frame"); + break; + } + + count++; + } + + findXingHeader(stream.anc_ptr, stream.anc_bitlen); + result = done; + if ((stream.error != MAD_ERROR_BUFLEN)) + break; + + input_bytes = &input_buf[input_bytes] - (char *) stream.next_frame; + memmove(input_buf, stream.next_frame, input_bytes); + } + + if (result && count) + { + freq = frame.header.samplerate; + channels = MAD_NCHANNELS(&frame.header); + bitrate = frame.header.bitrate / 1000; + calcLength(&frame.header); + } + + return result; +} + +void DecoderMAD::calcLength(struct mad_header *header) +{ + if (! input() || input()->isSequential()) + return; + + totalTime = 0.; + if (xing.flags & XING_FRAMES) + { + mad_timer_t timer; + + timer = header->duration; + mad_timer_multiply(&timer, xing.frames); + + totalTime = double(mad_timer_count(timer, MAD_UNITS_MILLISECONDS)) / 1000.; + } + else if (header->bitrate > 0) + totalTime = input()->size() * 8 / header->bitrate; +} + +double DecoderMAD::lengthInSeconds() +{ + if (! inited) + return 0.; + return totalTime; +} + +void DecoderMAD::seek(double pos) +{ + seekTime = pos; +} + +void DecoderMAD::stop() +{ + user_stop = TRUE; +} + +void DecoderMAD::flush(bool final) +{ + ulong min = final ? 0 : bks; + + while ((! done && ! finish) && output_bytes > min) + { + output()->recycler()->mutex()->lock(); + + while ((! done && ! finish) && output()->recycler()->full()) + { + mutex()->unlock(); + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + + mutex()->lock(); + done = user_stop; + } + + if (user_stop || finish) + { + inited = FALSE; + done = TRUE; + } + else + { + output_bytes -= produceSound(output_buf, output_bytes, bitrate, channels); + output_size += bks; + output_at = output_bytes; + } + + if (output()->recycler()->full()) + { + output()->recycler()->cond()->wakeOne(); + } + + output()->recycler()->mutex()->unlock(); + } +} + +void DecoderMAD::run() +{ + mutex()->lock(); + + if (! inited) + { + mutex()->unlock(); + return; + } + + DecoderState::Type stat = DecoderState::Decoding; + + mutex()->unlock(); + + dispatch(stat); + + while (! done && ! finish && ! derror) + { + mutex()->lock(); + + if (seekTime >= 0.0) + { + long seek_pos = long(seekTime * input()->size() / totalTime); + input()->seek(seek_pos); + output_size = long(seekTime) * long(freq * channels * 16 / 2); + input_bytes = 0; + output_at = 0; + output_bytes = 0; + eof = false; + } + + finish = eof; + + if (! eof) + { + if (stream.next_frame && seekTime == -1.) + { + input_bytes = &input_buf[input_bytes] - (char *) stream.next_frame; + memmove(input_buf, stream.next_frame, input_bytes); + } + + if (input_bytes < globalBufferSize) + { + int len = input()->read((char *) input_buf + input_bytes, + globalBufferSize - input_bytes); + + if (len == 0) + { + eof = true; + } + else if (len < 0) + { + derror = true; + break; + } + + input_bytes += len; + } + + mad_stream_buffer(&stream, (unsigned char *) input_buf, input_bytes); + } + + seekTime = -1.; + + mutex()->unlock(); + + // decode + while (! done && ! finish && ! derror) + { + if (mad_frame_decode(&frame, &stream) == -1) + { + if (stream.error == MAD_ERROR_BUFLEN) + break; + + // error in decoding + if (! MAD_RECOVERABLE(stream.error)) + { + derror = true; + break; + } + continue; + } + + mutex()->lock(); + + if (seekTime >= 0.) + { + mutex()->unlock(); + break; + } + + if (useeq) + { + unsigned int nch, ch, ns, s, sb; + + nch = MAD_NCHANNELS(&frame.header); + ns = MAD_NSBSAMPLES(&frame.header); + + for (ch = 0; ch < nch; ++ch) + for (s = 0; s < ns; ++s) + for (sb = 0; sb < 32; ++sb) + frame.sbsample[ch][s][sb] = + mad_f_mul(frame.sbsample[ch][s][sb], eqbands[sb]); + } + + mad_synth_frame(&synth, &frame); + madOutput(); + mutex()->unlock(); + } + } + + mutex()->lock(); + + if (! user_stop && eof) + { + flush(TRUE); + + if (output()) + { + output()->recycler()->mutex()->lock(); + // end of stream + while (! output()->recycler()->empty() && ! user_stop) + { + output()->recycler()->cond()->wakeOne(); + mutex()->unlock(); + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + mutex()->lock(); + } + output()->recycler()->mutex()->unlock(); + } + + done = TRUE; + if (! user_stop) + finish = TRUE; + } + + if (finish) + stat = DecoderState::Finished; + else if (user_stop) + stat = DecoderState::Stopped; + + mutex()->unlock(); + + dispatch(stat); + + if (input()) + input()->close(); + deinit(); + +} + +static inline signed int scale(mad_fixed_t sample) +{ + /* round */ + sample += (1L << (MAD_F_FRACBITS - 16)); + + /* clip */ + if (sample >= MAD_F_ONE) + sample = MAD_F_ONE - 1; + else if (sample < -MAD_F_ONE) + sample = -MAD_F_ONE; + + /* quantize */ + return sample >> (MAD_F_FRACBITS + 1 - 16); +} + +static inline signed long fix_sample(unsigned int bits, mad_fixed_t sample) +{ + mad_fixed_t quantized, check; + // clip + quantized = sample; + check = (sample >> MAD_F_FRACBITS) + 1; + if (check & ~1) + { + if (sample >= MAD_F_ONE) + quantized = MAD_F_ONE - 1; + else if (sample < -MAD_F_ONE) + quantized = -MAD_F_ONE; + } + // quantize + quantized &= ~((1L << (MAD_F_FRACBITS + 1 - bits)) - 1); + // scale + return quantized >> (MAD_F_FRACBITS + 1 - bits); +} + +enum mad_flow DecoderMAD::madOutput() +{ + unsigned int samples, channels; + mad_fixed_t const *left, *right; + + samples = synth.pcm.length; + channels = synth.pcm.channels; + left = synth.pcm.samples[0]; + right = synth.pcm.samples[1]; + + + bitrate = frame.header.bitrate / 1000; + done = user_stop; + + while (samples-- && !user_stop) + { + signed int sample; + + if (output_bytes + 4096 > globalBufferSize) + flush(); + + sample = fix_sample(16, *left++); + *(output_buf + output_at++) = ((sample >> 0) & 0xff); + *(output_buf + output_at++) = ((sample >> 8) & 0xff); + output_bytes += 2; + + if (channels == 2) + { + sample = fix_sample(16, *right++); + *(output_buf + output_at++) = ((sample >> 0) & 0xff); + *(output_buf + output_at++) = ((sample >> 8) & 0xff); + output_bytes += 2; + } + } + + if (done || finish) + { + return MAD_FLOW_STOP; + } + + return MAD_FLOW_CONTINUE; +} + +enum mad_flow DecoderMAD::madError(struct mad_stream *stream, + struct mad_frame *) +{ + if (MAD_RECOVERABLE(stream->error)) + return MAD_FLOW_CONTINUE; + qFatal("MADERROR!\n"); + return MAD_FLOW_STOP; +} diff --git a/src/plugins/Input/mad/decoder_mad.h b/src/plugins/Input/mad/decoder_mad.h new file mode 100644 index 000000000..ecbb160cb --- /dev/null +++ b/src/plugins/Input/mad/decoder_mad.h @@ -0,0 +1,95 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#ifndef __decoder_mad_h +#define __decoder_mad_h + +class DecoderMAD; + +#include "decoder.h" +#include "decodermadfactory.h" + +extern "C" { +#include +} + + +class DecoderMAD : public Decoder +{ +public: + DecoderMAD(QObject *parent = 0, DecoderFactory *d = 0, + QIODevice *i = 0, Output *o = 0); + virtual ~DecoderMAD(); + + // standard decoder API + bool initialize(); + double lengthInSeconds(); + void seek(double); + void stop(); + + // Equalizer + //bool isEQSupported() const { return TRUE; } + //void setEQEnabled(bool); + //void setEQ(const EqPreset &); + + static const int maxDecodeRetries; + static const int maxFrameSize; + static const int maxFrameCheck; + static const int initialFrameSize; + + +private: + // thread run function + void run(); + + enum mad_flow madOutput(); + enum mad_flow madError(struct mad_stream *, struct mad_frame *); + + // helper functions + void flush(bool = FALSE); + void deinit(); + bool findHeader(); + bool findXingHeader(struct mad_bitptr, unsigned int); + void calcLength(struct mad_header *); + + bool inited, user_stop, done, finish, derror, eof, useeq; + double totalTime, seekTime; + int channels; + long bitrate, freq, len; + unsigned int bks; + mad_fixed_t eqbands[32]; + + // file input buffer + char *input_buf; + unsigned long input_bytes; + + // output buffer + char *output_buf; + unsigned long output_bytes, output_at, output_size; + + // MAD decoder + struct { + int flags; + unsigned long frames; + unsigned long bytes; + unsigned char toc[100]; + long scale; + } xing; + + enum { + XING_FRAMES = 0x0001, + XING_BYTES = 0x0002, + XING_TOC = 0x0004, + XING_SCALE = 0x0008 + }; + + struct mad_stream stream; + struct mad_frame frame; + struct mad_synth synth; +}; + + +#endif // __decoder_mad_h diff --git a/src/plugins/Input/mad/decodermadfactory.cpp b/src/plugins/Input/mad/decodermadfactory.cpp new file mode 100644 index 000000000..8bb04aca1 --- /dev/null +++ b/src/plugins/Input/mad/decodermadfactory.cpp @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "detailsdialog.h" +#include "settingsdialog.h" +#include "decoder_mad.h" +#include "decodermadfactory.h" + +// DecoderMADFactory + +bool DecoderMADFactory::supports(const QString &source) const +{ + QString ext = source.right(4).toLower(); + return ext == ".mp1" || ext == ".mp2" || ext == ".mp3"; +} + +bool DecoderMADFactory::canDecode(QIODevice *input) const +{ + char buf[16 * 512]; + + if (input->peek(buf,sizeof(buf)) == sizeof(buf)) + { + struct mad_stream stream; + struct mad_header header; + int dec_res; + + mad_stream_init (&stream); + mad_header_init (&header); + mad_stream_buffer (&stream, (unsigned char *) buf, sizeof(buf)); + stream.error = MAD_ERROR_NONE; + + while ((dec_res = mad_header_decode(&header, &stream)) == -1 + && MAD_RECOVERABLE(stream.error)) + ; + return dec_res != -1 ? TRUE: FALSE; + } + return FALSE; +} + +const DecoderProperties DecoderMADFactory::properties() const +{ + DecoderProperties properties; + properties.name = tr("MPEG Plugin"); + properties.filter = "*.mp1 *.mp2 *.mp3"; + properties.description = tr("MPEG Files"); + properties.contentType = "audio/mp3;audio/mpeg"; + properties.hasAbout = TRUE; + properties.hasSettings = TRUE; + return properties; +} + +Decoder *DecoderMADFactory::create(QObject *parent, QIODevice *input, Output *output) +{ + return new DecoderMAD(parent, this, input, output); +} + +FileTag *DecoderMADFactory::createTag(const QString &source) +{ + FileTag *ftag = new FileTag(); + TagLib::Tag *tag = 0; + TagLib::MPEG::File fileRef(source.toLocal8Bit ()); + + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("MAD"); + QTextCodec *codec_v1 = + QTextCodec::codecForName(settings.value("ID3v1_encoding","UTF-8" ) + .toByteArray ()); + QTextCodec *codec_v2 = + QTextCodec::codecForName(settings.value("ID3v2_encoding","UTF-8" ) + .toByteArray ()); + if (!codec_v1) + codec_v1 = QTextCodec::codecForName ("UTF-8"); + if (!codec_v2) + codec_v2 = QTextCodec::codecForName ("UTF-8"); + + QTextCodec *codec = 0; + + uint tag_array[3]; + tag_array[0] = settings.value("tag_1", SettingsDialog::ID3v2).toInt(); + tag_array[1] = settings.value("tag_2", SettingsDialog::Disabled).toInt(); + tag_array[2] = settings.value("tag_3", SettingsDialog::Disabled).toInt(); + + + for (int i = 0; i < 3; ++i) + { + switch ((uint) tag_array[i]) + { + case SettingsDialog::ID3v1: + { + codec = codec_v1; + tag = fileRef.ID3v1Tag(); + break; + } + case SettingsDialog::ID3v2: + { + codec = codec_v2; + tag = fileRef.ID3v2Tag(); + break; + } + case SettingsDialog::APE: + { + codec = QTextCodec::codecForName ("UTF-8"); + tag = fileRef.APETag(); + break; + } + case SettingsDialog::Disabled: + { + break; + } + } + if(tag && !tag->isEmpty()) + break; + } + settings.endGroup(); + + if (tag && codec) + { + bool utf = codec->name ().contains("UTF"); + TagLib::String album = tag->album(); + TagLib::String artist = tag->artist(); + TagLib::String comment = tag->comment(); + TagLib::String genre = tag->genre(); + TagLib::String title = tag->title(); + + ftag->setValue(FileTag::ALBUM, + codec->toUnicode(album.toCString(utf)).trimmed()); + ftag->setValue(FileTag::ARTIST, + codec->toUnicode(artist.toCString(utf)).trimmed()); + ftag->setValue(FileTag::COMMENT, + codec->toUnicode(comment.toCString(utf)).trimmed()); + ftag->setValue(FileTag::GENRE, + codec->toUnicode(genre.toCString(utf)).trimmed()); + ftag->setValue(FileTag::TITLE, + codec->toUnicode(title.toCString(utf)).trimmed()); + ftag->setValue(FileTag::YEAR, + tag->year()); + ftag->setValue(FileTag::TRACK, + tag->track()); + } + if (fileRef.audioProperties()) + ftag->setValue(FileTag::LENGTH,fileRef.audioProperties()->length()); + return ftag; +} + +QObject* DecoderMADFactory::showDetails(QWidget *parent, const QString &path) +{ + DetailsDialog *d = new DetailsDialog(parent, path); + d -> show(); + return d; +} + +void DecoderMADFactory::showSettings(QWidget *parent) +{ + SettingsDialog *s = new SettingsDialog(parent); + s -> show(); +} + +void DecoderMADFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About MPEG Audio Plugin"), + tr("Qmmp MPEG Audio Plugin")+"\n"+ + tr("Compiled against libmad version:")+" "+ + QString("%1.%2.%3%4").arg(MAD_VERSION_MAJOR) + .arg(MAD_VERSION_MINOR) + .arg(MAD_VERSION_PATCH).arg(MAD_VERSION_EXTRA)+"\n"+ + tr("Writen by: Ilya Kotov ")+"\n"+ + tr("Source code based on mq3 progect") + ); +} + +QTranslator *DecoderMADFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/mad_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(DecoderMADFactory) diff --git a/src/plugins/Input/mad/decodermadfactory.h b/src/plugins/Input/mad/decodermadfactory.h new file mode 100644 index 000000000..2c7da8e47 --- /dev/null +++ b/src/plugins/Input/mad/decodermadfactory.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DECODERMADFACTORY_H +#define DECODERMADFACTORY_H + +#include +#include +#include +#include + +#include +#include +#include + + + + +class DecoderMADFactory : public QObject, + DecoderFactory +{ +Q_OBJECT +Q_INTERFACES(DecoderFactory); + +public: + bool supports(const QString &source) const; + bool canDecode(QIODevice *input) const; + const DecoderProperties properties() const; + Decoder *create(QObject *, QIODevice *, Output *); + FileTag *createTag(const QString &source); + QObject* showDetails(QWidget *parent, const QString &path); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); +}; + +#endif diff --git a/src/plugins/Input/mad/detailsdialog.cpp b/src/plugins/Input/mad/detailsdialog.cpp new file mode 100644 index 000000000..af9b466cd --- /dev/null +++ b/src/plugins/Input/mad/detailsdialog.cpp @@ -0,0 +1,294 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "detailsdialog.h" + +DetailsDialog::DetailsDialog(QWidget *parent, const QString &path) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + m_path = path; + setWindowTitle (path.section('/',-1)); + ui.pathLineEdit->setText(m_path); + + if (!QFile::exists(m_path)) + return; + + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("MAD"); + m_codec_v1 = + QTextCodec::codecForName(settings.value("ID3v1_encoding","UTF-8" ) + .toByteArray ()); + m_codec_v2 = + QTextCodec::codecForName(settings.value("ID3v2_encoding","UTF-8" ) + .toByteArray ()); + if (!m_codec_v1) + m_codec_v1 = QTextCodec::codecForName ("UTF-8"); + if (!m_codec_v2) + m_codec_v2 = QTextCodec::codecForName ("UTF-8"); + + QString tag_name = settings.value("current_tag","ID3v2").toString (); + + if (tag_name == "ID3v1") + ui.id3v1RadioButton->setChecked(TRUE); + else if (tag_name == "ID3v2") + ui.id3v2RadioButton->setChecked(TRUE); + else if (tag_name == "APE") + ui.apeRadioButton->setChecked(TRUE); + else + ui.id3v2RadioButton->setChecked(TRUE); + + settings.endGroup(); + + loadMPEGInfo(); + QFileInfo info(m_path); + m_rw = info.isWritable(); + loadTag(); + connect(ui.saveButton, SIGNAL(clicked()), SLOT(save())); + connect(ui.createButton, SIGNAL(clicked()), SLOT(create())); + connect(ui.deleteButton, SIGNAL(clicked()), SLOT(deleteTag())); + connect(ui.id3v1RadioButton, SIGNAL(clicked()), SLOT(loadTag())); + connect(ui.id3v2RadioButton, SIGNAL(clicked()), SLOT(loadTag())); + connect(ui.apeRadioButton, SIGNAL(clicked()), SLOT(loadTag())); +} + + +DetailsDialog::~DetailsDialog() +{} + +void DetailsDialog::loadMPEGInfo() +{ + TagLib::MPEG::File f (m_path.toLocal8Bit()); + //l.label + //ui. f.audioProperties()->level(); + QString text; + text = QString("%1").arg(f.audioProperties()->layer()); + ui.levelLabel->setText("MPEG layer "+text); //TODO: add MPEG version + text = QString("%1").arg(f.audioProperties()->bitrate()); + ui.bitRateLabel->setText(text+" "+tr("kbps")); + text = QString("%1").arg(f.audioProperties()->sampleRate()); + ui.sampleRateLabel->setText(text+" "+tr("Hz")); + switch (f.audioProperties()->channelMode()) + { + case TagLib::MPEG::Header::Stereo: + ui.modeLabel->setText("Stereo"); + break; + case TagLib::MPEG::Header::JointStereo: + ui.modeLabel->setText("Joint stereo"); + break; + case TagLib::MPEG::Header::DualChannel: + ui.modeLabel->setText("Dual channel"); + break; + case TagLib::MPEG::Header::SingleChannel: + ui.modeLabel->setText("Single channel"); + break; + } + text = QString("%1 "+tr("KB")).arg(f.length()/1024); + ui.fileSizeLabel->setText(text); + /*if (f.audioProperties()->protectionEnabled()) + ui.errProtectionLabel->setText(tr("Yes")); + else + ui.errProtectionLabel->setText(tr("No"));*/ + if (f.audioProperties()->isCopyrighted()) + ui.copyrightLabel->setText(tr("Yes")); + else + ui.copyrightLabel->setText(tr("No")); + if (f.audioProperties()->isOriginal()) + ui.originalLabel->setText(tr("Yes")); + else + ui.originalLabel->setText(tr("No")); +} + +void DetailsDialog::loadTag() +{ + TagLib::MPEG::File f (m_path.toLocal8Bit()); + QTextCodec *codec = QTextCodec::codecForName ("UTF-8"); + TagLib::Tag *tag = 0; + + if (selectedTag() == TagLib::MPEG::File::ID3v1) + { + tag = f.ID3v1Tag(); + codec = m_codec_v1; + ui.tagGroupBox->setTitle(tr("ID3v1 Tag")); + } + else if (selectedTag() == TagLib::MPEG::File::ID3v2) + { + tag = f.ID3v2Tag(); + codec = m_codec_v2; + ui.tagGroupBox->setTitle(tr("ID3v2 Tag")); + } + else if (selectedTag() == TagLib::MPEG::File::APE) + { + ui.tagGroupBox->setTitle(tr("APE Tag")); + tag = f.APETag(); + } + ui.saveButton->setEnabled(tag && m_rw); + ui.createButton->setEnabled(!tag && m_rw); + ui.deleteButton->setEnabled(tag && m_rw); + ui.tagsWidget->setEnabled(tag); + //clear old values + ui.titleLineEdit->clear(); + ui.artistLineEdit->clear(); + ui.albumLineEdit->clear(); + ui.commentLineEdit->clear(); + ui.yearLineEdit->clear(); + ui.trackLineEdit->clear(); + ui.genreLineEdit->clear(); + + if (tag) + { + bool utf = codec->name().contains("UTF"); + TagLib::String title = tag->title(); + TagLib::String artist = tag->artist(); + TagLib::String album = tag->album(); + TagLib::String comment = tag->comment(); + TagLib::String genre = tag->genre(); + QString string = codec->toUnicode(title.toCString(utf)).trimmed(); + ui.titleLineEdit->setText(string); + string = codec->toUnicode(artist.toCString(utf)).trimmed(); + ui.artistLineEdit->setText(string); + string = codec->toUnicode(album.toCString(utf)).trimmed(); + ui.albumLineEdit->setText(string); + string = codec->toUnicode(comment.toCString(utf)).trimmed(); + ui.commentLineEdit->setText(string); + string = QString("%1").arg(tag->year()); + ui.yearLineEdit->setText(string); + string = QString("%1").arg(tag->track()); + ui.trackLineEdit->setText(string); + string = codec->toUnicode(genre.toCString(utf)).trimmed(); + ui.genreLineEdit->setText(string); + } +} + +void DetailsDialog::save() +{ + TagLib::MPEG::File* f = new TagLib::MPEG::File(m_path.toLocal8Bit()); + TagLib::String::Type type = TagLib::String::Latin1; + + QTextCodec *codec = 0; + TagLib::Tag *tag = 0; + + if (selectedTag() == TagLib::MPEG::File::ID3v1) + { + codec = m_codec_v1; + tag = f->ID3v1Tag(TRUE); + if (codec->name().contains("UTF")) + { + delete f; + loadTag(); + } + } + if (selectedTag() == TagLib::MPEG::File::ID3v2) + { + codec = m_codec_v2; + tag = f->ID3v2Tag(TRUE); + if (codec->name().contains("UTF")) + { + TagLib::ID3v2::FrameFactory *factory = TagLib::ID3v2::FrameFactory::instance(); + factory->setDefaultTextEncoding(TagLib::String::UTF8); + f->setID3v2FrameFactory(factory); + type = TagLib::String::UTF8; + } + } + if (selectedTag() == TagLib::MPEG::File::APE) + { + codec = QTextCodec::codecForName ("UTF-8"); + tag = f->APETag(TRUE); + type = TagLib::String::UTF8; + } + + tag->setTitle(TagLib::String(codec->fromUnicode(ui.titleLineEdit->text()).constData(), type)); + tag->setArtist(TagLib::String(codec->fromUnicode(ui.artistLineEdit->text()).constData(), type)); + tag->setAlbum(TagLib::String(codec->fromUnicode(ui.albumLineEdit->text()).constData(), type)); + tag->setComment(TagLib::String(codec->fromUnicode(ui.commentLineEdit->text()).constData(), type)); + tag->setGenre(TagLib::String(codec->fromUnicode(ui.genreLineEdit->text()).constData(), type)); + tag->setYear(ui.yearLineEdit->text().toUInt()); + tag->setTrack(ui.trackLineEdit->text().toUInt()); + + f->save(selectedTag(), FALSE); + delete f; + loadTag(); +} + +void DetailsDialog::create() +{ + TagLib::MPEG::File *f = new TagLib::MPEG::File (m_path.toLocal8Bit()); + TagLib::Tag *tag = 0; + if (selectedTag() == TagLib::MPEG::File::ID3v1) + tag = f->ID3v1Tag(TRUE); + else if (selectedTag() == TagLib::MPEG::File::ID3v2) + tag = f->ID3v2Tag(TRUE); + else if (selectedTag() == TagLib::MPEG::File::APE) + tag = f->APETag(TRUE); + + f->save(selectedTag(), FALSE); + delete f; + loadTag(); + ui.tagsWidget->setEnabled(TRUE); + ui.saveButton->setEnabled(m_rw); +} + +void DetailsDialog::deleteTag() +{ + TagLib::MPEG::File *f = new TagLib::MPEG::File (m_path.toLocal8Bit()); + f->strip(selectedTag()); + delete f; + loadTag(); +} + +uint DetailsDialog::selectedTag() +{ + if (ui.id3v1RadioButton->isChecked()) + return TagLib::MPEG::File::ID3v1; + else if (ui.id3v2RadioButton->isChecked()) + return TagLib::MPEG::File::ID3v2; + else if (ui.apeRadioButton->isChecked()) + return TagLib::MPEG::File::APE; + return TagLib::MPEG::File::ID3v2; +} + +void DetailsDialog::closeEvent (QCloseEvent *) +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("MAD"); + if (ui.id3v1RadioButton->isChecked()) + settings.setValue("current_tag","ID3v1"); + else if (ui.id3v2RadioButton->isChecked()) + settings.setValue("current_tag","ID3v2"); + else if (ui.apeRadioButton->isChecked()) + settings.setValue("current_tag","APE"); + settings.endGroup(); +} diff --git a/src/plugins/Input/mad/detailsdialog.h b/src/plugins/Input/mad/detailsdialog.h new file mode 100644 index 000000000..bc92724a3 --- /dev/null +++ b/src/plugins/Input/mad/detailsdialog.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DETAILSDIALOG_H +#define DETAILSDIALOG_H + +#include + +#include "ui_detailsdialog.h" + +/** + @author Ilya Kotov +*/ + +class QTextCodec; + +class DetailsDialog : public QDialog +{ + Q_OBJECT +public: + DetailsDialog(QWidget *parent = 0, const QString &path = 0); + + ~DetailsDialog(); + +protected: + virtual void closeEvent (QCloseEvent *); + +private slots: + void save(); + void create(); + void deleteTag(); + void loadTag(); + +private: + void loadMPEGInfo(); + uint selectedTag(); + //void loadTag(); + //void loadID3v2Tag(); + Ui::DetailsDialog ui; + QString m_path; + QTextCodec *m_codec_v1; + QTextCodec *m_codec_v2; + bool m_rw; + +}; + +#endif diff --git a/src/plugins/Input/mad/detailsdialog.ui b/src/plugins/Input/mad/detailsdialog.ui new file mode 100644 index 000000000..6f9a00c31 --- /dev/null +++ b/src/plugins/Input/mad/detailsdialog.ui @@ -0,0 +1,392 @@ + + DetailsDialog + + + + 0 + 0 + 593 + 402 + + + + Details + + + + + + + + File path: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + true + + + + + + + + + + + + 0 + 0 + + + + Tag Choice + + + + + + ID3v1 + + + + + + + ID3v2 + + + + + + + APE + + + + + + + + + + + 200 + 16 + + + + MPEG Info + + + + + + MPEG level: + + + Qt::AutoText + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Bit rate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Sample rate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + File size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Mode: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Copyright: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Original: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + + + + + + ID3v1 Tag + + + + + + true + + + + + + Title: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Artist: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Album: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Comment: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Year: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Track number: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Genre: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + Create + + + + + + + Delete + + + + + + + false + + + Save + + + + + + + + + + + + Qt::Horizontal + + + + 111 + 20 + + + + + + + + Close + + + + + + + + + pushButton_3 + clicked() + DetailsDialog + close() + + + 623 + 353 + + + 539 + 352 + + + + + diff --git a/src/plugins/Input/mad/mad.pro b/src/plugins/Input/mad/mad.pro new file mode 100644 index 000000000..7a320b370 --- /dev/null +++ b/src/plugins/Input/mad/mad.pro @@ -0,0 +1,39 @@ +# ???? ?????? ? KDevelop ?????????? qmake. +# ------------------------------------------- +# ?????????? ???????????? ???????? ???????? ???????: ./Plugins/Input/mad +# ???? - ??????????: + +include(../../plugins.pri) + + +FORMS += detailsdialog.ui \ + settingsdialog.ui +HEADERS += decodermadfactory.h \ + decoder_mad.h \ + detailsdialog.h \ + settingsdialog.h +SOURCES += decoder_mad.cpp \ + decodermadfactory.cpp \ + detailsdialog.cpp \ + settingsdialog.cpp + +TARGET=$$PLUGINS_PREFIX/Input/mad +QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libmad.so + +INCLUDEPATH += ../../../qmmp +CONFIG += release \ +warn_on \ +plugin \ +link_pkgconfig +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmp +PKGCONFIG += taglib mad +#TRANSLATIONS = translations/mad_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/Input +INSTALLS += target diff --git a/src/plugins/Input/mad/settingsdialog.cpp b/src/plugins/Input/mad/settingsdialog.cpp new file mode 100644 index 000000000..667e8598a --- /dev/null +++ b/src/plugins/Input/mad/settingsdialog.cpp @@ -0,0 +1,107 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "settingsdialog.h" + +SettingsDialog::SettingsDialog(QWidget *parent) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + findCodecs(); + foreach (QTextCodec *codec, codecs) + { + ui.id3v1EncComboBox->addItem(codec->name()); + ui.id3v2EncComboBox->addItem(codec->name()); + } + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("MAD"); + int pos = ui.id3v1EncComboBox->findText + (settings.value("ID3v1_encoding","UTF-8").toString()); + ui.id3v1EncComboBox->setCurrentIndex(pos); + pos = ui.id3v2EncComboBox->findText + (settings.value("ID3v2_encoding","UTF-8").toString()); + ui.id3v2EncComboBox->setCurrentIndex(pos); + + ui.firstTagComboBox->setCurrentIndex(settings.value("tag_1", ID3v2).toInt()); + ui.secondTagComboBox->setCurrentIndex(settings.value("tag_2", Disabled).toInt()); + ui.thirdTagComboBox->setCurrentIndex(settings.value("tag_3", Disabled).toInt()); + + settings.endGroup(); + connect(ui.okButton, SIGNAL(clicked()), SLOT(writeSettings())); +} + + +SettingsDialog::~SettingsDialog() +{} + +void SettingsDialog::writeSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("MAD"); + settings.setValue("ID3v1_encoding", ui.id3v1EncComboBox->currentText()); + settings.setValue("ID3v2_encoding", ui.id3v2EncComboBox->currentText()); + settings.setValue("tag_1", ui.firstTagComboBox->currentIndex()); + settings.setValue("tag_2", ui.secondTagComboBox->currentIndex()); + settings.setValue("tag_3", ui.thirdTagComboBox->currentIndex()); + settings.endGroup(); + accept(); +} + +void SettingsDialog::findCodecs() +{ + QMap codecMap; + QRegExp iso8859RegExp("ISO[- ]8859-([0-9]+).*"); + + foreach (int mib, QTextCodec::availableMibs()) + { + QTextCodec *codec = QTextCodec::codecForMib(mib); + + QString sortKey = codec->name().toUpper(); + int rank; + + if (sortKey.startsWith("UTF-8")) + { + rank = 1; + } + else if (sortKey.startsWith("UTF-16")) + { + rank = 2; + } + else if (iso8859RegExp.exactMatch(sortKey)) + { + if (iso8859RegExp.cap(1).size() == 1) + rank = 3; + else + rank = 4; + } + else + { + rank = 5; + } + sortKey.prepend(QChar('0' + rank)); + + codecMap.insert(sortKey, codec); + } + codecs = codecMap.values(); +} diff --git a/src/plugins/Input/mad/settingsdialog.h b/src/plugins/Input/mad/settingsdialog.h new file mode 100644 index 000000000..2ad1ed188 --- /dev/null +++ b/src/plugins/Input/mad/settingsdialog.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include + + +#include "ui_settingsdialog.h" + +/** + @author Ilya Kotov +*/ +class SettingsDialog : public QDialog +{ +Q_OBJECT +public: + SettingsDialog(QWidget *parent = 0); + + ~SettingsDialog(); + + enum TagType {ID3v1 = 0, ID3v2, APE, Disabled}; + +private slots: + void writeSettings(); + +private: + void findCodecs(); + + Ui::SettingsDialog ui; + QList codecs; + +}; + +#endif diff --git a/src/plugins/Input/mad/settingsdialog.ui b/src/plugins/Input/mad/settingsdialog.ui new file mode 100644 index 000000000..3ace8fcec --- /dev/null +++ b/src/plugins/Input/mad/settingsdialog.ui @@ -0,0 +1,306 @@ + + SettingsDialog + + + + 0 + 0 + 242 + 303 + + + + MPEG Plugin Settings + + + + + + Tag Priority + + + + + + + + + 0 + 0 + + + + First: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0 + + + + ID3v1 + + + + + ID3v2 + + + + + APE + + + + + Disabled + + + + + + + + + + + + + 0 + 0 + + + + Second: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0 + + + + ID3v1 + + + + + ID3v2 + + + + + APE + + + + + Disabled + + + + + + + + + + + + + 0 + 0 + + + + Third: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 0 + + + + ID3v1 + + + + + ID3v2 + + + + + APE + + + + + Disabled + + + + + + + + + + + + + Encodings + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ID3v1 encoding: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ID3v2 encoding: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 131 + 31 + + + + + + + + OK + + + + + + + Cancel + + + + + + + + + + + cancelButton + clicked() + SettingsDialog + reject() + + + 336 + 210 + + + 179 + 224 + + + + + diff --git a/src/plugins/Input/mad/translations/mad_plugin_ru.qm b/src/plugins/Input/mad/translations/mad_plugin_ru.qm new file mode 100644 index 000000000..16bea746b Binary files /dev/null and b/src/plugins/Input/mad/translations/mad_plugin_ru.qm differ diff --git a/src/plugins/Input/mad/translations/mad_plugin_ru.ts b/src/plugins/Input/mad/translations/mad_plugin_ru.ts new file mode 100644 index 000000000..6406f6045 --- /dev/null +++ b/src/plugins/Input/mad/translations/mad_plugin_ru.ts @@ -0,0 +1,242 @@ + + + + DecoderMADFactory + + + MPEG Plugin + Модуль MPEG + + + + MPEG Files + Файлы MPEG + + + + About MPEG Audio Plugin + Об аудио-модуле MPEG + + + + Qmmp MPEG Audio Plugin + Аудио-модуль MPEG для Qmmp + + + + Compiled against libmad version: + Собрано с версией libmad: + + + + Writen by: Ilya Kotov <forkotov02@hotmail.ru> + Разработчик: Илья Котов <forkotov02@hotmail.ru> + + + + Source code based on mq3 progect + Исходный код основан на проекте mq3 + + + + DetailsDialog + + + Hz + Гц + + + + Yes + Есть + + + + No + Нет + + + + ID3v1 Tag + ID3v1-тег + + + + Save + Сохранить + + + + Track number: + Номер трека: + + + + Year: + Год: + + + + Genre: + Жанр: + + + + Comment: + Комментарий: + + + + Album: + Альбом: + + + + Artist: + Исполнитель: + + + + Title: + Название: + + + + Close + Закрыть + + + + ID3v2 Tag + ID3v2-тег + + + + MPEG Info + Информация MPEG + + + + - + + + + + Original: + Оригинальный: + + + + Copyright: + Авторские права: + + + + Mode: + Режим: + + + + File size: + Размер файла: + + + + Sample rate: + Дискретизация: + + + + Bit rate: + Битовая частота: + + + + MPEG level: + Уровень MPEG: + + + + File path: + Путь к файлу: + + + + KB + Кб + + + + Details + Информация + + + + kbps + Кб/с + + + + SettingsDialog + + + ID3 Tags + ID3-теги + + + + Default tag version: + Версия тегов по умолчанию: + + + + ID3v1 + + + + + ID3v2 + + + + + Enable ID3v1 + Использовать ID3v1 + + + + Enable ID3v2 + Использовать ID3v2 + + + + ID3v1 encoding: + Кодировка ID3v1: + + + + Default + По-умолчанию + + + + ID3v2 encoding: + Кодировка ID3v2: + + + + OK + Применить + + + + Cancel + Отмена + + + + MPEG Plugin Settings + Настройка модуля MPEG + + + diff --git a/src/plugins/Input/mad/translations/translations.qrc b/src/plugins/Input/mad/translations/translations.qrc new file mode 100644 index 000000000..34dbabbca --- /dev/null +++ b/src/plugins/Input/mad/translations/translations.qrc @@ -0,0 +1,6 @@ + + + + mad_plugin_ru.qm + + diff --git a/src/plugins/Input/mad/ui_detailsdialog.h b/src/plugins/Input/mad/ui_detailsdialog.h new file mode 100644 index 000000000..d630be894 --- /dev/null +++ b/src/plugins/Input/mad/ui_detailsdialog.h @@ -0,0 +1,400 @@ +/******************************************************************************** +** Form generated from reading ui file 'detailsdialog.ui' +** +** Created: Thu Feb 7 00:21:43 2008 +** by: Qt User Interface Compiler version 4.3.0 +** +** WARNING! All changes made in this file will be lost when recompiling ui file! +********************************************************************************/ + +#ifndef UI_DETAILSDIALOG_H +#define UI_DETAILSDIALOG_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Ui_DetailsDialog +{ +public: + QGridLayout *gridLayout; + QHBoxLayout *hboxLayout; + QLabel *label_28; + QLineEdit *pathLineEdit; + QVBoxLayout *vboxLayout; + QGroupBox *groupBox_3; + QHBoxLayout *hboxLayout1; + QRadioButton *id3v1RadioButton; + QRadioButton *id3v2RadioButton; + QRadioButton *apeRadioButton; + QGroupBox *groupBox; + QGridLayout *gridLayout1; + QLabel *label; + QLabel *levelLabel; + QLabel *label_2; + QLabel *bitRateLabel; + QLabel *label_3; + QLabel *sampleRateLabel; + QLabel *label_5; + QLabel *fileSizeLabel; + QLabel *label_6; + QLabel *modeLabel; + QLabel *label_8; + QLabel *copyrightLabel; + QLabel *label_9; + QLabel *originalLabel; + QGroupBox *tagGroupBox; + QVBoxLayout *vboxLayout1; + QWidget *tagsWidget; + QGridLayout *gridLayout2; + QLabel *label_21; + QLineEdit *titleLineEdit; + QLabel *label_22; + QLineEdit *artistLineEdit; + QLabel *label_23; + QLineEdit *albumLineEdit; + QLabel *label_24; + QLineEdit *commentLineEdit; + QLabel *label_25; + QLineEdit *yearLineEdit; + QLabel *label_26; + QLineEdit *trackLineEdit; + QLabel *label_27; + QLineEdit *genreLineEdit; + QHBoxLayout *hboxLayout2; + QPushButton *createButton; + QPushButton *deleteButton; + QPushButton *saveButton; + QSpacerItem *spacerItem; + QPushButton *pushButton_3; + + void setupUi(QDialog *DetailsDialog) + { + if (DetailsDialog->objectName().isEmpty()) + DetailsDialog->setObjectName(QString::fromUtf8("DetailsDialog")); + QSize size(593, 402); + size = size.expandedTo(DetailsDialog->minimumSizeHint()); + DetailsDialog->resize(size); + gridLayout = new QGridLayout(DetailsDialog); + gridLayout->setObjectName(QString::fromUtf8("gridLayout")); + hboxLayout = new QHBoxLayout(); + hboxLayout->setObjectName(QString::fromUtf8("hboxLayout")); + label_28 = new QLabel(DetailsDialog); + label_28->setObjectName(QString::fromUtf8("label_28")); + label_28->setAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); + + hboxLayout->addWidget(label_28); + + pathLineEdit = new QLineEdit(DetailsDialog); + pathLineEdit->setObjectName(QString::fromUtf8("pathLineEdit")); + pathLineEdit->setReadOnly(true); + + hboxLayout->addWidget(pathLineEdit); + + + gridLayout->addLayout(hboxLayout, 0, 0, 1, 3); + + vboxLayout = new QVBoxLayout(); + vboxLayout->setObjectName(QString::fromUtf8("vboxLayout")); + groupBox_3 = new QGroupBox(DetailsDialog); + groupBox_3->setObjectName(QString::fromUtf8("groupBox_3")); + QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(groupBox_3->sizePolicy().hasHeightForWidth()); + groupBox_3->setSizePolicy(sizePolicy); + hboxLayout1 = new QHBoxLayout(groupBox_3); + hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1")); + id3v1RadioButton = new QRadioButton(groupBox_3); + id3v1RadioButton->setObjectName(QString::fromUtf8("id3v1RadioButton")); + + hboxLayout1->addWidget(id3v1RadioButton); + + id3v2RadioButton = new QRadioButton(groupBox_3); + id3v2RadioButton->setObjectName(QString::fromUtf8("id3v2RadioButton")); + + hboxLayout1->addWidget(id3v2RadioButton); + + apeRadioButton = new QRadioButton(groupBox_3); + apeRadioButton->setObjectName(QString::fromUtf8("apeRadioButton")); + + hboxLayout1->addWidget(apeRadioButton); + + + vboxLayout->addWidget(groupBox_3); + + groupBox = new QGroupBox(DetailsDialog); + groupBox->setObjectName(QString::fromUtf8("groupBox")); + groupBox->setMinimumSize(QSize(200, 16)); + gridLayout1 = new QGridLayout(groupBox); + gridLayout1->setObjectName(QString::fromUtf8("gridLayout1")); + label = new QLabel(groupBox); + label->setObjectName(QString::fromUtf8("label")); + label->setTextFormat(Qt::AutoText); + label->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout1->addWidget(label, 0, 0, 1, 1); + + levelLabel = new QLabel(groupBox); + levelLabel->setObjectName(QString::fromUtf8("levelLabel")); + + gridLayout1->addWidget(levelLabel, 0, 1, 1, 1); + + label_2 = new QLabel(groupBox); + label_2->setObjectName(QString::fromUtf8("label_2")); + label_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout1->addWidget(label_2, 1, 0, 1, 1); + + bitRateLabel = new QLabel(groupBox); + bitRateLabel->setObjectName(QString::fromUtf8("bitRateLabel")); + + gridLayout1->addWidget(bitRateLabel, 1, 1, 1, 1); + + label_3 = new QLabel(groupBox); + label_3->setObjectName(QString::fromUtf8("label_3")); + label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout1->addWidget(label_3, 2, 0, 1, 1); + + sampleRateLabel = new QLabel(groupBox); + sampleRateLabel->setObjectName(QString::fromUtf8("sampleRateLabel")); + + gridLayout1->addWidget(sampleRateLabel, 2, 1, 1, 1); + + label_5 = new QLabel(groupBox); + label_5->setObjectName(QString::fromUtf8("label_5")); + label_5->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout1->addWidget(label_5, 3, 0, 1, 1); + + fileSizeLabel = new QLabel(groupBox); + fileSizeLabel->setObjectName(QString::fromUtf8("fileSizeLabel")); + + gridLayout1->addWidget(fileSizeLabel, 3, 1, 1, 1); + + label_6 = new QLabel(groupBox); + label_6->setObjectName(QString::fromUtf8("label_6")); + label_6->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout1->addWidget(label_6, 4, 0, 1, 1); + + modeLabel = new QLabel(groupBox); + modeLabel->setObjectName(QString::fromUtf8("modeLabel")); + + gridLayout1->addWidget(modeLabel, 4, 1, 1, 1); + + label_8 = new QLabel(groupBox); + label_8->setObjectName(QString::fromUtf8("label_8")); + label_8->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout1->addWidget(label_8, 5, 0, 1, 1); + + copyrightLabel = new QLabel(groupBox); + copyrightLabel->setObjectName(QString::fromUtf8("copyrightLabel")); + + gridLayout1->addWidget(copyrightLabel, 5, 1, 1, 1); + + label_9 = new QLabel(groupBox); + label_9->setObjectName(QString::fromUtf8("label_9")); + label_9->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout1->addWidget(label_9, 6, 0, 1, 1); + + originalLabel = new QLabel(groupBox); + originalLabel->setObjectName(QString::fromUtf8("originalLabel")); + + gridLayout1->addWidget(originalLabel, 6, 1, 1, 1); + + + vboxLayout->addWidget(groupBox); + + + gridLayout->addLayout(vboxLayout, 1, 0, 2, 1); + + tagGroupBox = new QGroupBox(DetailsDialog); + tagGroupBox->setObjectName(QString::fromUtf8("tagGroupBox")); + vboxLayout1 = new QVBoxLayout(tagGroupBox); + vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1")); + tagsWidget = new QWidget(tagGroupBox); + tagsWidget->setObjectName(QString::fromUtf8("tagsWidget")); + tagsWidget->setEnabled(true); + gridLayout2 = new QGridLayout(tagsWidget); + gridLayout2->setObjectName(QString::fromUtf8("gridLayout2")); + label_21 = new QLabel(tagsWidget); + label_21->setObjectName(QString::fromUtf8("label_21")); + label_21->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout2->addWidget(label_21, 0, 0, 1, 1); + + titleLineEdit = new QLineEdit(tagsWidget); + titleLineEdit->setObjectName(QString::fromUtf8("titleLineEdit")); + + gridLayout2->addWidget(titleLineEdit, 0, 1, 1, 3); + + label_22 = new QLabel(tagsWidget); + label_22->setObjectName(QString::fromUtf8("label_22")); + label_22->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout2->addWidget(label_22, 1, 0, 1, 1); + + artistLineEdit = new QLineEdit(tagsWidget); + artistLineEdit->setObjectName(QString::fromUtf8("artistLineEdit")); + + gridLayout2->addWidget(artistLineEdit, 1, 1, 1, 3); + + label_23 = new QLabel(tagsWidget); + label_23->setObjectName(QString::fromUtf8("label_23")); + label_23->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout2->addWidget(label_23, 2, 0, 1, 1); + + albumLineEdit = new QLineEdit(tagsWidget); + albumLineEdit->setObjectName(QString::fromUtf8("albumLineEdit")); + + gridLayout2->addWidget(albumLineEdit, 2, 1, 1, 3); + + label_24 = new QLabel(tagsWidget); + label_24->setObjectName(QString::fromUtf8("label_24")); + label_24->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout2->addWidget(label_24, 3, 0, 1, 1); + + commentLineEdit = new QLineEdit(tagsWidget); + commentLineEdit->setObjectName(QString::fromUtf8("commentLineEdit")); + + gridLayout2->addWidget(commentLineEdit, 3, 1, 1, 3); + + label_25 = new QLabel(tagsWidget); + label_25->setObjectName(QString::fromUtf8("label_25")); + label_25->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout2->addWidget(label_25, 4, 0, 1, 1); + + yearLineEdit = new QLineEdit(tagsWidget); + yearLineEdit->setObjectName(QString::fromUtf8("yearLineEdit")); + + gridLayout2->addWidget(yearLineEdit, 4, 1, 1, 1); + + label_26 = new QLabel(tagsWidget); + label_26->setObjectName(QString::fromUtf8("label_26")); + label_26->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout2->addWidget(label_26, 4, 2, 1, 1); + + trackLineEdit = new QLineEdit(tagsWidget); + trackLineEdit->setObjectName(QString::fromUtf8("trackLineEdit")); + + gridLayout2->addWidget(trackLineEdit, 4, 3, 1, 1); + + label_27 = new QLabel(tagsWidget); + label_27->setObjectName(QString::fromUtf8("label_27")); + label_27->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout2->addWidget(label_27, 5, 0, 1, 1); + + genreLineEdit = new QLineEdit(tagsWidget); + genreLineEdit->setObjectName(QString::fromUtf8("genreLineEdit")); + + gridLayout2->addWidget(genreLineEdit, 5, 1, 1, 3); + + + vboxLayout1->addWidget(tagsWidget); + + hboxLayout2 = new QHBoxLayout(); + hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2")); + createButton = new QPushButton(tagGroupBox); + createButton->setObjectName(QString::fromUtf8("createButton")); + + hboxLayout2->addWidget(createButton); + + deleteButton = new QPushButton(tagGroupBox); + deleteButton->setObjectName(QString::fromUtf8("deleteButton")); + + hboxLayout2->addWidget(deleteButton); + + saveButton = new QPushButton(tagGroupBox); + saveButton->setObjectName(QString::fromUtf8("saveButton")); + saveButton->setEnabled(false); + + hboxLayout2->addWidget(saveButton); + + + vboxLayout1->addLayout(hboxLayout2); + + + gridLayout->addWidget(tagGroupBox, 1, 1, 1, 2); + + spacerItem = new QSpacerItem(111, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + gridLayout->addItem(spacerItem, 2, 1, 1, 1); + + pushButton_3 = new QPushButton(DetailsDialog); + pushButton_3->setObjectName(QString::fromUtf8("pushButton_3")); + + gridLayout->addWidget(pushButton_3, 2, 2, 1, 1); + + + retranslateUi(DetailsDialog); + QObject::connect(pushButton_3, SIGNAL(clicked()), DetailsDialog, SLOT(close())); + + QMetaObject::connectSlotsByName(DetailsDialog); + } // setupUi + + void retranslateUi(QDialog *DetailsDialog) + { + DetailsDialog->setWindowTitle(QApplication::translate("DetailsDialog", "Details", 0, QApplication::UnicodeUTF8)); + label_28->setText(QApplication::translate("DetailsDialog", "File path:", 0, QApplication::UnicodeUTF8)); + groupBox_3->setTitle(QApplication::translate("DetailsDialog", "Tag Choice", 0, QApplication::UnicodeUTF8)); + id3v1RadioButton->setText(QApplication::translate("DetailsDialog", "ID3v1", 0, QApplication::UnicodeUTF8)); + id3v2RadioButton->setText(QApplication::translate("DetailsDialog", "ID3v2", 0, QApplication::UnicodeUTF8)); + apeRadioButton->setText(QApplication::translate("DetailsDialog", "APE", 0, QApplication::UnicodeUTF8)); + groupBox->setTitle(QApplication::translate("DetailsDialog", "MPEG Info", 0, QApplication::UnicodeUTF8)); + label->setText(QApplication::translate("DetailsDialog", "MPEG level:", 0, QApplication::UnicodeUTF8)); + levelLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8)); + label_2->setText(QApplication::translate("DetailsDialog", "Bit rate:", 0, QApplication::UnicodeUTF8)); + bitRateLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8)); + label_3->setText(QApplication::translate("DetailsDialog", "Sample rate:", 0, QApplication::UnicodeUTF8)); + sampleRateLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8)); + label_5->setText(QApplication::translate("DetailsDialog", "File size:", 0, QApplication::UnicodeUTF8)); + fileSizeLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8)); + label_6->setText(QApplication::translate("DetailsDialog", "Mode:", 0, QApplication::UnicodeUTF8)); + modeLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8)); + label_8->setText(QApplication::translate("DetailsDialog", "Copyright:", 0, QApplication::UnicodeUTF8)); + copyrightLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8)); + label_9->setText(QApplication::translate("DetailsDialog", "Original:", 0, QApplication::UnicodeUTF8)); + originalLabel->setText(QApplication::translate("DetailsDialog", "-", 0, QApplication::UnicodeUTF8)); + tagGroupBox->setTitle(QApplication::translate("DetailsDialog", "ID3v1 Tag", 0, QApplication::UnicodeUTF8)); + label_21->setText(QApplication::translate("DetailsDialog", "Title:", 0, QApplication::UnicodeUTF8)); + label_22->setText(QApplication::translate("DetailsDialog", "Artist:", 0, QApplication::UnicodeUTF8)); + label_23->setText(QApplication::translate("DetailsDialog", "Album:", 0, QApplication::UnicodeUTF8)); + label_24->setText(QApplication::translate("DetailsDialog", "Comment:", 0, QApplication::UnicodeUTF8)); + label_25->setText(QApplication::translate("DetailsDialog", "Year:", 0, QApplication::UnicodeUTF8)); + label_26->setText(QApplication::translate("DetailsDialog", "Track number:", 0, QApplication::UnicodeUTF8)); + label_27->setText(QApplication::translate("DetailsDialog", "Genre:", 0, QApplication::UnicodeUTF8)); + createButton->setText(QApplication::translate("DetailsDialog", "Create", 0, QApplication::UnicodeUTF8)); + deleteButton->setText(QApplication::translate("DetailsDialog", "Delete", 0, QApplication::UnicodeUTF8)); + saveButton->setText(QApplication::translate("DetailsDialog", "Save", 0, QApplication::UnicodeUTF8)); + pushButton_3->setText(QApplication::translate("DetailsDialog", "Close", 0, QApplication::UnicodeUTF8)); + Q_UNUSED(DetailsDialog); + } // retranslateUi + +}; + +namespace Ui { + class DetailsDialog: public Ui_DetailsDialog {}; +} // namespace Ui + +#endif // UI_DETAILSDIALOG_H diff --git a/src/plugins/Input/mad/ui_settingsdialog.h b/src/plugins/Input/mad/ui_settingsdialog.h new file mode 100644 index 000000000..47cdac64f --- /dev/null +++ b/src/plugins/Input/mad/ui_settingsdialog.h @@ -0,0 +1,245 @@ +/******************************************************************************** +** Form generated from reading ui file 'settingsdialog.ui' +** +** Created: Thu Feb 7 00:21:43 2008 +** by: Qt User Interface Compiler version 4.3.0 +** +** WARNING! All changes made in this file will be lost when recompiling ui file! +********************************************************************************/ + +#ifndef UI_SETTINGSDIALOG_H +#define UI_SETTINGSDIALOG_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Ui_SettingsDialog +{ +public: + QVBoxLayout *vboxLayout; + QGroupBox *groupBox_2; + QVBoxLayout *vboxLayout1; + QHBoxLayout *hboxLayout; + QLabel *label_15_2; + QComboBox *firstTagComboBox; + QHBoxLayout *hboxLayout1; + QLabel *label_15_3; + QComboBox *secondTagComboBox; + QHBoxLayout *hboxLayout2; + QLabel *label_15_4; + QComboBox *thirdTagComboBox; + QGroupBox *groupBox; + QVBoxLayout *vboxLayout2; + QHBoxLayout *hboxLayout3; + QLabel *label_17_2_2; + QComboBox *id3v1EncComboBox; + QHBoxLayout *hboxLayout4; + QLabel *label_18_2_2; + QComboBox *id3v2EncComboBox; + QHBoxLayout *hboxLayout5; + QSpacerItem *spacerItem; + QPushButton *okButton; + QPushButton *cancelButton; + + void setupUi(QDialog *SettingsDialog) + { + if (SettingsDialog->objectName().isEmpty()) + SettingsDialog->setObjectName(QString::fromUtf8("SettingsDialog")); + QSize size(242, 303); + size = size.expandedTo(SettingsDialog->minimumSizeHint()); + SettingsDialog->resize(size); + vboxLayout = new QVBoxLayout(SettingsDialog); + vboxLayout->setObjectName(QString::fromUtf8("vboxLayout")); + groupBox_2 = new QGroupBox(SettingsDialog); + groupBox_2->setObjectName(QString::fromUtf8("groupBox_2")); + vboxLayout1 = new QVBoxLayout(groupBox_2); + vboxLayout1->setObjectName(QString::fromUtf8("vboxLayout1")); + hboxLayout = new QHBoxLayout(); + hboxLayout->setObjectName(QString::fromUtf8("hboxLayout")); + label_15_2 = new QLabel(groupBox_2); + label_15_2->setObjectName(QString::fromUtf8("label_15_2")); + QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth(label_15_2->sizePolicy().hasHeightForWidth()); + label_15_2->setSizePolicy(sizePolicy); + label_15_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + hboxLayout->addWidget(label_15_2); + + firstTagComboBox = new QComboBox(groupBox_2); + firstTagComboBox->setObjectName(QString::fromUtf8("firstTagComboBox")); + + hboxLayout->addWidget(firstTagComboBox); + + + vboxLayout1->addLayout(hboxLayout); + + hboxLayout1 = new QHBoxLayout(); + hboxLayout1->setObjectName(QString::fromUtf8("hboxLayout1")); + label_15_3 = new QLabel(groupBox_2); + label_15_3->setObjectName(QString::fromUtf8("label_15_3")); + sizePolicy.setHeightForWidth(label_15_3->sizePolicy().hasHeightForWidth()); + label_15_3->setSizePolicy(sizePolicy); + label_15_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + hboxLayout1->addWidget(label_15_3); + + secondTagComboBox = new QComboBox(groupBox_2); + secondTagComboBox->setObjectName(QString::fromUtf8("secondTagComboBox")); + + hboxLayout1->addWidget(secondTagComboBox); + + + vboxLayout1->addLayout(hboxLayout1); + + hboxLayout2 = new QHBoxLayout(); + hboxLayout2->setObjectName(QString::fromUtf8("hboxLayout2")); + label_15_4 = new QLabel(groupBox_2); + label_15_4->setObjectName(QString::fromUtf8("label_15_4")); + sizePolicy.setHeightForWidth(label_15_4->sizePolicy().hasHeightForWidth()); + label_15_4->setSizePolicy(sizePolicy); + label_15_4->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + hboxLayout2->addWidget(label_15_4); + + thirdTagComboBox = new QComboBox(groupBox_2); + thirdTagComboBox->setObjectName(QString::fromUtf8("thirdTagComboBox")); + + hboxLayout2->addWidget(thirdTagComboBox); + + + vboxLayout1->addLayout(hboxLayout2); + + + vboxLayout->addWidget(groupBox_2); + + groupBox = new QGroupBox(SettingsDialog); + groupBox->setObjectName(QString::fromUtf8("groupBox")); + vboxLayout2 = new QVBoxLayout(groupBox); + vboxLayout2->setObjectName(QString::fromUtf8("vboxLayout2")); + hboxLayout3 = new QHBoxLayout(); + hboxLayout3->setSpacing(6); + hboxLayout3->setObjectName(QString::fromUtf8("hboxLayout3")); + hboxLayout3->setContentsMargins(0, 0, 0, 0); + label_17_2_2 = new QLabel(groupBox); + label_17_2_2->setObjectName(QString::fromUtf8("label_17_2_2")); + label_17_2_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + hboxLayout3->addWidget(label_17_2_2); + + id3v1EncComboBox = new QComboBox(groupBox); + id3v1EncComboBox->setObjectName(QString::fromUtf8("id3v1EncComboBox")); + + hboxLayout3->addWidget(id3v1EncComboBox); + + + vboxLayout2->addLayout(hboxLayout3); + + hboxLayout4 = new QHBoxLayout(); + hboxLayout4->setSpacing(6); + hboxLayout4->setObjectName(QString::fromUtf8("hboxLayout4")); + hboxLayout4->setContentsMargins(0, 0, 0, 0); + label_18_2_2 = new QLabel(groupBox); + label_18_2_2->setObjectName(QString::fromUtf8("label_18_2_2")); + label_18_2_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + hboxLayout4->addWidget(label_18_2_2); + + id3v2EncComboBox = new QComboBox(groupBox); + id3v2EncComboBox->setObjectName(QString::fromUtf8("id3v2EncComboBox")); + + hboxLayout4->addWidget(id3v2EncComboBox); + + + vboxLayout2->addLayout(hboxLayout4); + + + vboxLayout->addWidget(groupBox); + + hboxLayout5 = new QHBoxLayout(); + hboxLayout5->setSpacing(6); + hboxLayout5->setObjectName(QString::fromUtf8("hboxLayout5")); + hboxLayout5->setContentsMargins(0, 0, 0, 0); + spacerItem = new QSpacerItem(131, 31, QSizePolicy::Expanding, QSizePolicy::Minimum); + + hboxLayout5->addItem(spacerItem); + + okButton = new QPushButton(SettingsDialog); + okButton->setObjectName(QString::fromUtf8("okButton")); + + hboxLayout5->addWidget(okButton); + + cancelButton = new QPushButton(SettingsDialog); + cancelButton->setObjectName(QString::fromUtf8("cancelButton")); + + hboxLayout5->addWidget(cancelButton); + + + vboxLayout->addLayout(hboxLayout5); + + + retranslateUi(SettingsDialog); + QObject::connect(cancelButton, SIGNAL(clicked()), SettingsDialog, SLOT(reject())); + + firstTagComboBox->setCurrentIndex(0); + secondTagComboBox->setCurrentIndex(0); + thirdTagComboBox->setCurrentIndex(0); + + + QMetaObject::connectSlotsByName(SettingsDialog); + } // setupUi + + void retranslateUi(QDialog *SettingsDialog) + { + SettingsDialog->setWindowTitle(QApplication::translate("SettingsDialog", "MPEG Plugin Settings", 0, QApplication::UnicodeUTF8)); + groupBox_2->setTitle(QApplication::translate("SettingsDialog", "Tag Priority", 0, QApplication::UnicodeUTF8)); + label_15_2->setText(QApplication::translate("SettingsDialog", "First:", 0, QApplication::UnicodeUTF8)); + firstTagComboBox->clear(); + firstTagComboBox->insertItems(0, QStringList() + << QApplication::translate("SettingsDialog", "ID3v1", 0, QApplication::UnicodeUTF8) + << QApplication::translate("SettingsDialog", "ID3v2", 0, QApplication::UnicodeUTF8) + << QApplication::translate("SettingsDialog", "APE", 0, QApplication::UnicodeUTF8) + << QApplication::translate("SettingsDialog", "Disabled", 0, QApplication::UnicodeUTF8) + ); + label_15_3->setText(QApplication::translate("SettingsDialog", "Second:", 0, QApplication::UnicodeUTF8)); + secondTagComboBox->clear(); + secondTagComboBox->insertItems(0, QStringList() + << QApplication::translate("SettingsDialog", "ID3v1", 0, QApplication::UnicodeUTF8) + << QApplication::translate("SettingsDialog", "ID3v2", 0, QApplication::UnicodeUTF8) + << QApplication::translate("SettingsDialog", "APE", 0, QApplication::UnicodeUTF8) + << QApplication::translate("SettingsDialog", "Disabled", 0, QApplication::UnicodeUTF8) + ); + label_15_4->setText(QApplication::translate("SettingsDialog", "Third:", 0, QApplication::UnicodeUTF8)); + thirdTagComboBox->clear(); + thirdTagComboBox->insertItems(0, QStringList() + << QApplication::translate("SettingsDialog", "ID3v1", 0, QApplication::UnicodeUTF8) + << QApplication::translate("SettingsDialog", "ID3v2", 0, QApplication::UnicodeUTF8) + << QApplication::translate("SettingsDialog", "APE", 0, QApplication::UnicodeUTF8) + << QApplication::translate("SettingsDialog", "Disabled", 0, QApplication::UnicodeUTF8) + ); + groupBox->setTitle(QApplication::translate("SettingsDialog", "Encodings", 0, QApplication::UnicodeUTF8)); + label_17_2_2->setText(QApplication::translate("SettingsDialog", "ID3v1 encoding:", 0, QApplication::UnicodeUTF8)); + label_18_2_2->setText(QApplication::translate("SettingsDialog", "ID3v2 encoding:", 0, QApplication::UnicodeUTF8)); + okButton->setText(QApplication::translate("SettingsDialog", "OK", 0, QApplication::UnicodeUTF8)); + cancelButton->setText(QApplication::translate("SettingsDialog", "Cancel", 0, QApplication::UnicodeUTF8)); + Q_UNUSED(SettingsDialog); + } // retranslateUi + +}; + +namespace Ui { + class SettingsDialog: public Ui_SettingsDialog {}; +} // namespace Ui + +#endif // UI_SETTINGSDIALOG_H diff --git a/src/plugins/Input/mpc/CMakeLists.txt b/src/plugins/Input/mpc/CMakeLists.txt new file mode 100644 index 000000000..dccd6dd6b --- /dev/null +++ b/src/plugins/Input/mpc/CMakeLists.txt @@ -0,0 +1,86 @@ +project(libmpc) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +# libmpc and taglib +PKGCONFIG(taglib TAGLIB_INCLUDE_DIR TAGLIB_LINK_DIR TAGLIB_LINK_FLAGS TAGLIB_CFLAGS) + +IF(NOT TAGLIB_LINK_FLAGS) + SET(TAGLIB_LINK_FLAGS -ltag) + SET(TAGLIB_INCLUDE_DIR /usr/include/taglib) + SET(TAGLIB_CFLAGS -I/usr/include/taglib) +ENDIF(NOT TAGLIB_LINK_FLAGS) + +include_directories(${FLAC_INCLUDE_DIR} ${TAGLIB_INCLUDE_DIR}) +link_directories(${FLAC_LINK_DIR} ${TAGLIB_LINK_DIR}) + +ADD_DEFINITIONS(${TAGLIB_CFLAGS}) + + +SET(libmpc_SRCS + decoder_mpc.cpp + decodermpcfactory.cpp + detailsdialog.cpp +) + +SET(libmpc_MOC_HDRS + decodermpcfactory.h + decoder_mpc.h + detailsdialog.h +) + +SET(libmpc_RCCS translations/translations.qrc) + +QT4_ADD_RESOURCES(libmpc_RCC_SRCS ${libmpc_RCCS}) + +QT4_WRAP_CPP(libmpc_MOC_SRCS ${libmpc_MOC_HDRS}) + +# user interface + + +SET(libmpc_UIS + detailsdialog.ui +) + +QT4_WRAP_UI(libmpc_UIS_H ${libmpc_UIS}) +# Don't forget to include output directory, otherwise +# the UI file won't be wrapped! +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(mpc SHARED ${libmpc_SRCS} ${libmpc_MOC_SRCS} ${libmpc_UIS_H} + ${libmpc_RCC_SRCS}) +target_link_libraries(mpc ${QT_LIBRARIES} -lqmmp -lmpcdec ${TAGLIB_LINK_FLAGS} ${TAGLIB_CFLAGS}) +install(TARGETS mpc DESTINATION ${LIB_DIR}/qmmp/Input PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) + +# clean remaining files + +SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES + "CMakeCache.txt;Makefile;cmake_install.cmake" +) + diff --git a/src/plugins/Input/mpc/Makefile b/src/plugins/Input/mpc/Makefile new file mode 100644 index 000000000..7aa3ee7b3 --- /dev/null +++ b/src/plugins/Input/mpc/Makefile @@ -0,0 +1,254 @@ +############################################################################# +# Makefile for building: libmpc.so +# Generated by qmake (2.01a) (Qt 4.3.1) on: Thu Feb 7 14:07:02 2008 +# Project: mpc.pro +# Template: lib +# Command: /usr/local/Trolltech/Qt-4.3.1/bin/qmake -unix -o Makefile mpc.pro +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DQT_NO_DEBUG -DQT_PLUGIN -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -pipe -O2 -I/usr/include/taglib -Wall -W -D_REENTRANT -fPIC $(DEFINES) +CXXFLAGS = -pipe -O2 -I/usr/include/taglib -Wall -W -D_REENTRANT -fPIC $(DEFINES) +INCPATH = -I/usr/local/Trolltech/Qt-4.3.1/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.3.1/include/QtCore -I/usr/local/Trolltech/Qt-4.3.1/include/QtCore -I/usr/local/Trolltech/Qt-4.3.1/include/QtGui -I/usr/local/Trolltech/Qt-4.3.1/include/QtGui -I/usr/local/Trolltech/Qt-4.3.1/include -I../../../qmmp -I.build/moc -I.build/ui +LINK = g++ +LFLAGS = -Wl,-rpath,/usr/local/Trolltech/Qt-4.3.1/lib -shared +LIBS = $(SUBLIBS) -L../../../../lib -L/usr/local/Trolltech/Qt-4.3.1/lib -lqmmp -L/usr/lib -lmpcdec -I/usr/include -ltag -lQtGui -L/usr/local/Trolltech/Qt-4.3.1/lib -L/usr/X11R6/lib -lpng -lSM -lICE -pthread -pthread -lXi -lXrender -lXrandr -lXfixes -lXcursor -lXinerama -lfreetype -lfontconfig -lXext -lX11 -lQtCore -lz -lm -pthread -lgthread-2.0 -lglib-2.0 -lrt -ldl -lpthread +AR = ar cqs +RANLIB = +QMAKE = /usr/local/Trolltech/Qt-4.3.1/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -sf +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = .build/obj/ + +####### Files + +SOURCES = decoder_mpc.cpp \ + decodermpcfactory.cpp \ + detailsdialog.cpp .build/moc/moc_decodermpcfactory.cpp \ + .build/moc/moc_detailsdialog.cpp +OBJECTS = .build/obj/decoder_mpc.o \ + .build/obj/decodermpcfactory.o \ + .build/obj/detailsdialog.o \ + .build/obj/moc_decodermpcfactory.o \ + .build/obj/moc_detailsdialog.o +DIST = /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/g++.conf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/unix.conf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/linux.conf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/qconfig.pri \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_functions.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_config.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/exclusive_builds.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_pre.prf \ + ../../../../qmmp.pri \ + ../../plugins.pri \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/release.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_post.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/link_pkgconfig.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/warn_on.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/unix/thread.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/moc.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/resources.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/uic.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/yacc.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/lex.prf \ + mpc.pro +QMAKE_TARGET = mpc +DESTDIR = ../../../../lib/qmmp/Input/ +TARGET = libmpc.so +TARGETD = libmpc.so + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile ../../../../lib/qmmp/Input/$(TARGET) + +../../../../lib/qmmp/Input/$(TARGET): .build/ui/ui_detailsdialog.h $(OBJECTS) $(SUBLIBS) $(OBJCOMP) + @$(CHK_DIR_EXISTS) ../../../../lib/qmmp/Input/ || $(MKDIR) ../../../../lib/qmmp/Input/ + -$(DEL_FILE) $(TARGET) + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP) + -$(MOVE) $(TARGET) ../../../../lib/qmmp/Input/ + + + +Makefile: mpc.pro /usr/local/Trolltech/Qt-4.3.1/mkspecs/linux-g++/qmake.conf /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/g++.conf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/unix.conf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/common/linux.conf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/qconfig.pri \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_functions.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_config.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/exclusive_builds.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_pre.prf \ + ../../../../qmmp.pri \ + ../../plugins.pri \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/release.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_post.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/link_pkgconfig.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/warn_on.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/unix/thread.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/moc.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/resources.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/uic.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/yacc.prf \ + /usr/local/Trolltech/Qt-4.3.1/mkspecs/features/lex.prf \ + /usr/local/Trolltech/Qt-4.3.1/lib/libQtGui.prl \ + /usr/local/Trolltech/Qt-4.3.1/lib/libQtCore.prl + $(QMAKE) -unix -o Makefile mpc.pro +/usr/local/Trolltech/Qt-4.3.1/mkspecs/common/g++.conf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/common/unix.conf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/common/linux.conf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/qconfig.pri: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_functions.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt_config.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/exclusive_builds.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_pre.prf: +../../../../qmmp.pri: +../../plugins.pri: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/release.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/default_post.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/link_pkgconfig.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/warn_on.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/qt.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/unix/thread.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/moc.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/resources.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/uic.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/yacc.prf: +/usr/local/Trolltech/Qt-4.3.1/mkspecs/features/lex.prf: +/usr/local/Trolltech/Qt-4.3.1/lib/libQtGui.prl: +/usr/local/Trolltech/Qt-4.3.1/lib/libQtCore.prl: +qmake: FORCE + @$(QMAKE) -unix -o Makefile mpc.pro + +dist: + @$(CHK_DIR_EXISTS) .build/obj/mpc1.0.0 || $(MKDIR) .build/obj/mpc1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .build/obj/mpc1.0.0/ && $(COPY_FILE) --parents decodermpcfactory.h decoder_mpc.h detailsdialog.h .build/obj/mpc1.0.0/ && $(COPY_FILE) --parents decoder_mpc.cpp decodermpcfactory.cpp detailsdialog.cpp .build/obj/mpc1.0.0/ && $(COPY_FILE) --parents detailsdialog.ui .build/obj/mpc1.0.0/ && (cd `dirname .build/obj/mpc1.0.0` && $(TAR) mpc1.0.0.tar mpc1.0.0 && $(COMPRESS) mpc1.0.0.tar) && $(MOVE) `dirname .build/obj/mpc1.0.0`/mpc1.0.0.tar.gz . && $(DEL_FILE) -r .build/obj/mpc1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) ../../../../lib/qmmp/Input/libmpc.so + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile + + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: .build/moc/moc_decodermpcfactory.cpp .build/moc/moc_detailsdialog.cpp +compiler_moc_header_clean: + -$(DEL_FILE) .build/moc/moc_decodermpcfactory.cpp .build/moc/moc_detailsdialog.cpp +.build/moc/moc_decodermpcfactory.cpp: decodermpcfactory.h + /usr/local/Trolltech/Qt-4.3.1/bin/moc $(DEFINES) $(INCPATH) decodermpcfactory.h -o .build/moc/moc_decodermpcfactory.cpp + +.build/moc/moc_detailsdialog.cpp: .build/ui/ui_detailsdialog.h \ + detailsdialog.h + /usr/local/Trolltech/Qt-4.3.1/bin/moc $(DEFINES) $(INCPATH) detailsdialog.h -o .build/moc/moc_detailsdialog.cpp + +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_uic_make_all: .build/ui/ui_detailsdialog.h +compiler_uic_clean: + -$(DEL_FILE) .build/ui/ui_detailsdialog.h +.build/ui/ui_detailsdialog.h: detailsdialog.ui + /usr/local/Trolltech/Qt-4.3.1/bin/uic detailsdialog.ui -o .build/ui/ui_detailsdialog.h + +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean compiler_uic_clean + +####### Compile + +.build/obj/decoder_mpc.o: decoder_mpc.cpp decoder_mpc.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/decoder_mpc.o decoder_mpc.cpp + +.build/obj/decodermpcfactory.o: decodermpcfactory.cpp detailsdialog.h \ + .build/ui/ui_detailsdialog.h \ + decoder_mpc.h \ + decodermpcfactory.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/decodermpcfactory.o decodermpcfactory.cpp + +.build/obj/detailsdialog.o: detailsdialog.cpp detailsdialog.h \ + .build/ui/ui_detailsdialog.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/detailsdialog.o detailsdialog.cpp + +.build/obj/moc_decodermpcfactory.o: .build/moc/moc_decodermpcfactory.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/moc_decodermpcfactory.o .build/moc/moc_decodermpcfactory.cpp + +.build/obj/moc_detailsdialog.o: .build/moc/moc_detailsdialog.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/moc_detailsdialog.o .build/moc/moc_detailsdialog.cpp + +####### Install + +install_target: first FORCE + @$(CHK_DIR_EXISTS) $(INSTALL_ROOT)/lib/qmmp/Input/ || $(MKDIR) $(INSTALL_ROOT)/lib/qmmp/Input/ + -$(INSTALL_PROGRAM) "../../../../lib/qmmp/Input/$(TARGET)" "$(INSTALL_ROOT)/lib/qmmp/Input/$(TARGET)" + -strip --strip-unneeded "$(INSTALL_ROOT)/lib/qmmp/Input/$(TARGET)" + +uninstall_target: FORCE + -$(DEL_FILE) "$(INSTALL_ROOT)/lib/qmmp/Input/$(TARGET)" + -$(DEL_DIR) $(INSTALL_ROOT)/lib/qmmp/Input/ + + +install: install_target FORCE + +uninstall: uninstall_target FORCE + +FORCE: + diff --git a/src/plugins/Input/mpc/decoder_mpc.cpp b/src/plugins/Input/mpc/decoder_mpc.cpp new file mode 100644 index 000000000..10591a384 --- /dev/null +++ b/src/plugins/Input/mpc/decoder_mpc.cpp @@ -0,0 +1,386 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +#include +#include + +#include "constants.h" +#include "buffer.h" +#include "output.h" +#include "recycler.h" + +#include "decoder_mpc.h" + +// this function used from xmms +inline static void copyBuffer(MPC_SAMPLE_FORMAT* pInBuf, char* pOutBuf, unsigned pLength) +{ + unsigned pSize = 16; + int clipMin = -1 << (pSize - 1); + int clipMax = (1 << (pSize - 1)) - 1; + int floatScale = 1 << (pSize - 1); + for (unsigned n = 0; n < 2 * pLength; n++) + { + int val; +#ifdef MPC_FIXED_POINT + val = shiftSigned(pInBuf[n], pSize - MPC_FIXED_POINT_SCALE_SHIFT); +#else + val = (int) (pInBuf[n] * floatScale); +#endif + if (val < clipMin) + val = clipMin; + else if (val > clipMax) + val = clipMax; + unsigned shift = 0; + do + { + pOutBuf[n * 2 + (shift / 8)] = (unsigned char) ((val >> shift) & 0xFF); + shift += 8; + } + while (shift < pSize); + } +} + +// mpc callbacks + +static mpc_int32_t mpc_callback_read (void *data, void *buffer, mpc_int32_t size) +{ + DecoderMPC *dmpc = (DecoderMPC *) data; + qint64 res; + + res = dmpc->input()->read((char *)buffer, size); + + return res; +} + +static mpc_bool_t mpc_callback_seek (void *data, mpc_int32_t offset) +{ + DecoderMPC *dmpc = (DecoderMPC *) data; + + return dmpc->input()->seek(offset); // ? TRUE : FALSE; +} + +static mpc_int32_t mpc_callback_tell (void *data) +{ + DecoderMPC *dmpc = (DecoderMPC *) data; + return dmpc->input()->pos (); +} + +static mpc_bool_t mpc_callback_canseek (void *data) +{ + DecoderMPC *dmpc = (DecoderMPC *) data; + return !dmpc->input()->isSequential () ; +} + +static mpc_int32_t mpc_callback_get_size (void *data) +{ + DecoderMPC *dmpc = (DecoderMPC *) data; + return dmpc->input()->size(); +} + +// Decoder class + +DecoderMPC::DecoderMPC(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o) + : Decoder(parent, d, i, o) +{ + inited = FALSE; + user_stop = FALSE; + stat = 0; + output_buf = 0; + output_bytes = 0; + output_at = 0; + bks = 0; + done = FALSE; + finish = FALSE; + len = 0; + freq = 0; + bitrate = 0; + seekTime = -1.0; + totalTime = 0.0; + chan = 0; + output_size = 0; + m_data = 0; + + + + +} + + +DecoderMPC::~DecoderMPC() +{ + deinit(); + if(data()) + { + delete data(); + m_data = 0; + } + if (output_buf) + delete [] output_buf; + output_buf = 0; +} + + +void DecoderMPC::stop() +{ + user_stop = TRUE; +} + + +void DecoderMPC::flush(bool final) +{ + ulong min = final ? 0 : bks; + + while ((! done && ! finish) && output_bytes > min) + { + output()->recycler()->mutex()->lock (); + + while ((! done && ! finish) && output()->recycler()->full()) + { + mutex()->unlock(); + + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + + mutex()->lock (); + done = user_stop; + } + + if (user_stop || finish) + { + inited = FALSE; + done = TRUE; + } + else + { + output_bytes -= produceSound(output_buf, output_bytes, bitrate, chan); + output_size += bks; + output_at = output_bytes; + } + + if (output()->recycler()->full()) + { + output()->recycler()->cond()->wakeOne(); + } + + output()->recycler()->mutex()->unlock(); + } +} + + +bool DecoderMPC::initialize() +{ + bks = blockSize(); + inited = user_stop = done = finish = FALSE; + len = freq = bitrate = 0; + stat = chan = 0; + output_size = 0; + seekTime = -1.0; + totalTime = 0.0; + + + if (! input()) + { + error("DecoderMPC: cannot initialize. No input."); + + return FALSE; + } + + if (! output_buf) + output_buf = new char[globalBufferSize]; + output_at = 0; + output_bytes = 0; + + if (! input()) + { + error("DecoderMPC: cannot initialize. No input."); + + return FALSE; + } + + if (! output_buf) + output_buf = new char[globalBufferSize]; + output_at = 0; + output_bytes = 0; + + if (! input()->isOpen()) + { + if (! input()->open(QIODevice::ReadOnly)) + { + error("DecoderMPC: cannot open input."); + return FALSE; + } + } + if (!m_data) + { + m_data = new mpc_data; + } + + qDebug("DecoderMPC: setting callbacks"); + m_data->reader.read = mpc_callback_read; + m_data->reader.seek = mpc_callback_seek; + m_data->reader.tell = mpc_callback_tell; + m_data->reader.canseek = mpc_callback_canseek; + m_data->reader.get_size = mpc_callback_get_size; + m_data->reader.data = this; + + mpc_streaminfo_init (&m_data->info); + + if (mpc_streaminfo_read (&m_data->info, &m_data->reader) != ERROR_CODE_OK) + return FALSE; + chan = data()->info.channels; + configure(data()->info.sample_freq, chan, 16, data()->info.bitrate); + + mpc_decoder_setup (&data()->decoder, &data()->reader); + + //mpc_decoder_scale_output (&data()->decoder, 3.0); + + if (!mpc_decoder_initialize (&data()->decoder, &data()->info)) + { + error("DecoderMPC: cannot get info."); + return FALSE; + } + totalTime = mpc_streaminfo_get_length(&data()->info); + inited = TRUE; + qDebug("DecoderMPC: initialize succes"); + return TRUE; +} + + +double DecoderMPC::lengthInSeconds() +{ + if (! inited) + return 0; + + return totalTime; +} + + +void DecoderMPC::seek(double pos) +{ + seekTime = pos; +} + + +void DecoderMPC::deinit() +{ + //FLAC__stream_decoder_finish (data()->decoder); + inited = user_stop = done = finish = FALSE; + len = freq = bitrate = 0; + stat = chan = 0; + output_size = 0; +} + +void DecoderMPC::run() +{ + mpc_uint32_t vbrAcc = 0; + mpc_uint32_t vbrUpd = 0; + mutex()->lock (); + + if (! inited) + { + mutex()->unlock(); + + return; + } + stat = DecoderState::Decoding; + mutex()->unlock(); + { + dispatch(DecoderState ((DecoderState::Type) stat)); + } + + while (! done && ! finish) + { + mutex()->lock (); + // decode + + if (seekTime >= 0.0) + { + mpc_decoder_seek_seconds(&data()->decoder, seekTime); + seekTime = -1.0; + } + MPC_SAMPLE_FORMAT buffer[MPC_DECODER_BUFFER_LENGTH]; + + len = mpc_decoder_decode (&data()->decoder, buffer, &vbrAcc, &vbrUpd); + + copyBuffer(buffer, (char *) (output_buf + output_at), len); + + len = len * 4; + + if (len > 0) + { + bitrate = vbrUpd * data()->info.sample_freq / 1152; + output_at += len; + output_bytes += len; + + if (output()) + flush(); + + } + else if (len == 0) + { + flush(TRUE); + + if (output()) + { + output()->recycler()->mutex()->lock (); + // end of stream + while (! output()->recycler()->empty() && ! user_stop) + { + output()->recycler()->cond()->wakeOne(); + mutex()->unlock(); + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + mutex()->lock (); + } + output()->recycler()->mutex()->unlock(); + } + + done = TRUE; + if (! user_stop) + { + finish = TRUE; + } + } + else + { + // error in read + error("DecoderMPC: Error while decoding stream, File appears to be " + "corrupted"); + + finish = TRUE; + } + + mutex()->unlock(); + } + + mutex()->lock (); + + if (finish) + stat = DecoderState::Finished; + else if (user_stop) + stat = DecoderState::Stopped; + + mutex()->unlock(); + + { + dispatch(DecoderState ((DecoderState::Type) stat)); + } + + deinit(); +} diff --git a/src/plugins/Input/mpc/decoder_mpc.h b/src/plugins/Input/mpc/decoder_mpc.h new file mode 100644 index 000000000..3b17b100e --- /dev/null +++ b/src/plugins/Input/mpc/decoder_mpc.h @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef __decoder_mpc_h +#define __decoder_mpc_h + +#include + +#include "decoder.h" + +struct mpc_data +{ + mpc_decoder decoder; + mpc_reader reader; + mpc_streaminfo info; +}; + +class DecoderMPC : public Decoder +{ +public: + DecoderMPC(QObject *, DecoderFactory *, QIODevice *, Output *); + virtual ~DecoderMPC(); + + // Standard Decoder API + bool initialize(); + double lengthInSeconds(); + void seek(double); + void stop(); + + // Equalizer + bool isEQSupported() const { return FALSE; } + void setEQEnabled(bool) { ; } + void setEQGain(int) { ; } + void setEQBands(int[10]) { ; } + + struct mpc_data *data() { return m_data; } + + +private: + // thread run function + void run(); + struct mpc_data *m_data; + // helper functions + void flush(bool = FALSE); + void deinit(); + + bool inited, user_stop; + int stat; + + // output buffer + char *output_buf; + ulong output_bytes, output_at; + + unsigned int bks; + bool done, finish; + long len, freq, bitrate; + int chan; + unsigned long output_size; + double totalTime, seekTime; +}; + + +#endif // __decoder_mpc_h diff --git a/src/plugins/Input/mpc/decodermpcfactory.cpp b/src/plugins/Input/mpc/decodermpcfactory.cpp new file mode 100644 index 000000000..f2874a08d --- /dev/null +++ b/src/plugins/Input/mpc/decodermpcfactory.cpp @@ -0,0 +1,95 @@ +#include +#include +#include + +#include "detailsdialog.h" +#include "decoder_mpc.h" +#include "decodermpcfactory.h" + + +// DecoderMPCFactory + +bool DecoderMPCFactory::supports(const QString &source) const +{ + + return (source.right(4).toLower() == ".mpc"); +} + +bool DecoderMPCFactory::canDecode(QIODevice *) const +{ + return FALSE; +} + +const DecoderProperties DecoderMPCFactory::properties() const +{ + DecoderProperties properties; + properties.name = tr("Musepack Plugin"); + properties.filter = "*.mpc"; + properties.description = tr("Musepack Files"); + //properties.contentType = ; + properties.hasAbout = TRUE; + properties.hasSettings = FALSE; + return properties; +} + +Decoder *DecoderMPCFactory::create(QObject *parent, QIODevice *input, + Output *output) +{ + return new DecoderMPC(parent, this, input, output); +} + +FileTag *DecoderMPCFactory::createTag(const QString &source) +{ + FileTag *ftag = new FileTag(); + + TagLib::FileRef fileRef(source.toLocal8Bit ()); + TagLib::Tag *tag = fileRef.tag(); + + if (tag && !tag->isEmpty()) + { + ftag->setValue(FileTag::ALBUM, + QString::fromUtf8(tag->album().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::ARTIST, + QString::fromUtf8(tag->artist().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::COMMENT, + QString::fromUtf8(tag->comment().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::GENRE, + QString::fromUtf8(tag->genre().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::TITLE, + QString::fromUtf8(tag->title().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::YEAR, tag->year()); + ftag->setValue(FileTag::TRACK, tag->track()); + } + + if (fileRef.audioProperties()) + ftag->setValue(FileTag::LENGTH, fileRef.audioProperties()->length()); + + return ftag; +} + +QObject* DecoderMPCFactory::showDetails(QWidget *parent, const QString &path) +{ + DetailsDialog *d = new DetailsDialog(parent, path); + d -> show(); + return d; +} + +void DecoderMPCFactory::showSettings(QWidget *) +{} + +void DecoderMPCFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About Musepack Audio Plugin"), + tr("Qmmp Musepack Audio Plugin")+"\n"+ + tr("Writen by: Ilya Kotov ")); +} + +QTranslator *DecoderMPCFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/mpc_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(DecoderMPCFactory) diff --git a/src/plugins/Input/mpc/decodermpcfactory.h b/src/plugins/Input/mpc/decodermpcfactory.h new file mode 100644 index 000000000..0f8dda55f --- /dev/null +++ b/src/plugins/Input/mpc/decodermpcfactory.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DECODERMPCFACTORY_H +#define DECODERMPCFACTORY_H + +#include +#include +#include +#include + +#include +#include +#include +#include + + + + +class DecoderMPCFactory : public QObject, + DecoderFactory +{ +Q_OBJECT +Q_INTERFACES(DecoderFactory); + +public: + bool supports(const QString &source) const; + bool canDecode(QIODevice *input) const; + const DecoderProperties properties() const; + Decoder *create(QObject *, QIODevice *, Output *); + FileTag *createTag(const QString &source); + QObject* showDetails(QWidget *parent, const QString &path); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); +}; + +#endif diff --git a/src/plugins/Input/mpc/detailsdialog.cpp b/src/plugins/Input/mpc/detailsdialog.cpp new file mode 100644 index 000000000..472046717 --- /dev/null +++ b/src/plugins/Input/mpc/detailsdialog.cpp @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include +#include + +#include "detailsdialog.h" + +#define QStringToTString_qt4(s) TagLib::String(s.toUtf8().constData(), TagLib::String::UTF8) + +DetailsDialog::DetailsDialog(QWidget *parent, const QString &path) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + m_path = path; + setWindowTitle (path.section('/',-1)); + path.section('/',-1); + ui.pathLineEdit->setText(m_path); + if(QFile::exists(m_path)) + { + loadMPCInfo(); + loadTag(); + } +} + + +DetailsDialog::~DetailsDialog() +{} + +void DetailsDialog::loadMPCInfo() +{ + TagLib::MPC::File f (m_path.toLocal8Bit()); + QString text; + text = QString("%1").arg(f.audioProperties()->length()/60); + text +=":"+QString("%1").arg(f.audioProperties()->length()%60,2,10,QChar('0')); + ui.lengthLabel->setText(text); + text = QString("%1").arg(f.audioProperties()->sampleRate()); + ui.sampleRateLabel->setText(text+" "+tr("Hz")); + text = QString("%1").arg(f.audioProperties()->channels()); + ui.channelsLabel->setText(text); + text = QString("%1").arg(f.audioProperties()->bitrate()); + ui.bitrateLabel->setText(text+" "+tr("kbps")); + text = QString("%1").arg(f.audioProperties()->mpcVersion()); + ui.versionLabel->setText(text); + text = QString("%1 "+tr("KB")).arg(f.length()/1024); + ui.fileSizeLabel->setText(text); +} + +void DetailsDialog::loadTag() +{ + TagLib::FileRef f (m_path.toLocal8Bit()); + + if (f.tag()) + { //TODO: load codec name from config + + TagLib::String title = f.tag()->title(); + TagLib::String artist = f.tag()->artist(); + TagLib::String album = f.tag()->album(); + TagLib::String comment = f.tag()->comment(); + TagLib::String genre = f.tag()->genre(); + QString string = QString::fromUtf8(title.toCString(TRUE)).trimmed(); + ui.titleLineEdit->setText(string); + string = QString::fromUtf8(artist.toCString(TRUE)).trimmed(); + ui.artistLineEdit->setText(string); + string = QString::fromUtf8(album.toCString(TRUE)).trimmed(); + ui.albumLineEdit->setText(string); + string = QString::fromUtf8(comment.toCString(TRUE)).trimmed(); + ui.commentLineEdit->setText(string); + string = QString("%1").arg(f.tag()->year()); + ui.yearLineEdit->setText(string); + string = QString("%1").arg(f.tag()->track()); + ui.trackLineEdit->setText(string); + string = QString::fromUtf8(genre.toCString(TRUE)).trimmed(); + ui.genreLineEdit->setText(string); + } + QFileInfo info(m_path); + ui.saveButton->setEnabled(info.isWritable()); + connect(ui.saveButton, SIGNAL(clicked()), SLOT(saveTag())); +} + +void DetailsDialog::saveTag() +{ + TagLib::FileRef f (m_path.toLocal8Bit()); + + f.tag()->setTitle(QStringToTString_qt4(ui.titleLineEdit->text())); + f.tag()->setArtist(QStringToTString_qt4(ui.artistLineEdit->text())); + f.tag()->setAlbum(QStringToTString_qt4(ui.albumLineEdit->text())); + f.tag()->setComment(QStringToTString_qt4(ui.commentLineEdit->text())); + f.tag()->setGenre(QStringToTString_qt4(ui.genreLineEdit->text())); + f.tag()->setYear(ui.yearLineEdit->text().toUInt()); + f.tag()->setTrack(ui.trackLineEdit->text().toUInt()); + + f.save(); +} diff --git a/src/plugins/Input/mpc/detailsdialog.h b/src/plugins/Input/mpc/detailsdialog.h new file mode 100644 index 000000000..70540bda1 --- /dev/null +++ b/src/plugins/Input/mpc/detailsdialog.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DETAILSDIALOG_H +#define DETAILSDIALOG_H + +#include + +#include "ui_detailsdialog.h" + +/** + @author Ilya Kotov +*/ +class DetailsDialog : public QDialog +{ +Q_OBJECT +public: + DetailsDialog(QWidget *parent = 0, const QString &path = 0); + + ~DetailsDialog(); + +private slots: + void saveTag(); + +private: + void loadMPCInfo(); + void loadTag(); + Ui::DetailsDialog ui; + QString m_path; + +}; + +#endif diff --git a/src/plugins/Input/mpc/detailsdialog.ui b/src/plugins/Input/mpc/detailsdialog.ui new file mode 100644 index 000000000..918dd3abf --- /dev/null +++ b/src/plugins/Input/mpc/detailsdialog.ui @@ -0,0 +1,349 @@ + + DetailsDialog + + + + 0 + 0 + 449 + 375 + + + + Details + + + + 8 + + + 6 + + + + + + 175 + 16 + + + + Musepack Info + + + + 8 + + + 6 + + + + + Qt::Vertical + + + + 74 + 151 + + + + + + + + - + + + + + + + Length: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Sample rate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Qt::LeftToRight + + + Channels: + + + Qt::PlainText + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + File size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Bitrate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::LeftToRight + + + - + + + + + + + - + + + + + + + Stream version: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + + + + true + + + + + + + File path: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Close + + + + + + + Qt::Horizontal + + + + 111 + 20 + + + + + + + + + 5 + 5 + 0 + 0 + + + + Musepack Tag + + + + 8 + + + 6 + + + + + false + + + Save + + + + + + + + + + Track number: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Year: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Genre: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Comment: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Album: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Artist: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Title: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + + + + + + + + + + + + pushButton_3 + clicked() + DetailsDialog + close() + + + 623 + 353 + + + 539 + 352 + + + + + diff --git a/src/plugins/Input/mpc/mpc.pro b/src/plugins/Input/mpc/mpc.pro new file mode 100644 index 000000000..f1a50683d --- /dev/null +++ b/src/plugins/Input/mpc/mpc.pro @@ -0,0 +1,32 @@ +include(../../plugins.pri) + +FORMS += detailsdialog.ui +HEADERS += decodermpcfactory.h \ + decoder_mpc.h \ + detailsdialog.h +SOURCES += decoder_mpc.cpp \ + decodermpcfactory.cpp \ + detailsdialog.cpp + +TARGET=$$PLUGINS_PREFIX/Input/mpc +QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libmpc.so + + +INCLUDEPATH += ../../../qmmp +CONFIG += release \ +warn_on \ +plugin \ +link_pkgconfig +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmp -L/usr/lib -lmpcdec -I/usr/include +PKGCONFIG += taglib +#TRANSLATIONS = translations/mpc_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} + +target.path = $$LIB_DIR/qmmp/Input +INSTALLS += target diff --git a/src/plugins/Input/mpc/translations/mpc_plugin_ru.qm b/src/plugins/Input/mpc/translations/mpc_plugin_ru.qm new file mode 100644 index 000000000..0eb8c1533 Binary files /dev/null and b/src/plugins/Input/mpc/translations/mpc_plugin_ru.qm differ diff --git a/src/plugins/Input/mpc/translations/mpc_plugin_ru.ts b/src/plugins/Input/mpc/translations/mpc_plugin_ru.ts new file mode 100644 index 000000000..53ecd8dc8 --- /dev/null +++ b/src/plugins/Input/mpc/translations/mpc_plugin_ru.ts @@ -0,0 +1,149 @@ + + + + DecoderMPCFactory + + + Musepack Plugin + Модуль Musepack + + + + Musepack Files + Файлы Musepack + + + + About Musepack Audio Plugin + Об аудио-модуле Musepack + + + + Qmmp Musepack Audio Plugin + Аудио-модуль Musepack для Qmmp + + + + Writen by: Ilya Kotov <forkotov02@hotmail.ru> + Разработчик: Илья Котов <forkotov02@hotmail.ru> + + + + DetailsDialog + + + Hz + Гц + + + + Musepack Info + Информация Musepack + + + + - + + + + + Length: + Длительность: + + + + Sample rate: + Дискретизация: + + + + Channels: + Каналов: + + + + File size: + Размер файла: + + + + Bitrate: + Битовая частота: + + + + Stream version: + Версия потока: + + + + File path: + Путь к файлу: + + + + Close + Закрыть + + + + Musepack Tag + Musepack-тег + + + + Save + Сохранить + + + + Track number: + Номер трека: + + + + Year: + Год: + + + + Genre: + Жанр: + + + + Comment: + Комментарий: + + + + Album: + Альбом: + + + + Artist: + Исполнитель: + + + + Title: + Название: + + + + Details + Информация + + + + kbps + Кб/с + + + + KB + Кб + + + diff --git a/src/plugins/Input/mpc/translations/translations.qrc b/src/plugins/Input/mpc/translations/translations.qrc new file mode 100644 index 000000000..cc88de9ce --- /dev/null +++ b/src/plugins/Input/mpc/translations/translations.qrc @@ -0,0 +1,6 @@ + + + + mpc_plugin_ru.qm + + diff --git a/src/plugins/Input/sndfile/CMakeLists.txt b/src/plugins/Input/sndfile/CMakeLists.txt new file mode 100644 index 000000000..974db398e --- /dev/null +++ b/src/plugins/Input/sndfile/CMakeLists.txt @@ -0,0 +1,74 @@ +project(libsndfile) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +# libsndfile +PKGCONFIG(sndfile SNDFILE_INCLUDE_DIR SNDFILE_LINK_DIR SNDFILE_LINK_FLAGS SNDFILE_CFLAGS) + +IF(NOT SNDFILE_LINK_FLAGS) + SET(SNDFILE_LINK_FLAGS -lsndfile) + SET(SNDFILE_INCLUDE_DIR /usr/include) + SET(SNDFILE_CFLAGS -I/usr/include) +ENDIF(NOT SNDFILE_LINK_FLAGS) + +include_directories(${SNDFILE_INCLUDE_DIR}) +link_directories(${SNDFILE_LINK_DIR}) + +ADD_DEFINITIONS(${SNDFILE_CFLAGS}) + + +SET(libsndfile_SRCS + decoder_sndfile.cpp + decodersndfilefactory.cpp +) + +SET(libsndfile_MOC_HDRS + decodersndfilefactory.h + decoder_sndfile.h +) + +#SET(libsndfile_RCCS translations/translations.qrc) + +#QT4_ADD_RESOURCES(libsndfile_RCC_SRCS ${libsndfile_RCCS}) + +QT4_WRAP_CPP(libsndfile_MOC_SRCS ${libsndfile_MOC_HDRS}) + + +# Don't forget to include output directory, otherwise +# the UI file won't be wrapped! +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(sndfile SHARED ${libsndfile_SRCS} ${libsndfile_MOC_SRCS} ${libsndfile_UIS_H} + ${libsndfile_RCC_SRCS}) + +target_link_libraries(sndfile ${QT_LIBRARIES} -lqmmp ${SNDFILE_LINK_FLAGS}) +install(TARGETS sndfile DESTINATION ${LIB_DIR}/qmmp/Input) + + + diff --git a/src/plugins/Input/sndfile/decoder_sndfile.cpp b/src/plugins/Input/sndfile/decoder_sndfile.cpp new file mode 100644 index 000000000..b4baa2ba4 --- /dev/null +++ b/src/plugins/Input/sndfile/decoder_sndfile.cpp @@ -0,0 +1,282 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + + + +#include "constants.h" +#include "buffer.h" +#include "output.h" +#include "recycler.h" + +#include "decoder_sndfile.h" + +// Decoder class + +DecoderSndFile::DecoderSndFile(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o) + : Decoder(parent, d, i, o) +{ + m_inited = FALSE; + m_user_stop = FALSE; + m_output_buf = 0; + m_output_bytes = 0; + m_output_at = 0; + bks = 0; + m_done = FALSE; + m_finish = FALSE; + m_freq = 0; + m_bitrate = 0; + m_seekTime = -1.0; + m_totalTime = 0.0; + m_chan = 0; + m_output_size = 0; + m_buf = 0; + m_sndfile = 0; +} + + +DecoderSndFile::~DecoderSndFile() +{ + deinit(); +} + + +void DecoderSndFile::stop() +{ + m_user_stop = TRUE; +} + + +void DecoderSndFile::flush(bool final) +{ + ulong min = final ? 0 : bks; + + while ((! m_done && ! m_finish) && m_output_bytes > min) + { + output()->recycler()->mutex()->lock (); + + while ((! m_done && ! m_finish) && output()->recycler()->full()) + { + mutex()->unlock(); + + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + + mutex()->lock (); + m_done = m_user_stop; + } + + if (m_user_stop || m_finish) + { + m_inited = FALSE; + m_done = TRUE; + } + else + { + m_output_bytes -= produceSound(m_output_buf, m_output_bytes, m_bitrate, m_chan); + m_output_size += bks; + m_output_at = m_output_bytes; + } + + if (output()->recycler()->full()) + { + output()->recycler()->cond()->wakeOne(); + } + + output()->recycler()->mutex()->unlock(); + } +} + + +bool DecoderSndFile::initialize() +{ + bks = blockSize(); + m_inited = m_user_stop = m_done = m_finish = FALSE; + m_freq = m_bitrate = 0; + m_output_size = 0; + m_seekTime = -1.0; + m_totalTime = 0.0; + SF_INFO snd_info; + + + if (! input()) + { + error("DecoderSndFile: cannot initialize. No input."); + + return FALSE; + } + + if (! m_output_buf) + m_output_buf = new char[globalBufferSize]; + m_output_at = 0; + m_output_bytes = 0; + + QString filename = qobject_cast(input())->fileName (); + input()->close(); + + memset (&snd_info, 0, sizeof(snd_info)); + snd_info.format=0; + m_sndfile = sf_open(filename.toLocal8Bit(), SFM_READ, &snd_info); + if (!m_sndfile) + { + qWarning("DecoderSndFile: failed to open: %s", qPrintable(filename)); + return FALSE; + } + + m_freq = snd_info.samplerate; + m_chan = snd_info.channels; + + m_totalTime = (double) snd_info.frames / m_freq; + + m_bitrate = QFileInfo(filename).size () * 8.0 / m_totalTime / 1000.0 + 0.5; + + configure(m_freq, m_chan, 16, m_bitrate); + m_buf = new short[blockSize() / sizeof(short)]; + m_inited = TRUE; + qDebug("DecoderSndFile: detected format: %08X", snd_info.format); + qDebug("DecoderSndFile: initialize succes"); + return TRUE; +} + + +double DecoderSndFile::lengthInSeconds() +{ + if (! m_inited) + return 0; + + return m_totalTime; +} + + +void DecoderSndFile::seek(double pos) +{ + m_seekTime = pos; +} + + +void DecoderSndFile::deinit() +{ + m_inited = m_user_stop = m_done = m_finish = FALSE; + m_freq = m_bitrate = m_chan = 0; + m_output_size = 0; + if (m_inited) + { + delete m_buf; + m_buf = 0; + sf_close(m_sndfile); + m_sndfile = 0; + } +} + +void DecoderSndFile::run() +{ + + long len = 0; + int stat = 0; + + mutex()->lock (); + + if (! m_inited) + { + mutex()->unlock(); + + return; + } + + stat = DecoderState::Decoding; + mutex()->unlock(); + + { + dispatch(DecoderState ((DecoderState::Type) stat)); + } + + while (! m_done && ! m_finish) + { + mutex()->lock (); + // decode + + if (m_seekTime >= 0.0) + { + m_output_size = sf_seek(m_sndfile, m_freq*m_seekTime, SEEK_SET); + m_seekTime = -1.0; + } + + len = sizeof(short)* sf_read_short (m_sndfile, m_buf, blockSize() / sizeof(short)); + + if (len > 0) + { + memmove((char *)(m_output_buf + m_output_at), (char *) m_buf, len); + m_output_at += len; + m_output_bytes += len; + + if (output()) + flush(); + } + else if (len == 0) + { + flush(TRUE); + + if (output()) + { + output()->recycler()->mutex()->lock (); + // end of stream + while (! output()->recycler()->empty() && ! m_user_stop) + { + output()->recycler()->cond()->wakeOne(); + mutex()->unlock(); + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + mutex()->lock (); + } + output()->recycler()->mutex()->unlock(); + } + + m_done = TRUE; + if (! m_user_stop) + { + m_finish = TRUE; + } + } + else + { + // error in read + error("DecoderSndFile: Error while decoding stream, File appears to be " + "corrupted"); + + m_finish = TRUE; + } + + mutex()->unlock(); + } + + mutex()->lock (); + + if (m_finish) + stat = DecoderState::Finished; + else if (m_user_stop) + stat = DecoderState::Stopped; + + mutex()->unlock(); + + dispatch(DecoderState ((DecoderState::Type) stat)); + deinit(); +} + diff --git a/src/plugins/Input/sndfile/decoder_sndfile.h b/src/plugins/Input/sndfile/decoder_sndfile.h new file mode 100644 index 000000000..53bb8fd81 --- /dev/null +++ b/src/plugins/Input/sndfile/decoder_sndfile.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef DECODER_AUDIOFILE_H +#define DECODER_AUDIOFILE_H + +extern "C"{ +#include +} +#include "decoder.h" + + +class DecoderSndFile : public Decoder +{ +public: + DecoderSndFile(QObject *, DecoderFactory *, QIODevice *, Output *); + virtual ~DecoderSndFile(); + + // Standard Decoder API + bool initialize(); + double lengthInSeconds(); + void seek(double); + void stop(); + + +private: + // thread run function + void run(); + // helper functions + void flush(bool = FALSE); + void deinit(); + + // output buffer + char *m_output_buf; + + SNDFILE *m_sndfile; + ulong m_output_bytes, m_output_at; + //struct sndfile_data *m_data; + short *m_buf; + unsigned int bks; + bool m_done, m_finish, m_inited, m_user_stop; + long m_freq, m_bitrate; + int m_chan; + unsigned long m_output_size; + double m_totalTime, m_seekTime; +}; + + +#endif // DECODER_SNDFILE_H diff --git a/src/plugins/Input/sndfile/decodersndfilefactory.cpp b/src/plugins/Input/sndfile/decodersndfilefactory.cpp new file mode 100644 index 000000000..b918d32fc --- /dev/null +++ b/src/plugins/Input/sndfile/decodersndfilefactory.cpp @@ -0,0 +1,126 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +#include "decoder_sndfile.h" +#include "decodersndfilefactory.h" + + +// DecoderSndFileFactory + +bool DecoderSndFileFactory::supports(const QString &source) const +{ + + return (source.right(4).toLower() == ".wav") || + (source.right(3).toLower() == ".au") || + (source.right(4).toLower() == ".snd") || + (source.right(4).toLower() == ".aif") || + (source.right(5).toLower() == ".aiff") || + (source.right(5).toLower() == ".8svx") || + (source.right(4).toLower() == ".wav") || + (source.right(4).toLower() == ".sph") || + (source.right(3).toLower() == ".sf") || + (source.right(4).toLower() == ".voc"); +} + +bool DecoderSndFileFactory::canDecode(QIODevice *) const +{ + return FALSE; +} + +const DecoderProperties DecoderSndFileFactory::properties() const +{ + DecoderProperties properties; + properties.name = tr("Sndfile Plugin"); + properties.filter = "*.wav *.au *.snd *.aif *.aiff *.8svx *.sph *.sf *.voc"; + properties.description = tr("PCM Files"); + //properties.contentType = ""; + properties.hasAbout = TRUE; + properties.hasSettings = FALSE; + return properties; +} + +Decoder *DecoderSndFileFactory::create(QObject *parent, QIODevice *input, + Output *output) +{ + return new DecoderSndFile(parent, this, input, output); +} + +FileTag *DecoderSndFileFactory::createTag(const QString &source) +{ + FileTag *ftag = new FileTag(); + SF_INFO snd_info; + SNDFILE *sndfile = 0; + memset (&snd_info, 0, sizeof(snd_info)); + snd_info.format = 0; + sndfile = sf_open(source.toLocal8Bit(), SFM_READ, &snd_info); + if (!sndfile) + return ftag; + + if (sf_get_string(sndfile, SF_STR_TITLE)) + { + char* title = strdup(sf_get_string(sndfile, SF_STR_TITLE)); + ftag->setValue(FileTag::TITLE, QString::fromUtf8(title).trimmed()); + } + if (sf_get_string(sndfile, SF_STR_ARTIST)) + { + char* artist = strdup(sf_get_string(sndfile, SF_STR_ARTIST)); + ftag->setValue(FileTag::ARTIST, QString::fromUtf8(artist).trimmed()); + } + if (sf_get_string(sndfile, SF_STR_COMMENT)) + { + char* comment = strdup(sf_get_string(sndfile, SF_STR_COMMENT)); + ftag->setValue(FileTag::COMMENT, QString::fromUtf8(comment).trimmed()); + } + + ftag->setValue(FileTag::LENGTH ,int(snd_info.frames / snd_info.samplerate)); + + sf_close(sndfile); + return ftag; +} + +QObject* DecoderSndFileFactory::showDetails(QWidget *parent, const QString &path) +{ + return 0; +} + +void DecoderSndFileFactory::showSettings(QWidget *) +{} + +void DecoderSndFileFactory::showAbout(QWidget *parent) +{ + char version [128] ; + sf_command (NULL, SFC_GET_LIB_VERSION, version, sizeof (version)) ; + QMessageBox::about (parent, tr("About Sndfile Audio Plugin"), + tr("Qmmp Sndfile Audio Plugin")+"\n"+ + tr("Compiled against")+" "+QString(version)+"\n" + + tr("Writen by: Ilya Kotov ")); +} + +QTranslator *DecoderSndFileFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/sndfile_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(DecoderSndFileFactory) diff --git a/src/plugins/Input/sndfile/decodersndfilefactory.h b/src/plugins/Input/sndfile/decodersndfilefactory.h new file mode 100644 index 000000000..8439594fb --- /dev/null +++ b/src/plugins/Input/sndfile/decodersndfilefactory.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DECODERSNDFILEFACTORY_H +#define DECODERSNDFILEFACTORY_H + +#include +#include +#include +#include + +#include +#include +#include +#include + + + + +class DecoderSndFileFactory : public QObject, + DecoderFactory +{ +Q_OBJECT +Q_INTERFACES(DecoderFactory); + +public: + bool supports(const QString &source) const; + bool canDecode(QIODevice *input) const; + const DecoderProperties properties() const; + Decoder *create(QObject *, QIODevice *, Output *); + FileTag *createTag(const QString &source); + QObject* showDetails(QWidget *parent, const QString &path); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); +}; + +#endif diff --git a/src/plugins/Input/sndfile/sndfile.pro b/src/plugins/Input/sndfile/sndfile.pro new file mode 100644 index 000000000..701ea58fb --- /dev/null +++ b/src/plugins/Input/sndfile/sndfile.pro @@ -0,0 +1,28 @@ +include(../../plugins.pri) + +HEADERS += decodersndfilefactory.h \ + decoder_sndfile.h +SOURCES += decoder_sndfile.cpp \ + decodersndfilefactory.cpp + +TARGET=$$PLUGINS_PREFIX/Input/sndfile +QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libsndfile.so + +INCLUDEPATH += ../../../qmmp +CONFIG += release \ +warn_on \ +plugin \ +link_pkgconfig +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmp -L/usr/lib -I/usr/include + +PKGCONFIG += sndfile +#TRANSLATIONS = translations/ffmpeg_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/Input +INSTALLS += target diff --git a/src/plugins/Input/vorbis/CMakeLists.txt b/src/plugins/Input/vorbis/CMakeLists.txt new file mode 100644 index 000000000..baf5bad8c --- /dev/null +++ b/src/plugins/Input/vorbis/CMakeLists.txt @@ -0,0 +1,96 @@ +project(libvorbis) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +# libvorbis and taglib +PKGCONFIG(ogg OGG_INCLUDE_DIR OGG_LINK_DIR OGG_LINK_FLAGS OGG_CFLAGS) +PKGCONFIG(vorbis VORBIS_INCLUDE_DIR VORBIS_LINK_DIR VORBIS_LINK_FLAGS VORBIS_CFLAGS) +PKGCONFIG(vorbisfile VORBISFILE_INCLUDE_DIR VORBISFILE_LINK_DIR VORBISFILE_LINK_FLAGS VORBISFILE_CFLAGS) + +PKGCONFIG(taglib TAGLIB_INCLUDE_DIR TAGLIB_LINK_DIR TAGLIB_LINK_FLAGS TAGLIB_CFLAGS) + +IF(NOT OGG_LINK_FLAGS) + SET(OGG_LINK_FLAGS -logg) +ENDIF(NOT OGG_LINK_FLAGS) + +IF(NOT VORBIS_LINK_FLAGS) + SET(VORBIS_LINK_FLAGS -lvorbis) +ENDIF(NOT VORBIS_LINK_FLAGS) + +IF(NOT VORBISFILE_LINK_FLAGS) + SET(VORBISFILE_LINK_FLAGS -lvorbisfile) +ENDIF(NOT VORBISFILE_LINK_FLAGS) + +IF(NOT TAGLIB_LINK_FLAGS) + SET(TAGLIB_LINK_FLAGS -ltag) + SET(TAGLIB_INCLUDE_DIR /usr/include/taglib) + SET(TAGLIB_CFLAGS -I/usr/include/taglib) +ENDIF(NOT TAGLIB_LINK_FLAGS) + +include_directories(${VORBIS_INCLUDE_DIR} ${TAGLIB_INCLUDE_DIR}) +link_directories(${VORBIS_LINK_DIR} ${TAGLIB_LINK_DIR}) + +#ADD_DEFINITIONS(${VORBIS_CFLAGS}) +ADD_DEFINITIONS(${TAGLIB_CFLAGS}) + + +SET(libvorbis_SRCS + decoder_vorbis.cpp + decodervorbisfactory.cpp + detailsdialog.cpp +) + +SET(libvorbis_MOC_HDRS + decodervorbisfactory.h + decoder_vorbis.h + detailsdialog.h +) + +SET(libvorbis_RCCS translations/translations.qrc) + +QT4_ADD_RESOURCES(libvorbis_RCC_SRCS ${libvorbis_RCCS}) + +QT4_WRAP_CPP(libvorbis_MOC_SRCS ${libvorbis_MOC_HDRS}) + +# user interface + + +SET(libvorbis_UIS + detailsdialog.ui +) + +QT4_WRAP_UI(libvorbis_UIS_H ${libvorbis_UIS}) +# Don't forget to include output directory, otherwise +# the UI file won't be wrapped! +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(vorbis SHARED ${libvorbis_SRCS} ${libvorbis_MOC_SRCS} ${libvorbis_UIS_H} + ${libvorbis_RCC_SRCS}) +target_link_libraries(vorbis ${QT_LIBRARIES} -lqmmp ${VORBIS_LINK_FLAGS} ${VORBISFILE_LINK_FLAGS} ${OGG_LINK_FLAGS} ${TAGLIB_LINK_FLAGS} ${TAGLIB_CFLAGS}) +install(TARGETS vorbis DESTINATION ${LIB_DIR}/qmmp/Input PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) diff --git a/src/plugins/Input/vorbis/decoder_vorbis.cpp b/src/plugins/Input/vorbis/decoder_vorbis.cpp new file mode 100644 index 000000000..31fb99c6f --- /dev/null +++ b/src/plugins/Input/vorbis/decoder_vorbis.cpp @@ -0,0 +1,425 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#include "decoder_vorbis.h" +#include "constants.h" +#include "buffer.h" +#include "output.h" +#include "recycler.h" +#include "filetag.h" + +#include +#include + + +// ic functions for OggVorbis + +static size_t oggread (void *buf, size_t size, size_t nmemb, void *src) +{ + if (! src) return 0; + + DecoderVorbis *dogg = (DecoderVorbis *) src; + int len = dogg->input()->read((char *) buf, (size * nmemb)); + return len / size; +} + + +static int oggseek(void *src, int64_t offset, int whence) +{ + DecoderVorbis *dogg = (DecoderVorbis *) src; + + if ( dogg->input()->isSequential ()) + return -1; + + long start = 0; + switch (whence) + { + case SEEK_END: + start = dogg->input()->size(); + break; + + case SEEK_CUR: + start = dogg->input()->pos(); + break; + + case SEEK_SET: + default: + start = 0; + } + + if (dogg->input()->seek(start + offset)) + return 0; + return -1; +} + + +static int oggclose(void *src) +{ + DecoderVorbis *dogg = (DecoderVorbis *) src; + dogg->input()->close(); + return 0; +} + + +static long oggtell(void *src) +{ + DecoderVorbis *dogg = (DecoderVorbis *) src; + long t = dogg->input()->pos(); + return t; +} + + +// Decoder class + +DecoderVorbis::DecoderVorbis(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o) + : Decoder(parent, d, i, o) +{ + inited = FALSE; + user_stop = FALSE; + stat = 0; + output_buf = 0; + output_bytes = 0; + output_at = 0; + bks = 0; + done = FALSE; + finish = FALSE; + len = 0; + freq = 0; + bitrate = 0; + seekTime = -1.0; + totalTime = 0.0; + chan = 0; + output_size = 0; +} + + +DecoderVorbis::~DecoderVorbis() +{ + deinit(); + + if (output_buf) + delete [] output_buf; + output_buf = 0; +} + + +void DecoderVorbis::stop() +{ + user_stop = TRUE; +} + + +void DecoderVorbis::flush(bool final) +{ + ulong min = final ? 0 : bks; + + while ((! done && ! finish) && output_bytes > min) + { + output()->recycler()->mutex()->lock (); + + while ((! done && ! finish) && output()->recycler()->full()) + { + mutex()->unlock(); + + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + + mutex()->lock (); + done = user_stop; + } + + if (user_stop || finish) + { + inited = FALSE; + done = TRUE; + } + else + { + /*ulong sz = output_bytes < bks ? output_bytes : bks; + Buffer *b = output()->recycler()->get(); + + memcpy(b->data, output_buf, sz); + if (sz != bks) memset(b->data + sz, 0, bks - sz); + + b->nbytes = bks; + b->rate = bitrate; + output_size += b->nbytes; + output()->recycler()->add(); + + output_bytes -= sz; + memmove(output_buf, output_buf + sz, output_bytes);*/ + output_bytes -= produceSound(output_buf, output_bytes, bitrate, chan); + output_size += bks; + output_at = output_bytes; + } + + if (output()->recycler()->full()) + { + output()->recycler()->cond()->wakeOne(); + } + + output()->recycler()->mutex()->unlock(); + } +} + + +bool DecoderVorbis::initialize() +{ + qDebug("DecoderVorbis: initialize"); + bks = blockSize(); + + inited = user_stop = done = finish = FALSE; + len = freq = bitrate = 0; + stat = chan = 0; + output_size = 0; + seekTime = -1.0; + totalTime = 0.0; + if (! input()) + { + qDebug("DecoderVorbis: cannot initialize. No input"); + + return FALSE; + } + + if (! output_buf) + output_buf = new char[globalBufferSize]; + output_at = 0; + output_bytes = 0; + + if (! input()->isOpen()) + { + if (! input()->open(QIODevice::ReadOnly)) + { + qWarning(qPrintable("DecoderVorbis: failed to open input. " + + input()->errorString () + ".")); + return FALSE; + } + } + + ov_callbacks oggcb = + { + oggread, + oggseek, + oggclose, + oggtell + }; + if (ov_open_callbacks(this, &oggfile, NULL, 0, oggcb) < 0) + { + qWarning("DecoderVorbis: cannot open stream"); + + return FALSE; + } + + freq = 0; + bitrate = ov_bitrate(&oggfile, -1) / 1000; + chan = 0; + + totalTime = long(ov_time_total(&oggfile, 0)); + totalTime = totalTime < 0 ? 0 : totalTime; + + vorbis_info *ogginfo = ov_info(&oggfile, -1); + if (ogginfo) + { + freq = ogginfo->rate; + chan = ogginfo->channels; + } + + configure(freq, chan, 16, bitrate); + + inited = TRUE; + return TRUE; +} + + +double DecoderVorbis::lengthInSeconds() +{ + if (! inited) + return 0; + + return totalTime; +} + + +void DecoderVorbis::seek(double pos) +{ + seekTime = pos; +} + + +void DecoderVorbis::deinit() +{ + if (inited) + ov_clear(&oggfile); + inited = user_stop = done = finish = FALSE; + len = freq = bitrate = 0; + stat = chan = 0; + output_size = 0; +} + +void DecoderVorbis::updateTags() +{ + int i; + vorbis_comment *comments; + + FileTag tag; + comments = ov_comment (&oggfile, -1); + for (i = 0; i < comments->comments; i++) + { + if (!strncasecmp(comments->user_comments[i], "title=", + strlen ("title="))) + tag.setValue(FileTag::TITLE, QString::fromUtf8(comments->user_comments[i] + + strlen ("title="))); + else if (!strncasecmp(comments->user_comments[i], + "artist=", strlen ("artist="))) + tag.setValue(FileTag::ARTIST, + QString::fromUtf8(comments->user_comments[i] + + strlen ("artist="))); + else if (!strncasecmp(comments->user_comments[i], + "album=", strlen ("album="))) + tag.setValue(FileTag::ALBUM, + QString::fromUtf8(comments->user_comments[i] + + strlen ("album="))); + else if (!strncasecmp(comments->user_comments[i], + "comment=", strlen ("comment="))) + tag.setValue(FileTag::COMMENT, + QString::fromUtf8(comments->user_comments[i] + + strlen ("comment="))); + else if (!strncasecmp(comments->user_comments[i], + "genre=", strlen ("genre="))) + tag.setValue(FileTag::GENRE, QString::fromUtf8 (comments->user_comments[i] + + strlen ("genre="))); + else if (!strncasecmp(comments->user_comments[i], + "tracknumber=", + strlen ("tracknumber="))) + tag.setValue(FileTag::TRACK, atoi (comments->user_comments[i] + + strlen ("tracknumber="))); + else if (!strncasecmp(comments->user_comments[i], + "track=", strlen ("track="))) + tag.setValue(FileTag::TRACK, atoi (comments->user_comments[i] + + strlen ("track="))); + else if (!strncasecmp(comments->user_comments[i], + "date=", strlen ("date="))) + tag.setValue(FileTag::YEAR, atoi (comments->user_comments[i] + + strlen ("date="))); + + } + tag.setValue(FileTag::LENGTH, uint(totalTime)); + dispatch(tag); +} + +void DecoderVorbis::run() +{ + mutex()->lock (); + + if (! inited) + { + mutex()->unlock(); + + return; + } + + //stat = DecoderEvent::Decoding; + stat = DecoderState::Decoding; + mutex()->unlock(); + + { + //DecoderEvent e((DecoderEvent::Type) stat); + //dispatch(e); + //DecoderStatus st ((DecoderStatus::Type) stat); + dispatch(DecoderState ((DecoderState::Type) stat)); + + //emit statusChanged(stat); + } + + int section = 0; + int last_section = -1; + + while (! done && ! finish) + { + mutex()->lock (); + // decode + + if (seekTime >= 0.0) + { + ov_time_seek(&oggfile, double(seekTime)); + seekTime = -1.0; + + output_size = long(ov_time_tell(&oggfile)) * long(freq * chan * 2); + } + len = -1; + while (len < 0) + { + len = ov_read(&oggfile, (char *) (output_buf + output_at), bks, 0, 2, 1, + §ion); + } + if (section != last_section) + updateTags(); + last_section = section; + + if (len > 0) + { + bitrate = ov_bitrate_instant(&oggfile) / 1000; + + output_at += len; + output_bytes += len; + + if (output()) + flush(); + } + else if (len == 0) + { + flush(TRUE); + + if (output()) + { + output()->recycler()->mutex()->lock (); + // end of stream + while (! output()->recycler()->empty() && ! user_stop) + { + output()->recycler()->cond()->wakeOne(); + mutex()->unlock(); + output()->recycler()->cond()->wait(output()->recycler()->mutex()); + mutex()->lock (); + } + output()->recycler()->mutex()->unlock(); + } + + done = TRUE; + if (! user_stop) + { + finish = TRUE; + } + } + else + { + // error in read + error("DecoderVorbis: Error while decoding stream, File appears to be " + "corrupted"); + + finish = TRUE; + } + + mutex()->unlock(); + } + + mutex()->lock (); + + if (finish) + stat = DecoderState::Finished; + else if (user_stop) + stat = DecoderState::Stopped; + + mutex()->unlock(); + + { + /*DecoderEvent e((DecoderEvent::Type) stat); + dispatch(e);*/ + //DecoderStatus st ((DecoderStatus::Type) stat); + //emit statusChanged(st); + dispatch(DecoderState ((DecoderState::Type) stat)); + } + + deinit(); +} diff --git a/src/plugins/Input/vorbis/decoder_vorbis.h b/src/plugins/Input/vorbis/decoder_vorbis.h new file mode 100644 index 000000000..091d856ff --- /dev/null +++ b/src/plugins/Input/vorbis/decoder_vorbis.h @@ -0,0 +1,63 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#ifndef __decoder_vorbis_h +#define __decoder_vorbis_h + +#include "decoder.h" + +#include + + +class DecoderVorbis : public Decoder +{ +public: + DecoderVorbis(QObject *, DecoderFactory *, QIODevice *, Output *); + virtual ~DecoderVorbis(); + + // Standard Decoder API + bool initialize(); + double lengthInSeconds(); + void seek(double); + void stop(); + + // Equalizer + bool isEQSupported() const { return FALSE; } + void setEQEnabled(bool) { ; } + void setEQGain(int) { ; } + void setEQBands(int[10]) { ; } + + +private: + // thread run function + void run(); + + // helper functions + void flush(bool = FALSE); + void deinit(); + + void updateTags(); + + bool inited, user_stop; + int stat; + + // output buffer + char *output_buf; + ulong output_bytes, output_at; + + // OggVorbis Decoder + OggVorbis_File oggfile; + + unsigned int bks; + bool done, finish; + long len, freq, bitrate; + int chan; + unsigned long output_size; + double totalTime, seekTime; +}; + + +#endif // __decoder_vorbis_h diff --git a/src/plugins/Input/vorbis/decodervorbisfactory.cpp b/src/plugins/Input/vorbis/decodervorbisfactory.cpp new file mode 100644 index 000000000..c3b31ec52 --- /dev/null +++ b/src/plugins/Input/vorbis/decodervorbisfactory.cpp @@ -0,0 +1,105 @@ +#include +#include +#include +#include + +#include "detailsdialog.h" +#include "decoder_vorbis.h" +#include "decodervorbisfactory.h" + + +// DecoderOggFactory + +bool DecoderVorbisFactory::supports(const QString &source) const +{ + return source.right(4).toLower() == ".ogg"; +} + +bool DecoderVorbisFactory::canDecode(QIODevice *input) const +{ + char buf[36]; + if (input->peek(buf, 36) == 36 && !memcmp(buf, "OggS", 4) + && !memcmp(buf + 29, "vorbis", 6)) + return TRUE; + + return FALSE; +} + +const DecoderProperties DecoderVorbisFactory::properties() const +{ + DecoderProperties properties; + properties.name = tr("Ogg Vorbis Plugin"); + properties.filter = "*.ogg"; + properties.description = tr("Ogg Vorbis Files"); + properties.contentType = "application/ogg;audio/x-vorbis+ogg"; + properties.hasAbout = TRUE; + properties.hasSettings = FALSE; + return properties; +} + +Decoder *DecoderVorbisFactory::create(QObject *parent, QIODevice *input, + Output *output) +{ + return new DecoderVorbis(parent, this, input, output); +} + +FileTag *DecoderVorbisFactory::createTag(const QString &source) +{ + FileTag *ftag = new FileTag(); + + TagLib::FileRef fileRef(source.toLocal8Bit ()); + TagLib::Tag *tag = fileRef.tag(); + + if (tag && !tag->isEmpty()) + { + ftag->setValue(FileTag::ALBUM, + QString::fromUtf8(tag->album().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::ARTIST, + QString::fromUtf8(tag->artist().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::COMMENT, + QString::fromUtf8(tag->comment().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::GENRE, + QString::fromUtf8(tag->genre().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::TITLE, + QString::fromUtf8(tag->title().toCString(TRUE)).trimmed()); + ftag->setValue(FileTag::YEAR, tag->year()); + ftag->setValue(FileTag::TRACK, tag->track()); + } + + if (fileRef.audioProperties()) + ftag->setValue(FileTag::LENGTH, fileRef.audioProperties()->length()); + + return ftag; +} + +QObject* DecoderVorbisFactory::showDetails(QWidget *parent, const QString &path) +{ + DetailsDialog *d = new DetailsDialog(parent, path); + d -> show(); + return d; +} + +void DecoderVorbisFactory::showSettings(QWidget *) +{ + /*SettingsDialog *s = new SettingsDialog(parent); + s -> show();*/ +} + +void DecoderVorbisFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About Ogg Vorbis Audio Plugin"), + tr("Qmmp Ogg Vorbis Audio Plugin")+"\n"+ + tr("Writen by: Ilya Kotov ")+"\n"+ + tr("Source code based on mq3 progect") + ); +} + +QTranslator *DecoderVorbisFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/vorbis_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(DecoderVorbisFactory) diff --git a/src/plugins/Input/vorbis/decodervorbisfactory.h b/src/plugins/Input/vorbis/decodervorbisfactory.h new file mode 100644 index 000000000..6830fc102 --- /dev/null +++ b/src/plugins/Input/vorbis/decodervorbisfactory.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DECODERVORBISFACTORY_H +#define DECODERVORBISFACTORY_H + +#include +#include +#include +#include + +#include +#include +#include +#include + + + + +class DecoderVorbisFactory : public QObject, + DecoderFactory +{ +Q_OBJECT +Q_INTERFACES(DecoderFactory); + +public: + bool supports(const QString &source) const; + bool canDecode(QIODevice *input) const; + const DecoderProperties properties() const; + Decoder *create(QObject *, QIODevice *, Output *); + FileTag *createTag(const QString &source); + QObject* showDetails(QWidget *parent, const QString &path); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); +}; + +#endif diff --git a/src/plugins/Input/vorbis/detailsdialog.cpp b/src/plugins/Input/vorbis/detailsdialog.cpp new file mode 100644 index 000000000..bbe441703 --- /dev/null +++ b/src/plugins/Input/vorbis/detailsdialog.cpp @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include +#include + +#include "detailsdialog.h" + +#define QStringToTString_qt4(s) TagLib::String(s.toUtf8().constData(), TagLib::String::UTF8) + +DetailsDialog::DetailsDialog(QWidget *parent, const QString &path) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + m_path = path; + setWindowTitle (path.section('/',-1)); + path.section('/',-1); + ui.pathLineEdit->setText(m_path); + if(QFile::exists(m_path)) + { + loadVorbisInfo(); + loadTag(); + } +} + + +DetailsDialog::~DetailsDialog() +{} + +void DetailsDialog::loadVorbisInfo() +{ + TagLib::Ogg::Vorbis::File f (m_path.toLocal8Bit()); + //l.label + //ui. f.audioProperties()->level(); + QString text; + text = QString("%1").arg(f.audioProperties()->length()/60); + text +=":"+QString("%1").arg(f.audioProperties()->length()%60,2,10,QChar('0')); + ui.lengthLabel->setText(text); + text = QString("%1").arg(f.audioProperties()->sampleRate()); + ui.sampleRateLabel->setText(text+" "+tr("Hz")); + text = QString("%1").arg(f.audioProperties()->channels()); + ui.channelsLabel->setText(text); + text = QString("%1").arg(f.audioProperties()->bitrateNominal()); + ui.nominalLabel->setText(text+" "+tr("kbps")); + text = QString("%1").arg(f.audioProperties()->bitrateMaximum()); + ui.maximumLabel->setText(text+" "+tr("kbps")); + text = QString("%1").arg(f.audioProperties()->bitrateMinimum()); + ui.minimumLabel->setText(text+" "+tr("kbps")); + text = QString("%1 "+tr("KB")).arg(f.length()/1024); + ui.fileSizeLabel->setText(text); + +} + +void DetailsDialog::loadTag() +{ + TagLib::FileRef f (m_path.toLocal8Bit()); + + if (f.tag()) + { //TODO: load codec name from config + + TagLib::String title = f.tag()->title(); + TagLib::String artist = f.tag()->artist(); + TagLib::String album = f.tag()->album(); + TagLib::String comment = f.tag()->comment(); + TagLib::String genre = f.tag()->genre(); + QString string = QString::fromUtf8(title.toCString(TRUE)).trimmed(); + ui.titleLineEdit->setText(string); + string = QString::fromUtf8(artist.toCString(TRUE)).trimmed(); + ui.artistLineEdit->setText(string); + string = QString::fromUtf8(album.toCString(TRUE)).trimmed(); + ui.albumLineEdit->setText(string); + string = QString::fromUtf8(comment.toCString(TRUE)).trimmed(); + ui.commentLineEdit->setText(string); + string = QString("%1").arg(f.tag()->year()); + ui.yearLineEdit->setText(string); + string = QString("%1").arg(f.tag()->track()); + ui.trackLineEdit->setText(string); + string = QString::fromUtf8(genre.toCString(TRUE)).trimmed(); + ui.genreLineEdit->setText(string); + } + QFileInfo info(m_path); + ui.saveButton->setEnabled(info.isWritable()); + connect(ui.saveButton, SIGNAL(clicked()), SLOT(saveTag())); +} + +void DetailsDialog::saveTag() +{ + TagLib::FileRef f (m_path.toLocal8Bit()); + + f.tag()->setTitle(QStringToTString_qt4(ui.titleLineEdit->text())); + f.tag()->setArtist(QStringToTString_qt4(ui.artistLineEdit->text())); + f.tag()->setAlbum(QStringToTString_qt4(ui.albumLineEdit->text())); + f.tag()->setComment(QStringToTString_qt4(ui.commentLineEdit->text())); + f.tag()->setGenre(QStringToTString_qt4(ui.genreLineEdit->text())); + f.tag()->setYear(ui.yearLineEdit->text().toUInt()); + f.tag()->setTrack(ui.trackLineEdit->text().toUInt()); + + f.save(); +} diff --git a/src/plugins/Input/vorbis/detailsdialog.h b/src/plugins/Input/vorbis/detailsdialog.h new file mode 100644 index 000000000..94d4243b8 --- /dev/null +++ b/src/plugins/Input/vorbis/detailsdialog.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DETAILSDIALOG_H +#define DETAILSDIALOG_H + +#include + +#include "ui_detailsdialog.h" + +/** + @author Ilya Kotov +*/ +class DetailsDialog : public QDialog +{ +Q_OBJECT +public: + DetailsDialog(QWidget *parent = 0, const QString &path = 0); + + ~DetailsDialog(); + +private slots: + void saveTag(); + +private: + void loadVorbisInfo(); + void loadTag(); + Ui::DetailsDialog ui; + QString m_path; + +}; + +#endif diff --git a/src/plugins/Input/vorbis/detailsdialog.ui b/src/plugins/Input/vorbis/detailsdialog.ui new file mode 100644 index 000000000..1804ab268 --- /dev/null +++ b/src/plugins/Input/vorbis/detailsdialog.ui @@ -0,0 +1,384 @@ + + DetailsDialog + + + + 0 + 0 + 536 + 375 + + + + Details + + + + 8 + + + 6 + + + + + + 220 + 16 + + + + Ogg Vorbis Info + + + + 8 + + + 6 + + + + + - + + + + + + + Qt::LeftToRight + + + - + + + + + + + Length: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Sample rate: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Qt::LeftToRight + + + Channels: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Bit Rate + + + Qt::AlignHCenter + + + + 8 + + + 6 + + + + + - + + + + + + + - + + + + + + + Qt::LeftToRight + + + Minimum: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + - + + + + + + + Maximum: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Nominal: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + File size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + true + + + + + + + File path: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Close + + + + + + + Qt::Horizontal + + + + 111 + 20 + + + + + + + + + 5 + 5 + 0 + 0 + + + + Ogg Vorbis Tag + + + + 8 + + + 6 + + + + + false + + + Save + + + + + + + + + + Track number: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Year: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Genre: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Comment: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Album: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Artist: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Title: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + + + + + + + + + + + + + + pushButton_3 + clicked() + DetailsDialog + close() + + + 623 + 353 + + + 539 + 352 + + + + + diff --git a/src/plugins/Input/vorbis/translations/translations.qrc b/src/plugins/Input/vorbis/translations/translations.qrc new file mode 100644 index 000000000..c5cacdfb0 --- /dev/null +++ b/src/plugins/Input/vorbis/translations/translations.qrc @@ -0,0 +1,6 @@ + + + + vorbis_plugin_ru.qm + + diff --git a/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.qm b/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.qm new file mode 100644 index 000000000..a6a3a77b7 Binary files /dev/null and b/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.qm differ diff --git a/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.ts b/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.ts new file mode 100644 index 000000000..16cf81ea3 --- /dev/null +++ b/src/plugins/Input/vorbis/translations/vorbis_plugin_ru.ts @@ -0,0 +1,164 @@ + + + + DecoderVorbisFactory + + + Ogg Vorbis Plugin + Модуль Ogg Vorbis + + + + Ogg Vorbis Files + Файлы Ogg Vorbis + + + + About Ogg Vorbis Audio Plugin + Об аудио-модуле Ogg Vorbis + + + + Qmmp Ogg Vorbis Audio Plugin + Аудио-модуль Ogg Vorbis для Qmmp + + + + Writen by: Ilya Kotov <forkotov02@hotmail.ru> + Разработчик: Илья Котов <forkotov02@hotmail.ru> + + + + Source code based on mq3 progect + Исходный код основан на проекте mq3 + + + + DetailsDialog + + + Hz + Гц + + + + Save + Сохранить + + + + Track number: + Номер трека: + + + + Year: + Год: + + + + Genre: + Жанр: + + + + Comment: + Комментарий: + + + + Album: + Альбом: + + + + Artist: + Исполнитель: + + + + Title: + Название: + + + + Close + Закрыть + + + + - + + + + + File size: + Размер файла: + + + + Sample rate: + Дискретизация: + + + + File path: + Путь к файлу: + + + + Ogg Vorbis Info + Информация Ogg Vorbis + + + + Length: + Длительность: + + + + Channels: + Каналов: + + + + Bit Rate + Битовая частота + + + + Minimum: + Минимальная: + + + + Maximum: + Максимальная: + + + + Nominal: + Номинальная: + + + + Ogg Vorbis Tag + Оgg Vorbis-тег + + + + kbps + Кб/с + + + + KB + Кб + + + + Details + Информация + + + diff --git a/src/plugins/Input/vorbis/vorbis.pro b/src/plugins/Input/vorbis/vorbis.pro new file mode 100644 index 000000000..afd7b6510 --- /dev/null +++ b/src/plugins/Input/vorbis/vorbis.pro @@ -0,0 +1,35 @@ +# ???? ?????? ? KDevelop ?????????? qmake. +# ------------------------------------------- +# ?????????? ???????????? ???????? ???????? ???????: ./Plugins/Input/ogg +# ???? - ??????????: + +include(../../plugins.pri) + +FORMS += detailsdialog.ui +HEADERS += decodervorbisfactory.h \ + decoder_vorbis.h \ + detailsdialog.h +SOURCES += decoder_vorbis.cpp \ + decodervorbisfactory.cpp \ + detailsdialog.cpp + +TARGET=$$PLUGINS_PREFIX/Input/vorbis +QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libvorbis.so + +INCLUDEPATH += ../../../qmmp +CONFIG += release \ +warn_on \ +plugin \ +link_pkgconfig +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmp -L/usr/lib +PKGCONFIG += taglib ogg vorbisfile vorbis +#TRANSLATIONS = translations/vorbis_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/Input +INSTALLS += target diff --git a/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption.pro b/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption.pro new file mode 100644 index 000000000..1832a0166 --- /dev/null +++ b/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = IncDecVolumeOption diff --git a/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/IncDecVolumeOption.pro b/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/IncDecVolumeOption.pro new file mode 100644 index 000000000..fdcef5e38 --- /dev/null +++ b/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/IncDecVolumeOption.pro @@ -0,0 +1,26 @@ +include(../../../../../qmmp.pri) + +QMMPSRCROOT = ../../../../ + +INCLUDEPATH += $$QMMPSRCROOT/ui \ + $$QMMPSRCROOT/qmmp \ + $$QMMPSRCROOT + +HEADERS += incdecvolumeoption.h \ + $$QMMPSRCROOT/ui/mainwindow.h \ + $$QMMPSRCROOT/qmmp/soundcore.h + +SOURCES += incdecvolumeoption.cpp \ + $$QMMPSRCROOT/qmmp/soundcore.cpp \ + $$QMMPSRCROOT/ui/mainwindow.cpp + +DESTDIR = ../ +QMAKE_CLEAN = ../libincdecvolumeoption.so + + + +CONFIG += release warn_on plugin + +TEMPLATE = lib + + diff --git a/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/Makefile b/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/Makefile new file mode 100644 index 000000000..0ac10a77d --- /dev/null +++ b/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/Makefile @@ -0,0 +1,301 @@ +############################################################################# +# Makefile for building: libIncDecVolumeOption.so +# Generated by qmake (2.01a) (Qt 4.3.0) on: Thu Feb 7 01:34:34 2008 +# Project: IncDecVolumeOption.pro +# Template: lib +# Command: /usr/local/Trolltech/Qt-4.3.0/bin/qmake -unix -o Makefile IncDecVolumeOption.pro +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DQT_NO_DEBUG -DQT_PLUGIN -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -pipe -O2 -Wall -W -D_REENTRANT -fPIC $(DEFINES) +CXXFLAGS = -pipe -O2 -Wall -W -D_REENTRANT -fPIC $(DEFINES) +INCPATH = -I/usr/local/Trolltech/Qt-4.3.0/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.3.0/include/QtCore -I/usr/local/Trolltech/Qt-4.3.0/include/QtCore -I/usr/local/Trolltech/Qt-4.3.0/include/QtGui -I/usr/local/Trolltech/Qt-4.3.0/include/QtGui -I/usr/local/Trolltech/Qt-4.3.0/include -I../../../../ui -I../../../../qmmp -I../../../.. -I.build/moc -I./.build/ui/ +LINK = g++ +LFLAGS = -Wl,-rpath,/usr/local/Trolltech/Qt-4.3.0/lib -shared +LIBS = $(SUBLIBS) -L/usr/local/Trolltech/Qt-4.3.0/lib -lQtGui -L/usr/local/Trolltech/Qt-4.3.0/lib -L/usr/X11R6/lib -lpng -lSM -lICE -pthread -pthread -lXi -lXrender -lXrandr -lXfixes -lXcursor -lXinerama -lfreetype -lfontconfig -lXext -lX11 -lQtCore -lz -lm -pthread -lgthread-2.0 -lrt -lglib-2.0 -ldl -lpthread +AR = ar cqs +RANLIB = +QMAKE = /usr/local/Trolltech/Qt-4.3.0/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -sf +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = .build/obj/ + +####### Files + +SOURCES = incdecvolumeoption.cpp \ + ../../../../qmmp/soundcore.cpp \ + ../../../../ui/mainwindow.cpp .build/moc/moc_incdecvolumeoption.cpp \ + .build/moc/moc_mainwindow.cpp \ + .build/moc/moc_soundcore.cpp +OBJECTS = .build/obj/incdecvolumeoption.o \ + .build/obj/soundcore.o \ + .build/obj/mainwindow.o \ + .build/obj/moc_incdecvolumeoption.o \ + .build/obj/moc_mainwindow.o \ + .build/obj/moc_soundcore.o +DIST = /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/g++.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/unix.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/linux.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/qconfig.pri \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_functions.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_config.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/exclusive_builds.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_pre.prf \ + /rest/qmmp/qmmp/qmmp.pri \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/release.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_post.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/warn_on.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/unix/thread.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/moc.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/resources.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/uic.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/yacc.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/lex.prf \ + IncDecVolumeOption.pro +QMAKE_TARGET = IncDecVolumeOption +DESTDIR = ../ +TARGET = libIncDecVolumeOption.so +TARGETD = libIncDecVolumeOption.so + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile ../$(TARGET) + +../$(TARGET): $(OBJECTS) $(SUBLIBS) $(OBJCOMP) + @$(CHK_DIR_EXISTS) ../ || $(MKDIR) ../ + -$(DEL_FILE) $(TARGET) + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP) + -$(MOVE) $(TARGET) ../ + + + +Makefile: IncDecVolumeOption.pro /usr/local/Trolltech/Qt-4.3.0/mkspecs/linux-g++/qmake.conf /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/g++.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/unix.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/linux.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/qconfig.pri \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_functions.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_config.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/exclusive_builds.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_pre.prf \ + /rest/qmmp/qmmp/qmmp.pri \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/release.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_post.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/warn_on.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/unix/thread.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/moc.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/resources.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/uic.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/yacc.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/lex.prf \ + /usr/local/Trolltech/Qt-4.3.0/lib/libQtGui.prl \ + /usr/local/Trolltech/Qt-4.3.0/lib/libQtCore.prl + $(QMAKE) -unix -o Makefile IncDecVolumeOption.pro +/usr/local/Trolltech/Qt-4.3.0/mkspecs/common/g++.conf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/common/unix.conf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/common/linux.conf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/qconfig.pri: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_functions.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_config.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/exclusive_builds.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_pre.prf: +/rest/qmmp/qmmp/qmmp.pri: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/release.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_post.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/warn_on.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/unix/thread.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/moc.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/resources.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/uic.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/yacc.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/lex.prf: +/usr/local/Trolltech/Qt-4.3.0/lib/libQtGui.prl: +/usr/local/Trolltech/Qt-4.3.0/lib/libQtCore.prl: +qmake: FORCE + @$(QMAKE) -unix -o Makefile IncDecVolumeOption.pro + +dist: + @$(CHK_DIR_EXISTS) .build/obj/IncDecVolumeOption1.0.0 || $(MKDIR) .build/obj/IncDecVolumeOption1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .build/obj/IncDecVolumeOption1.0.0/ && $(COPY_FILE) --parents incdecvolumeoption.h ../../../../ui/mainwindow.h ../../../../qmmp/soundcore.h .build/obj/IncDecVolumeOption1.0.0/ && $(COPY_FILE) --parents incdecvolumeoption.cpp ../../../../qmmp/soundcore.cpp ../../../../ui/mainwindow.cpp .build/obj/IncDecVolumeOption1.0.0/ && (cd `dirname .build/obj/IncDecVolumeOption1.0.0` && $(TAR) IncDecVolumeOption1.0.0.tar IncDecVolumeOption1.0.0 && $(COMPRESS) IncDecVolumeOption1.0.0.tar) && $(MOVE) `dirname .build/obj/IncDecVolumeOption1.0.0`/IncDecVolumeOption1.0.0.tar.gz . && $(DEL_FILE) -r .build/obj/IncDecVolumeOption1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) ../libincdecvolumeoption.so + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile + + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: .build/moc/moc_incdecvolumeoption.cpp .build/moc/moc_mainwindow.cpp .build/moc/moc_soundcore.cpp +compiler_moc_header_clean: + -$(DEL_FILE) .build/moc/moc_incdecvolumeoption.cpp .build/moc/moc_mainwindow.cpp .build/moc/moc_soundcore.cpp +.build/moc/moc_incdecvolumeoption.cpp: incdecvolumeoption.h + /usr/local/Trolltech/Qt-4.3.0/bin/moc $(DEFINES) $(INCPATH) incdecvolumeoption.h -o .build/moc/moc_incdecvolumeoption.cpp + +.build/moc/moc_mainwindow.cpp: ../../../../qmmp/output.h \ + ../../../../qmmp/visual.h \ + ../../../../qmmp/outputfactory.h \ + ../../../../qmmp/visualfactory.h \ + ../../../../qmmp/recycler.h \ + ../../../../qmmp/decoder.h \ + ../../../../qmmp/filetag.h \ + ../../../../ui/display.h \ + ../../../../ui/pixmapwidget.h \ + ../../../../ui/mediafile.h \ + ../../../../qmmp/decoderfactory.h \ + ../../../../ui/titlebar.h \ + ../../../../ui/playlist.h \ + ../../../../ui/mainwindow.h \ + ../../../../ui/mainwindow.h + /usr/local/Trolltech/Qt-4.3.0/bin/moc $(DEFINES) $(INCPATH) ../../../../ui/mainwindow.h -o .build/moc/moc_mainwindow.cpp + +.build/moc/moc_soundcore.cpp: ../../../../qmmp/decoder.h \ + ../../../../qmmp/filetag.h \ + ../../../../qmmp/output.h \ + ../../../../qmmp/visual.h \ + ../../../../qmmp/outputfactory.h \ + ../../../../qmmp/visualfactory.h \ + ../../../../qmmp/recycler.h \ + ../../../../qmmp/soundcore.h + /usr/local/Trolltech/Qt-4.3.0/bin/moc $(DEFINES) $(INCPATH) ../../../../qmmp/soundcore.h -o .build/moc/moc_soundcore.cpp + +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_uic_make_all: +compiler_uic_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean + +####### Compile + +.build/obj/incdecvolumeoption.o: incdecvolumeoption.cpp incdecvolumeoption.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/incdecvolumeoption.o incdecvolumeoption.cpp + +.build/obj/soundcore.o: ../../../../qmmp/soundcore.cpp ../../../../qmmp/decoderfactory.h \ + ../../../../qmmp/constants.h \ + ../../../../qmmp/config.h \ + ../../../../qmmp/streamreader.h \ + ../../../../qmmp/effect.h \ + ../../../../qmmp/soundcore.h \ + ../../../../qmmp/decoder.h \ + ../../../../qmmp/filetag.h \ + ../../../../qmmp/output.h \ + ../../../../qmmp/visual.h \ + ../../../../qmmp/outputfactory.h \ + ../../../../qmmp/visualfactory.h \ + ../../../../qmmp/recycler.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/soundcore.o ../../../../qmmp/soundcore.cpp + +.build/obj/mainwindow.o: ../../../../ui/mainwindow.cpp ../../../../ui/textscroller.h \ + ../../../../ui/mainwindow.h \ + ../../../../qmmp/output.h \ + ../../../../qmmp/visual.h \ + ../../../../qmmp/outputfactory.h \ + ../../../../qmmp/visualfactory.h \ + ../../../../qmmp/recycler.h \ + ../../../../qmmp/decoder.h \ + ../../../../qmmp/filetag.h \ + ../../../../ui/display.h \ + ../../../../ui/pixmapwidget.h \ + ../../../../ui/mediafile.h \ + ../../../../qmmp/decoderfactory.h \ + ../../../../ui/titlebar.h \ + ../../../../ui/playlist.h \ + ../../../../qmmp/constants.h \ + ../../../../qmmp/config.h \ + ../../../../ui/fileloader.h \ + ../../../../ui/skin.h \ + ../../../../ui/playlistmodel.h \ + ../../../../ui/configdialog.h \ + ../../../../ui/dock.h \ + ../../../../ui/eqwidget.h \ + ../../../../ui/mainvisual.h \ + ../../../../ui/logscale.h \ + ../../../../ui/playlistformat.h \ + ../../../../ui/jumptotrackdialog.h \ + ../../../../ui/aboutdialog.h \ + ../../../../ui/filedialog.h \ + ../../../../ui/listwidget.h \ + ../../../../ui/visualmenu.h \ + ../../../../ui/commandlineoption.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/mainwindow.o ../../../../ui/mainwindow.cpp + +.build/obj/moc_incdecvolumeoption.o: .build/moc/moc_incdecvolumeoption.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/moc_incdecvolumeoption.o .build/moc/moc_incdecvolumeoption.cpp + +.build/obj/moc_mainwindow.o: .build/moc/moc_mainwindow.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/moc_mainwindow.o .build/moc/moc_mainwindow.cpp + +.build/obj/moc_soundcore.o: .build/moc/moc_soundcore.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o .build/obj/moc_soundcore.o .build/moc/moc_soundcore.cpp + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff --git a/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/incdecvolumeoption.cpp b/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/incdecvolumeoption.cpp new file mode 100644 index 000000000..4bd35a910 --- /dev/null +++ b/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/incdecvolumeoption.cpp @@ -0,0 +1,53 @@ +#include + +#include "incdecvolumeoption.h" +#include +#include "mainwindow.h" + +bool IncDecVolumeCommandLineOption::identify(const QString & str) const +{ + if( + str == QString("--volume-inc") || + str == QString("--volume-dec") + ) + { + return TRUE; + } + + return FALSE; +} + +const QString IncDecVolumeCommandLineOption::helpString() const +{ + return QString( + "--volume-inc Increase volume with step 10\n" + "--volume-dec Decrease volume with step 10\n" + ); +} + + +void IncDecVolumeCommandLineOption::executeCommand(const QString & option_string, MainWindow *mw) +{ + if (option_string == "--volume-inc") + { + int l = 0; + int r = 0; + mw->soundCore()->volume(&l,&r); + mw->soundCore()->setVolume(l+10,r+10); + } + else if (option_string == "--volume-dec") + { + int l = 0; + int r = 0; + mw->soundCore()->volume(&l,&r); + mw->soundCore()->setVolume(l-10,r-10); + } +} + +const QString IncDecVolumeCommandLineOption::name() const +{ + return "IncDecVolumeCommandLineOption"; +} + +Q_EXPORT_PLUGIN(IncDecVolumeCommandLineOption) + diff --git a/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/incdecvolumeoption.h b/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/incdecvolumeoption.h new file mode 100644 index 000000000..6fbf3d24a --- /dev/null +++ b/src/plugins/Misc/CommandLineOptions/IncDecVolumeOption/incdecvolumeoption.h @@ -0,0 +1,23 @@ +#ifndef IncDecVolumeCommandLineOption_H +#define IncDecVolumeCommandLineOption_H + +#include + +#include +#include + +class MainWindow; + +class IncDecVolumeCommandLineOption : public QObject, public CommandLineOption +{ +Q_OBJECT +Q_INTERFACES(CommandLineOption) +public: + virtual bool identify(const QString& opt_str)const; + virtual const QString name()const; + virtual const QString helpString()const; + virtual void executeCommand(const QString& opt_str,MainWindow* mw); +}; + +#endif + diff --git a/src/plugins/Misc/FileDialogs/FileDialogs.pro b/src/plugins/Misc/FileDialogs/FileDialogs.pro new file mode 100644 index 000000000..a15058c1f --- /dev/null +++ b/src/plugins/Misc/FileDialogs/FileDialogs.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs +SUBDIRS = Qt3FileDialog \ + QmmpFileDialog \ No newline at end of file diff --git a/src/plugins/Misc/FileDialogs/Makefile b/src/plugins/Misc/FileDialogs/Makefile new file mode 100644 index 000000000..5e0580ccf --- /dev/null +++ b/src/plugins/Misc/FileDialogs/Makefile @@ -0,0 +1,134 @@ +############################################################################# +# Makefile for building: FileDialogs +# Generated by qmake (2.01a) (Qt 4.2.3) on: Tue Jul 24 19:08:22 2007 +# Project: FileDialogs.pro +# Template: subdirs +# Command: /usr/local/Trolltech/Qt-4.2.3/bin/qmake -unix -o Makefile FileDialogs.pro +############################################################################# + +first: make_default +MAKEFILE = Makefile +QMAKE = /usr/local/Trolltech/Qt-4.2.3/bin/qmake +DEL_FILE = rm -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p +COPY = cp -f +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +INSTALL_FILE = install -m 644 -p +INSTALL_PROGRAM = install -m 755 -p +INSTALL_DIR = $(COPY_DIR) +DEL_FILE = rm -f +SYMLINK = ln -sf +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p +SUBTARGETS = \ + sub-Qt3FileDialog \ + sub-QmmpFileDialog + +Qt3FileDialog/$(MAKEFILE): + @$(CHK_DIR_EXISTS) Qt3FileDialog/ || $(MKDIR) Qt3FileDialog/ + cd Qt3FileDialog && $(QMAKE) Qt3FileDialog.pro -unix -o $(MAKEFILE) +sub-Qt3FileDialog-qmake_all: FORCE + @$(CHK_DIR_EXISTS) Qt3FileDialog/ || $(MKDIR) Qt3FileDialog/ + cd Qt3FileDialog && $(QMAKE) Qt3FileDialog.pro -unix -o $(MAKEFILE) +sub-Qt3FileDialog: Qt3FileDialog/$(MAKEFILE) FORCE + cd Qt3FileDialog && $(MAKE) -f $(MAKEFILE) +sub-Qt3FileDialog-make_default: Qt3FileDialog/$(MAKEFILE) FORCE + cd Qt3FileDialog && $(MAKE) -f $(MAKEFILE) +sub-Qt3FileDialog-make_first: Qt3FileDialog/$(MAKEFILE) FORCE + cd Qt3FileDialog && $(MAKE) -f $(MAKEFILE) first +sub-Qt3FileDialog-all: Qt3FileDialog/$(MAKEFILE) FORCE + cd Qt3FileDialog && $(MAKE) -f $(MAKEFILE) all +sub-Qt3FileDialog-clean: Qt3FileDialog/$(MAKEFILE) FORCE + cd Qt3FileDialog && $(MAKE) -f $(MAKEFILE) clean +sub-Qt3FileDialog-distclean: Qt3FileDialog/$(MAKEFILE) FORCE + cd Qt3FileDialog && $(MAKE) -f $(MAKEFILE) distclean +sub-Qt3FileDialog-install_subtargets: Qt3FileDialog/$(MAKEFILE) FORCE + cd Qt3FileDialog && $(MAKE) -f $(MAKEFILE) install +sub-Qt3FileDialog-uninstall_subtargets: Qt3FileDialog/$(MAKEFILE) FORCE + cd Qt3FileDialog && $(MAKE) -f $(MAKEFILE) uninstall +QmmpFileDialog/$(MAKEFILE): + @$(CHK_DIR_EXISTS) QmmpFileDialog/ || $(MKDIR) QmmpFileDialog/ + cd QmmpFileDialog && $(QMAKE) QmmpFileDialog.pro -unix -o $(MAKEFILE) +sub-QmmpFileDialog-qmake_all: FORCE + @$(CHK_DIR_EXISTS) QmmpFileDialog/ || $(MKDIR) QmmpFileDialog/ + cd QmmpFileDialog && $(QMAKE) QmmpFileDialog.pro -unix -o $(MAKEFILE) +sub-QmmpFileDialog: QmmpFileDialog/$(MAKEFILE) FORCE + cd QmmpFileDialog && $(MAKE) -f $(MAKEFILE) +sub-QmmpFileDialog-make_default: QmmpFileDialog/$(MAKEFILE) FORCE + cd QmmpFileDialog && $(MAKE) -f $(MAKEFILE) +sub-QmmpFileDialog-make_first: QmmpFileDialog/$(MAKEFILE) FORCE + cd QmmpFileDialog && $(MAKE) -f $(MAKEFILE) first +sub-QmmpFileDialog-all: QmmpFileDialog/$(MAKEFILE) FORCE + cd QmmpFileDialog && $(MAKE) -f $(MAKEFILE) all +sub-QmmpFileDialog-clean: QmmpFileDialog/$(MAKEFILE) FORCE + cd QmmpFileDialog && $(MAKE) -f $(MAKEFILE) clean +sub-QmmpFileDialog-distclean: QmmpFileDialog/$(MAKEFILE) FORCE + cd QmmpFileDialog && $(MAKE) -f $(MAKEFILE) distclean +sub-QmmpFileDialog-install_subtargets: QmmpFileDialog/$(MAKEFILE) FORCE + cd QmmpFileDialog && $(MAKE) -f $(MAKEFILE) install +sub-QmmpFileDialog-uninstall_subtargets: QmmpFileDialog/$(MAKEFILE) FORCE + cd QmmpFileDialog && $(MAKE) -f $(MAKEFILE) uninstall + +Makefile: FileDialogs.pro /usr/local/Trolltech/Qt-4.2.3/mkspecs/linux-g++/qmake.conf /usr/local/Trolltech/Qt-4.2.3/mkspecs/common/unix.conf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/common/g++.conf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/common/linux.conf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/qconfig.pri \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/qt_functions.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/qt_config.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/exclusive_builds.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/default_pre.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/release.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/default_post.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/warn_on.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/qt.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/unix/thread.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/moc.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/resources.prf \ + /usr/local/Trolltech/Qt-4.2.3/mkspecs/features/uic.prf + $(QMAKE) -unix -o Makefile FileDialogs.pro +/usr/local/Trolltech/Qt-4.2.3/mkspecs/common/unix.conf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/common/g++.conf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/common/linux.conf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/qconfig.pri: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/qt_functions.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/qt_config.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/exclusive_builds.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/default_pre.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/release.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/default_post.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/warn_on.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/qt.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/unix/thread.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/moc.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/resources.prf: +/usr/local/Trolltech/Qt-4.2.3/mkspecs/features/uic.prf: +qmake: qmake_all FORCE + @$(QMAKE) -unix -o Makefile FileDialogs.pro + +qmake_all: sub-Qt3FileDialog-qmake_all sub-QmmpFileDialog-qmake_all FORCE + +make_default: sub-Qt3FileDialog-make_default sub-QmmpFileDialog-make_default FORCE +make_first: sub-Qt3FileDialog-make_first sub-QmmpFileDialog-make_first FORCE +all: sub-Qt3FileDialog-all sub-QmmpFileDialog-all FORCE +clean: sub-Qt3FileDialog-clean sub-QmmpFileDialog-clean FORCE +distclean: sub-Qt3FileDialog-distclean sub-QmmpFileDialog-distclean FORCE + -$(DEL_FILE) Makefile +install_subtargets: sub-Qt3FileDialog-install_subtargets sub-QmmpFileDialog-install_subtargets FORCE +uninstall_subtargets: sub-Qt3FileDialog-uninstall_subtargets sub-QmmpFileDialog-uninstall_subtargets FORCE + +/usr/local/Trolltech/Qt-4.2.3/bin/moc: + (cd $(QTDIR)/src/tools/moc && $(MAKE)) + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all +install: install_subtargets FORCE + +uninstall: uninstall_subtargets FORCE + +FORCE: + diff --git a/src/plugins/Misc/FileDialogs/QmmpFileDialog/QmmpFileDialog.pro b/src/plugins/Misc/FileDialogs/QmmpFileDialog/QmmpFileDialog.pro new file mode 100644 index 000000000..d9b8a96df --- /dev/null +++ b/src/plugins/Misc/FileDialogs/QmmpFileDialog/QmmpFileDialog.pro @@ -0,0 +1,28 @@ +QMMPROOT = ../../../qmmp + +INCLUDEPATH += $$QMMPROOT/src +INCLUDEPATH += $$QMMPROOT/lib + +HEADERS += qmmpfiledialog.h \ + qmmpfiledialogimpl.h \ + $$QMMPROOT/src/filedialog.h \ + $$QMMPROOT/src/playlistmodel.h + +SOURCES += qmmpfiledialog.cpp \ + qmmpfiledialogimpl.cpp \ + $$QMMPROOT/src/filedialog.cpp \ + $$QMMPROOT/src/playlistmodel.cpp + + +FORMS += qmmpfiledialog.ui + +RESOURCES += images/images.qrc + +DESTDIR = ../ +QMAKE_CLEAN += ../libqmmpfiledialog.so + + +CONFIG += release warn_on plugin + +TEMPLATE = lib + diff --git a/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/cdup.png b/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/cdup.png new file mode 100644 index 000000000..5d966a77b Binary files /dev/null and b/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/cdup.png differ diff --git a/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/detail.png b/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/detail.png new file mode 100644 index 000000000..2e552a425 Binary files /dev/null and b/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/detail.png differ diff --git a/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/images.qrc b/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/images.qrc new file mode 100644 index 000000000..c194a6b91 --- /dev/null +++ b/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/images.qrc @@ -0,0 +1,8 @@ + + + + cdup.png + detail.png + list.png + + diff --git a/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/list.png b/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/list.png new file mode 100644 index 000000000..13b44a620 Binary files /dev/null and b/src/plugins/Misc/FileDialogs/QmmpFileDialog/images/list.png differ diff --git a/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.cpp b/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.cpp new file mode 100644 index 000000000..fce9f6e53 --- /dev/null +++ b/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.cpp @@ -0,0 +1,44 @@ +#include + +#include "qmmpfiledialogimpl.h" +#include "qmmpfiledialog.h" + + + +QmmpFileDialog::QmmpFileDialog() +{ + m_dialog = new QmmpFileDialogImpl(); + connect(m_dialog,SIGNAL(filesAdded(const QStringList&)),this,SIGNAL(filesAdded(const QStringList&))); +} + +void QmmpFileDialog::handleSelected(/*const QStringList& s */) +{ +} + +bool QmmpFileDialog::modal()const +{ + return FALSE; +} + +QmmpFileDialog::~QmmpFileDialog() +{ + qWarning("QmmpFileDialog::~QmmpFileDialog()"); + delete m_dialog; +} +void QmmpFileDialog::raise(const QString& d,Mode m,const QStringList& f) +{ + m_dialog->setModeAndMask(d,m,f); + m_dialog->show(); + m_dialog->raise(); +} + + +FileDialog* QmmpFileDialogFactory::create(){ return new QmmpFileDialog();} + +QString QmmpFileDialogFactory::name(){return QmmpFileDialogFactoryName;} + +QString QmmpFileDialogFactory::QmmpFileDialogFactoryName = "Qmmp File Dialog"; + + +Q_EXPORT_PLUGIN(QmmpFileDialogFactory) + diff --git a/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.h b/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.h new file mode 100644 index 000000000..30a4fef59 --- /dev/null +++ b/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.h @@ -0,0 +1,40 @@ +#ifndef QMMPFILEDIALOG_H +#define QMMPFILEDIALOG_H + +#include + +class QmmpFileDialogImpl; + +class QmmpFileDialog : public FileDialog +{ +Q_OBJECT + public: + QmmpFileDialog(); + virtual ~QmmpFileDialog(); + virtual bool modal()const; + virtual void raise(const QString&,Mode = AddFiles,const QStringList& = QStringList()); + public slots: + void handleSelected(); + + private: + QmmpFileDialogImpl * m_dialog; +}; + + + + +class QmmpFileDialogFactory : public QObject, public FileDialogFactory +{ + Q_OBJECT + Q_INTERFACES(FileDialogFactory); + public: + virtual FileDialog* create(); + virtual QString name(); + virtual ~QmmpFileDialogFactory(){;} + static QString QmmpFileDialogFactoryName; +}; + + +#endif + + diff --git a/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.ui b/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.ui new file mode 100644 index 000000000..dbfb2edc2 --- /dev/null +++ b/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialog.ui @@ -0,0 +1,216 @@ + + QmmpFileDialog + + + + 0 + 0 + 517 + 312 + + + + Add Files + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + Look in: + + + + + + + + 5 + 0 + 1 + 0 + + + + true + + + + + + + Up + + + :/cdup.png + + + + + + + List view + + + lst + + + :/list.png + + + true + + + + + + + Icon view + + + icn + + + :/detail.png + + + + 16 + 16 + + + + true + + + + + + + + + QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::NoDragDrop + + + false + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectItems + + + QListView::Static + + + QListView::Batched + + + QListView::ListMode + + + true + + + + + + + 0 + + + 6 + + + + + File name: + + + + + + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add + + + + + + + Close + + + + + + + + + + + + + closePushButton + clicked() + QmmpFileDialog + reject() + + + 459 + 291 + + + 153 + 289 + + + + + diff --git a/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialogimpl.cpp b/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialogimpl.cpp new file mode 100644 index 000000000..984cc7204 --- /dev/null +++ b/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialogimpl.cpp @@ -0,0 +1,109 @@ +#include "qmmpfiledialogimpl.h" + +#include +#include + +QmmpFileDialogImpl::QmmpFileDialogImpl( QWidget * parent, Qt::WindowFlags f) : QDialog(parent,f) +{ + setupUi(this); + setAttribute(Qt::WA_QuitOnClose, FALSE); + m_model = new QDirModel(this); + m_model->setSorting(QDir::Type /*| QDir::Name*/); + fileListView->setModel(m_model); + //fileListView->setViewMode(QListView::IconMode); + listToolButton->setChecked(true); +} + +QmmpFileDialogImpl::~QmmpFileDialogImpl() +{ +} + +void QmmpFileDialogImpl::on_lookInComboBox_activated(const QString&) +{ + qWarning("TODO: %s %d",__FILE__,__LINE__); +} + +void QmmpFileDialogImpl::on_upToolButton_clicked() +{ + fileListView->setRootIndex(m_model->parent(fileListView->rootIndex())); + lookInComboBox->setEditText(m_model->filePath(fileListView->rootIndex())); +} + +void QmmpFileDialogImpl::on_fileListView_doubleClicked(const QModelIndex& ind) +{ + if(ind.isValid()) + { + QFileInfo info = m_model->fileInfo(ind); + if(info.isDir()) + { + fileListView->setRootIndex(ind); + lookInComboBox->setEditText(m_model->filePath(ind)); + } + else + { + QStringList l; + l << m_model->filePath(ind); + emit filesAdded(l); + } + } + +} + +void QmmpFileDialogImpl::on_fileNameLineEdit_returnPressed() +{ + on_addPushButton_clicked(); +} + +void QmmpFileDialogImpl::on_addPushButton_clicked() +{ + QModelIndexList ml = fileListView->selectionModel()->selectedIndexes(); + QStringList l; + foreach(QModelIndex i,ml) + l << m_model->filePath(i); + qWarning("!!!!!!!!!"); + emit filesAdded(l); +} + +void QmmpFileDialogImpl::setModeAndMask(const QString& d,FileDialog::Mode m, const QStringList & mask) +{ + if(m == FileDialog::AddFiles) + { + setWindowTitle("Add Files"); + m_model->setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); + } + else if(m == FileDialog::AddDirs) + { + setWindowTitle("Add Dirs"); + m_model->setFilter(QDir::Dirs | QDir::NoDotAndDotDot); + } + else + { + setWindowTitle("Save File"); + m_model->setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); + qWarning("To be implemented..."); + } + + m_model->setSorting(QDir::Type); + fileListView->setRootIndex(m_model->index(d)); + m_model->sort(0); + lookInComboBox->setEditText(d); +} + +void QmmpFileDialogImpl::on_listToolButton_toggled(bool yes) +{ + if(yes) + { + iconToolButton->setChecked(false); + fileListView->setViewMode(QListView::ListMode); + } +} + +void QmmpFileDialogImpl::on_iconToolButton_toggled(bool yes) +{ + if(yes) + { + listToolButton->setChecked(false); + fileListView->setViewMode(QListView::IconMode); + } +} + diff --git a/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialogimpl.h b/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialogimpl.h new file mode 100644 index 000000000..2be25bf05 --- /dev/null +++ b/src/plugins/Misc/FileDialogs/QmmpFileDialog/qmmpfiledialogimpl.h @@ -0,0 +1,33 @@ +#ifndef QMMPFILEDIALOGIMPL_H +#define QMMPFILEDIALOGIMPL_H + +#include "ui_qmmpfiledialog.h" +#include + +#include "filedialog.h" + +class QDirModel; + + +class QmmpFileDialogImpl : public QDialog , private Ui::QmmpFileDialog +{ +Q_OBJECT +public: + QmmpFileDialogImpl( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~QmmpFileDialogImpl(); + void setModeAndMask(const QString&,FileDialog::Mode m,const QStringList& mask); +protected slots: + void on_lookInComboBox_activated(const QString&); + void on_upToolButton_clicked(); + void on_fileListView_doubleClicked(const QModelIndex&); + void on_fileNameLineEdit_returnPressed(); + void on_addPushButton_clicked(); + void on_listToolButton_toggled(bool); + void on_iconToolButton_toggled(bool); +signals: + void filesAdded(const QStringList&); +protected: + QDirModel* m_model; + +}; +#endif //QMMPFILEDIALOGIMPL_H diff --git a/src/plugins/Misc/FileDialogs/Qt3FileDialog/Qt3FileDialog.pro b/src/plugins/Misc/FileDialogs/Qt3FileDialog/Qt3FileDialog.pro new file mode 100644 index 000000000..7954ebf01 --- /dev/null +++ b/src/plugins/Misc/FileDialogs/Qt3FileDialog/Qt3FileDialog.pro @@ -0,0 +1,28 @@ +QMMPROOT = ../../../qmmp + +INCLUDEPATH += $$QMMPROOT/src +INCLUDEPATH += $$QMMPROOT/lib + +HEADERS += qt3filedialogfactory.h \ + qt3filedialog.h \ + $$QMMPROOT/src/filedialog.h \ + $$QMMPROOT/src/playlistmodel.h + +SOURCES += qt3filedialog.cpp \ + qt3filedialogfactory.cpp \ + $$QMMPROOT/src/filedialog.cpp \ + $$QMMPROOT/src/playlistmodel.cpp + + +DESTDIR = ../ +QMAKE_CLEAN += ../libqt3filedialog.so + + +CONFIG += release warn_on plugin + +TEMPLATE = lib + +QT += qt3support + +#target.path = /plugins/FileDialogs +#INSTALLS += target diff --git a/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialog.cpp b/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialog.cpp new file mode 100644 index 000000000..b9b9bc898 --- /dev/null +++ b/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialog.cpp @@ -0,0 +1,35 @@ +#include "qt3filedialog.h" +#include + +Qt3SupportFileDialog::~Qt3SupportFileDialog() +{ + qWarning("Qt3SupportFileDialog::~Qt3SupportFileDialog()"); +} + +QString Qt3SupportFileDialog::existingDirectory(QWidget * parent , const QString & caption, const QString & dir) +{ + return Q3FileDialog::getExistingDirectory ( dir, + parent, + 0, + caption, + true, + true ); +} + +QString Qt3SupportFileDialog::openFileName(QWidget * parent,const QString & caption,const QString & /*dir*/,const QString & filter, + QString * selectedFilter) +{ + return Q3FileDialog::getOpenFileName ( QString(),filter,parent,0,caption,selectedFilter); +} + +QStringList Qt3SupportFileDialog::openFileNames(QWidget * parent, const QString & caption , const QString & dir , + const QString & filter, QString * selectedFilter) +{ + return Q3FileDialog::getOpenFileNames(filter,dir,parent,0,caption,selectedFilter); +} + +QString Qt3SupportFileDialog::saveFileName ( QWidget * parent, const QString & caption, + const QString &, const QString & filter, QString * selectedFilter) +{ + return Q3FileDialog::getSaveFileName(QString(),filter,parent,0,caption,selectedFilter); +} diff --git a/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialog.h b/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialog.h new file mode 100644 index 000000000..bbce2e3c8 --- /dev/null +++ b/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialog.h @@ -0,0 +1,23 @@ +#ifndef QT3FILEDIALOG_H +#define QT3FILEDIALOG_H + +#include + + +class Qt3SupportFileDialog : public FileDialog +{ + public: + virtual ~Qt3SupportFileDialog(); + virtual QString existingDirectory(QWidget * parent , const QString & , const QString & dir); + virtual QString openFileName(QWidget * parent,const QString & caption,const QString & dir,const QString & filter, + QString * selectedFilter); + virtual QStringList openFileNames(QWidget * parent, const QString & caption , const QString & dir , + const QString & filter, QString * selectedFilter); + virtual QString saveFileName ( QWidget * parent, const QString & caption, + const QString & dir, const QString & filter, QString * selectedFilter); + +}; + +#endif + + diff --git a/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialogfactory.cpp b/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialogfactory.cpp new file mode 100644 index 000000000..45b4260bb --- /dev/null +++ b/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialogfactory.cpp @@ -0,0 +1,20 @@ +#include +#include "qt3filedialogfactory.h" +#include "qt3filedialog.h" + + +FileDialog* Qt3SupportFileDialogFactory::create() +{ + return new Qt3SupportFileDialog(); +} + +QString Qt3SupportFileDialogFactory::name() +{ + return Qt3SupportFileDialogFactory::Qt3SupportFileDialogFactoryName; +} + + +QString Qt3SupportFileDialogFactory::Qt3SupportFileDialogFactoryName = "Qt3 File Dialog"; + +Q_EXPORT_PLUGIN(Qt3SupportFileDialogFactory) + diff --git a/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialogfactory.h b/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialogfactory.h new file mode 100644 index 000000000..e5d3b4595 --- /dev/null +++ b/src/plugins/Misc/FileDialogs/Qt3FileDialog/qt3filedialogfactory.h @@ -0,0 +1,19 @@ +#ifndef QT3FILEDIALOGFACTORY_H +#define QT3FILEDIALOGFACTORY_H + + +#include + +class Qt3SupportFileDialogFactory : public QObject, public FileDialogFactory +{ + Q_OBJECT + Q_INTERFACES(FileDialogFactory); + public: + virtual FileDialog* create(); + virtual QString name(); + virtual ~Qt3SupportFileDialogFactory(){;} + static QString Qt3SupportFileDialogFactoryName; +}; + +#endif + diff --git a/src/plugins/Misc/FileDialogs/Qt3FileDialog/readme b/src/plugins/Misc/FileDialogs/Qt3FileDialog/readme new file mode 100644 index 000000000..966f7201d --- /dev/null +++ b/src/plugins/Misc/FileDialogs/Qt3FileDialog/readme @@ -0,0 +1,14 @@ +This is simple example of File Dialog plugin. +Requires Qt3Support library. This plugin developed +mostly for QMMP customizing demonstration - +we don't think that somebody will prefer use Qt3 +look&feel :) + +Build: Change QMMPROOT variable in .pro file according your +QMMP build tree location.Then qmake && make + +Install: copy library into ~/.qmmp/plugins/FileDialogs directory. + + + vovanec@gmail.com + diff --git a/src/plugins/Misc/FileDialogs/libQmmpFileDialog.so b/src/plugins/Misc/FileDialogs/libQmmpFileDialog.so new file mode 100755 index 000000000..d04ccf53a Binary files /dev/null and b/src/plugins/Misc/FileDialogs/libQmmpFileDialog.so differ diff --git a/src/plugins/Misc/FileDialogs/libQt3FileDialog.so b/src/plugins/Misc/FileDialogs/libQt3FileDialog.so new file mode 100755 index 000000000..efbb0d313 Binary files /dev/null and b/src/plugins/Misc/FileDialogs/libQt3FileDialog.so differ diff --git a/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/CSVPlaylistFormat.pro b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/CSVPlaylistFormat.pro new file mode 100644 index 000000000..11c27c3d3 --- /dev/null +++ b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/CSVPlaylistFormat.pro @@ -0,0 +1,20 @@ +QMMPROOT = ../../../qmmp + +HEADERS += csvplaylistformat.h + +SOURCES += csvplaylistformat.cpp \ + $$QMMPROOT/src/mediafile.cpp + +DESTDIR = ../ +QMAKE_CLEAN = ../libcsvplaylistformat.so + +INCLUDEPATH += $$QMMPROOT/src \ + $$QMMPROOT/lib + +CONFIG += release warn_on plugin + +TEMPLATE = lib + +#QMAKE_LIBDIR += ../../../ +#LIBS += -lqmmp -L/usr/lib -I/usr/include + diff --git a/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/Makefile b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/Makefile new file mode 100644 index 000000000..5afa50b01 --- /dev/null +++ b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/Makefile @@ -0,0 +1,213 @@ +############################################################################# +# Makefile for building: libCSVPlaylistFormat.so +# Generated by qmake (2.01a) (Qt 4.3.0) on: Mon Dec 24 01:59:02 2007 +# Project: CSVPlaylistFormat.pro +# Template: lib +# Command: /usr/local/Trolltech/Qt-4.3.0/bin/qmake -unix -o Makefile CSVPlaylistFormat.pro +############################################################################# + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DQT_NO_DEBUG -DQT_PLUGIN -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -pipe -O2 -Wall -W -D_REENTRANT -fPIC $(DEFINES) +CXXFLAGS = -pipe -O2 -Wall -W -D_REENTRANT -fPIC $(DEFINES) +INCPATH = -I/usr/local/Trolltech/Qt-4.3.0/mkspecs/linux-g++ -I. -I/usr/local/Trolltech/Qt-4.3.0/include/QtCore -I/usr/local/Trolltech/Qt-4.3.0/include/QtCore -I/usr/local/Trolltech/Qt-4.3.0/include/QtGui -I/usr/local/Trolltech/Qt-4.3.0/include/QtGui -I/usr/local/Trolltech/Qt-4.3.0/include -I../../../qmmp/src -I../../../qmmp/lib -I. -I. +LINK = g++ +LFLAGS = -Wl,-rpath,/usr/local/Trolltech/Qt-4.3.0/lib -shared +LIBS = $(SUBLIBS) -L/usr/local/Trolltech/Qt-4.3.0/lib -lQtGui -L/usr/local/Trolltech/Qt-4.3.0/lib -L/usr/X11R6/lib -lpng -lSM -lICE -pthread -pthread -lXi -lXrender -lXrandr -lXfixes -lXcursor -lXinerama -lfreetype -lfontconfig -lXext -lX11 -lQtCore -lz -lm -pthread -lgthread-2.0 -lrt -lglib-2.0 -ldl -lpthread +AR = ar cqs +RANLIB = +QMAKE = /usr/local/Trolltech/Qt-4.3.0/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +INSTALL_FILE = install -m 644 -p +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = install -m 755 -p +DEL_FILE = rm -f +SYMLINK = ln -sf +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p + +####### Output directory + +OBJECTS_DIR = ./ + +####### Files + +SOURCES = csvplaylistformat.cpp \ + ../../../qmmp/src/mediafile.cpp moc_csvplaylistformat.cpp +OBJECTS = csvplaylistformat.o \ + mediafile.o \ + moc_csvplaylistformat.o +DIST = /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/g++.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/unix.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/linux.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/qconfig.pri \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_functions.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_config.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/exclusive_builds.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_pre.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/release.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_post.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/warn_on.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/unix/thread.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/moc.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/resources.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/uic.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/yacc.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/lex.prf \ + CSVPlaylistFormat.pro +QMAKE_TARGET = CSVPlaylistFormat +DESTDIR = ../ +TARGET = libCSVPlaylistFormat.so +TARGETD = libCSVPlaylistFormat.so + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile ../$(TARGET) + +../$(TARGET): $(OBJECTS) $(SUBLIBS) $(OBJCOMP) + @$(CHK_DIR_EXISTS) ../ || $(MKDIR) ../ + -$(DEL_FILE) $(TARGET) + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(LIBS) $(OBJCOMP) + -$(MOVE) $(TARGET) ../ + + + +Makefile: CSVPlaylistFormat.pro /usr/local/Trolltech/Qt-4.3.0/mkspecs/linux-g++/qmake.conf /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/g++.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/unix.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/linux.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/qconfig.pri \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_functions.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_config.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/exclusive_builds.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_pre.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/release.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_post.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/warn_on.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/unix/thread.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/moc.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/resources.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/uic.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/yacc.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/lex.prf \ + /usr/local/Trolltech/Qt-4.3.0/lib/libQtGui.prl \ + /usr/local/Trolltech/Qt-4.3.0/lib/libQtCore.prl + $(QMAKE) -unix -o Makefile CSVPlaylistFormat.pro +/usr/local/Trolltech/Qt-4.3.0/mkspecs/common/g++.conf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/common/unix.conf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/common/linux.conf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/qconfig.pri: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_functions.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_config.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/exclusive_builds.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_pre.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/release.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_post.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/warn_on.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/unix/thread.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/moc.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/resources.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/uic.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/yacc.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/lex.prf: +/usr/local/Trolltech/Qt-4.3.0/lib/libQtGui.prl: +/usr/local/Trolltech/Qt-4.3.0/lib/libQtCore.prl: +qmake: FORCE + @$(QMAKE) -unix -o Makefile CSVPlaylistFormat.pro + +dist: + @$(CHK_DIR_EXISTS) .tmp/CSVPlaylistFormat1.0.0 || $(MKDIR) .tmp/CSVPlaylistFormat1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/CSVPlaylistFormat1.0.0/ && $(COPY_FILE) --parents csvplaylistformat.h .tmp/CSVPlaylistFormat1.0.0/ && $(COPY_FILE) --parents csvplaylistformat.cpp ../../../qmmp/src/mediafile.cpp .tmp/CSVPlaylistFormat1.0.0/ && (cd `dirname .tmp/CSVPlaylistFormat1.0.0` && $(TAR) CSVPlaylistFormat1.0.0.tar CSVPlaylistFormat1.0.0 && $(COMPRESS) CSVPlaylistFormat1.0.0.tar) && $(MOVE) `dirname .tmp/CSVPlaylistFormat1.0.0`/CSVPlaylistFormat1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/CSVPlaylistFormat1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) ../libcsvplaylistformat.so + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) $(TARGET) + -$(DEL_FILE) Makefile + + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_moc_header_make_all: moc_csvplaylistformat.cpp +compiler_moc_header_clean: + -$(DEL_FILE) moc_csvplaylistformat.cpp +moc_csvplaylistformat.cpp: csvplaylistformat.h + /usr/local/Trolltech/Qt-4.3.0/bin/moc $(DEFINES) $(INCPATH) csvplaylistformat.h -o moc_csvplaylistformat.cpp + +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_uic_make_all: +compiler_uic_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean + +####### Compile + +csvplaylistformat.o: csvplaylistformat.cpp csvplaylistformat.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o csvplaylistformat.o csvplaylistformat.cpp + +mediafile.o: ../../../qmmp/src/mediafile.cpp ../../../qmmp/src/mediafile.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o mediafile.o ../../../qmmp/src/mediafile.cpp + +moc_csvplaylistformat.o: moc_csvplaylistformat.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_csvplaylistformat.o moc_csvplaylistformat.cpp + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff --git a/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/csvplaylistformat.cpp b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/csvplaylistformat.cpp new file mode 100644 index 000000000..bff8a20b5 --- /dev/null +++ b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/csvplaylistformat.cpp @@ -0,0 +1,72 @@ +#include +#include + +#include "csvplaylistformat.h" +#include + + +bool CSVPlaylistFormat::hasFormat(const QString & f) +{ + foreach(QString s,m_supported_formats) + if(f == s) + return true; + + return false; +} + +QStringList CSVPlaylistFormat::getExtensions() const +{ + return m_supported_formats; +} + +CSVPlaylistFormat::CSVPlaylistFormat() +{ + m_supported_formats << "csv"; +} + +QString CSVPlaylistFormat::name() const +{ + return "CSVPlaylistFormat"; +} + + +QStringList CSVPlaylistFormat::decode(const QString & contents) +{ + qWarning("CONTENTS: %s",qPrintable(contents)); + QStringList out; + QStringList splitted = contents.split("\n"); + if(!splitted.isEmpty()) + { + foreach(QString str, splitted) + { + QStringList song = str.split(";"); + qWarning("SONG: %s",qPrintable(song[0])); + if(song.count() > 1) + { + QString unverified = song[1]; + if(QFileInfo(unverified).exists()) + out << QFileInfo(unverified).absoluteFilePath(); + else + qWarning("File %s does not exist",unverified.toLocal8Bit().data()); + } + + } + return out; + } + else + qWarning("Error parsing CSV playlist format"); + + return QStringList(); +} + +QString CSVPlaylistFormat::encode(const QList< MediaFile * > & contents) +{ + QStringList out; + foreach(MediaFile* f,contents) + out.append(f->title() + ";" + f->path() + ";" + QString::number(f->length())); + + return out.join("\n"); +} + +Q_EXPORT_PLUGIN(CSVPlaylistFormat) + diff --git a/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/csvplaylistformat.h b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/csvplaylistformat.h new file mode 100644 index 000000000..45e93d346 --- /dev/null +++ b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/csvplaylistformat.h @@ -0,0 +1,33 @@ +#ifndef CSVPLAYLISTFORMAT_H +#define CSVPLAYLISTFORMAT_H + +#include + +#include + +class MediaFile; + +/*! + * Example of custom playlist CSV semicolon separated format. + * Each line represents a song in the next format: + * TITLE;FILEPATH;DURATION + */ + +class CSVPlaylistFormat : public QObject, public PlaylistFormat +{ +Q_OBJECT +Q_INTERFACES(PlaylistFormat) +public: + CSVPlaylistFormat(); + virtual ~CSVPlaylistFormat(){;} + virtual QStringList decode(const QString& contents); + virtual QString encode(const QList& contents); + virtual QStringList getExtensions()const; + virtual bool hasFormat(const QString& ext); + virtual QString name()const; +protected: + QStringList m_supported_formats; +}; + +#endif //CSVPLAYLISTFORMAT_H + diff --git a/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/moc_csvplaylistformat.cpp b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/moc_csvplaylistformat.cpp new file mode 100644 index 000000000..133bf4692 --- /dev/null +++ b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/moc_csvplaylistformat.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'csvplaylistformat.h' +** +** Created: Mon Dec 24 01:59:05 2007 +** by: The Qt Meta Object Compiler version 59 (Qt 4.3.0) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include "csvplaylistformat.h" +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'csvplaylistformat.h' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 59 +#error "This file was generated using the moc from 4.3.0. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +static const uint qt_meta_data_CSVPlaylistFormat[] = { + + // content: + 1, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + + 0 // eod +}; + +static const char qt_meta_stringdata_CSVPlaylistFormat[] = { + "CSVPlaylistFormat\0" +}; + +const QMetaObject CSVPlaylistFormat::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_CSVPlaylistFormat, + qt_meta_data_CSVPlaylistFormat, 0 } +}; + +const QMetaObject *CSVPlaylistFormat::metaObject() const +{ + return &staticMetaObject; +} + +void *CSVPlaylistFormat::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_CSVPlaylistFormat)) + return static_cast(const_cast< CSVPlaylistFormat*>(this)); + if (!strcmp(_clname, "PlaylistFormat")) + return static_cast< PlaylistFormat*>(const_cast< CSVPlaylistFormat*>(this)); + if (!strcmp(_clname, "PlaylistFormatInterface/1.0")) + return static_cast< PlaylistFormat*>(const_cast< CSVPlaylistFormat*>(this)); + return QObject::qt_metacast(_clname); +} + +int CSVPlaylistFormat::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} diff --git a/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/readme b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/readme new file mode 100644 index 000000000..a047e358b --- /dev/null +++ b/src/plugins/Misc/PlaylistFormats/CSVPlaylistFormat/readme @@ -0,0 +1,12 @@ +This is simple example of custom Playlist Format plugin. +It represents CVS semicolon-separated format storage. +This plugin developed mostly for QMMP customizing demonstration. + +Build: Change QMMPROOT variable in .pro file according your +QMMP build tree location.Then qmake && make + +Install: copy library into ~/.qmmp/plugins/PlaylistFormats directory. + + + vovanec@gmail.com + diff --git a/src/plugins/Misc/PlaylistFormats/Makefile b/src/plugins/Misc/PlaylistFormats/Makefile new file mode 100644 index 000000000..cbf632042 --- /dev/null +++ b/src/plugins/Misc/PlaylistFormats/Makefile @@ -0,0 +1,112 @@ +############################################################################# +# Makefile for building: PlaylistFormats +# Generated by qmake (2.01a) (Qt 4.3.0) on: Mon Dec 24 01:59:00 2007 +# Project: PlaylistFormats.pro +# Template: subdirs +# Command: /usr/local/Trolltech/Qt-4.3.0/bin/qmake -unix -o Makefile PlaylistFormats.pro +############################################################################# + +first: make_default +MAKEFILE = Makefile +QMAKE = /usr/local/Trolltech/Qt-4.3.0/bin/qmake +DEL_FILE = rm -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p +COPY = cp -f +COPY_FILE = $(COPY) +COPY_DIR = $(COPY) -r +INSTALL_FILE = install -m 644 -p +INSTALL_PROGRAM = install -m 755 -p +INSTALL_DIR = $(COPY_DIR) +DEL_FILE = rm -f +SYMLINK = ln -sf +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p +SUBTARGETS = \ + sub-CSVPlaylistFormat + +CSVPlaylistFormat//$(MAKEFILE): + @$(CHK_DIR_EXISTS) CSVPlaylistFormat/ || $(MKDIR) CSVPlaylistFormat/ + cd CSVPlaylistFormat/ && $(QMAKE) CSVPlaylistFormat.pro -unix -o $(MAKEFILE) +sub-CSVPlaylistFormat-qmake_all: FORCE + @$(CHK_DIR_EXISTS) CSVPlaylistFormat/ || $(MKDIR) CSVPlaylistFormat/ + cd CSVPlaylistFormat/ && $(QMAKE) CSVPlaylistFormat.pro -unix -o $(MAKEFILE) +sub-CSVPlaylistFormat: CSVPlaylistFormat//$(MAKEFILE) FORCE + cd CSVPlaylistFormat/ && $(MAKE) -f $(MAKEFILE) +sub-CSVPlaylistFormat-make_default: CSVPlaylistFormat//$(MAKEFILE) FORCE + cd CSVPlaylistFormat/ && $(MAKE) -f $(MAKEFILE) +sub-CSVPlaylistFormat-make_first: CSVPlaylistFormat//$(MAKEFILE) FORCE + cd CSVPlaylistFormat/ && $(MAKE) -f $(MAKEFILE) first +sub-CSVPlaylistFormat-all: CSVPlaylistFormat//$(MAKEFILE) FORCE + cd CSVPlaylistFormat/ && $(MAKE) -f $(MAKEFILE) all +sub-CSVPlaylistFormat-clean: CSVPlaylistFormat//$(MAKEFILE) FORCE + cd CSVPlaylistFormat/ && $(MAKE) -f $(MAKEFILE) clean +sub-CSVPlaylistFormat-distclean: CSVPlaylistFormat//$(MAKEFILE) FORCE + cd CSVPlaylistFormat/ && $(MAKE) -f $(MAKEFILE) distclean +sub-CSVPlaylistFormat-install_subtargets: CSVPlaylistFormat//$(MAKEFILE) FORCE + cd CSVPlaylistFormat/ && $(MAKE) -f $(MAKEFILE) install +sub-CSVPlaylistFormat-uninstall_subtargets: CSVPlaylistFormat//$(MAKEFILE) FORCE + cd CSVPlaylistFormat/ && $(MAKE) -f $(MAKEFILE) uninstall + +Makefile: PlaylistFormats.pro /usr/local/Trolltech/Qt-4.3.0/mkspecs/linux-g++/qmake.conf /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/g++.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/unix.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/common/linux.conf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/qconfig.pri \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_functions.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_config.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/exclusive_builds.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_pre.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/release.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_post.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/warn_on.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/unix/thread.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/moc.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/resources.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/uic.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/yacc.prf \ + /usr/local/Trolltech/Qt-4.3.0/mkspecs/features/lex.prf + $(QMAKE) -unix -o Makefile PlaylistFormats.pro +/usr/local/Trolltech/Qt-4.3.0/mkspecs/common/g++.conf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/common/unix.conf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/common/linux.conf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/qconfig.pri: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_functions.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt_config.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/exclusive_builds.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_pre.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/release.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/default_post.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/warn_on.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/qt.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/unix/thread.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/moc.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/resources.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/uic.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/yacc.prf: +/usr/local/Trolltech/Qt-4.3.0/mkspecs/features/lex.prf: +qmake: qmake_all FORCE + @$(QMAKE) -unix -o Makefile PlaylistFormats.pro + +qmake_all: sub-CSVPlaylistFormat-qmake_all FORCE + +make_default: sub-CSVPlaylistFormat-make_default FORCE +make_first: sub-CSVPlaylistFormat-make_first FORCE +all: sub-CSVPlaylistFormat-all FORCE +clean: sub-CSVPlaylistFormat-clean FORCE +distclean: sub-CSVPlaylistFormat-distclean FORCE + -$(DEL_FILE) Makefile +install_subtargets: sub-CSVPlaylistFormat-install_subtargets FORCE +uninstall_subtargets: sub-CSVPlaylistFormat-uninstall_subtargets FORCE + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all +install: install_subtargets FORCE + +uninstall: uninstall_subtargets FORCE + +FORCE: + diff --git a/src/plugins/Misc/PlaylistFormats/PlaylistFormats.pro b/src/plugins/Misc/PlaylistFormats/PlaylistFormats.pro new file mode 100644 index 000000000..4235b3190 --- /dev/null +++ b/src/plugins/Misc/PlaylistFormats/PlaylistFormats.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = CSVPlaylistFormat \ No newline at end of file diff --git a/src/plugins/Misc/PlaylistFormats/libCSVPlaylistFormat.so b/src/plugins/Misc/PlaylistFormats/libCSVPlaylistFormat.so new file mode 100755 index 000000000..f9677157c Binary files /dev/null and b/src/plugins/Misc/PlaylistFormats/libCSVPlaylistFormat.so differ diff --git a/src/plugins/Output/CMakeLists.txt b/src/plugins/Output/CMakeLists.txt new file mode 100644 index 000000000..864d945c1 --- /dev/null +++ b/src/plugins/Output/CMakeLists.txt @@ -0,0 +1,24 @@ +SET(USE_ALSA TRUE CACHE BOOL "enable/disable alsa plugin") +SET(USE_JACK TRUE CACHE BOOL "enable/disable jack plugin") +SET(USE_OSS TRUE CACHE BOOL "enable/disable oss plugin") + +IF(USE_ALSA) +MESSAGE( STATUS "ALSA ON") +add_subdirectory(alsa) +ELSE(USE_ALSA) +MESSAGE( STATUS "ALSA OFF") +ENDIF(USE_ALSA) + +IF(USE_JACK) +MESSAGE( STATUS "JACK ON") +add_subdirectory(jack) +ELSE(USE_JACK) +MESSAGE( STATUS "JACK OFF") +ENDIF(USE_JACK) + +IF(USE_OSS) +MESSAGE( STATUS "OSS ON") +add_subdirectory(oss) +ELSE(USE_OSS) +MESSAGE( STATUS "OSS OFF") +ENDIF(USE_OSS) \ No newline at end of file diff --git a/src/plugins/Output/Output.pro b/src/plugins/Output/Output.pro new file mode 100644 index 000000000..eed8b9f14 --- /dev/null +++ b/src/plugins/Output/Output.pro @@ -0,0 +1,26 @@ +# ???? ?????? ? KDevelop ?????????? qmake. +# ------------------------------------------- +# ?????????? ???????????? ???????? ???????? ???????: ./Plugins/Output +# ???? - ?????? ? ????????????? + +include(../../../qmmp.pri) + +CONFIG += release warn_on +TEMPLATE = subdirs + +SUBDIRS += alsa + +contains(CONFIG, JACK_PLUGIN){ + SUBDIRS += jack + message(***********************) + message(* JACK plugin enabled *) + message(***********************) +} + +contains(CONFIG, OSS_PLUGIN){ + SUBDIRS += oss + message(**********************) + message(* OSS plugin enabled *) + message(**********************) +} + diff --git a/src/plugins/Output/alsa/CMakeLists.txt b/src/plugins/Output/alsa/CMakeLists.txt new file mode 100644 index 000000000..92f7af8d9 --- /dev/null +++ b/src/plugins/Output/alsa/CMakeLists.txt @@ -0,0 +1,65 @@ +project(libalsa) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +SET(libalsa_SRCS + outputalsa.cpp + outputalsafactory.cpp + settingsdialog.cpp +) + +SET(libalsa_MOC_HDRS + outputalsa.h + outputalsafactory.h + settingsdialog.h +) + +SET(libalsa_RCCS translations/translations.qrc) + +QT4_ADD_RESOURCES(libalsa_RCC_SRCS ${libalsa_RCCS}) + +QT4_WRAP_CPP(libalsa_MOC_SRCS ${libalsa_MOC_HDRS}) + +# user interface + + +SET(libalsa_UIS + settingsdialog.ui +) + +QT4_WRAP_UI(libalsa_UIS_H ${libalsa_UIS}) +# Don't forget to include output directory, otherwise +# the UI file won't be wrapped! +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(alsa SHARED ${libalsa_SRCS} ${libalsa_MOC_SRCS} ${libalsa_UIS_H} + ${libalsa_RCC_SRCS}) +target_link_libraries(alsa ${QT_LIBRARIES} -lqmmp -lasound) +install(TARGETS alsa DESTINATION ${LIB_DIR}/qmmp/Output PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) + diff --git a/src/plugins/Output/alsa/alsa.pro b/src/plugins/Output/alsa/alsa.pro new file mode 100644 index 000000000..465fabe4a --- /dev/null +++ b/src/plugins/Output/alsa/alsa.pro @@ -0,0 +1,37 @@ +# ???? ?????? ? KDevelop ?????????? qmake. +# ------------------------------------------- +# ?????????? ???????????? ???????? ???????? ???????: ./Plugins/Output/alsa +# ???? - ??????????: + +include(../../plugins.pri) + +HEADERS += outputalsa.h \ + outputalsafactory.h \ + settingsdialog.h +SOURCES += outputalsa.cpp \ + outputalsafactory.cpp \ + settingsdialog.cpp + +TARGET=$$PLUGINS_PREFIX/Output/alsa +QMAKE_CLEAN =$$PLUGINS_PREFIX/Output/libalsa.so + + +INCLUDEPATH += ../../../qmmp +QMAKE_LIBDIR += ../../../../lib + +CONFIG += release \ +warn_on \ +thread \ +plugin +TEMPLATE = lib +LIBS += -lqmmp -lasound +FORMS += settingsdialog.ui +#TRANSLATIONS = translations/alsa_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} + +target.path = $$LIB_DIR/qmmp/Output +INSTALLS += target diff --git a/src/plugins/Output/alsa/outputalsa.cpp b/src/plugins/Output/alsa/outputalsa.cpp new file mode 100644 index 000000000..66c031bbb --- /dev/null +++ b/src/plugins/Output/alsa/outputalsa.cpp @@ -0,0 +1,539 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "outputalsa.h" +#include "constants.h" +#include "buffer.h" +#include "visual.h" + +OutputALSA::OutputALSA(QObject * parent, bool useVolume) + : Output(parent), m_inited(FALSE), m_pause(FALSE), m_play(FALSE), + m_userStop(FALSE), m_totalWritten(0), m_currentSeconds(-1), + m_bps(-1), m_frequency(-1), m_channels(-1), m_precision(-1) +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + QString dev_name = settings.value("ALSA/device","default").toString(); + pcm_name = strdup(dev_name.toAscii().data()); + stream = SND_PCM_STREAM_PLAYBACK; + snd_pcm_hw_params_alloca(&hwparams); + pcm_handle = 0; + //alsa mixer + mixer = 0; + if (useVolume) + { + QString card = settings.value("ALSA/mixer_card","hw:0").toString(); + QString dev = settings.value("ALSA/mixer_device", "PCM").toString(); + setupMixer(card, dev); + } +} + +OutputALSA::~OutputALSA() +{ + uninitialize(); + free (pcm_name); + if (mixer) + snd_mixer_close(mixer); +} + +void OutputALSA::stop() +{ + m_userStop = TRUE; +} + +void OutputALSA::status() +{ + long ct = (m_totalWritten - latency()) / m_bps; + + if (ct < 0) + ct = 0; + + if (ct > m_currentSeconds) + { + m_currentSeconds = ct; + dispatch(m_currentSeconds, m_totalWritten, m_rate, + m_frequency, m_precision, m_channels); + } +} + +long OutputALSA::written() +{ + return m_totalWritten; +} + +void OutputALSA::seek(long pos) +{ + m_totalWritten = (pos * m_bps); + m_currentSeconds = -1; +} + +void OutputALSA::configure(long freq, int chan, int prec, int brate) +{ + // we need to configure + if (freq != m_frequency || chan != m_channels || prec != m_precision) + { + m_frequency = freq; + m_channels = chan; + m_precision = prec; + m_bps = freq * chan * (prec / 8); + snd_pcm_hw_params_alloca(&hwparams); + if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) + { + qWarning("OutputALSA: Can not configure this PCM device."); + return; + } + + uint rate = m_frequency; /* Sample rate */ + uint exact_rate = m_frequency; /* Sample rate returned by */ + + /* load settings from config */ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("ALSA"); + uint buffer_time = settings.value("buffer_time",500).toUInt()*1000; + uint period_time = settings.value("period_time",100).toUInt()*1000; + settings.endGroup(); + + if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) + { + qWarning("OutputALSA: Error setting access."); + return; + } + + + if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE) < 0) + { + qDebug("OutputALSA: Error setting format."); + return; + } + + + exact_rate = rate;// = 11000; + qDebug("OutputALSA: frequency=%d, channels=%d, bitrate=%d", + rate, chan, brate); + if (snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &exact_rate, 0) < 0) + { + qWarning("OutputALSA: Error setting rate.\n"); + return; + } + if (rate != exact_rate) + { + qWarning("OutputALSA: The rate %d Hz is not supported by your hardware.\n==> Using %d Hz instead.", rate, exact_rate); + } + + uint c = m_channels; + if (snd_pcm_hw_params_set_channels_near(pcm_handle, hwparams, &c) < 0) + { + qWarning("OutputALSA: Error setting channels."); + return; + } + + if (snd_pcm_hw_params_set_period_time_near(pcm_handle, hwparams, + &period_time ,0) < 0 ) + { + qWarning("OutputALSA: Error setting HW buffer."); + return; + } + if (snd_pcm_hw_params_set_buffer_time_near(pcm_handle, hwparams, + &buffer_time ,0) < 0 ) + { + qWarning("Error setting HW buffer.\n"); + return; + } + if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) + { + qWarning("OutputALSA: Error setting HW params."); + return; + } + } +} + +void OutputALSA::reset() +{ + if (pcm_handle) + { + snd_pcm_close(pcm_handle); + pcm_handle = 0; + } + if (snd_pcm_open(&pcm_handle, pcm_name, stream, SND_PCM_NONBLOCK) < 0) + { + qWarning ("OutputALSA: Error opening PCM device %s", pcm_name); + return; + } +} + + +void OutputALSA::pause() +{ + if (!m_play) + return; + m_pause = (m_pause) ? FALSE : TRUE; + OutputState::Type state = m_pause ? OutputState::Paused: OutputState::Playing; + dispatch(state); +} + +bool OutputALSA::initialize() +{ + m_inited = m_pause = m_play = m_userStop = FALSE; + + if (!pcm_handle < 0) + return FALSE; + + m_currentSeconds = -1; + m_totalWritten = 0; + if (snd_pcm_open(&pcm_handle, pcm_name, stream, SND_PCM_NONBLOCK) < 0) + { + qWarning ("OutputALSA: Error opening PCM device %s", pcm_name); + return FALSE; + } + + m_inited = TRUE; + return TRUE; +} + + +long OutputALSA::latency() +{ + long used = 0; + + /*if (! m_pause) + { + if (ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &used) == -1) + used = 0; + }*/ + + return used; +} + +void OutputALSA::run() +{ + + mutex()->lock (); + if (! m_inited) + { + mutex()->unlock(); + return; + } + + m_play = TRUE; + + mutex()->unlock(); + + Buffer *b = 0; + bool done = FALSE; + unsigned long n = 0; + long m = 0; + snd_pcm_uframes_t l; + + dispatch(OutputState::Playing); + + while (! done) + { + mutex()->lock (); + recycler()->mutex()->lock (); + + done = m_userStop; + + while (! done && (recycler()->empty() || m_pause)) + { + mutex()->unlock(); + recycler()->cond()->wakeOne(); + recycler()->cond()->wait(recycler()->mutex()); + mutex()->lock (); + done = m_userStop; + status(); + } + + if (! b) + { + b = recycler()->next(); + if (b->rate) + m_rate = b->rate; + } + + recycler()->cond()->wakeOne(); + recycler()->mutex()->unlock(); + + if (b) + { + l = snd_pcm_bytes_to_frames(pcm_handle, b->nbytes - n); + while (l>0) + { + m = snd_pcm_writei (pcm_handle, b->data+n, l); + + if (m > 0) + { + n += snd_pcm_frames_to_bytes(pcm_handle, m); + l -= m; + status(); + dispatchVisual(b, m_totalWritten, m_channels, m_precision); + } + else if (m == -EAGAIN) + { + mutex()->unlock(); + snd_pcm_wait(pcm_handle, 500); + mutex()->lock (); + } + else if (m == -EPIPE) + { + qDebug ("OutputALSA: underrun!"); + if ((m = snd_pcm_prepare(pcm_handle)) < 0) + { + qDebug ("OutputALSA: Can't recover after underrun: %s", + snd_strerror(m)); + /* TODO: reopen the device */ + break; + } + } + else if (m == -ESTRPIPE) + { + qDebug ("OutputALSA: Suspend, trying to resume"); + while ((m = snd_pcm_resume(pcm_handle)) + == -EAGAIN) + sleep (1); + if (m < 0) + { + qDebug ("OutputALSA: Failed, restarting"); + if ((m = snd_pcm_prepare(pcm_handle)) + < 0) + { + qDebug ("OutputALSA: Failed to restart device: %s.", + snd_strerror(m)); + break; + } + } + } + else if (m < 0) + { + qDebug ("OutputALSA: Can't play: %s", snd_strerror(m)); + break; + } + } + status(); + // force buffer change + m_totalWritten += n; + n = b->nbytes; + m = 0; + } + if (n == b->nbytes) + { + recycler()->mutex()->lock (); + recycler()->done(); + recycler()->mutex()->unlock(); + b = 0; + n = 0; + } + mutex()->unlock(); + } + + mutex()->lock (); + + m_play = FALSE; + + dispatch(OutputState::Stopped); + + mutex()->unlock(); + +} + +void OutputALSA::uninitialize() +{ + if (!m_inited) + return; + m_inited = FALSE; + m_pause = FALSE; + m_play = FALSE; + m_userStop = FALSE; + m_totalWritten = 0; + m_currentSeconds = -1; + m_bps = -1; + m_frequency = -1; + m_channels = -1; + m_precision = -1; + if (pcm_handle) + { + qDebug("OutputALSA: closing pcm_handle"); + snd_pcm_close(pcm_handle); + pcm_handle = 0; + } + dispatch(OutputState::Stopped); +} +/* ****** MIXER ******* */ + +int OutputALSA::setupMixer(QString card, QString device) +{ + char *name; + long int a, b; + long alsa_min_vol = 0, alsa_max_vol = 100; + int err, index; + + qDebug("OutputALSA: setupMixer()"); + + if ((err = getMixer(&mixer, card)) < 0) + return err; + + parseMixerName(device.toAscii().data(), &name, &index); + + pcm_element = getMixerElem(mixer, name, index); + + free(name); + + if (!pcm_element) + { + qWarning("OutputALSA: Failed to find mixer element"); + return -1; + } + + /* This hack was copied from xmms. + * Work around a bug in alsa-lib up to 1.0.0rc2 where the + * new range don't take effect until the volume is changed. + * This hack should be removed once we depend on Alsa 1.0.0. + */ + snd_mixer_selem_get_playback_volume(pcm_element, + SND_MIXER_SCHN_FRONT_LEFT, &a); + snd_mixer_selem_get_playback_volume(pcm_element, + SND_MIXER_SCHN_FRONT_RIGHT, &b); + + snd_mixer_selem_get_playback_volume_range(pcm_element, + &alsa_min_vol, &alsa_max_vol); + snd_mixer_selem_set_playback_volume_range(pcm_element, 0, 100); + + if (alsa_max_vol == 0) + { + pcm_element = NULL; + return -1; + } + + setVolume(a * 100 / alsa_max_vol, b * 100 / alsa_max_vol); + + qDebug("OutputALSA: setupMixer() succes"); + + return 0; +} + +void OutputALSA::parseMixerName(char *str, char **name, int *index) +{ + char *end; + + while (isspace(*str)) + str++; + + if ((end = strchr(str, ',')) != NULL) + { + *name = strndup(str, end - str); + end++; + *index = atoi(end); + } + else + { + *name = strdup(str); + *index = 0; + } +} + +snd_mixer_elem_t* OutputALSA::getMixerElem(snd_mixer_t *mixer, char *name, int index) +{ + snd_mixer_selem_id_t* selem_id; + snd_mixer_elem_t* elem; + snd_mixer_selem_id_alloca(&selem_id); + + if (index != -1) + snd_mixer_selem_id_set_index(selem_id, index); + if (name != NULL) + snd_mixer_selem_id_set_name(selem_id, name); + + elem = snd_mixer_find_selem(mixer, selem_id); + + return elem; +} + +void OutputALSA::setVolume(int l, int r) +{ + + if (!pcm_element) + return; + + snd_mixer_selem_set_playback_volume(pcm_element, + SND_MIXER_SCHN_FRONT_LEFT, l); + snd_mixer_selem_set_playback_volume(pcm_element, + SND_MIXER_SCHN_FRONT_RIGHT, r); +} + +void OutputALSA::volume(int * l, int * r) +{ + if (!pcm_element) + return; + snd_mixer_handle_events(mixer); + snd_mixer_selem_get_playback_volume(pcm_element, + SND_MIXER_SCHN_FRONT_LEFT, (long int*)l); + snd_mixer_selem_get_playback_volume(pcm_element, + SND_MIXER_SCHN_FRONT_RIGHT, (long int*)r); +} + +int OutputALSA::getMixer(snd_mixer_t **mixer, QString card) +{ + char *dev; + int err; + + + dev = strdup(card.toAscii().data()); + + if ((err = snd_mixer_open(mixer, 0)) < 0) + { + qWarning("OutputALSA: Failed to open empty mixer: %s", + snd_strerror(-err)); + mixer = NULL; + return -1; + } + if ((err = snd_mixer_attach(*mixer, dev)) < 0) + { + qWarning("OutputALSA: Attaching to mixer %s failed: %s", + dev, snd_strerror(-err)); + return -1; + } + if ((err = snd_mixer_selem_register(*mixer, NULL, NULL)) < 0) + { + qWarning("OutputALSA: Failed to register mixer: %s", + snd_strerror(-err)); + return -1; + } + if ((err = snd_mixer_load(*mixer)) < 0) + { + qWarning("OutputALSA: Failed to load mixer: %s", + snd_strerror(-err)); + return -1; + } + + free(dev); + + return (*mixer != NULL); +} + + + diff --git a/src/plugins/Output/alsa/outputalsa.h b/src/plugins/Output/alsa/outputalsa.h new file mode 100644 index 000000000..f3dd222fe --- /dev/null +++ b/src/plugins/Output/alsa/outputalsa.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef OUTPUTALSA_H +#define OUTPUTALSA_H + +class OutputALSA; + +#include +#include +extern "C" { +#include +} +#if defined( Q_OS_WIN32 ) +#include +#include "constants.h" +#endif + + +class OutputALSA : public Output +{ +Q_OBJECT +public: + OutputALSA(QObject * parent = 0, bool useVolume = TRUE); + ~OutputALSA(); + + bool initialize(); + bool isInitialized() const { return m_inited; } + void uninitialize(); + void configure(long, int, int, int); + void stop(); + void pause(); + long written(); + long latency(); + void seek(long); + void setVolume(int l, int r); + void volume(int *l, int *r); + void checkVolume(); + +private: + // thread run function + void run(); + + // helper functions + void reset(); + void status(); + + bool m_inited, m_pause, m_play, m_userStop; + long m_totalWritten, m_currentSeconds, m_bps; + int m_rate, m_frequency, m_channels, m_precision; + //alsa + snd_pcm_t *pcm_handle; + snd_pcm_stream_t stream; + snd_pcm_hw_params_t *hwparams; + char *pcm_name; + //alsa + + //alsa mixer + int setupMixer(QString card, QString device); + void parseMixerName(char *str, char **name, int *index); + int getMixer(snd_mixer_t **mixer, QString card); + snd_mixer_elem_t* getMixerElem(snd_mixer_t *mixer, char *name, int index); + snd_mixer_t *mixer; + snd_mixer_elem_t *pcm_element; +}; + + +#endif // OUTPUTALSA_H diff --git a/src/plugins/Output/alsa/outputalsafactory.cpp b/src/plugins/Output/alsa/outputalsafactory.cpp new file mode 100644 index 000000000..641ff1278 --- /dev/null +++ b/src/plugins/Output/alsa/outputalsafactory.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "settingsdialog.h" +#include "outputalsa.h" +#include "outputalsafactory.h" + + +const OutputProperties OutputALSAFactory::properties() const +{ + OutputProperties properties; + properties.name = tr("ALSA Plugin"); + properties.hasAbout = TRUE; + properties.hasSettings = TRUE; + return properties; +} + +Output* OutputALSAFactory::create(QObject* parent, bool volume) +{ + return new OutputALSA(parent, volume); +} + +void OutputALSAFactory::showSettings(QWidget* parent) +{ + SettingsDialog *s = new SettingsDialog(parent); + s -> show(); +} + +void OutputALSAFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About ALSA Output Plugin"), + tr("Qmmp ALSA Output Plugin")+"\n"+ + tr("Writen by: Ilya Kotov ")); +} + +QTranslator *OutputALSAFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/alsa_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(OutputALSAFactory) diff --git a/src/plugins/Output/alsa/outputalsafactory.h b/src/plugins/Output/alsa/outputalsafactory.h new file mode 100644 index 000000000..afaa18358 --- /dev/null +++ b/src/plugins/Output/alsa/outputalsafactory.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef OUTPUTALSAFACTORY_H +#define OUTPUTALSAFACTORY_H + + +#include +#include +#include +#include + +#include +#include + + +class OutputALSAFactory : public QObject, + OutputFactory +{ +Q_OBJECT +Q_INTERFACES(OutputFactory); + +public: + const OutputProperties properties() const; + Output* create(QObject* parent, bool volume); + void showSettings(QWidget* parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); + +}; + +#endif diff --git a/src/plugins/Output/alsa/settingsdialog.cpp b/src/plugins/Output/alsa/settingsdialog.cpp new file mode 100644 index 000000000..89c6cae84 --- /dev/null +++ b/src/plugins/Output/alsa/settingsdialog.cpp @@ -0,0 +1,237 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +extern "C" +{ +#include +} + +#include "settingsdialog.h" + +SettingsDialog::SettingsDialog ( QWidget *parent ) + : QDialog ( parent ) +{ + ui.setupUi ( this ); + setAttribute ( Qt::WA_DeleteOnClose ); + ui.deviceComboBox->setEditable ( TRUE ); + getCards(); + connect (ui.deviceComboBox, SIGNAL(activated(int)),SLOT(setText(int))); + connect(ui.okButton, SIGNAL(clicked()), SLOT(writeSettings())); + connect(ui.mixerCardComboBox, SIGNAL(activated(int)), SLOT(showMixerDevices(int))); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("ALSA"); + ui.deviceComboBox->setEditText(settings.value("device","default").toString()); + ui.bufferSpinBox->setValue(settings.value("buffer_time",500).toInt()); + ui.periodSpinBox->setValue(settings.value("period_time",100).toInt()); + + int d = m_cards.indexOf(settings.value("mixer_card","hw:0").toString()); + if (d >= 0) + ui.mixerCardComboBox->setCurrentIndex(d); + + showMixerDevices(ui.mixerCardComboBox->currentIndex ()); + d = ui.mixerDeviceComboBox->findText(settings.value("mixer_device", + "PCM").toString()); + + if (d >= 0) + ui.mixerDeviceComboBox->setCurrentIndex(d); + + settings.endGroup(); +} + + +SettingsDialog::~SettingsDialog() +{} + +void SettingsDialog::getCards() +{ + int card = -1, err; + + m_devices.clear(); + m_devices << "default"; + ui.deviceComboBox->addItem("Default PCM device (default)"); + + if ((err = snd_card_next(&card)) !=0) + qWarning("SettingsDialog (ALSA): snd_next_card() failed: %s", + snd_strerror(-err)); + + while (card > -1) + { + getCardDevices(card); + m_cards << QString("hw:%1").arg(card); + if ((err = snd_card_next(&card)) !=0) + { + qWarning("SettingsDialog (ALSA): snd_next_card() failed: %s", + snd_strerror(-err)); + break; + } + } +} + +void SettingsDialog::getCardDevices(int card) +{ + int pcm_device = -1, err; + snd_pcm_info_t *pcm_info; + snd_ctl_t *ctl; + char dev[64], *card_name; + + sprintf(dev, "hw:%i", card); + + if ((err = snd_ctl_open(&ctl, dev, 0)) < 0) + { + qWarning("SettingsDialog (ALSA): snd_ctl_open() failed: %s", + snd_strerror(-err)); + return; + } + + if ((err = snd_card_get_name(card, &card_name)) != 0) + { + qWarning("SettingsDialog (ALSA): snd_card_get_name() failed: %s", + snd_strerror(-err)); + card_name = "Unknown soundcard"; + } + ui.mixerCardComboBox->addItem(QString(card_name)); + + snd_pcm_info_alloca(&pcm_info); + + qDebug("SettingsDialog (ALSA): detected sound cards:"); + + for (;;) + { + QString device; + if ((err = snd_ctl_pcm_next_device(ctl, &pcm_device)) < 0) + { + qWarning("SettingsDialog (ALSA): snd_ctl_pcm_next_device() failed: %s", + snd_strerror(-err)); + pcm_device = -1; + } + if (pcm_device < 0) + break; + + snd_pcm_info_set_device(pcm_info, pcm_device); + snd_pcm_info_set_subdevice(pcm_info, 0); + snd_pcm_info_set_stream(pcm_info, SND_PCM_STREAM_PLAYBACK); + + if ((err = snd_ctl_pcm_info(ctl, pcm_info)) < 0) + { + if (err != -ENOENT) + qWarning("SettingsDialog (ALSA): get_devices_for_card(): " + "snd_ctl_pcm_info() " + "failed (%d:%d): %s.", card, + pcm_device, snd_strerror(-err)); + } + device = QString("hw:%1,%2").arg(card).arg(pcm_device); + m_devices << device; + QString str; + str = QString(card_name) + ": "+ + snd_pcm_info_get_name(pcm_info)+" ("+device+")"; + qDebug(str.toAscii()); + ui.deviceComboBox->addItem(str); + } + + snd_ctl_close(ctl); +} + +void SettingsDialog::getMixerDevices(QString card) +{ + ui.mixerDeviceComboBox->clear(); + int err; + snd_mixer_t *mixer; + snd_mixer_elem_t *current; + + if ((err = getMixer(&mixer, card)) < 0) + return; + + current = snd_mixer_first_elem(mixer); + + while (current) + { + const char *sname = snd_mixer_selem_get_name(current); + if (snd_mixer_selem_is_active(current) && + snd_mixer_selem_has_playback_volume(current)) + ui.mixerDeviceComboBox->addItem(QString(sname)); + current = snd_mixer_elem_next(current); + } +} + +void SettingsDialog::setText(int n) +{ + ui.deviceComboBox->setEditText(m_devices.at(n)); +} + +void SettingsDialog::writeSettings() +{ + qDebug("SettingsDialog (ALSA):: writeSettings()"); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("ALSA"); + settings.setValue("device", ui.deviceComboBox->currentText ()); + settings.setValue("buffer_time",ui.bufferSpinBox->value()); + settings.setValue("period_time",ui.periodSpinBox->value()); + QString card = m_cards.at(ui.mixerCardComboBox->currentIndex()); + settings.setValue("mixer_card", card); + settings.setValue("mixer_device", ui.mixerDeviceComboBox->currentText ()); + settings.endGroup(); + accept(); +} + +int SettingsDialog::getMixer(snd_mixer_t **mixer, QString card) +{ + char *dev; + int err; + + dev = strdup(QString(card).toAscii().data()); + if ((err = snd_mixer_open(mixer, 0)) < 0) + { + qWarning("SettingsDialog (ALSA): alsa_get_mixer(): " + "Failed to open empty mixer: %s", snd_strerror(-err)); + mixer = NULL; + return -1; + } + if ((err = snd_mixer_attach(*mixer, dev)) < 0) + { + qWarning("SettingsDialog (ALSA): alsa_get_mixer(): " + "Attaching to mixer %s failed: %s", dev, snd_strerror(-err)); + return -1; + } + if ((err = snd_mixer_selem_register(*mixer, NULL, NULL)) < 0) + { + qWarning("SettingsDialog (ALSA): alsa_get_mixer(): " + "Failed to register mixer: %s", snd_strerror(-err)); + return -1; + } + if ((err = snd_mixer_load(*mixer)) < 0) + { + qWarning("SettingsDialog (ALSA): alsa_get_mixer(): Failed to load mixer: %s", + snd_strerror(-err)); + return -1; + } + + free (dev); + + return (*mixer != NULL); +} + +void SettingsDialog::showMixerDevices(int d) +{ + if (0<=d && d + +extern "C"{ +#include +} +//#include + +#include "ui_settingsdialog.h" + +/** + @author Ilya Kotov +*/ +class SettingsDialog : public QDialog +{ +Q_OBJECT +public: + SettingsDialog(QWidget *parent = 0); + + ~SettingsDialog(); + +private slots: + void setText(int); + void writeSettings(); + void showMixerDevices(int); + +private: + Ui::SettingsDialog ui; + void getCards(); + void getCardDevices(int card); + void getMixerDevices(QString card); + int getMixer(snd_mixer_t **mixer, QString card); + QStringList m_devices; + QList m_cards; + +}; + +#endif diff --git a/src/plugins/Output/alsa/settingsdialog.ui b/src/plugins/Output/alsa/settingsdialog.ui new file mode 100644 index 000000000..2f9a20753 --- /dev/null +++ b/src/plugins/Output/alsa/settingsdialog.ui @@ -0,0 +1,261 @@ + + SettingsDialog + + + + 0 + 0 + 403 + 300 + + + + ALSA Plugin Settings + + + + 9 + + + 6 + + + + + 0 + + + + Device Settings + + + + 9 + + + 6 + + + + + Audio device + + + + + 11 + 47 + 338 + 22 + + + + + + + + + Mixer + + + + 9 + + + 6 + + + + + + + + Mixer card: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Mixer device: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + + + Advanced Settings + + + + 9 + + + 6 + + + + + Soundcard + + + + 9 + + + 6 + + + + + Qt::Vertical + + + + 20 + 111 + + + + + + + + Qt::Horizontal + + + + 188 + 20 + + + + + + + + 5000 + + + 20 + + + 100 + + + + + + + 10000 + + + 200 + + + 500 + + + + + + + Buffer time (ms): + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Period time (ms): + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 188 + 20 + + + + + + + + + + + + + + + Qt::Horizontal + + + + 191 + 20 + + + + + + + + Cancel + + + + + + + OK + + + + + + + + + cancelButton + clicked() + SettingsDialog + reject() + + + 338 + 283 + + + 164 + 294 + + + + + diff --git a/src/plugins/Output/alsa/translations/alsa_plugin_cs.ts b/src/plugins/Output/alsa/translations/alsa_plugin_cs.ts new file mode 100644 index 000000000..3108490ec --- /dev/null +++ b/src/plugins/Output/alsa/translations/alsa_plugin_cs.ts @@ -0,0 +1,90 @@ + + + + + OutputALSAFactory + + + ALSA Plugin + Plugin ALSA + + + + About ALSA Output Plugin + O pluginu ALSA + + + + Qmmp ALSA Output Plugin + Výstupní plugin Qmmp ALSA + + + + Writen by: Ilya Kotov <forkotov02@hotmail.ru> + Autor: Ilja Kotov <forkotov02@hotmail.ru> + + + + SettingsDialog + + + ALSA Plugin Settings + Nastavení pluginu ALSA + + + + Device Settings + Nastavení zařízení + + + + Audio device + Zvukové zařízení + + + + Mixer + Mixér + + + + Mixer card: + Zvuková karta: + + + + Mixer device: + Ovládání hlasitosti: + + + + Advanced Settings + Pokročilá nastavení + + + + Soundcard + Zvuková karta + + + + Buffer time (ms): + Velikost bufferu (ms): + + + + Period time (ms): + Délka periody (ms): + + + + Cancel + Zrušit + + + + OK + OK + + + diff --git a/src/plugins/Output/alsa/translations/alsa_plugin_ru.qm b/src/plugins/Output/alsa/translations/alsa_plugin_ru.qm new file mode 100644 index 000000000..78ed38962 Binary files /dev/null and b/src/plugins/Output/alsa/translations/alsa_plugin_ru.qm differ diff --git a/src/plugins/Output/alsa/translations/alsa_plugin_ru.ts b/src/plugins/Output/alsa/translations/alsa_plugin_ru.ts new file mode 100644 index 000000000..2c7296750 --- /dev/null +++ b/src/plugins/Output/alsa/translations/alsa_plugin_ru.ts @@ -0,0 +1,89 @@ + + + + OutputALSAFactory + + + ALSA Plugin + Модуль ALSA + + + + About ALSA Output Plugin + О модуле вывода ALSA + + + + Qmmp ALSA Output Plugin + Модуль вывода ALSA для Qmmp + + + + Writen by: Ilya Kotov <forkotov02@hotmail.ru> + Разработчик: Илья Котов <forkotov02@hotmail.ru> + + + + SettingsDialog + + + Device Settings + Параметры устройства + + + + Audio device + Аудио устройство + + + + Mixer + Микшер + + + + Mixer card: + Карта микшера: + + + + Mixer device: + Устройство микшера: + + + + Advanced Settings + Дополнительные настройки + + + + Soundcard + Звуковая карта + + + + Buffer time (ms): + Время буферизации (мс): + + + + Period time (ms): + Время периода (мс): + + + + Cancel + Отмена + + + + OK + Применить + + + + ALSA Plugin Settings + Настройки модуля ALSA + + + diff --git a/src/plugins/Output/alsa/translations/translations.qrc b/src/plugins/Output/alsa/translations/translations.qrc new file mode 100644 index 000000000..beac1cd17 --- /dev/null +++ b/src/plugins/Output/alsa/translations/translations.qrc @@ -0,0 +1,6 @@ + + + + alsa_plugin_ru.qm + + diff --git a/src/plugins/Output/jack/CMakeLists.txt b/src/plugins/Output/jack/CMakeLists.txt new file mode 100644 index 000000000..665a6fb13 --- /dev/null +++ b/src/plugins/Output/jack/CMakeLists.txt @@ -0,0 +1,74 @@ +project(libjack) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +# libjack and taglib +PKGCONFIG(jack JACK_INCLUDE_DIR JACK_LINK_DIR JACK_LINK_FLAGS JACK_CFLAGS) +PKGCONFIG(samplerate SAMPLERATE_INCLUDE_DIR SAMPLERATE_LINK_DIR SAMPLERATE_LINK_FLAGS SAMPLERATE_CFLAGS) + + +IF(NOT JACK_LINK_FLAGS) + SET(JACK_LINK_FLAGS -ljack -lrt) +ENDIF(NOT JACK_LINK_FLAGS) + +IF(NOT SAMPLERATE_LINK_FLAGS) + SET(SAMPLERATE_LINK_FLAGS -lsamplerate) +ENDIF(NOT SAMPLERATE_LINK_FLAGS) + +include_directories(${JACK_INCLUDE_DIR} ${JACK_INCLUDE_DIR}) +link_directories(${SAMPLERATE_LINK_DIR} ${SAMPLERATE_LINK_DIR}) + +ADD_DEFINITIONS(${JACK_CFLAGS}) +ADD_DEFINITIONS(${SAMPLERATE_CFLAGS}) + + +SET(libjack_SRCS + outputjackfactory.cpp + outputjack.cpp + bio2jack.c +) + +SET(libjack_MOC_HDRS + outputjackfactory.h + outputjack.h + bio2jack.h +) + +SET(libjack_RCCS translations/translations.qrc) + +QT4_ADD_RESOURCES(libjack_RCC_SRCS ${libjack_RCCS}) + +QT4_WRAP_CPP(libjack_MOC_SRCS ${libjack_MOC_HDRS}) + + + +ADD_LIBRARY(jack SHARED ${libjack_SRCS} ${libjack_MOC_SRCS} ${libjack_RCC_SRCS}) +target_link_libraries(jack ${QT_LIBRARIES} -lqmmp ${JACK_LINK_FLAGS} ${SAMPLERATE_LINK_FLAGS}) +install(TARGETS jack DESTINATION ${LIB_DIR}/qmmp/Output PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) + diff --git a/src/plugins/Output/jack/bio2jack.c b/src/plugins/Output/jack/bio2jack.c new file mode 100644 index 000000000..aef7ea9b7 --- /dev/null +++ b/src/plugins/Output/jack/bio2jack.c @@ -0,0 +1,2635 @@ +/* + * Copyright 2003-2006 Chris Morgan + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); \ + fflush(OUTFILE); +#else +#define TRACE(...) +#endif + +#if DEBUG_OUTPUT +#define DEBUG(format,args...) fprintf(OUTFILE, "%s::%s(%d) "format, __FILE__, __FUNCTION__, __LINE__,##args); \ + fflush(OUTFILE); +#else +#define DEBUG(...) +#endif + +#if TRACE_CALLBACK +#define CALLBACK_TRACE(format,args...) fprintf(OUTFILE, "%s::%s(%d) "format, __FILE__, __FUNCTION__, __LINE__,##args); \ + fflush(OUTFILE); +#else +#define CALLBACK_TRACE(...) +#endif + +#if ENABLE_WARNINGS +#define WARN(format,args...) fprintf(OUTFILE, "WARN: %s::%s(%d) "format, __FILE__,__FUNCTION__,__LINE__,##args); \ + fflush(OUTFILE); +#else +#define WARN(...) +#endif + +#define ERR(format,args...) fprintf(OUTFILE, "ERR: %s::%s(%d) "format, __FILE__,__FUNCTION__,__LINE__,##args); \ + fflush(OUTFILE); + +#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 + +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 (only 8 & 16 are currently supported) */ + + 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 */ + + unsigned long latencyMS; /* latency in ms between writing and actual audio output of the written data */ + + 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]; + + if(pthread_mutex_lock(&drv->mutex) != 0) + ERR("lock returned an error\n"); + + /* 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 + */ + if(pthread_mutex_unlock(&drv->mutex) != 0) + ERR("lock returned an error\n"); +} + + +/* 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_16BIT 32767.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; + } +} + +/* 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 inline void +sample_silence_float(sample_t * dst, unsigned long nsamples) +{ + /* ALERT: signed sign-extension portability !!! */ + while(nsamples--) + { + *dst = 0; + dst++; + } +} + +static inline bool +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; + + unsigned int i; + int 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 %lu 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; + unsigned int i; + int 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 = (char *) malloc(snprintf + (our_client_name, 0, "%s_%d_%d%02d", client_name, getpid(), + drv->deviceID, drv->clientCtr + 1) + 1); + sprintf(our_client_name, "%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_new(our_client_name)) == 0) + { + /* try once more */ + TRACE("trying once more to jack_client_new"); + if((drv->client = jack_client_new(our_client_name)) == 0) + { + ERR("jack server not running?\n"); + free(our_client_name); + return ERR_OPENING_JACK; + } + } + + 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 */ + unsigned 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]); + } + } + } + } + + 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; + } + 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 */ + unsigned 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]); + } + } + } + + 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; + } + 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++) + free(drv->jack_port_name[i]); + 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, 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, + 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, + 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; + 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: + break; + default: + ERR("invalid bits_per_channel\n"); + return ERR_OPENING_JACK; + } + + /* 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"); + 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 == %d, MAX_OUTPUT_PORTS == %d\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 == %d, MAX_INPUT_PORTS == %d\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 %d names, need %d\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 = + (char **) malloc(sizeof(char *) * drv->jack_port_name_count); + for(i = 0; i < drv->jack_port_name_count; i++) + { + drv->jack_port_name[i] = 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->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)); + + int periodSize = jack_get_buffer_size(drv->client); + int periods = 0; + /* FIXME: maybe we should keep different latency values for input vs output? */ + if(drv->num_output_channels > 0) + { + periods = jack_port_get_total_latency(drv->client, + drv->output_port[0]) / periodSize; + drv->latencyMS = periodSize * periods * 1000 / (drv->jack_sample_rate * + (drv->bits_per_channel / 8 * + drv->num_output_channels)); + } + else if(drv->num_input_channels > 0) + { + periods = jack_port_get_total_latency(drv->client, + drv->input_port[0]) / periodSize; + drv->latencyMS = + periodSize * periods * 1000 / (drv->jack_sample_rate * + (drv->bits_per_channel / 8 * + drv->num_input_channels)); + } + + TRACE("drv->latencyMS == %ldms\n", drv->latencyMS); + + *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) free(drv->callback_buffer1); + drv->callback_buffer1 = 0; + + drv->callback_buffer2_size = 0; + if(drv->callback_buffer2) free(drv->callback_buffer2); + drv->callback_buffer2 = 0; + + drv->rw_buffer1_size = 0; + if(drv->rw_buffer1) 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; + } + + 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)); + + unsigned 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 %d but we only have %ld 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; + + char *type_str = "UNKNOWN type"; + + /* 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) + { + type_str = "WRITTEN"; + return_val = drv->client_bytes; + } else if(type == WRITTEN_TO_JACK) + { + type_str = "WRITTEN_TO_JACK"; + return_val = drv->written_client_bytes; + } else if(type == PLAYED) /* account for the elapsed time for the played_bytes */ + { + type_str = "PLAYED"; + 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; + + if(drv->pPlayPtr == 0 || drv->bytes_per_jack_output_frame == 0) return_val = 0; + + /* adjust from jack bytes to client bytes */ + 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; + + if(drv->pRecPtr == 0 || drv->bytes_per_jack_input_frame == 0) return_val = 0; + + /* adjust from jack bytes to client bytes */ + 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) + return_val = jack_port_get_total_latency(drv->client, drv->output_port[0]); + + TRACE("got latency of %ld frames\n", return_val); + + releaseDriver(drv); + return return_val; +} + +/* Get the latency, in frames, of jack */ +long +JACK_GetJackInputLatency(int deviceID) +{ + jack_driver_t *drv = getDriver(deviceID); + long return_val = 0; + + if(drv->client && drv->num_input_channels) + return_val = jack_port_get_total_latency(drv->client, drv->input_port[0]); + + 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) free(client_name); + + /* jack_client_name_size() is the max length of a client name, including + the terminating null. */ + int size = strlen(name) + 1; /* take into account the terminating null */ + if(size > jack_client_name_size()) + size = jack_client_name_size(); + + client_name = malloc(size); + if(client_name) + snprintf(client_name, size, "%s", name); + else + ERR("unable to allocate %d bytes for client_name\n", size); + } +} + +void +JACK_SetPortConnectionMode(enum JACK_PORT_CONNECTION_MODE mode) +{ + port_connection_mode = mode; +} diff --git a/src/plugins/Output/jack/bio2jack.h b/src/plugins/Output/jack/bio2jack.h new file mode 100644 index 000000000..f81a7c777 --- /dev/null +++ b/src/plugins/Output/jack/bio2jack.h @@ -0,0 +1,145 @@ +/* + * Copyright 2003-2004 Chris Morgan + * + * 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 + +#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_sample, 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, + 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 */ +long JACK_GetJackInputLatency(int deviceID); /* return the input 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/plugins/Output/jack/jack.pro b/src/plugins/Output/jack/jack.pro new file mode 100644 index 000000000..a943a5b3b --- /dev/null +++ b/src/plugins/Output/jack/jack.pro @@ -0,0 +1,33 @@ +include(../../plugins.pri) + +HEADERS += outputjackfactory.h \ + outputjack.h \ + bio2jack.h + +SOURCES += outputjackfactory.cpp \ + outputjack.cpp \ + bio2jack.c + +TARGET=$$PLUGINS_PREFIX/Output/jack +QMAKE_CLEAN =$$PLUGINS_PREFIX/Output/libjack.so + + +INCLUDEPATH += ../../../qmmp +QMAKE_LIBDIR += ../../../../lib +CONFIG += release \ +warn_on \ +thread \ +plugin \ +link_pkgconfig +TEMPLATE = lib +LIBS += -lqmmp +PKGCONFIG += jack samplerate +#TRANSLATIONS = translations/jack_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} + +target.path = $$LIB_DIR/qmmp/Output +INSTALLS += target diff --git a/src/plugins/Output/jack/outputjack.cpp b/src/plugins/Output/jack/outputjack.cpp new file mode 100644 index 000000000..c8d3ebe86 --- /dev/null +++ b/src/plugins/Output/jack/outputjack.cpp @@ -0,0 +1,208 @@ +#include +#include +#include +#include +#include + +#include "outputjack.h" +#include "constants.h" +#include "buffer.h" +#include "visual.h" + +#include +#include + +void OutputJACK::stop() +{ + m_userStop = TRUE; +} + +void OutputJACK::status() +{ + long ct = (m_totalWritten - latency()) / m_bps; + + if (ct < 0) + ct = 0; + + if (ct > m_currentSeconds) + { + m_currentSeconds = ct; + dispatch(m_currentSeconds, m_totalWritten, m_rate, + m_frequency, m_precision, m_channels); + } +} + +long OutputJACK::written() +{ + return m_totalWritten; +} + +void OutputJACK::seek(long pos) +{ + recycler()->mutex()->lock (); + recycler()->clear(); + recycler()->mutex()->unlock(); + + m_totalWritten = (pos * m_bps); + m_currentSeconds = -1; +} + +OutputJACK::OutputJACK(QObject * parent, bool useVolume) + : Output(parent), m_inited(FALSE), m_pause(FALSE), m_play(FALSE), + m_userStop(FALSE), m_totalWritten(0), m_currentSeconds(-1), + m_bps(-1), m_frequency(-1), m_channels(-1), m_precision(-1) +{ + JACK_Init(); +} + +OutputJACK::~OutputJACK() +{ + uninitialize(); +} + +void OutputJACK::configure(long freq, int chan, int prec, int brate) +{ + qDebug("OutputJACK: configure"); + m_precision = prec; + m_channels = chan; + m_frequency = freq; + m_bps = freq * chan * (prec / 8); + if(JACK_Open(&jack_device, prec, (unsigned long *)&freq, chan)) + { + m_configure = FALSE; + return; + } + else + m_configure = TRUE; + + qDebug("OutputJACK: configure end"); +} + +void OutputJACK::pause() +{ + m_pause = (m_pause) ? FALSE : TRUE; + { + int state = m_pause ? OutputState::Paused: OutputState::Playing; + dispatch(OutputState((OutputState::Type) state)); + } + +} + +bool OutputJACK::initialize() +{ + m_inited = m_pause = m_play = m_userStop = FALSE; + m_currentSeconds = -1; + m_totalWritten = 0; + if (m_inited) + m_inited = TRUE; + m_inited = TRUE; + m_configure = FALSE; + jack_options_t options = JackNullOption; + jack_status_t status; + jack_client_t *client = jack_client_open ("test_qmmp", options, &status, NULL); + if (client == NULL) + { + qDebug("jack_client_open() failed."); + if (status & JackServerFailed) + { + qDebug("Unable to connect to JACK server."); + } + return FALSE; + } + jack_client_close (client); + return TRUE; +} + +long OutputJACK::latency() +{ + ulong used = 0; + return used; +} + +void OutputJACK::run() +{ + mutex()->lock (); + if (! m_inited) + { + mutex()->unlock(); + return; + } + + m_play = TRUE; + Buffer *b = 0; + bool done = FALSE; + long m = 0; + unsigned long l; + + dispatch(OutputState::Playing); + + mutex()->unlock(); + while (!done&&m_configure) + { + mutex()->lock (); + recycler()->mutex()->lock (); + done = m_userStop; + + while (! done && (recycler()->empty() || m_pause)) + { + mutex()->unlock(); + recycler()->cond()->wakeOne(); + recycler()->cond()->wait(recycler()->mutex()); + mutex()->lock (); + done = m_userStop; + status(); + } + + if (! b) + { + b = recycler()->next(); + if (b->rate) + m_rate = b->rate; + } + + recycler()->cond()->wakeOne(); + recycler()->mutex()->unlock(); + + if (b) + { + l = int(b->nbytes); + unsigned char *buf = b->data; + m_totalWritten += l; + while (l > 0) + { + m = JACK_Write(jack_device, (unsigned char*)buf, l); + if (!m) + usleep(2000); + usleep(((m/m_channels)*100000)/m_frequency); + l-=m; + buf+=m; + } + + status(); + dispatchVisual(b, m_totalWritten, m_channels, m_precision); + } + recycler()->mutex()->lock (); + recycler()->done(); + recycler()->mutex()->unlock(); + b = 0; + mutex()->unlock(); + } + mutex()->lock (); + m_play = FALSE; + dispatch(OutputState::Stopped); + mutex()->unlock(); +} + +void OutputJACK::uninitialize() +{ + if (!m_inited) + return; + m_inited = FALSE; + m_inited = m_pause = m_play = m_userStop = FALSE; + m_currentSeconds = -1; + m_totalWritten = 0; + if (m_configure) + JACK_Close(jack_device); + dispatch(OutputState::Stopped); +} + diff --git a/src/plugins/Output/jack/outputjack.h b/src/plugins/Output/jack/outputjack.h new file mode 100644 index 000000000..e01ced315 --- /dev/null +++ b/src/plugins/Output/jack/outputjack.h @@ -0,0 +1,49 @@ +#ifndef OUTPUTJACK_H +#define OUTPUTJACK_H + +class OutputJACK; + +#include +#include +extern "C" +{ +#include +} + +#include "bio2jack.h" + +class OutputJACK : public Output +{ + Q_OBJECT +public: + OutputJACK(QObject * parent = 0, bool useVolume = TRUE); + ~OutputJACK(); + bool initialize(); + bool isInitialized() const + { + return m_inited; + } + void uninitialize(); + void configure(long, int, int, int); + void stop(); + void pause(); + long written(); + long latency(); + void seek(long); + +private: + // thread run function + void run(); + // helper functions + void status(); + QString audio_device; + bool m_inited, m_configure, m_pause, m_play, m_userStop; + long m_totalWritten, m_currentSeconds, m_bps; + int m_rate, m_frequency, m_channels, m_precision, jack_device; + bool do_select; + int audio_fd; +}; + + +#endif + diff --git a/src/plugins/Output/jack/outputjackfactory.cpp b/src/plugins/Output/jack/outputjackfactory.cpp new file mode 100644 index 000000000..b41ba4487 --- /dev/null +++ b/src/plugins/Output/jack/outputjackfactory.cpp @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (C) 2007 by Zhuravlev Uriy * + * stalkerg@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; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "outputjack.h" +#include "outputjackfactory.h" + + +const OutputProperties OutputJACKFactory::properties() const +{ + OutputProperties properties; + properties.name = tr("JACK Plugin"); + properties.hasAbout = TRUE; + properties.hasSettings = TRUE; + return properties; +} + +Output* OutputJACKFactory::create(QObject* parent, bool volume) +{ + return new OutputJACK(parent); +} + +void OutputJACKFactory::showSettings(QWidget*) +{ +} + +void OutputJACKFactory::showAbout(QWidget *parent) +{ +QMessageBox::about (parent, tr("About Jack Output Plugin"), + tr("Qmmp Jack Output Plugin")+"\n"+ + tr("Writen by: Yuriy Zhuravlev ")); +} + +QTranslator *OutputJACKFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/jack_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(OutputJACKFactory) diff --git a/src/plugins/Output/jack/outputjackfactory.h b/src/plugins/Output/jack/outputjackfactory.h new file mode 100644 index 000000000..cc27990f1 --- /dev/null +++ b/src/plugins/Output/jack/outputjackfactory.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef OUTPUTJACKFACTORY_H +#define OUTPUTJACKFACTORY_H + + +#include +#include +#include +#include + +#include +#include + + +class OutputJACKFactory : public QObject, + OutputFactory +{ +Q_OBJECT +Q_INTERFACES(OutputFactory); + +public: + const OutputProperties properties() const; + Output* create(QObject* parent, bool volume); + void showSettings(QWidget* parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); + +}; + +#endif diff --git a/src/plugins/Output/jack/translations/jack_plugin_ru.qm b/src/plugins/Output/jack/translations/jack_plugin_ru.qm new file mode 100644 index 000000000..4050034bc Binary files /dev/null and b/src/plugins/Output/jack/translations/jack_plugin_ru.qm differ diff --git a/src/plugins/Output/jack/translations/jack_plugin_ru.ts b/src/plugins/Output/jack/translations/jack_plugin_ru.ts new file mode 100644 index 000000000..6f5057529 --- /dev/null +++ b/src/plugins/Output/jack/translations/jack_plugin_ru.ts @@ -0,0 +1,26 @@ + + + + OutputJACKFactory + + + JACK Plugin + Модуль JACK + + + + About Jack Output Plugin + О модуле вывода Jack + + + + Qmmp Jack Output Plugin + Модуль вывода Jack для Qmmp + + + + Writen by: Yuriy Zhuravlev <slalkerg@gmail.com> + Разработчик: Юрий Журавлёв <slalkerg@gmail.com> + + + diff --git a/src/plugins/Output/jack/translations/translations.qrc b/src/plugins/Output/jack/translations/translations.qrc new file mode 100644 index 000000000..af9447328 --- /dev/null +++ b/src/plugins/Output/jack/translations/translations.qrc @@ -0,0 +1,6 @@ + + + + jack_plugin_ru.qm + + diff --git a/src/plugins/Output/oss/CMakeLists.txt b/src/plugins/Output/oss/CMakeLists.txt new file mode 100644 index 000000000..8ab6f8d88 --- /dev/null +++ b/src/plugins/Output/oss/CMakeLists.txt @@ -0,0 +1,67 @@ +project(liboss) + +cmake_minimum_required(VERSION 2.4.0) + + +INCLUDE(UsePkgConfig) +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + + + +include_directories(${JACK_INCLUDE_DIR} ${JACK_INCLUDE_DIR}) +link_directories(${SAMPLERATE_LINK_DIR} ${SAMPLERATE_LINK_DIR}) + +ADD_DEFINITIONS(${JACK_CFLAGS}) +ADD_DEFINITIONS(${SAMPLERATE_CFLAGS}) + + +SET(liboss_SRCS + outputossfactory.cpp + outputoss.cpp + settingsdialog.cpp +) + +SET(liboss_MOC_HDRS + outputossfactory.h + outputoss.h + settingsdialog.h +) + +#SET(libjack_RCCS translations/translations.qrc) + +QT4_ADD_RESOURCES(libjack_RCC_SRCS ${libjack_RCCS}) + +QT4_WRAP_CPP(liboss_MOC_SRCS ${liboss_MOC_HDRS}) + +SET(liboss_UIS + settingsdialog.ui +) + +QT4_WRAP_UI(liboss_UIS_H ${liboss_UIS}) + +ADD_LIBRARY(oss SHARED ${liboss_SRCS} ${liboss_MOC_SRCS} ${liboss_UIS_H}) +target_link_libraries(oss ${QT_LIBRARIES} -lqmmp ) +install(TARGETS oss DESTINATION ${LIB_DIR}/qmmp/Output PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) + diff --git a/src/plugins/Output/oss/oss.pro b/src/plugins/Output/oss/oss.pro new file mode 100644 index 000000000..e401f14b0 --- /dev/null +++ b/src/plugins/Output/oss/oss.pro @@ -0,0 +1,36 @@ +include(../../plugins.pri) +FORMS += settingsdialog.ui + +HEADERS += outputossfactory.h \ + outputoss.h \ + settingsdialog.h + + +SOURCES += outputossfactory.cpp \ + outputoss.cpp \ + settingsdialog.cpp + +TARGET=$$PLUGINS_PREFIX/Output/oss +QMAKE_CLEAN =$$PLUGINS_PREFIX/Output/liboss.so + + +INCLUDEPATH += ../../../qmmp +QMAKE_LIBDIR += ../../../../lib +CONFIG += release \ +warn_on \ +thread \ +plugin + +TEMPLATE = lib +LIBS += -lqmmp + +#TRANSLATIONS = translations/oss_plugin_ru.ts \ +# translations/oss_plugin_uk_UA.ts \ +# translations/oss_plugin_zh_CN.ts +#RESOURCES = translations/translations.qrc +isEmpty (LIB_DIR){ +LIB_DIR = /lib +} + +target.path = $$LIB_DIR/qmmp/Output +INSTALLS += target diff --git a/src/plugins/Output/oss/outputoss.cpp b/src/plugins/Output/oss/outputoss.cpp new file mode 100644 index 000000000..9c52ac777 --- /dev/null +++ b/src/plugins/Output/oss/outputoss.cpp @@ -0,0 +1,505 @@ +/*************************************************************************** + * Copyright (C) 2007 by Uriy Zhuravlev stalkerg@gmail.com * + * * + * Copyright (c) 2000-2001 Brad Hughes bhughes@trolltech.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. * + ***************************************************************************/ + +#include + +#include "outputoss.h" +#include "constants.h" +#include "buffer.h" +#include "visual.h" + +#include +#include +#include +#include +#include + +#include + +//extern Q_EXPORT QApplication* qApp; + + +void OutputOSS::stop() +{ + m_userStop = TRUE; +} + +void OutputOSS::status() +{ + long ct = (m_totalWritten - latency()) / m_bps; + + if (ct < 0) + ct = 0; + + if (ct > m_currentSeconds) + { + m_currentSeconds = ct; + dispatch(m_currentSeconds, m_totalWritten, m_rate, + m_frequency, m_precision, m_channels); + } +} + +long OutputOSS::written() +{ + return m_totalWritten; +} + +void OutputOSS::seek(long pos) +{ + recycler()->mutex()->lock(); + recycler()->clear(); + recycler()->mutex()->unlock(); + + m_totalWritten = (pos * m_bps); + m_currentSeconds = -1; +} + + +#include +#include +#include +#include + +#if defined(__FreeBSD__) +# include +#elif defined(__linux__) +# include +#elif defined(__bsdi__) +# include +#endif + + +OutputOSS::OutputOSS(QObject * parent) + : Output(parent), m_inited(FALSE), m_pause(FALSE), m_play(FALSE), + m_userStop(FALSE), + m_totalWritten(0), m_currentSeconds(-1), + m_bps(1), m_frequency(-1), m_channels(-1), m_precision(-1), + do_select(TRUE), + m_audio_fd(-1), m_mixer_fd(-1) +{ +QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); +m_master = true; +m_audio_device = settings.value("OSS/device","/dev/dsp").toString(); +m_mixer_device = settings.value("OSS/mixer_device","/dev/mixer").toString(); +openMixer(); +} + +OutputOSS::~OutputOSS() +{ + if (m_audio_fd > 0) + { + close(m_audio_fd); + m_audio_fd = -1; + } + if (m_mixer_fd > 0) + { + close(m_mixer_fd); + m_mixer_fd = -1; + } +} + +void OutputOSS::configure(long freq, int chan, int prec, int rate) +{ + // we need to configure + if (freq != m_frequency || chan != m_channels || prec != m_precision) { + // we have already configured, but are changing settings... + // reset the device + resetDSP(); + + m_frequency = freq; + m_channels = chan; + m_precision = prec; + + m_bps = freq * chan * (prec / 8); + + int p; + switch(prec) { + default: + case 16: +#if defined(AFMT_S16_NE) + p = AFMT_S16_NE; +#else + p = AFMT_S16_LE; +#endif + break; + + case 8: + p = AFMT_S8; + break; + + } + + ioctl(m_audio_fd, SNDCTL_DSP_SETFMT, &p); + ioctl(m_audio_fd, SNDCTL_DSP_SAMPLESIZE, &prec); + int stereo = (chan > 1) ? 1 : 0; + ioctl(m_audio_fd, SNDCTL_DSP_STEREO, &stereo); + ioctl(m_audio_fd, SNDCTL_DSP_SPEED, &freq); + } + + m_rate = rate; +} + + +void OutputOSS::reset() +{ + if (m_audio_fd > 0) + { + close(m_audio_fd); + m_audio_fd = -1; + } + + m_audio_fd = open(m_audio_device.toAscii(), O_WRONLY, 0); + + if (m_audio_fd < 0) + { + error(QString("OSSOutput: failed to open output device '%1'"). + arg(m_audio_device)); + return; + } + + int flags; + if ((flags = fcntl(m_audio_fd, F_GETFL, 0)) > 0) + { + flags &= O_NDELAY; + fcntl(m_audio_fd, F_SETFL, flags); + } + + fd_set afd; + FD_ZERO(&afd); + FD_SET(m_audio_fd, &afd); + struct timeval tv; + tv.tv_sec = 0l; + tv.tv_usec = 50000l; + do_select = (select(m_audio_fd + 1, 0, &afd, 0, &tv) > 0); + + if (m_audio_fd > 0) + { + close(m_mixer_fd); + m_mixer_fd = -1; + } + openMixer(); +} + +void OutputOSS::openMixer() +{ + if (m_mixer_fd != -1) + return; + + if ((m_mixer_fd = open(m_mixer_device.toAscii(), O_RDWR)) == -1) + { + return; + } + if (m_audio_fd < 0) + { + error(QString("OSSOutput: failed to open mixer device '%1'"). + arg(m_mixer_device)); + return; + } +} + +void OutputOSS::pause() +{ + m_pause = (m_pause) ? FALSE : TRUE; +} + +void OutputOSS::post() +{ + if (m_audio_fd < 1) + return; + + int unused; + ioctl(m_audio_fd, SNDCTL_DSP_POST, &unused); +} + +void OutputOSS::sync() +{ + if (m_audio_fd < 1) + return; + + int unused; + ioctl(m_audio_fd, SNDCTL_DSP_SYNC, &unused); +} + + +void OutputOSS::resetDSP() +{ + if (m_audio_fd < 1) + return; + + int unused; + ioctl(m_audio_fd, SNDCTL_DSP_RESET, &unused); +} + + +bool OutputOSS::initialize() +{ + m_inited = m_pause = m_play = m_userStop = FALSE; + + + reset(); + if (m_audio_fd < 0) + return FALSE; + if (m_mixer_fd < 0) + return FALSE; + + + m_currentSeconds = -1; + m_totalWritten = 0; + stat = OutputState::Stopped; + + m_inited = TRUE; + return TRUE; +} + +void OutputOSS::uninitialize() +{ + if (!m_inited) + return; + m_inited = FALSE; + m_pause = FALSE; + m_play = FALSE; + m_userStop = FALSE; + m_totalWritten = 0; + m_currentSeconds = -1; + m_bps = -1; + m_frequency = -1; + m_channels = -1; + m_precision = -1; + resetDSP(); + if (m_audio_fd > 0) + { + close(m_audio_fd); + m_audio_fd = -1; + } + if (m_audio_fd > 0) + { + close(m_mixer_fd); + m_mixer_fd = -1; + } + + qDebug("OutputOSS: uninitialize"); + dispatch(OutputState::Stopped); +} + +long OutputOSS::latency() +{ + ulong used = 0; + + if (! m_pause) + { + if (ioctl(m_audio_fd, SNDCTL_DSP_GETODELAY, &used) == -1) + used = 0; + } + + return used; +} + +void OutputOSS::run() +{ + mutex()->lock(); + + if (! m_inited) + { + mutex()->unlock(); + + return; + } + + m_play = TRUE; + + mutex()->unlock(); + + fd_set afd; + struct timeval tv; + Buffer *b = 0; + bool done = FALSE; + unsigned long n = 0, m = 0, l = 0; + + dispatch(OutputState::Playing); + + FD_ZERO(&afd); + + while (! done) { + mutex()->lock(); + + recycler()->mutex()->lock(); + + done = m_userStop; + + while (! done && (recycler()->empty() || m_pause)) { + post(); + + mutex()->unlock(); + + { + stat = m_pause ? OutputState::Paused : OutputState::Buffering; + OutputState e((OutputState::Type) stat); + dispatch(e); + } + + recycler()->cond()->wakeOne(); + recycler()->cond()->wait(recycler()->mutex()); + + mutex()->lock(); + done = m_userStop; + status(); + } + + if (! b) { + b = recycler()->next(); + if (b->rate) + m_rate = b->rate; + } + + recycler()->cond()->wakeOne(); + recycler()->mutex()->unlock(); + + FD_ZERO(&afd); + FD_SET(m_audio_fd, &afd); + // nice long poll timeout + tv.tv_sec = 5l; + tv.tv_usec = 0l; + + if (b && + (! do_select || (select(m_audio_fd + 1, 0, &afd, 0, &tv) > 0 && + FD_ISSET(m_audio_fd, &afd)))) { + l = qMin(int(2048), int(b->nbytes - n)); + if (l > 0) { + m = write(m_audio_fd, b->data + n, l); + n += m; + + status(); + dispatchVisual(b, m_totalWritten, m_channels, m_precision); + } else { + // force buffer change + n = b->nbytes; + m = 0; + } + } + + m_totalWritten += m; + + if (n == b->nbytes) { + recycler()->mutex()->lock(); + recycler()->done(); + recycler()->mutex()->unlock(); + + b = 0; + n = 0; + } + + mutex()->unlock(); + } + + mutex()->lock(); + + if (! m_userStop) + sync(); + resetDSP(); + + m_play = FALSE; + + dispatch(OutputState::Stopped); + mutex()->unlock(); +} + + +void OutputOSS::setVolume(int l, int r) +{ + int v, devs; + long cmd; + + ioctl(m_mixer_fd, SOUND_MIXER_READ_DEVMASK, &devs); + if ((devs & SOUND_MASK_PCM) && (m_master == false)) + cmd = SOUND_MIXER_WRITE_PCM; + else if ((devs & SOUND_MASK_VOLUME) && (m_master == true)) + cmd = SOUND_MIXER_WRITE_VOLUME; + else + { + //close(mifd); + return; + } + v = (r << 8) | l; + ioctl(m_mixer_fd, cmd, &v); +} + +void OutputOSS::volume(int *ll,int *rr) +{ + *ll = 0; + *rr = 0; + int cmd; + int v, devs; + + ioctl(m_mixer_fd, SOUND_MIXER_READ_DEVMASK, &devs); + if ((devs & SOUND_MASK_PCM) && (m_master == 0)) + cmd = SOUND_MIXER_READ_PCM; + else if ((devs & SOUND_MASK_VOLUME) && (m_master == 1)) + cmd = SOUND_MIXER_READ_VOLUME; + else + return; + + ioctl(m_mixer_fd, cmd, &v); + *ll = (v & 0xFF00) >> 8; + *rr = (v & 0x00FF); + + *ll = (*ll > 100) ? 100 : *ll; + *rr = (*rr > 100) ? 100 : *rr; + *ll = (*ll < 0) ? 0 : *ll; + *rr = (*rr < 0) ? 0 : *rr; +} + + +void OutputOSS::checkVolume() +{ + long ll = 0, lr = 0, cmd; + int v, devs; + + /* + * We dont show any errors if this fails, as this is called + * rather often + */ +// if (!open_mixer_device()) { + ioctl(m_mixer_fd, SOUND_MIXER_READ_DEVMASK, &devs); + if ((devs & SOUND_MASK_PCM) && (m_master == 0)) + cmd = SOUND_MIXER_READ_PCM; + else if ((devs & SOUND_MASK_VOLUME) && (m_master == 1)) + cmd = SOUND_MIXER_READ_VOLUME; + else + return; + + ioctl(m_mixer_fd, cmd, &v); + ll = (v & 0xFF00) >> 8; + lr = (v & 0x00FF); + + ll = (ll > 100) ? 100 : ll; + lr = (lr > 100) ? 100 : lr; + ll = (ll < 0) ? 0 : ll; + lr = (lr < 0) ? 0 : lr; + if (bl!=ll || br!=lr) + { + bl = ll; + br = lr; + dispatchVolume(ll,lr); + } +// } +} + + diff --git a/src/plugins/Output/oss/outputoss.h b/src/plugins/Output/oss/outputoss.h new file mode 100644 index 000000000..a2f260057 --- /dev/null +++ b/src/plugins/Output/oss/outputoss.h @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (C) 2007 by Uriy Zhuravlev stalkerg@gmail.com * + * * + * Copyright (c) 2000-2001 Brad Hughes bhughes@trolltech.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. * + ***************************************************************************/ + + +#ifndef OUTPUTOSS_H +#define OUTPUTOSS_H + +class OutputOSS; + +#include +#include + +class OutputOSS : public Output +{ +Q_OBJECT +public: + OutputOSS(QObject * parent = 0); + virtual ~OutputOSS(); + + bool isInitialized() const { return m_inited; } + bool initialize(); + void uninitialize(); + void configure(long, int, int, int); + void stop(); + void pause(); + long written(); + long latency(); + void seek(long); + void setVolume(int l, int r); + void volume(int* l,int* r); + void checkVolume(); + +private: + // thread run function + void run(); + + // helper functions + void reset(); + void resetDSP(); + void status(); + void post(); + void sync(); + void openMixer(); + + QString m_audio_device, m_mixer_device; + + bool m_inited, m_pause, m_play, m_userStop, m_master; + long m_totalWritten, m_currentSeconds, m_bps; + int stat; + int m_rate, m_frequency, m_channels, m_precision; + + bool do_select; + int m_audio_fd, m_mixer_fd; + long bl, br; +}; + + +#endif diff --git a/src/plugins/Output/oss/outputossfactory.cpp b/src/plugins/Output/oss/outputossfactory.cpp new file mode 100644 index 000000000..3fa8c07a2 --- /dev/null +++ b/src/plugins/Output/oss/outputossfactory.cpp @@ -0,0 +1,70 @@ +/*************************************************************************** + * Copyright (C) 2007 by Zhuravlev Uriy * + * stalkerg@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; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "settingsdialog.h" +#include "outputoss.h" +#include "outputossfactory.h" + + +const QString& OutputOSSFactory::name() const +{ + static QString name(tr("OSS Plugin")); + return name; +} + +Output* OutputOSSFactory::create(QObject* parent,bool) +{ + return new OutputOSS(parent); +} + +const OutputProperties OutputOSSFactory::properties() const +{ + OutputProperties properties; + properties.name = name(); + properties.hasAbout = TRUE; + properties.hasSettings = TRUE; + return properties; +} + +void OutputOSSFactory::showSettings(QWidget* parent) +{ + SettingsDialog *s = new SettingsDialog(parent); + s -> show(); +} + +void OutputOSSFactory::showAbout(QWidget *parent) +{ +QMessageBox::about (parent, tr("About OSS Output Plugin"), + tr("Qmmp OSS Output Plugin")+"\n"+ + tr("Writen by: Yuriy Zhuravlev ")+"\n"+ + tr("Based on code by:Brad Hughes ")); +} + +QTranslator *OutputOSSFactory::createTranslator(QObject *parent) +{ + QTranslator *translator = new QTranslator(parent); + QString locale = QLocale::system().name(); + translator->load(QString(":/oss_plugin_") + locale); + return translator; +} + +Q_EXPORT_PLUGIN(OutputOSSFactory) diff --git a/src/plugins/Output/oss/outputossfactory.h b/src/plugins/Output/oss/outputossfactory.h new file mode 100644 index 000000000..03166bb94 --- /dev/null +++ b/src/plugins/Output/oss/outputossfactory.h @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef OUTPUTOSSFACTORY_H +#define OUTPUTOSSFACTORY_H + + +#include +#include +#include +#include + +#include +#include + + +class OutputOSSFactory : public QObject, + OutputFactory +{ +Q_OBJECT +Q_INTERFACES(OutputFactory); + +public: + const QString& name() const; + Output* create(QObject* parent,bool); + void showSettings(QWidget* parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); + const OutputProperties properties() const; +}; + +#endif diff --git a/src/plugins/Output/oss/settingsdialog.cpp b/src/plugins/Output/oss/settingsdialog.cpp new file mode 100644 index 000000000..8d75b06eb --- /dev/null +++ b/src/plugins/Output/oss/settingsdialog.cpp @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (C) 2007 by Zhuravlev Uriy * + * stalkerg@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; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +#include "settingsdialog.h" + +SettingsDialog::SettingsDialog ( QWidget *parent ) + : QDialog ( parent ) +{ + ui.setupUi ( this ); + setAttribute ( Qt::WA_DeleteOnClose ); + connect(ui.okButton, SIGNAL(clicked()), SLOT(writeSettings())); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("OSS"); + ui.lineEdit->insert(settings.value("device","/dev/dsp").toString()); + ui.lineEdit_2->insert(settings.value("mixer_device","/dev/mixer").toString()); + ui.bufferSpinBox->setValue(settings.value("buffer_time",500).toInt()); + ui.periodSpinBox->setValue(settings.value("period_time",100).toInt()); + + settings.endGroup(); +} + + +SettingsDialog::~SettingsDialog() +{} + + + +void SettingsDialog::writeSettings() +{ + qDebug("SettingsDialog (OSS):: writeSettings()"); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("OSS"); + settings.setValue("device", ui.lineEdit->text()); + settings.setValue("buffer_time",ui.bufferSpinBox->value()); + settings.setValue("period_time",ui.periodSpinBox->value()); + settings.setValue("mixer_device", ui.lineEdit_2->text()); + settings.endGroup(); + accept(); +} + + diff --git a/src/plugins/Output/oss/settingsdialog.h b/src/plugins/Output/oss/settingsdialog.h new file mode 100644 index 000000000..fd75c5698 --- /dev/null +++ b/src/plugins/Output/oss/settingsdialog.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2007 by Zhuravlev Uriy * + * stalkerg@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; 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. * + ***************************************************************************/ +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include + + +#include "ui_settingsdialog.h" + +/** + @author Yuriy Zhuravlev +*/ +class SettingsDialog : public QDialog +{ +Q_OBJECT +public: + SettingsDialog(QWidget *parent = 0); + + ~SettingsDialog(); + +private slots: + void writeSettings(); + +private: + Ui::SettingsDialog ui; + +}; + +#endif diff --git a/src/plugins/Output/oss/settingsdialog.ui b/src/plugins/Output/oss/settingsdialog.ui new file mode 100644 index 000000000..ce1c40894 --- /dev/null +++ b/src/plugins/Output/oss/settingsdialog.ui @@ -0,0 +1,309 @@ + + SettingsDialog + + + + 0 + 0 + 422 + 334 + + + + OSS Plugin Settings + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + 6 + + + + + 0 + + + + Device Settings + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Audio device + + + + + + + + + + + + + + + + Mixer device + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + 6 + + + + + + + + + + + + + + + + Advanced Settings + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Soundcard + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + 6 + + + + + Qt::Vertical + + + + 20 + 111 + + + + + + + + Qt::Horizontal + + + + 188 + 20 + + + + + + + + 20 + + + 5000 + + + 100 + + + + + + + 200 + + + 10000 + + + 500 + + + + + + + Buffer time (ms): + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Period time (ms): + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 188 + 20 + + + + + + + + + + + + + + + PCM over Master + + + + + + + + + + + + + + Qt::Horizontal + + + + 191 + 20 + + + + + + + + Cancel + + + + + + + OK + + + + + + + + + cancelButton + clicked() + SettingsDialog + reject() + + + 338 + 283 + + + 164 + 294 + + + + + diff --git a/src/plugins/Output/oss/translations/oss_plugin_cs.ts b/src/plugins/Output/oss/translations/oss_plugin_cs.ts new file mode 100644 index 000000000..424d320e7 --- /dev/null +++ b/src/plugins/Output/oss/translations/oss_plugin_cs.ts @@ -0,0 +1,90 @@ + + + + + OutputOSSFactory + + + OSS Plugin + Plugin OSS + + + + About OSS Output Plugin + O pluginu OSS + + + + Qmmp OSS Output Plugin + Výstupní plugin Qmmp OSS + + + + Writen by: Yuriy Zhuravlev <slalkerg@gmail.com> + Autor: Jurij Žuravljov <slalkerg@gmail.com> + + + + Based on code by:Brad Hughes <bhughes@trolltech.com> + Založeno na kódu Brada Hughese <bhughes@trolltech.com> + + + + SettingsDialog + + + OSS Plugin Settings + Nastavení pluginu OSS + + + + Device Settings + Nastavení zařízení + + + + Audio device + Zvukové zařízení + + + + Mixer device + Ovládání hlasitosti + + + + Advanced Settings + Pokročilá nastavení + + + + Soundcard + Zvuková karta + + + + Buffer time (ms): + Velikost bufferu (ms): + + + + Period time (ms): + + + + + PCM over Master + + + + + Cancel + Zrušit + + + + OK + OK + + + diff --git a/src/plugins/Visual/CMakeLists.txt b/src/plugins/Visual/CMakeLists.txt new file mode 100644 index 000000000..df35bdf14 --- /dev/null +++ b/src/plugins/Visual/CMakeLists.txt @@ -0,0 +1,8 @@ +SET(USE_ANALYZER TRUE CACHE BOOL "enable/disable analyzer plugin") + +IF(USE_ANALYZER) +MESSAGE( STATUS "ANALYZER ON") +add_subdirectory(analyzer) +ELSE(USE_ANALYZER) +MESSAGE( STATUS "ANALYZER OFF") +ENDIF(USE_ANALYZER) diff --git a/src/plugins/Visual/Visual.pro b/src/plugins/Visual/Visual.pro new file mode 100644 index 000000000..e30196780 --- /dev/null +++ b/src/plugins/Visual/Visual.pro @@ -0,0 +1,3 @@ +TEMPLATE = subdirs + +SUBDIRS += analyzer diff --git a/src/plugins/Visual/analyzer/CMakeLists.txt b/src/plugins/Visual/analyzer/CMakeLists.txt new file mode 100644 index 000000000..7de2ca687 --- /dev/null +++ b/src/plugins/Visual/analyzer/CMakeLists.txt @@ -0,0 +1,70 @@ +project(libanalyzer) + +cmake_minimum_required(VERSION 2.4.0) + + + +INCLUDE(FindQt4) + +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt plugin +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(QT_INCLUDES + ${QT_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR}/../../../ +) + +# libqmmp +include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) +link_directories(${CMAKE_CURRENT_BINARY_DIR}/../../../) + +SET(libanalyzer_SRCS + analyzer.cpp + colorwidget.cpp + settingsdialog.cpp + visualanalyzerfactory.cpp + fft.c +) + +SET(libanalyzer_MOC_HDRS + analyzer.h + colorwidget.h + fft.h + inlines.h + settingsdialog.h + visualanalyzerfactory.h +) + +#SET(libanalyzer_RCCS translations/translations.qrc) + +#QT4_ADD_RESOURCES(libanalyzer_RCC_SRCS ${libanalyzer_RCCS}) + +QT4_WRAP_CPP(libanalyzer_MOC_SRCS ${libanalyzer_MOC_HDRS}) + +# user interface + + +SET(libanalyzer_UIS + settingsdialog.ui +) + +QT4_WRAP_UI(libanalyzer_UIS_H ${libanalyzer_UIS}) +# Don't forget to include output directory, otherwise +# the UI file won't be wrapped! +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +ADD_LIBRARY(analyzer SHARED ${libanalyzer_SRCS} ${libanalyzer_MOC_SRCS} ${libanalyzer_UIS_H} + ${libanalyzer_RCC_SRCS}) +target_link_libraries(analyzer ${QT_LIBRARIES} -lqmmp) +install(TARGETS analyzer DESTINATION ${LIB_DIR}/qmmp/Visual PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) + diff --git a/src/plugins/Visual/analyzer/analyzer.cpp b/src/plugins/Visual/analyzer/analyzer.cpp new file mode 100644 index 000000000..efcb8b7d7 --- /dev/null +++ b/src/plugins/Visual/analyzer/analyzer.cpp @@ -0,0 +1,308 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +//#include "skin.h" +#include "fft.h" +#include "inlines.h" +#include "analyzer.h" + + +Analyzer::Analyzer (QWidget *parent) + : Visual (parent), m_fps ( 20 ) +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + restoreGeometry(settings.value("Analyzer/geometry").toByteArray()); + setFixedSize(2*300-30,105); + m_pixmap = QPixmap (75,20); + m_timer = new QTimer (this); + connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout())); + m_nodes.clear(); + + clear(); + setWindowTitle (tr("Qmmp Analyzer")); + + double peaks_speed[] = { 0.05, 0.1, 0.2, 0.4, 0.8 }; + double analyzer_speed[] = { 1.2, 1.8, 2.2, 2.8, 2.4 }; + int intervals[] = { 20 , 40 , 100 , 200 }; + + m_peaks_falloff = + peaks_speed[settings.value("Analyzer/peaks_falloff", 3).toInt()-1]; + m_analyzer_falloff = + analyzer_speed[settings.value("Analyzer/analyzer_falloff", 3).toInt()-1]; + m_show_peaks = settings.value("Analyzer/show_peaks", TRUE).toBool(); + m_timer->setInterval(intervals[settings.value("Analyzer/refresh_rate", 2).toInt() - 1]); + m_color1.setNamedColor(settings.value("Analyzer/color1", "Green").toString()); + m_color2.setNamedColor(settings.value("Analyzer/color2", "Yellow").toString()); + m_color3.setNamedColor(settings.value("Analyzer/color3", "Red").toString()); + m_bgColor.setNamedColor(settings.value("Analyzer/bg_color", "Black").toString()); + m_peakColor.setNamedColor(settings.value("Analyzer/peak_color", "Cyan").toString()); +} + +Analyzer::~Analyzer() +{ + while (!m_nodes.isEmpty()) + m_nodes.removeFirst(); +} + +void Analyzer::clear() +{ + while (!m_nodes.isEmpty()) + m_nodes.removeFirst(); + for ( int i = 0; i< 75; ++i ) + { + m_intern_vis_data[i] = 0; + m_peaks[i] = 0; + } + update(); +} + +void Analyzer::add ( Buffer *b, unsigned long w, int c, int p ) +{ + if (!m_timer->isActive ()) + return; + long len = b->nbytes, cnt; + short *l = 0, *r = 0; + + len /= c; + len /= ( p / 8 ); + if ( len > 512 ) + len = 512; + cnt = len; + + if ( c == 2 ) + { + l = new short[len]; + r = new short[len]; + + if ( p == 8 ) + stereo16_from_stereopcm8 ( l, r, b->data, cnt ); + else if ( p == 16 ) + stereo16_from_stereopcm16 ( l, r, ( short * ) b->data, cnt ); + } + else if ( c == 1 ) + { + l = new short[len]; + + if ( p == 8 ) + mono16_from_monopcm8 ( l, b->data, cnt ); + else if ( p == 16 ) + mono16_from_monopcm16 ( l, ( short * ) b->data, cnt ); + } + else + len = 0; + + if (len) + m_nodes.append (new VisualNode (l, r, len, w)); +} + +void Analyzer::timeout() +{ + VisualNode *node = 0; + + if ( /*playing &&*/ output()) + { + //output()->mutex()->lock (); + //long olat = output()->latency(); + //long owrt = output()->written(); + //output()->mutex()->unlock(); + + //long synctime = owrt < olat ? 0 : owrt - olat; + + mutex()->lock (); + VisualNode *prev = 0; + while ((!m_nodes.isEmpty())) + { + node = m_nodes.takeFirst(); + /*if ( node->offset > synctime ) + break;*/ + + if (prev) + delete prev; + prev = node; + } + mutex()->unlock(); + node = prev; + } + + if (!node) + return; + process (node); + delete node; + update(); +} + +void Analyzer::paintEvent (QPaintEvent * e) +{ + QPainter painter (this); + painter.fillRect(e->rect(),m_bgColor); + draw(&painter); +} + +void Analyzer::hideEvent (QHideEvent *) +{ + m_timer->stop(); +} + +void Analyzer::showEvent (QShowEvent *) +{ + m_timer->start(); +} + +void Analyzer::closeEvent (QCloseEvent *event) +{ + //save geometry + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.setValue("Analyzer/geometry", saveGeometry()); + Visual::closeEvent(event); //removes visualization before class deleting +} + +bool Analyzer::process (VisualNode *node) +{ + static fft_state *state = 0; + if ( !state ) + state = fft_init(); + + short dest_l[256]; + short dest_r[256]; + + const int xscale_short[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 15, 20, 27, + 36, 47, 62, 82, 107, 141, 184, 255 + }; + + if ( node ) + { + //i = node->length; + calc_freq ( dest_l, node->left ); + if (node->right) + calc_freq ( dest_r, node->right ); + } + else + return FALSE; + const double y_scale = 3.60673760222; /* 20.0 / log(256) */ + int yl,yr, j; + + for (int i = 0; i < 19; i++) + { + yl = yr = 0; + + for ( j = xscale_short[i]; j < xscale_short[i + 1]; j++ ) + { + if ( dest_l[j] > yl ) + yl = dest_l[j]; + if ( dest_r[j] > yr && node->right) + yr = dest_r[j]; + } + yl >>= 7; + int magnitude_l = 0; + int magnitude_r = 0; + if (node->right) + { + yr >>= 7; + } + if (yl) + { + magnitude_l = int(log (yl) * y_scale); + if ( magnitude_l > 15 ) + magnitude_l = 15; + if ( magnitude_l < 0 ) + magnitude_l = 0; + } + if (yr && node->right) + { + magnitude_r = int(log (yr) * y_scale); + if ( magnitude_r > 15 ) + magnitude_r = 15; + if ( magnitude_r < 0 ) + magnitude_r = 0; + } + + m_intern_vis_data[i] -= m_analyzer_falloff; + m_intern_vis_data[i] = magnitude_l > m_intern_vis_data[i] + ? magnitude_l : m_intern_vis_data[i]; + if (node->right) + { + m_intern_vis_data[37-i] -= m_analyzer_falloff; + m_intern_vis_data[37-i] = magnitude_r > m_intern_vis_data[37-i] + ? magnitude_r : m_intern_vis_data[37-i]; + } + + if (m_show_peaks) + { + m_peaks[i] -= m_peaks_falloff; + m_peaks[i] = magnitude_l > m_peaks[i] + ? magnitude_l : m_peaks[i]; + if (node->right) + { + m_peaks[37-i] -= m_peaks_falloff; + m_peaks[37-i] = magnitude_r > m_peaks[37-i] + ? magnitude_r : m_peaks[37-i]; + } + } + } + return TRUE; +} + +void Analyzer::draw (QPainter *p) +{ + QBrush brush(Qt::SolidPattern); + for (int j = 0; j < 19; ++j) + { + for (int i = 0; i <= m_intern_vis_data[j]; ++i) + { + if (i <= 5) + brush.setColor(m_color1); + else if (i > 5 && i <= 10) + brush.setColor(m_color2); + else + brush.setColor(m_color3); + p->fillRect (j*15+1, height() - i*7, 12, 4, brush); + } + + for (int i = 0; i <= m_intern_vis_data[19+j]; ++i) + { + if (i <= 5) + brush.setColor(m_color1); + else if (i > 5 && i <= 10) + brush.setColor(m_color2); + else + brush.setColor(m_color3); + p->fillRect ((j+19)*15+1, height() - i*7, 12, 4, brush); + } + + if (m_show_peaks) + { + p->fillRect (j*15+1, height() - int(m_peaks[j])*7, 12, 4, m_peakColor); + p->fillRect ((j+19)*15+1, height() - int(m_peaks[j+19])*7, 12, 4, m_peakColor); + } + } +} diff --git a/src/plugins/Visual/analyzer/analyzer.h b/src/plugins/Visual/analyzer/analyzer.h new file mode 100644 index 000000000..ab08d3af0 --- /dev/null +++ b/src/plugins/Visual/analyzer/analyzer.h @@ -0,0 +1,102 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef ANALYZER_H +#define ANALYZER_H + +#include +#include +#include +#include +#include + +class QSettings; +class QTimer; +class QMenu; +class QActionGroup; + +class Buffer; + + +class VisualNode +{ +public: + VisualNode(short *l, short *r, unsigned long n, unsigned long o) + : left(l), right(r), length(n), offset(o) + { + // left and right are allocated and then passed to this class + // the code that allocated left and right should give up all ownership + } + + ~VisualNode() + { + delete [] left; + delete [] right; + } + + short *left, *right; + long length, offset; +}; + +class Analyzer : public Visual +{ + Q_OBJECT + +public: + Analyzer( QWidget *parent = 0); + virtual ~Analyzer(); + + void add(Buffer *, unsigned long, int, int); + void clear(); + void paintEvent( QPaintEvent * ); + +protected: + virtual void hideEvent (QHideEvent *); + virtual void showEvent (QShowEvent *); + virtual void closeEvent (QCloseEvent *); + +public slots: + void timeout(); + +private slots: + void updateSettings(); + +private: + bool process(VisualNode *node); + void draw(QPainter *p); + QPixmap m_pixmap; + QPixmap m_bg; + QList m_nodes; + QTimer *m_timer; + int m_fps; + double m_intern_vis_data[75]; + double m_peaks[75]; + double m_peaks_falloff; + double m_analyzer_falloff; + bool m_show_peaks; + //colors + QColor m_color1; + QColor m_color2; + QColor m_color3; + QColor m_bgColor; + QColor m_peakColor; +}; + + +#endif diff --git a/src/plugins/Visual/analyzer/analyzer.pro b/src/plugins/Visual/analyzer/analyzer.pro new file mode 100644 index 000000000..05d95a1ff --- /dev/null +++ b/src/plugins/Visual/analyzer/analyzer.pro @@ -0,0 +1,35 @@ +include(../../plugins.pri) + +TARGET=$$PLUGINS_PREFIX/Visual/analyzer +QMAKE_CLEAN =$$PLUGINS_PREFIX/Visual/libanalyzer.so + + +#FORMS += detailsdialog.ui +HEADERS += analyzer.h \ + fft.h \ + visualanalyzerfactory.h \ + inlines.h \ + colorwidget.h \ + settingsdialog.h +SOURCES += analyzer.cpp \ + fft.c \ + visualanalyzerfactory.cpp \ + colorwidget.cpp \ + settingsdialog.cpp +INCLUDEPATH += ../../../qmmp +CONFIG += release \ +warn_on \ +plugin +TEMPLATE = lib +QMAKE_LIBDIR += ../../../../lib +LIBS += -lqmmp -L/usr/lib -I/usr/include +#TRANSLATIONS = translations/ffmpeg_plugin_ru.ts +#RESOURCES = translations/translations.qrc + +isEmpty(LIB_DIR){ + LIB_DIR = /lib +} +target.path = $$LIB_DIR/qmmp/Visual +INSTALLS += target +FORMS += settingsdialog.ui + diff --git a/src/plugins/Visual/analyzer/colorwidget.cpp b/src/plugins/Visual/analyzer/colorwidget.cpp new file mode 100644 index 000000000..7117a6cac --- /dev/null +++ b/src/plugins/Visual/analyzer/colorwidget.cpp @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (C) 2005 by Ilya Kotov * + * qmmeter_freedevelop@mail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "colorwidget.h" + + +ColorWidget::ColorWidget(QWidget *parent) : QFrame(parent) +{ + setFrameShape(QFrame::Box); + setAutoFillBackground(TRUE); +} + + +ColorWidget::~ColorWidget() +{} + +void ColorWidget::mousePressEvent( QMouseEvent *) +{ + QColor color = QColorDialog::getColor(); + if (color.isValid()) + { + QPalette palette; + palette.setColor(this->backgroundRole(), color); + this->setPalette(palette); + } +} + +void ColorWidget::setColor(QString c) +{ + QPalette palette; + palette.setColor(this->backgroundRole(), c); + this->setPalette(palette); +} + +QString ColorWidget::colorName() +{ + QPalette palette; + palette = this->palette(); + return (palette.color(this->backgroundRole())).name(); +} diff --git a/src/plugins/Visual/analyzer/colorwidget.h b/src/plugins/Visual/analyzer/colorwidget.h new file mode 100644 index 000000000..c145c1035 --- /dev/null +++ b/src/plugins/Visual/analyzer/colorwidget.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2005 by Ilya Kotov * + * qmmeter_freedevelop@mail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef COLORWIDGET_H +#define COLORWIDGET_H + +#include +#include +#include + +/** +@author user +*/ +class ColorWidget : public QFrame +{ + Q_OBJECT +public: + ColorWidget(QWidget *parent = 0); + + ~ColorWidget(); + + QString colorName(); + +public slots: + void setColor (QString); + + +protected: + virtual void mousePressEvent ( QMouseEvent *); + + +}; + +#endif diff --git a/src/plugins/Visual/analyzer/fft.c b/src/plugins/Visual/analyzer/fft.c new file mode 100644 index 000000000..7ca1978a5 --- /dev/null +++ b/src/plugins/Visual/analyzer/fft.c @@ -0,0 +1,296 @@ +/* fft.c: Iterative implementation of a FFT + * Copyright (C) 1999 Richard Boulton + * Convolution stuff by Ralph Loader + * + * This program is free software; 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. + */ + +/* + * TODO + * Remove compiling in of FFT_BUFFER_SIZE? (Might slow things down, but would + * be nice to be able to change size at runtime.) + * Finish making / checking thread-safety. + * More optimisations. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "fft.h" + +//#include +#include +#include +#ifndef PI +#ifdef M_PI +#define PI M_PI +#else +#define PI 3.14159265358979323846 /* pi */ +#endif +#endif + +/* ########### */ +/* # Structs # */ +/* ########### */ + +struct _struct_fft_state { + /* Temporary data stores to perform FFT in. */ + float real[FFT_BUFFER_SIZE]; + float imag[FFT_BUFFER_SIZE]; +}; + +/* ############################# */ +/* # Local function prototypes # */ +/* ############################# */ + +static void fft_prepare(const sound_sample * input, float *re, float *im); +static void fft_calculate(float *re, float *im); +static void fft_output(const float *re, const float *im, float *output); +static int reverseBits(unsigned int initial); + +/* #################### */ +/* # Global variables # */ +/* #################### */ + +/* Table to speed up bit reverse copy */ +static unsigned int bitReverse[FFT_BUFFER_SIZE]; + +/* The next two tables could be made to use less space in memory, since they + * overlap hugely, but hey. */ +static float sintable[FFT_BUFFER_SIZE / 2]; +static float costable[FFT_BUFFER_SIZE / 2]; + +/* ############################## */ +/* # Externally called routines # */ +/* ############################## */ + +/* --------- */ +/* FFT stuff */ +/* --------- */ + +/* + * Initialisation routine - sets up tables and space to work in. + * Returns a pointer to internal state, to be used when performing calls. + * On error, returns NULL. + * The pointer should be freed when it is finished with, by fft_close(). + */ +fft_state * +fft_init(void) +{ + fft_state *state; + unsigned int i; + + state = (fft_state *) malloc(sizeof(fft_state)); + if (!state) + return NULL; + + for (i = 0; i < FFT_BUFFER_SIZE; i++) { + bitReverse[i] = reverseBits(i); + } + for (i = 0; i < FFT_BUFFER_SIZE / 2; i++) { + float j = 2 * PI * i / FFT_BUFFER_SIZE; + costable[i] = cos(j); + sintable[i] = sin(j); + } + + return state; +} + +/* + * Do all the steps of the FFT, taking as input sound data (as described in + * sound.h) and returning the intensities of each frequency as floats in the + * range 0 to ((FFT_BUFFER_SIZE / 2) * 32768) ^ 2 + * + * FIXME - the above range assumes no frequencies present have an amplitude + * larger than that of the sample variation. But this is false: we could have + * a wave such that its maximums are always between samples, and it's just + * inside the representable range at the places samples get taken. + * Question: what _is_ the maximum value possible. Twice that value? Root + * two times that value? Hmmm. Think it depends on the frequency, too. + * + * The input array is assumed to have FFT_BUFFER_SIZE elements, + * and the output array is assumed to have (FFT_BUFFER_SIZE / 2 + 1) elements. + * state is a (non-NULL) pointer returned by fft_init. + */ +void +fft_perform(const sound_sample * input, float *output, fft_state * state) +{ + /* Convert data from sound format to be ready for FFT */ + fft_prepare(input, state->real, state->imag); + + /* Do the actual FFT */ + fft_calculate(state->real, state->imag); + + /* Convert the FFT output into intensities */ + fft_output(state->real, state->imag, output); +} + +/* + * Free the state. + */ +void +fft_close(fft_state * state) +{ + if (state) + free(state); +} + +/* ########################### */ +/* # Locally called routines # */ +/* ########################### */ + +/* + * Prepare data to perform an FFT on + */ +static void +fft_prepare(const sound_sample * input, float *re, float *im) +{ + unsigned int i; + float *realptr = re; + float *imagptr = im; + + /* Get input, in reverse bit order */ + for (i = 0; i < FFT_BUFFER_SIZE; i++) { + *realptr++ = input[bitReverse[i]]; + *imagptr++ = 0; + } +} + +/* + * Take result of an FFT and calculate the intensities of each frequency + * Note: only produces half as many data points as the input had. + * This is roughly a consequence of the Nyquist sampling theorm thingy. + * (FIXME - make this comment better, and helpful.) + * + * The two divisions by 4 are also a consequence of this: the contributions + * returned for each frequency are split into two parts, one at i in the + * table, and the other at FFT_BUFFER_SIZE - i, except for i = 0 and + * FFT_BUFFER_SIZE which would otherwise get float (and then 4* when squared) + * the contributions. + */ +static void +fft_output(const float *re, const float *im, float *output) +{ + float *outputptr = output; + const float *realptr = re; + const float *imagptr = im; + float *endptr = output + FFT_BUFFER_SIZE / 2; + +#ifdef DEBUG + unsigned int i, j; +#endif + + while (outputptr <= endptr) { + *outputptr = (*realptr * *realptr) + (*imagptr * *imagptr); + outputptr++; + realptr++; + imagptr++; + } + /* Do divisions to keep the constant and highest frequency terms in scale + * with the other terms. */ + *output /= 4; + *endptr /= 4; + +#ifdef DEBUG + printf("Recalculated input:\n"); + for (i = 0; i < FFT_BUFFER_SIZE; i++) { + float val_real = 0; + float val_imag = 0; + for (j = 0; j < FFT_BUFFER_SIZE; j++) { + float fact_real = cos(-2 * j * i * PI / FFT_BUFFER_SIZE); + float fact_imag = sin(-2 * j * i * PI / FFT_BUFFER_SIZE); + val_real += fact_real * re[j] - fact_imag * im[j]; + val_imag += fact_real * im[j] + fact_imag * re[j]; + } + printf("%5d = %8f + i * %8f\n", i, + val_real / FFT_BUFFER_SIZE, val_imag / FFT_BUFFER_SIZE); + } + printf("\n"); +#endif +} + +/* + * Actually perform the FFT + */ +static void +fft_calculate(float *re, float *im) +{ + unsigned int i, j, k; + unsigned int exchanges; + float fact_real, fact_imag; + float tmp_real, tmp_imag; + unsigned int factfact; + + /* Set up some variables to reduce calculation in the loops */ + exchanges = 1; + factfact = FFT_BUFFER_SIZE / 2; + + /* Loop through the divide and conquer steps */ + for (i = FFT_BUFFER_SIZE_LOG; i != 0; i--) { + /* In this step, we have 2 ^ (i - 1) exchange groups, each with + * 2 ^ (FFT_BUFFER_SIZE_LOG - i) exchanges + */ + /* Loop through the exchanges in a group */ + for (j = 0; j != exchanges; j++) { + /* Work out factor for this exchange + * factor ^ (exchanges) = -1 + * So, real = cos(j * PI / exchanges), + * imag = sin(j * PI / exchanges) + */ + fact_real = costable[j * factfact]; + fact_imag = sintable[j * factfact]; + + /* Loop through all the exchange groups */ + for (k = j; k < FFT_BUFFER_SIZE; k += exchanges << 1) { + int k1 = k + exchanges; + /* newval[k] := val[k] + factor * val[k1] + * newval[k1] := val[k] - factor * val[k1] + **/ +#ifdef DEBUG + printf("%d %d %d\n", i, j, k); + printf("Exchange %d with %d\n", k, k1); + printf("Factor %9f + i * %8f\n", fact_real, fact_imag); +#endif + /* FIXME - potential scope for more optimization here? */ + tmp_real = fact_real * re[k1] - fact_imag * im[k1]; + tmp_imag = fact_real * im[k1] + fact_imag * re[k1]; + re[k1] = re[k] - tmp_real; + im[k1] = im[k] - tmp_imag; + re[k] += tmp_real; + im[k] += tmp_imag; +#ifdef DEBUG + for (k1 = 0; k1 < FFT_BUFFER_SIZE; k1++) { + printf("%5d = %8f + i * %8f\n", k1, real[k1], imag[k1]); + } +#endif + } + } + exchanges <<= 1; + factfact >>= 1; + } +} + +static int +reverseBits(unsigned int initial) +{ + unsigned int reversed = 0, loop; + for (loop = 0; loop < FFT_BUFFER_SIZE_LOG; loop++) { + reversed <<= 1; + reversed += (initial & 1); + initial >>= 1; + } + return reversed; +} diff --git a/src/plugins/Visual/analyzer/fft.h b/src/plugins/Visual/analyzer/fft.h new file mode 100644 index 000000000..431afa365 --- /dev/null +++ b/src/plugins/Visual/analyzer/fft.h @@ -0,0 +1,45 @@ +/* fft.h: Header for iterative implementation of a FFT + * Copyright (C) 1999 Richard Boulton + * + * This program is free software; 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. + */ + +#ifndef _FFT_H_ +#define _FFT_H_ + +#define FFT_BUFFER_SIZE_LOG 9 + +#define FFT_BUFFER_SIZE (1 << FFT_BUFFER_SIZE_LOG) + +/* sound sample - should be an signed 16 bit value */ +typedef short int sound_sample; + +#ifdef __cplusplus +extern "C" { +#endif + +/* FFT library */ + typedef struct _struct_fft_state fft_state; + fft_state *fft_init(void); + void fft_perform(const sound_sample * input, float *output, + fft_state * state); + void fft_close(fft_state * state); + + + +#ifdef __cplusplus +} +#endif +#endif /* _FFT_H_ */ diff --git a/src/plugins/Visual/analyzer/inlines.h b/src/plugins/Visual/analyzer/inlines.h new file mode 100644 index 000000000..3efccf0de --- /dev/null +++ b/src/plugins/Visual/analyzer/inlines.h @@ -0,0 +1,505 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#ifndef INLINES_H +#define INLINES_H + +#include "fft.h" + +// *fast* convenience functions +static inline void +calc_freq(short* dest, short *src) +{ + static fft_state *state = NULL; + float tmp_out[257]; + int i; + + if (!state) + state = fft_init(); + + fft_perform(src, tmp_out, state); + + for (i = 0; i < 256; i++) + dest[i] = ((int) sqrt(tmp_out[i + 1])) >> 8; +} + +static inline void +calc_mono_freq(short dest[2][256], short src[2][512], int nch) +{ + int i; + short *d, *sl, *sr, tmp[512]; + + if (nch == 1) + calc_freq(dest[0], src[0]); + else + { + d = tmp; + sl = src[0]; + sr = src[1]; + for (i = 0; i < 512; i++) + { + *(d++) = (*(sl++) + *(sr++)) >> 1; + } + calc_freq(dest[0], tmp); + } +} + +static inline void stereo16_from_stereopcm8(register short *l, + register short *r, + register uchar *c, + long cnt) +{ + while (cnt >= 4l) + { + l[0] = c[0]; + r[0] = c[1]; + l[1] = c[2]; + r[1] = c[3]; + l[2] = c[4]; + r[2] = c[5]; + l[3] = c[6]; + r[3] = c[7]; + l += 4; + r += 4; + c += 8; + cnt -= 4l; + } + + if (cnt > 0l) + { + l[0] = c[0]; + r[0] = c[1]; + if (cnt > 1l) + { + l[1] = c[2]; + r[1] = c[3]; + if (cnt > 2l) + { + l[2] = c[4]; + r[2] = c[5]; + } + } + } +} + + +static inline void stereo16_from_stereopcm16(register short *l, + register short *r, + register short *s, + long cnt) +{ + while (cnt >= 4l) + { + l[0] = s[0]; + r[0] = s[1]; + l[1] = s[2]; + r[1] = s[3]; + l[2] = s[4]; + r[2] = s[5]; + l[3] = s[6]; + r[3] = s[7]; + l += 4; + r += 4; + s += 8; + cnt -= 4l; + } + + if (cnt > 0l) + { + l[0] = s[0]; + r[0] = s[1]; + if (cnt > 1l) + { + l[1] = s[2]; + r[1] = s[3]; + if (cnt > 2l) + { + l[2] = s[4]; + r[2] = s[5]; + } + } + } +} + + +static inline void mono16_from_monopcm8(register short *l, + register uchar *c, + long cnt) +{ + while (cnt >= 4l) + { + l[0] = c[0]; + l[1] = c[1]; + l[2] = c[2]; + l[3] = c[3]; + l += 4; + c += 4; + cnt -= 4l; + } + + if (cnt > 0l) + { + l[0] = c[0]; + if (cnt > 1l) + { + l[1] = c[1]; + if (cnt > 2l) + { + l[2] = c[2]; + } + } + } +} + + +static inline void mono16_from_monopcm16(register short *l, + register short *s, + long cnt) +{ + while (cnt >= 4l) + { + l[0] = s[0]; + l[1] = s[1]; + l[2] = s[2]; + l[3] = s[3]; + l += 4; + s += 4; + cnt -= 4l; + } + + if (cnt > 0l) + { + l[0] = s[0]; + if (cnt > 1l) + { + l[1] = s[1]; + if (cnt > 2l) + { + l[2] = s[2]; + } + } + } +} + + +static inline void fast_short_set(register short *p, + short v, + long c) +{ + while (c >= 4l) + { + p[0] = v; + p[1] = v; + p[2] = v; + p[3] = v; + p += 4; + c -= 4l; + } + + if (c > 0l) + { + p[0] = v; + if (c > 1l) + { + p[1] = v; + if (c > 2l) + { + p[2] = v; + } + } + } +} + +#ifdef FFTW +static inline void fast_real_set(register fftw_real *p, + fftw_real v, + long c) +{ + while (c >= 4l) + { + p[0] = v; + p[1] = v; + p[2] = v; + p[3] = v; + p += 4; + c -= 4l; + } + + if (c > 0l) + { + p[0] = v; + if (c > 1l) + { + p[1] = v; + if (c > 2l) + { + p[2] = v; + } + } + } +} + +static inline void fast_complex_set(register fftw_complex *p, + fftw_complex v, + long c) +{ + while (c >= 4l) + { + p[0] = v; + p[1] = v; + p[2] = v; + p[3] = v; + p += 4; + c -= 4l; + } + + if (c > 0l) + { + p[0] = v; + if (c > 1l) + { + p[1] = v; + if (c > 2l) + { + p[2] = v; + } + } + } +} + + +static inline void fast_real_set_from_short(register fftw_real *d, + register short *s, + long c) +{ + while (c >= 4l) + { + d[0] = fftw_real(s[0]); + d[1] = fftw_real(s[1]); + d[2] = fftw_real(s[2]); + d[3] = fftw_real(s[3]); + d += 4; + s += 4; + c -= 4l; + } + + if (c > 0l) + { + d[0] = fftw_real(s[0]); + if (c > 1l) + { + d[1] = fftw_real(s[1]); + if (c > 2l) + { + d[2] = fftw_real(s[2]); + } + } + } +} + +static inline void fast_complex_set_from_short(register fftw_complex *d, + register short *s, + long c) +{ + while (c >= 4l) + { + d[0].re = fftw_real(s[0]); + d[0].im = 0; + d[1].re = fftw_real(s[1]); + d[1].im = 0; + d[2].re = fftw_real(s[2]); + d[2].im = 0; + d[3].re = fftw_real(s[3]); + d[3].im = 0; + d += 4; + s += 4; + c -= 4l; + } + + if (c > 0l) + { + d[0].re = fftw_real(s[0]); + d[0].im = 0; + if (c > 1l) + { + d[1].re = fftw_real(s[1]); + d[1].im = 0; + if (c > 2l) + { + d[2].re = fftw_real(s[2]); + d[2].im = 0; + } + } + } +} + + +static inline void fast_real_avg_from_shorts(register fftw_real *d, + register short *s1, + register short *s2, + long c) +{ + fftw_real t0, t1, t2, t3; + while (c >= 4l) + { + t0 = (s1[0] + s2[0]) / 2; + t1 = (s1[1] + s2[1]) / 2; + t2 = (s1[2] + s2[2]) / 2; + t3 = (s1[3] + s2[3]) / 2; + d[0] = t0; + d[1] = t1; + d[2] = t2; + d[3] = t3; + d += 4; + s1 += 4; + s2 += 4; + c -= 4l; + } + + if (c > 0l) + { + d[0] = fftw_real((s1[0] + s2[0]) / 2); + if (c > 1l) + { + d[1] = fftw_real((s1[1] + s2[1]) / 2); + if (c > 2l) + { + d[2] = fftw_real((s1[2] + s2[2]) / 2); + } + } + } +} + +static inline void fast_complex_avg_from_shorts(register fftw_complex *d, + register short *s1, + register short *s2, + long c) +{ + fftw_real t0, t1, t2, t3; + while (c >= 4l) + { + t0 = (s1[0] + s2[0]) / 2; + t1 = (s1[1] + s2[1]) / 2; + t2 = (s1[2] + s2[2]) / 2; + t3 = (s1[3] + s2[3]) / 2; + d[0].re = t0; + d[0].im = 0; + d[1].re = t1; + d[1].im = 0; + d[2].re = t2; + d[2].im = 0; + d[3].re = t3; + d[3].im = 0; + d += 4; + s1 += 4; + s2 += 4; + c -= 4l; + } + + if (c > 0l) + { + d[0].re = fftw_real((s1[0] + s2[0]) / 2); + d[0].im = 0; + if (c > 1l) + { + d[1].re = fftw_real((s1[1] + s2[1]) / 2); + d[1].im = 0; + if (c > 2l) + { + d[2].re = fftw_real((s1[2] + s2[2]) / 2); + d[2].im = 0; + } + } + } +} + + +static inline fftw_complex fftw_complex_from_real( fftw_real re ) +{ + fftw_complex c; + + c.re = re; + c.im = 0; + + return c; +} + +static inline void fast_reals_set(register fftw_real *p1, + register fftw_real *p2, + fftw_real v, + long c) +{ + while (c >= 4l) + { + p1[0] = v; + p1[1] = v; + p1[2] = v; + p1[3] = v; + p2[0] = v; + p2[1] = v; + p2[2] = v; + p2[3] = v; + p1 += 4; + p2 += 4; + c -= 4l; + } + + if (c > 0l) + { + p1[0] = v; + p2[0] = v; + if (c > 1l) + { + p1[1] = v; + p2[1] = v; + if (c > 2l) + { + p1[2] = v; + p2[2] = v; + } + } + } +} + +static inline void fast_complex_set(register fftw_complex *p1, + register fftw_complex *p2, + fftw_complex v, + long c) +{ + while (c >= 4l) + { + p1[0] = v; + p1[1] = v; + p1[2] = v; + p1[3] = v; + p2[0] = v; + p2[1] = v; + p2[2] = v; + p2[3] = v; + p1 += 4; + p2 += 4; + c -= 4l; + } + + if (c > 0l) + { + p1[0] = v; + p2[0] = v; + if (c > 1l) + { + p1[1] = v; + p2[1] = v; + if (c > 2l) + { + p1[2] = v; + p2[2] = v; + } + } + } +} +#endif // FFTW + +#endif // INLINES_H diff --git a/src/plugins/Visual/analyzer/settingsdialog.cpp b/src/plugins/Visual/analyzer/settingsdialog.cpp new file mode 100644 index 000000000..badadc190 --- /dev/null +++ b/src/plugins/Visual/analyzer/settingsdialog.cpp @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "settingsdialog.h" + +SettingsDialog::SettingsDialog(QWidget *parent) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, TRUE); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + ui.analyzerComboBox->setCurrentIndex(settings.value("Analyzer/analyzer_falloff", 3).toInt()-1); + ui.peaksCheckBox->setChecked(settings.value("Analyzer/show_peaks", TRUE).toBool()); + ui.peaksComboBox->setCurrentIndex(settings.value("Analyzer/peaks_falloff", 3).toInt()-1); + ui.fpsComboBox->setCurrentIndex(settings.value("Analyzer/refresh_rate", 2).toInt()-1); + ui.colorWidget1->setColor(settings.value("Analyzer/color1", "Green").toString()); + ui.colorWidget2->setColor(settings.value("Analyzer/color2", "Yellow").toString()); + ui.colorWidget3->setColor(settings.value("Analyzer/color3", "Red").toString()); + ui.bgColorWidget->setColor(settings.value("Analyzer/bg_color", "Black").toString()); + ui.peakColorWidget->setColor(settings.value("Analyzer/peak_color", "Cyan").toString()); + connect (ui.okButton, SIGNAL(clicked()),SLOT(writeSettings())); +} + + +SettingsDialog::~SettingsDialog() +{ +} + +void SettingsDialog::writeSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.setValue("Analyzer/analyzer_falloff", ui.analyzerComboBox->currentIndex() + 1); + settings.setValue("Analyzer/peaks_falloff", ui.peaksComboBox->currentIndex() + 1); + settings.setValue("Analyzer/refresh_rate", ui.fpsComboBox->currentIndex() + 1); + settings.setValue("Analyzer/show_peaks", ui.peaksCheckBox->isChecked()); + settings.setValue("Analyzer/color1", ui.colorWidget1->colorName()); + settings.setValue("Analyzer/color2", ui.colorWidget2->colorName()); + settings.setValue("Analyzer/color3", ui.colorWidget3->colorName()); + settings.setValue("Analyzer/bg_color", ui.bgColorWidget->colorName()); + settings.setValue("Analyzer/peak_color", ui.peakColorWidget->colorName()); + accept(); +} diff --git a/src/plugins/Visual/analyzer/settingsdialog.h b/src/plugins/Visual/analyzer/settingsdialog.h new file mode 100644 index 000000000..b7c466477 --- /dev/null +++ b/src/plugins/Visual/analyzer/settingsdialog.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +#include + +#include "ui_settingsdialog.h" + +/** + @author Ilya Kotov +*/ +class SettingsDialog : public QDialog +{ +Q_OBJECT +public: + SettingsDialog(QWidget *parent = 0); + + ~SettingsDialog(); + +private slots: + void writeSettings(); + +private: + Ui::SettingsDialog ui; + +}; + +#endif diff --git a/src/plugins/Visual/analyzer/settingsdialog.ui b/src/plugins/Visual/analyzer/settingsdialog.ui new file mode 100644 index 000000000..4ddd391a3 --- /dev/null +++ b/src/plugins/Visual/analyzer/settingsdialog.ui @@ -0,0 +1,403 @@ + + SettingsDialog + + + + 0 + 0 + 292 + 327 + + + + Analyzer Plugin Settings + + + + + + + 0 + 0 + + + + General + + + + + + Qt::LeftToRight + + + Show peaks + + + + + + + Analyzer falloff: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 2 + + + + Slowest + + + + + Slow + + + + + Medium + + + + + Fast + + + + + Fastest + + + + + + + + Peaks falloff: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 2 + + + + Slowest + + + + + Slow + + + + + Medium + + + + + Fast + + + + + Fastest + + + + + + + + Refresh rate: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 0 + + + + 50 FPS + + + + + 25 FPS + + + + + 10 FPS + + + + + 5 FPS + + + + + + + + + + + + 0 + 0 + + + + Colors + + + + + + Peaks: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + + + + Analyzer #1: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + + + + Background: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + + + + Analyzer #2: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + + + + Qt::Horizontal + + + + 111 + 20 + + + + + + + + Analyzer #3: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 20 + 20 + + + + + + + + + + + Qt::Horizontal + + + QSizePolicy::Minimum + + + + 95 + 29 + + + + + + + + + 0 + 0 + + + + + 16777215 + 30 + + + + &OK + + + + + + + + 0 + 0 + + + + + 16777215 + 30 + + + + &Cancel + + + + + + + + ColorWidget + QWidget +
colorwidget.h
+ 1 +
+
+ + + + cancelButton + clicked() + SettingsDialog + reject() + + + 220 + 286 + + + 276 + 309 + + + + +
diff --git a/src/plugins/Visual/analyzer/visualanalyzerfactory.cpp b/src/plugins/Visual/analyzer/visualanalyzerfactory.cpp new file mode 100644 index 000000000..0e110b2cd --- /dev/null +++ b/src/plugins/Visual/analyzer/visualanalyzerfactory.cpp @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "settingsdialog.h" +#include "visualanalyzerfactory.h" +#include "analyzer.h" + +const VisualProperties VisualAnalyzerFactory::properties() const +{ + VisualProperties properties; + properties.name = tr("Analyzer Plugin"); + return properties; +}; + +Visual *VisualAnalyzerFactory::create(QWidget *parent) +{ + return new Analyzer(parent); +}; + +void VisualAnalyzerFactory::showSettings(QWidget *parent) +{ + SettingsDialog *s = new SettingsDialog(parent); + s -> show(); +}; + +void VisualAnalyzerFactory::showAbout(QWidget *parent) +{ + QMessageBox::about (parent, tr("About Analyzer Visual Plugin"), + tr("Qmmp Analyzer Visual Plugin")+"\n"+ + tr("Writen by: Ilya Kotov ")); +}; + +QTranslator *VisualAnalyzerFactory::createTranslator(QObject *parent) +{ + return 0; +}; + +Q_EXPORT_PLUGIN(VisualAnalyzerFactory) diff --git a/src/plugins/Visual/analyzer/visualanalyzerfactory.h b/src/plugins/Visual/analyzer/visualanalyzerfactory.h new file mode 100644 index 000000000..54f52bfe2 --- /dev/null +++ b/src/plugins/Visual/analyzer/visualanalyzerfactory.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef VISUALANALYZERFACTORY_H +#define VISUALANALYZERFACTORY_H + + +#include + +#include +#include + +/** + @author Ilya Kotov +*/ +class VisualAnalyzerFactory : public QObject, public VisualFactory +{ +Q_OBJECT +Q_INTERFACES(VisualFactory); + +public: + const VisualProperties properties() const; + Visual *create(QWidget *parent); + void showSettings(QWidget *parent); + void showAbout(QWidget *parent); + QTranslator *createTranslator(QObject *parent); +}; + + +#endif diff --git a/src/plugins/plugins.pri b/src/plugins/plugins.pri new file mode 100644 index 000000000..e109b7b46 --- /dev/null +++ b/src/plugins/plugins.pri @@ -0,0 +1,2 @@ +include(../../qmmp.pri) +PLUGINS_PREFIX=../../../../lib/qmmp \ No newline at end of file diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro new file mode 100644 index 000000000..9be0dd332 --- /dev/null +++ b/src/plugins/plugins.pro @@ -0,0 +1,7 @@ + +SUBDIRS += Input \ + Output \ + Visual \ + Effect \ + General +TEMPLATE = subdirs diff --git a/src/positionbar.cpp b/src/positionbar.cpp deleted file mode 100644 index 5431fd4f3..000000000 --- a/src/positionbar.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include - -#include "skin.h" -#include "button.h" -#include "mainwindow.h" - -#include "positionbar.h" - - -PositionBar::PositionBar(QWidget *parent) - : PixmapWidget(parent) -{ - m_skin = Skin::getPointer(); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); - setPixmap(m_skin->getPosBar()); - mw = qobject_cast(window()); - m_moving = FALSE; - m_min = 0; - m_max = 50; - m_old = m_value = 0; - draw(FALSE); -} - - -PositionBar::~PositionBar() -{} - -void PositionBar::mousePressEvent(QMouseEvent *e) -{ - - m_moving = TRUE; - press_pos = e->x(); - if(m_posx() && e->x()x()-m_pos; - } - else - { - m_value = convert(qMax(qMin(width()-30,e->x()-15),0)); - press_pos = 15; - if (m_value!=m_old) - { - emit sliderMoved(m_value); - - } - } - draw(); -} - -void PositionBar::mouseMoveEvent (QMouseEvent *e) -{ - if(m_moving) - { - int po = e->x(); - po = po - press_pos; - - if(0<=po && po<=width()-30) - { - m_value = convert(po); - draw(); - emit sliderMoved(m_value); - } - } -} - -void PositionBar::mouseReleaseEvent(QMouseEvent*) -{ - m_moving = FALSE; - draw(FALSE); - if (m_value!=m_old) - { - m_old = m_value; - mw->seek(m_value); - } - -} - -void PositionBar::setValue(int v) -{ - if (m_moving || m_max == 0) - return; - m_value = v; - draw(FALSE); -} - -void PositionBar::setMax(int max) -{ - m_max = max; - draw(FALSE); -} - -void PositionBar::updateSkin() -{ - draw(FALSE); - //setPixmap(m_skin->getPosBar()); - //setButtonPixmap(Skin::BT_POSBAR_N); -} - -void PositionBar::draw(bool pressed) -{ - int p=int(ceil(double(m_value-m_min)*(width()-30)/(m_max-m_min))); - m_pixmap = m_skin->getPosBar(); - QPainter paint(&m_pixmap); - if(pressed) - paint.drawPixmap(p,0,m_skin->getButton(Skin::BT_POSBAR_P)); - else - paint.drawPixmap(p,0,m_skin->getButton(Skin::BT_POSBAR_N)); - setPixmap(m_pixmap); - m_pos = p; -} - -int PositionBar::convert(int p) -{ - return int(ceil(double(m_max-m_min)*(p)/(width()-30)+m_min)); -} diff --git a/src/positionbar.h b/src/positionbar.h deleted file mode 100644 index ea03ef14a..000000000 --- a/src/positionbar.h +++ /dev/null @@ -1,72 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef POSITIONBAR_H -#define POSITIONBAR_H - -#include "pixmapwidget.h" - -/** - @author Ilya Kotov -*/ - -class QMouseEvent; - -class MainWindow; -class Skin; - - -class PositionBar : public PixmapWidget -{ - Q_OBJECT -public: - PositionBar(QWidget *parent = 0); - - ~PositionBar(); - -public slots: - void setValue(int); - int value()const{return m_value;} - void setMax(int); - -signals: - void sliderMoved (int); - -private slots: - void updateSkin(); - -private: - Skin *m_skin; - bool m_moving; - int press_pos; - int m_max, m_min, m_pos, m_value, m_old; - QPixmap m_pixmap; - MainWindow *mw; - int convert(int); // value = convert(position); - void draw(bool pressed = TRUE); - -protected: - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); - - -}; - -#endif diff --git a/src/preseteditor.cpp b/src/preseteditor.cpp deleted file mode 100644 index 1b55a229d..000000000 --- a/src/preseteditor.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "eqpreset.h" - -#include "preseteditor.h" - -PresetEditor::PresetEditor(QWidget *parent) - : QDialog(parent) -{ - ui.setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - connect(ui.loadButton,SIGNAL(clicked()),SLOT(loadPreset())); - connect(ui.deleteButton,SIGNAL(clicked()),SLOT(deletePreset())); -} - - -PresetEditor::~PresetEditor() -{ - while (ui.presetListWidget->count () !=0) - ui.presetListWidget->takeItem (0); - - while (ui.autoPresetListWidget->count () !=0) - ui.autoPresetListWidget->takeItem (0); -} - -void PresetEditor::addPresets(const QList &presets) -{ - foreach(QListWidgetItem *item, presets) - { - ui.presetListWidget->addItem(item); - } -} - -void PresetEditor::addAutoPresets(const QList &presets) -{ - foreach(QListWidgetItem *item, presets) - { - ui.autoPresetListWidget->addItem(item); - } -} - -void PresetEditor::loadPreset() -{ - EQPreset* preset = 0; - if (ui.tabWidget->currentIndex () == 0) - preset = (EQPreset *) ui.presetListWidget->currentItem (); - if (ui.tabWidget->currentIndex () == 1) - preset = (EQPreset *) ui.autoPresetListWidget->currentItem (); - if (preset) - emit presetLoaded(preset); -} - -void PresetEditor::deletePreset() -{ - EQPreset* preset = 0; - if (ui.tabWidget->currentIndex () == 0) - preset = (EQPreset *) ui.presetListWidget->currentItem (); - if (ui.tabWidget->currentIndex () == 1) - preset = (EQPreset *) ui.autoPresetListWidget->currentItem (); - if (preset) - emit presetDeleted(preset); -} diff --git a/src/preseteditor.h b/src/preseteditor.h deleted file mode 100644 index 35302b185..000000000 --- a/src/preseteditor.h +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef PRESETEDITOR_H -#define PRESETEDITOR_H - -#include - -#include "ui_preseteditor.h" - -/** - @author Ilya Kotov -*/ - -class EQPreset; - -class PresetEditor : public QDialog -{ -Q_OBJECT -public: - PresetEditor(QWidget *parent = 0); - - ~PresetEditor(); - - void addPresets(const QList&); - void addAutoPresets(const QList&); - -signals: - void presetLoaded(EQPreset*); - void presetDeleted(EQPreset*); - -private slots: - void loadPreset(); - void deletePreset(); - -private: - Ui::PresetEditor ui; - -}; - -#endif diff --git a/src/preseteditor.ui b/src/preseteditor.ui deleted file mode 100644 index 2f88d6d53..000000000 --- a/src/preseteditor.ui +++ /dev/null @@ -1,88 +0,0 @@ - - PresetEditor - - - - 0 - 0 - 225 - 248 - - - - Preset Editor - - - false - - - - 9 - - - 6 - - - - - Load - - - - - - - Delete - - - - - - - 0 - - - - Preset - - - - 9 - - - 6 - - - - - - - - - Auto-preset - - - - 9 - - - 6 - - - - - QAbstractItemView::NoEditTriggers - - - - - - - - - - - qPixmapFromMimeSource - - - diff --git a/src/qmmp/CMakeLists.txt b/src/qmmp/CMakeLists.txt new file mode 100644 index 000000000..79edd7152 --- /dev/null +++ b/src/qmmp/CMakeLists.txt @@ -0,0 +1,68 @@ +project(libqmmp) + +cmake_minimum_required(VERSION 2.4.0) + +include(FindQt4) +find_package(Qt4 REQUIRED) # find and setup Qt4 for this project +include(${QT_USE_FILE}) + +# qt lib +ADD_DEFINITIONS( -Wall ) +ADD_DEFINITIONS(${QT_DEFINITIONS}) +#ADD_DEFINITIONS(-DQT_PLUGIN) +ADD_DEFINITIONS(-DQT_NO_DEBUG) +ADD_DEFINITIONS(-DQT_SHARED) +ADD_DEFINITIONS(-DQT_THREAD) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET(libqmmp_SRCS + visual.cpp + recycler.cpp + decoder.cpp + output.cpp + filetag.cpp + equ/iir.c + equ/iir_cfs.c + equ/iir_fpu.c + soundcore.cpp + streamreader.cpp + downloader.cpp + effect.cpp +) + +SET(libqmmp_MOC_HDRS + visual.h + recycler.h + buffer.h + constants.h + decoder.h + output.h + filetag.h + outputfactory.h + equ/iir_cfs.h + equ/iir_fpu.h + equ/iir.h + decoderfactory.h + soundcore.h + streamreader.h + downloader.h + effectfactory.h + effect.h +) + +QT4_WRAP_CPP(libqmmp_MOC_SRCS ${libqmmp_MOC_HDRS}) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES config.h) + +EXEC_PROGRAM(echo ${CMAKE_CURRENT_BINARY_DIR} ARGS "\"#ifndef CONFIG_H\"" > ./config.h) +EXEC_PROGRAM(echo ${CMAKE_CURRENT_BINARY_DIR} ARGS "\"#define CONFIG_H\"" >> ./config.h) +EXEC_PROGRAM(echo ${CMAKE_CURRENT_BINARY_DIR} ARGS "\"#define LIB_DIR \\\"/${LIB_DIR}\\\"\"" >> ./config.h) +EXEC_PROGRAM(echo ${CMAKE_CURRENT_BINARY_DIR} ARGS "\"#endif\"" >> ./config.h) + + +ADD_LIBRARY(qmmp SHARED ${libqmmp_SRCS} ${libqmmp_MOC_SRCS}) +target_link_libraries(qmmp ${QT_LIBRARIES} curl) +install(TARGETS qmmp LIBRARY DESTINATION ${LIB_DIR} PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) diff --git a/src/qmmp/buffer.h b/src/qmmp/buffer.h new file mode 100644 index 000000000..c5ffadc0c --- /dev/null +++ b/src/qmmp/buffer.h @@ -0,0 +1,44 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#ifndef __buffer_h +#define __buffer_h + +#include "constants.h" + +class Buffer +{ +public: + Buffer() + { + data = new unsigned char[Buffer::size()]; + nbytes = 0; + rate = 0; + exceeding = 0; + } + ~Buffer() + { + delete data; + data = 0; + nbytes = 0; + rate = 0; + exceeding = 0; + } + + unsigned char *data; + unsigned long nbytes; + unsigned long rate; + unsigned long exceeding; + + static unsigned long size() + { + return globalBlockSize; + } +}; + + +#endif // __buffer_h + diff --git a/src/qmmp/constants.h b/src/qmmp/constants.h new file mode 100644 index 000000000..ee558f3a9 --- /dev/null +++ b/src/qmmp/constants.h @@ -0,0 +1,19 @@ +#ifndef CONSTANTS_H +#define CONSTANTS_H + +#ifdef Q_OS_UNIX +#include "config.h" +#endif + +#define VERSION "0.2.0" + +#ifndef LIB_DIR +#define LIB_DIR "/lib" +#endif + +const unsigned int historySize = 100; +const unsigned int globalBlockSize = 2 * 1024; //2*1024 +const unsigned int globalBufferSize = globalBlockSize * 32; +const unsigned int groupOpenTimeout = 750; + +#endif // CONSTANTS_H diff --git a/src/qmmp/decoder.cpp b/src/qmmp/decoder.cpp new file mode 100644 index 000000000..f2dceba92 --- /dev/null +++ b/src/qmmp/decoder.cpp @@ -0,0 +1,409 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// +#include +#include +#include +#include +#include +#include + + +#include "effect.h" +#include "effectfactory.h" + +#include "constants.h" +#include "buffer.h" +#include "output.h" +#include "visual.h" +#include "decoderfactory.h" +#include "streamreader.h" +extern "C" +{ +#include "equ/iir.h" +} +#include "decoder.h" + + +Decoder::Decoder(QObject *parent, DecoderFactory *d, QIODevice *i, Output *o) + : QThread(parent), fctry(d), in(i), m_output(o),m_eqInited(FALSE), + m_useEQ(FALSE) +{ + m_output->recycler()->clear(); + int b[] = {0,0,0,0,0,0,0,0,0,0}; + setEQ(b, 0); + qRegisterMetaType("DecoderState"); + blksize = Buffer::size(); + m_effects = Effect::create(this); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + m_useVolume = settings.value("Volume/software_volume", FALSE).toBool(); + m_volL = settings.value("Volume/left", 80).toInt(); + m_volR = settings.value("Volume/right", 80).toInt(); +} + +Decoder::~Decoder() +{ + fctry = 0; + in = 0; + m_output = 0; + blksize = 0; +} + +// static methods + +static QList *factories = 0; +static QStringList files; +static QStringList blacklist; + +static void checkFactories() +{ + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + blacklist = settings.value("Decoder/disabled_plugins").toStringList (); + if (! factories) + { + files.clear(); + factories = new QList; + + QDir pluginsDir (qApp->applicationDirPath()); + pluginsDir.cdUp(); + pluginsDir.cd("./"LIB_DIR"/qmmp/Input"); + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) + { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (loader.isLoaded()) + { + qDebug("Decoder: plugin loaded - %s", qPrintable(fileName)); + } + DecoderFactory *factory = 0; + if (plugin) + factory = qobject_cast(plugin); + + if (factory) + { + factories->append(factory); + files << pluginsDir.absoluteFilePath(fileName); + } + } + //remove physically deleted plugins from blacklist + QStringList names; + foreach (QString filePath, files) + { + names.append(filePath.section('/',-1)); + } + int i = 0; + while (i < blacklist.size()) + { + if (!names.contains(blacklist.at(i))) + blacklist.removeAt(i); + else + i++; + } + settings.setValue("Decoder/disabled_plugins",blacklist); + } +} + + +QStringList Decoder::all() +{ + checkFactories(); + + QStringList l; + DecoderFactory *fact; + foreach(fact, *factories) + { + l << fact->properties().description; + } + return l; +} + +QStringList Decoder::decoderFiles() +{ + checkFactories(); + return files; +} + + +bool Decoder::supports(const QString &source) +{ + checkFactories(); + + for (int i=0; isize(); ++i) + { + if (factories->at(i)->supports(source) && + !blacklist.contains(files.at(i).section('/',-1))) + { + return TRUE; + } + } + return FALSE; +} + +Decoder *Decoder::create(QObject *parent, const QString &source, + QIODevice *input, + Output *output) +{ + Decoder *decoder = 0; + qDebug(qPrintable(source)); + DecoderFactory *fact = 0; + + if (!input->open(QIODevice::ReadOnly)) + { + qDebug("Decoder: cannot open input"); + return decoder; + } + StreamReader* sreader = qobject_cast(input); + if (sreader) + { + fact = Decoder::findByMime(sreader->contentType()); + if (!fact) + fact = Decoder::findByContent(sreader); + } + else + fact = Decoder::findByPath(source); + + if (fact) + { + decoder = fact->create(parent, input, output); + } + if (!decoder) + input->close(); + + return decoder; +} + +DecoderFactory *Decoder::findByPath(const QString& source) +{ + checkFactories(); + + for (int i=0; isize(); ++i) + { + if (factories->at(i)->supports(source) && + !blacklist.contains(files.at(i).section('/',-1))) + { + return factories->at(i); + } + } + qDebug("Decoder: unable to find factory by path"); + return 0; +} + +DecoderFactory *Decoder::findByMime(const QString& type) +{ + checkFactories(); + for (int i=0; isize(); ++i) + { + if (!blacklist.contains(files.at(i).section('/',-1))) + { + QStringList types = factories->at(i)->properties().contentType.split(";"); + for (int j=0; jat(i); + } + } + } + qDebug("Decoder: unable to find factory by mime"); + return 0; +} + +DecoderFactory *Decoder::findByContent(QIODevice *input) +{ + checkFactories(); + + for (int i=0; isize(); ++i) + { + if (factories->at(i)->canDecode(input) && + !blacklist.contains(files.at(i).section('/',-1))) + { + return factories->at(i); + } + } + qDebug("Decoder: unable to find factory by content"); + return 0; +} + +FileTag *Decoder::createTag(const QString& source) +{ + DecoderFactory *fact = Decoder::findByPath(source); + if (fact && QFile::exists(source)) + { + return fact->createTag(source); + } + return 0; +} + +QString Decoder::filter() +{ + QString allflt(tr("All Supported Bitstreams (")); + QString flt; + + checkFactories(); + DecoderFactory *fact; + for (int i = 0; isize(); ++i) + { + if (!blacklist.contains(files.at(i).section('/',-1))) + { + fact = (*factories)[i]; + allflt +=fact->properties().filter.toLower() +" "; + flt += fact->properties().description + " (" + fact->properties().filter + ")"; + flt += ";;"; + } + } + if (!flt.isEmpty ()) + flt = flt.left(flt.size ()-2); + + allflt += ");;"; + + return allflt + flt; +} + +QStringList Decoder::nameFilters() +{ + checkFactories(); + QStringList filters; + for (int i=0; isize(); ++i) + { + if (!blacklist.contains(files.at(i).section('/',-1))) + filters << factories->at(i)->properties().filter.split(" ", QString::SkipEmptyParts); + } + return filters; +} + +QList *Decoder::decoderFactories() +{ + checkFactories(); + return factories; +} + +void Decoder::dispatch(const DecoderState &st) +{ + emit stateChanged(st); +} + +void Decoder::dispatch(DecoderState::Type st) +{ + emit stateChanged(DecoderState(st)); +} + +void Decoder::dispatch(const FileTag &tag) +{ + emit stateChanged(DecoderState(tag)); +} + +void Decoder::error(const QString &e) +{ + emit stateChanged(DecoderState(e)); +} + +ulong Decoder::produceSound(char *data, ulong output_bytes, ulong bitrate, int nch) +{ + ulong sz = output_bytes < blksize ? output_bytes : blksize; + + if (m_useEQ) + { + if (!m_eqInited) + { + init_iir(); + m_eqInited = TRUE; + } + iir((void*) data,sz,nch); + } + if (m_useVolume) + { + changeVolume(data, sz, nch); + } + char *out_data = data; + char *prev_data = data; + ulong w = sz; + Effect* effect = 0; + foreach(effect, m_effects) + { + w = effect->process(prev_data, sz, &out_data); + + if (w <= 0) + { + // copy data if plugin can not procees it + w = sz; + out_data = new char[w]; + memcpy(out_data, prev_data, w); + } + if (data != prev_data) + delete prev_data; + prev_data = out_data; + } + + Buffer *b = output()->recycler()->get(w); + + memcpy(b->data, out_data, w); + + if (data != out_data) + delete out_data; + + if (w < blksize + b->exceeding) + memset(b->data + w, 0, blksize + b->exceeding - w); + + b->nbytes = w;// blksize; + b->rate = bitrate; + + output()->recycler()->add(); + + output_bytes -= sz; + memmove(data, data + sz, output_bytes); + return sz; +} + +void Decoder::configure(long freq, int channels, int prec, int bitrate) +{ + Effect* effect = 0; + foreach(effect, m_effects) + { + effect->configure(freq, channels, prec); + freq = m_effects.at(0)->frequency(); + channels = effect->channels(); + prec = effect->resolution(); + } + if (m_output) + m_output->configure(freq, channels, prec, bitrate); +} + +void Decoder::setEQ(int bands[10], int preamp) +{ + set_preamp(0, 1.0 + 0.0932471 *preamp + 0.00279033 * preamp * preamp); + set_preamp(1, 1.0 + 0.0932471 *preamp + 0.00279033 * preamp * preamp); + for (int i=0; i<10; ++i) + { + int value = bands[i]; + set_gain(i,0, 0.03*value+0.000999999*value*value); + set_gain(i,1, 0.03*value+0.000999999*value*value); + } +} + +void Decoder::changeVolume(char *data, ulong sz, int channels) +{ + int r = pow( 10, (m_volR - 100)/40.0 ) * 256; + int l = pow( 10, (m_volL - 100)/40.0 ) * 256; + for (ulong i = 0; i < sz/2; i+=2) + { + ((short*)data)[i]*= r/256.0; + ((short*)data)[i+1]*= l/256.0; + } +} + +void Decoder::setVolume(int l, int r) +{ + mtx.lock(); + m_volR = l; + m_volL = r; + mtx.unlock(); +} + +void Decoder::volume(int *l, int *r) +{ + mtx.lock(); + *l = m_volL; + *r = m_volR; + mtx.unlock(); +} diff --git a/src/qmmp/decoder.h b/src/qmmp/decoder.h new file mode 100644 index 000000000..31d96cc6d --- /dev/null +++ b/src/qmmp/decoder.h @@ -0,0 +1,197 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#ifndef DECODER_H +#define DECODER_H + +#include +#include +#include +#include +#include +#include + +#include "filetag.h" + +class QObject; +class QIODevice; + +class Decoder; +class DecoderFactory; +class Buffer; +class Recycler; +class Output; +class Visualization; +class Effect; + + + +class DecoderState +{ +public: + enum Type { Decoding, Stopped, Finished, Info, Error }; + + DecoderState(const DecoderState &st) + : m_error_msg(0), m_tag(0) + { + m_type = st.type(); + if (m_type == Info) + m_tag = new FileTag(*st.tag()); + else if (m_type == Error) + m_error_msg = new QString(*st.errorMessage()); + } + + + DecoderState(Type t) + : m_type(t), m_error_msg(0), m_tag(0) +{} + + DecoderState(const QString &e) + : m_type(Error), m_tag(0) + { + m_error_msg = new QString(e); + } + + DecoderState() + : m_type(Stopped), m_error_msg(0), m_tag(0) + {} + + DecoderState(const FileTag &tag) + : m_type(Info), m_error_msg(0), m_tag(0) + { + m_tag = new FileTag(tag); + } + + ~DecoderState() + { + if (m_error_msg) + delete m_error_msg; + if (m_tag) + delete m_tag; + } + + const QString *errorMessage() const + { + return m_error_msg; + } + const Type &type() const + { + return m_type; + } + const FileTag *tag() const + { + return m_tag; + } + +private: + Type m_type; + const QString *m_error_msg; + FileTag *m_tag; +}; + + + +class Decoder : public QThread +{ + Q_OBJECT +public: + Decoder(QObject *parent, DecoderFactory *d, + QIODevice *i, Output *o); + virtual ~Decoder(); + + // Standard Decoder API + virtual bool initialize() = 0; + virtual double lengthInSeconds() = 0; + virtual void seek(double) = 0; + virtual void stop() = 0; + + DecoderFactory *factory() const + { + return fctry; + } + + QIODevice *input() + { + return in; + } + Output *output() + { + return m_output; + } + + QMutex *mutex() + { + return &mtx; + } + QWaitCondition *cond() + { + return &cnd; + } + + void setBlockSize(unsigned int sz) + { + blksize = sz; + } + + unsigned int blockSize() const + { + return blksize; + } + ulong produceSound(char *data, ulong output_bytes, ulong bitrate, int nch); + void setEQ(int bands[10], int preamp); + void setEQEnabled(bool on) + { + m_useEQ = on; + }; + void setVolume(int, int); + + void volume(int*, int*); + + // static methods + static QStringList all(); + static bool supports(const QString &); + //static void registerFactory(DecoderFactory *); + static Decoder *create(QObject *, const QString &, QIODevice *, Output *); + static DecoderFactory *findByPath(const QString&); + static DecoderFactory *findByMime(const QString&); + static DecoderFactory *findByContent(QIODevice *); + static FileTag *createTag(const QString&); + static QString filter(); + static QStringList nameFilters(); + static QList *decoderFactories(); + static QStringList decoderFiles(); + +signals: + void stateChanged(const DecoderState&); + +protected: + void configure(long freq, int channels, int prec, int bitrate); + void dispatch(DecoderState::Type); + void dispatch(const DecoderState&); + void dispatch(const FileTag&); + void error(const QString&); + +private: + DecoderFactory *fctry; + void changeVolume(char *data, ulong sz, int channels); + + QList m_effects; + QIODevice *in; + Output *m_output; + + QMutex mtx; + QWaitCondition cnd; + + uint blksize; + bool m_eqInited; + bool m_useEQ; + bool m_useVolume; + int m_volL; + int m_volR; + +}; + +#endif // DECODER_H diff --git a/src/qmmp/decoderfactory.h b/src/qmmp/decoderfactory.h new file mode 100644 index 000000000..d67d1b564 --- /dev/null +++ b/src/qmmp/decoderfactory.h @@ -0,0 +1,64 @@ + +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef DECODERFACTORY_H +#define DECODERFACTORY_H + +class QObject; +class QString; +class QIODevice; +class QWidget; +class QTranslator; + +class Decoder; +class Output; +class FileTag; + +struct DecoderProperties +{ + QString name; + QString filter; + QString description; + QString contentType; + bool hasAbout; + bool hasSettings; + //bool streamSupport; + //bool needInput; +}; + +class DecoderFactory +{ +public: + virtual ~DecoderFactory() {} + virtual bool supports(const QString &source) const = 0; + virtual bool canDecode(QIODevice *) const = 0; + virtual const DecoderProperties properties() const = 0; + virtual Decoder *create(QObject *, QIODevice *, Output *) = 0; + virtual FileTag *createTag(const QString &source) = 0; + virtual QObject* showDetails(QWidget *parent, const QString &path) = 0; + virtual void showSettings(QWidget *parent) = 0; + virtual void showAbout(QWidget *parent) = 0; + virtual QTranslator *createTranslator(QObject *parent) = 0; +}; + +Q_DECLARE_INTERFACE(DecoderFactory, "DecoderFactory/1.0"); + +#endif diff --git a/src/qmmp/downloader.cpp b/src/qmmp/downloader.cpp new file mode 100644 index 000000000..5b091b640 --- /dev/null +++ b/src/qmmp/downloader.cpp @@ -0,0 +1,344 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "downloader.h" + +//curl callbacks +static size_t curl_write_data(void *data, size_t size, size_t nmemb, + void *pointer) +{ + Downloader *dl = (Downloader *)pointer; + dl->mutex()->lock (); + size_t buf_start = dl->stream()->buf_fill; + size_t data_size = size * nmemb; + dl->stream()->buf_fill += data_size; + + dl->stream()->buf = (char *)realloc (dl->stream()->buf, dl->stream()->buf_fill); + memcpy (dl->stream()->buf + buf_start, data, data_size); + dl->mutex()->unlock(); + dl->checkBuffer(); + return data_size; +} + +static size_t curl_header(void *data, size_t size, size_t nmemb, + void *pointer) +{ + Downloader *dl = (Downloader *)pointer; + dl->mutex()->lock (); + size_t data_size = size * nmemb; + if (data_size < 3) + { + dl->mutex()->unlock(); + return data_size; + } + + //qDebug("header received: %s", (char*) data); + QString str = QString::fromAscii((char *) data, data_size); + str = str.trimmed (); + if (str.left(4).contains("HTTP")) + { + qDebug("Downloader: header received"); + //TODO open metadata socket + } + else if (str.left(4).contains("ICY")) + { + qDebug("Downloader: shoutcast header received"); + //dl->stream()->icy_meta_data = TRUE; + } + else + { + QString key = str.left(str.indexOf(":")).trimmed().toLower(); + QString value = str.right(str.size() - str.indexOf(":") - 1).trimmed().toLower(); + dl->stream()->header.insert(key, value); + qDebug("Downloader: key=%s, value=%s",qPrintable(key),qPrintable(value)); + + if (key == "icy-metaint") + { + dl->stream()->icy_metaint = value.toInt(); + dl->stream()->icy_meta_data = TRUE; + } + } + dl->mutex()->unlock(); + return data_size; +} + +int curl_progress(void *pointer, double dltotal, double dlnow, double ultotal, double ulnow) +{ + Downloader *dl = (Downloader *)pointer; + dl->mutex()->lock (); + bool aborted = dl->stream()->aborted; + dl->mutex()->unlock(); + if (aborted) + return -1; + return 0; +} + +Downloader::Downloader(QObject *parent, const QString &url) + : QThread(parent) +{ + m_url = url; + curl_global_init(CURL_GLOBAL_ALL); + m_stream.buf_fill = 0; + m_stream.buf = 0; + m_stream.icy_meta_data = FALSE; + m_stream.aborted = TRUE; + m_stream.icy_metaint = 0; + m_handle = 0; + m_metacount = 0; +} + + +Downloader::~Downloader() +{ + abort(); + curl_global_cleanup(); +} + + +qint64 Downloader::read(char* data, qint64 maxlen) +{ + + qint64 len = 0; + m_mutex.lock(); + if (!m_stream.icy_meta_data || m_stream.icy_metaint == 0) + len = readBuffer(data, maxlen); + else + { + qint64 nread = 0; + qint64 to_read; + while (maxlen > nread && m_stream.buf_fill > nread) + { + to_read = qMin(m_stream.icy_metaint - m_metacount, maxlen - nread); + //to_read = (maxlen - nread); + qint64 res = readBuffer(data + nread, to_read); + nread += res; + m_metacount += res; + if (m_metacount == m_stream.icy_metaint) + { + m_metacount = 0; + m_mutex.unlock(); + readICYMetaData(); + m_mutex.lock(); + } + + } + len = nread; + + } + m_mutex.unlock(); + return len; +} + +Stream *Downloader::stream() +{ + return &m_stream; +} + +QMutex *Downloader::mutex() +{ + return &m_mutex; +} + +QString Downloader::contentType() +{ + QString content; + if (m_stream.header.contains("content-type")) + content = m_stream.header.value("content-type"); + return content; +} + +void Downloader::abort() +{ + m_mutex.lock(); + + if (m_stream.aborted) + { + m_mutex.unlock(); + return; + } + m_stream.aborted = TRUE; + m_mutex.unlock(); + wait(); + if (m_handle) + { + curl_easy_cleanup(m_handle); + m_handle = 0; + } +} + +int Downloader::bytesAvailable() +{ + m_mutex.lock(); + int b = m_stream.buf_fill; + m_mutex.unlock(); + return b; +} + +void Downloader::run() +{ + qDebug("Downloader: starting download thread"); + m_handle = curl_easy_init(); + //proxy + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + if (settings.value ("Proxy/use_proxy", FALSE).toBool()) + curl_easy_setopt(m_handle, CURLOPT_PROXY, + strdup((settings.value("Proxy/host").toString()+":"+ + settings.value("Proxy/port").toString()). + toLatin1 ().constData ())); + + if (settings.value ("Proxy/authentication", FALSE).toBool()) + curl_easy_setopt(m_handle, CURLOPT_PROXYUSERPWD, + strdup((settings.value("Proxy/user").toString()+":"+ + settings.value("Proxy/passw").toString()). + toLatin1 ().constData ())); + + // Set url to download + curl_easy_setopt(m_handle, CURLOPT_URL, strdup(m_url.toAscii().constData())); + // callback for wrting + curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION, curl_write_data); + // Set destination file + curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this); + curl_easy_setopt(m_handle, CURLOPT_HEADERDATA, this); + curl_easy_setopt(m_handle, CURLOPT_HEADERFUNCTION, curl_header); + // Disable SSL + curl_easy_setopt(m_handle, CURLOPT_SSL_VERIFYPEER, FALSE); + curl_easy_setopt(m_handle, CURLOPT_SSL_VERIFYHOST, 0); + // Enable progress meter + curl_easy_setopt(m_handle, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(m_handle, CURLOPT_PROGRESSDATA, this); + curl_easy_setopt(m_handle, CURLOPT_PROGRESSFUNCTION, curl_progress); + // Any kind of authentication + curl_easy_setopt(m_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + curl_easy_setopt(m_handle, CURLOPT_VERBOSE, 1); + // Auto referrer + curl_easy_setopt(m_handle, CURLOPT_AUTOREFERER, 1); + // Follow redirections + curl_easy_setopt(m_handle, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(m_handle, CURLOPT_FAILONERROR, 1); + curl_easy_setopt(m_handle, CURLOPT_MAXREDIRS, 15); + // user agent + curl_easy_setopt(m_handle, CURLOPT_USERAGENT, "qmmp/0.2"); + curl_easy_setopt(m_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + + struct curl_slist *http200_aliases = curl_slist_append(NULL, "ICY"); + struct curl_slist *http_headers = curl_slist_append(NULL, "Icy-MetaData: 1"); + curl_easy_setopt(m_handle, CURLOPT_HTTP200ALIASES, http200_aliases); + curl_easy_setopt(m_handle, CURLOPT_HTTPHEADER, http_headers); + m_mutex.lock(); + m_stream.buf_fill = 0; + m_stream.buf = 0; + m_stream.aborted = FALSE; + m_stream.header.clear (); + m_ready = FALSE; + int return_code; + qDebug("Downloader: starting libcurl"); + m_mutex.unlock(); + return_code = curl_easy_perform(m_handle); + qDebug("curl_easy_perform %d", return_code); + + m_mutex.lock(); + m_stream.aborted = TRUE; + m_stream.buf_fill = 0; + if (m_stream.buf) + delete m_stream.buf; + m_stream.buf = 0; + m_mutex.unlock(); + qDebug("Downloader: thread exited"); +} + +qint64 Downloader::readBuffer(char* data, qint64 maxlen) +{ + if (m_stream.buf_fill > 0 && !m_stream.aborted) + { + int len = qMin(m_stream.buf_fill, maxlen); + memcpy(data, m_stream.buf, len); + m_stream.buf_fill -= len; + memmove(m_stream.buf, m_stream.buf + len, m_stream.buf_fill); + return len; + } + return 0; +} + +const QString &Downloader::title() const +{ + return m_title; +} + +void Downloader::checkBuffer() +{ + if(m_stream.buf_fill > BUFFER_SIZE && !m_ready) + { + m_ready = TRUE; + qDebug("Downloader: ready"); + emit readyRead(); + } + +} + +bool Downloader::isReady() +{ + return m_ready; +} + +void Downloader::readICYMetaData() +{ + uint8_t packet_size; + m_metacount = 0; + m_mutex.lock(); + readBuffer((char *)&packet_size, sizeof(packet_size)); + if (packet_size != 0) + { + int size = packet_size * 16; + char packet[size]; + while (m_stream.buf_fill < size && isRunning()) + { + m_mutex.unlock(); + qApp->processEvents(); + m_mutex.lock(); + } + readBuffer(packet, size); + qDebug("Downloader: ICY metadata: %s", packet); + parseICYMetaData(packet); + } + m_mutex.unlock(); + +} + +void Downloader::parseICYMetaData(char *data) +{ + QString str(data); + QStringList list(str.split(";", QString::SkipEmptyParts)); + foreach(QString line, list) + { + if (line.contains("StreamTitle=")) + { + line = line.right(line.size() - line.indexOf("=") - 1).trimmed(); + m_title = line.remove("'"); + if(!m_title.isEmpty()) + emit titleChanged (); + break; + } + } +} diff --git a/src/qmmp/downloader.h b/src/qmmp/downloader.h new file mode 100644 index 000000000..05175e379 --- /dev/null +++ b/src/qmmp/downloader.h @@ -0,0 +1,86 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DOWNLOADER_H +#define DOWNLOADER_H + +#include +#include +#include +#include + +#include + +#define BUFFER_SIZE 128000 + +/** + @author Ilya Kotov +*/ + +struct Stream +{ + char *buf; + int buf_fill; + QString content_type; + bool aborted; + QMap header; + bool icy_meta_data; + int icy_metaint; +}; + +class Downloader : public QThread +{ + Q_OBJECT +public: + Downloader(QObject *parent, const QString &url); + + ~Downloader(); + + qint64 read(char* data, qint64 maxlen); + Stream *stream(); + QMutex *mutex(); + QString contentType(); + void abort(); + int bytesAvailable(); + const QString& title() const; + void checkBuffer(); + bool isReady(); + +signals: + void titleChanged(); + void readyRead(); + +private: + qint64 readBuffer(char* data, qint64 maxlen); + void readICYMetaData(); + void parseICYMetaData(char *data); + CURL *m_handle; + QMutex m_mutex; + Stream m_stream; + QString m_url; + int m_metacount; + QString m_title; + bool m_ready; + +protected: + void run(); + +}; + +#endif diff --git a/src/qmmp/effect.cpp b/src/qmmp/effect.cpp new file mode 100644 index 000000000..c6d3ba0fb --- /dev/null +++ b/src/qmmp/effect.cpp @@ -0,0 +1,148 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include + +#include "effectfactory.h" +#include "constants.h" +#include "effect.h" + +Effect::Effect(QObject *parent) + : QObject(parent) +{} + +Effect::~Effect() +{} + +void Effect::configure(ulong freq, int chan, int res) +{ + m_freq = freq; + m_chan = chan; + m_res = res; + +} + +const ulong Effect::frequency() +{ + return m_freq; +} + +const int Effect::channels() +{ + return m_chan; +} + +const int Effect::resolution() +{ + return m_res; +} + +static QList *factories = 0; +static QStringList files; + +static void checkFactories() +{ + if (! factories) + { + files.clear(); + factories = new QList; + + QDir pluginsDir (qApp->applicationDirPath()); + pluginsDir.cdUp(); + pluginsDir.cd("./"LIB_DIR"/qmmp/Effect"); + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) + { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (loader.isLoaded()) + { + qDebug("Effect: plugin loaded - %s", qPrintable(fileName)); + } + EffectFactory *factory = 0; + if (plugin) + factory = qobject_cast(plugin); + + if (factory) + { + factories->append(factory); + files << pluginsDir.absoluteFilePath(fileName); + } + } + } +} + +QList Effect::create(QObject *parent) +{ + checkFactories(); + QList effects; + EffectFactory *factory = 0; + foreach (factory, *factories) + { + if(isEnabled(factory)) + effects.append(factory->create(parent)); + } + return effects; +} + +QList *Effect::effectFactories() +{ + checkFactories(); + return factories; +} + +QStringList Effect::effectFiles() +{ + checkFactories(); + return files; +} + +void Effect::setEnabled(EffectFactory* factory, bool enable) +{ + checkFactories(); + if(!factories->contains(factory)) + return; + + QString name = files.at(factories->indexOf(factory)).section('/',-1); + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + QStringList effList = settings.value("Effect/plugin_files").toStringList(); + + if(enable) + { + if (!effList.contains(name)) + effList << name; + } + else + effList.removeAll(name); + settings.setValue("Effect/plugin_files", effList); +} + +bool Effect::isEnabled(EffectFactory* factory) +{ + checkFactories(); + if(!factories->contains(factory)) + return FALSE; + QString name = files.at(factories->indexOf(factory)).section('/',-1); + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + QStringList effList = settings.value("Effect/plugin_files").toStringList(); + return effList.contains(name); +} + diff --git a/src/qmmp/effect.h b/src/qmmp/effect.h new file mode 100644 index 000000000..654c1c2b6 --- /dev/null +++ b/src/qmmp/effect.h @@ -0,0 +1,87 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef EFFECT_H +#define EFFECT_H + +#include +#include +#include + + +/** + @author Ilya Kotov +*/ + +class EffectFactory; + +class Effect : public QObject +{ + Q_OBJECT +public: + Effect(QObject *parent = 0); + + virtual ~Effect(); + + /*/*! + * Adds effect to the input data pointer \b in_data with the size \b size. + * Result is stored in the output data \b out_data. + * Return value is the size of the output data. Output data size should not be more then \b size. + * Subclass should implement this function. + */ + virtual const ulong process(char *in_data, const ulong size, char **out_data) = 0; + + //virtual const ulong process(char *in_data, const ulong size, char *out_data) = 0; + //virtual bool process(char *in_data, char *out_data, const ulong maxsize, ulong &rbytes, ulong &wbytes) = 0; + + + virtual void configure(ulong freq, int chan, int res); + + /*! + * Returns frequency. + * This function should be reimplemented if subclass changes default samplerate. + */ + virtual const ulong frequency(); + + /*! + * Returns channel number. + * This function should be reimplemented if subclass changes default channel number. + */ + virtual const int channels(); + + /*! + * Returns resolution. + * This function should be reimplemented if subclass changes default resolution. + */ + virtual const int resolution(); + + + static QList create(QObject *parent); + static QList *effectFactories(); + static QStringList effectFiles(); + static void setEnabled(EffectFactory* factory, bool enable = TRUE); + static bool isEnabled(EffectFactory* factory); + +private: + ulong m_freq; + int m_chan; + int m_res; +}; + +#endif diff --git a/src/qmmp/effectfactory.h b/src/qmmp/effectfactory.h new file mode 100644 index 000000000..96354cf6e --- /dev/null +++ b/src/qmmp/effectfactory.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef EFFECTFACTORY_H +#define EFFECTFACTORY_H + +#include + +/** + @author Ilya Kotov +*/ +class QObject; +class QWidget; +class QTranslator; + +class Effect; + +struct EffectProperties +{ + QString name; + bool hasAbout; + bool hasSettings; +}; + +class EffectFactory +{ +public: + virtual const EffectProperties properties() const = 0; + virtual Effect *create(QObject *parent) = 0; + virtual void showSettings(QWidget *parent) = 0; + virtual void showAbout(QWidget *parent) = 0; + virtual QTranslator *createTranslator(QObject *parent) = 0; +}; + +Q_DECLARE_INTERFACE(EffectFactory, "EffectFactory/1.0"); + +#endif diff --git a/src/qmmp/equ/iir.c b/src/qmmp/equ/iir.c new file mode 100644 index 000000000..9d826b86c --- /dev/null +++ b/src/qmmp/equ/iir.c @@ -0,0 +1,85 @@ +/* + * PCM time-domain equalizer + * + * Copyright (C) 2002-2005 Felipe Rivera + * + * This program is free software; 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. + * + * $Id: iir.c,v 1.15 2005/10/17 01:57:59 liebremx Exp $ + */ + +#include +#include "iir.h" + +/* Coefficients */ +sIIRCoefficients *iir_cf; + +/* Volume gain + * values should be between 0.0 and 1.0 + * Use the preamp from XMMS for now + * */ +float preamp[EQ_CHANNELS]; + +#ifdef BENCHMARK +#include "benchmark.h" +double timex = 0.0; +int count = 0; +unsigned int blength = 0; +#endif + +/* + * Global vars + */ +int rate; +int band_count; + +void set_preamp(int chn, float val) +{ + preamp[chn] = val; +} + +/* Init the filters */ +void init_iir() +{ + calc_coeffs(); +#if 0 + band_count = cfg.band_num; +#endif + + band_count = 10; + + rate = 44100; + + iir_cf = get_coeffs(&band_count, rate); + clean_history(); +} + +#ifdef ARCH_X86 +/* Round function provided by Frank Klemm which saves around 100K + * CPU cycles in my PIII for each call to the IIR function with 4K samples + */ +__inline__ int round_trick(float floatvalue_to_round) +{ + float floattmp ; + int rounded_value ; + + floattmp = (int) 0x00FD8000L + (floatvalue_to_round); + rounded_value = *(int*)(&floattmp) - (int)0x4B7D8000L; + + if ( rounded_value != (short) rounded_value ) + rounded_value = ( rounded_value >> 31 ) ^ 0x7FFF; + return rounded_value; +} +#endif diff --git a/src/qmmp/equ/iir.h b/src/qmmp/equ/iir.h new file mode 100644 index 000000000..e7ea5ef1a --- /dev/null +++ b/src/qmmp/equ/iir.h @@ -0,0 +1,84 @@ +/* + * PCM time-domain equalizer + * + * Copyright (C) 2002-2005 Felipe Rivera + * + * This program is free software; 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. + * + * $Id: iir.h,v 1.12 2005/10/17 01:57:59 liebremx Exp $ + */ +#ifndef IIR_H +#define IIR_H + +//#include +//#include "main.h" +#include "iir_cfs.h" + +/* + * Flush-to-zero to avoid flooding the CPU with underflow exceptions + */ +#ifdef SSE_MATH +#define FTZ 0x8000 +#define FTZ_ON { \ + unsigned int mxcsr; \ + __asm__ __volatile__ ("stmxcsr %0" : "=m" (*&mxcsr)); \ + mxcsr |= FTZ; \ + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (*&mxcsr)); \ +} +#define FTZ_OFF { \ + unsigned int mxcsr; \ + __asm__ __volatile__ ("stmxcsr %0" : "=m" (*&mxcsr)); \ + mxcsr &= ~FTZ; \ + __asm__ __volatile__ ("ldmxcsr %0" : : "m" (*&mxcsr)); \ +} +#else +#define FTZ_ON +#define FTZ_OFF +#endif + +/* + * Function prototypes + */ +void init_iir(); +void clean_history(); +void set_gain(int index, int chn, float val); +void set_preamp(int chn, float val); + + + int iir(void * d, int length, int nch); + +#ifdef ARCH_X86 +__inline__ int round_trick(float floatvalue_to_round); +#endif +#ifdef ARCH_PPC +__inline__ int round_ppc(float x); +#endif + +#define EQ_CHANNELS 2 +#define EQ_MAX_BANDS 10 + +extern float preamp[EQ_CHANNELS]; +extern sIIRCoefficients *iir_cf; +extern int rate; +extern int band_count; + +#ifdef BENCHMARK +extern double timex; +extern int count; +extern unsigned int blength; +#endif + +#endif /* #define IIR_H */ + diff --git a/src/qmmp/equ/iir_cfs.c b/src/qmmp/equ/iir_cfs.c new file mode 100644 index 000000000..f8e6f88a6 --- /dev/null +++ b/src/qmmp/equ/iir_cfs.c @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2002-2005 Felipe Rivera + * + * This program is free software; 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. + * + * + * Coefficient stuff + * + * $Id: iir_cfs.c,v 1.1 2005/10/17 01:57:59 liebremx Exp $ + */ + +#include "iir_cfs.h" +#include +#include + +/*************************** + * IIR filter coefficients * + ***************************/ +static sIIRCoefficients iir_cf10_11k_11025[10] __attribute__((aligned)); +static sIIRCoefficients iir_cf10_22k_22050[10] __attribute__((aligned)); +static sIIRCoefficients iir_cforiginal10_44100[10] __attribute__((aligned)); +static sIIRCoefficients iir_cforiginal10_48000[10] __attribute__((aligned)); +static sIIRCoefficients iir_cf10_44100[10] __attribute__((aligned)); +static sIIRCoefficients iir_cf10_48000[10] __attribute__((aligned)); +static sIIRCoefficients iir_cf15_44100[15] __attribute__((aligned)); +static sIIRCoefficients iir_cf15_48000[15] __attribute__((aligned)); +static sIIRCoefficients iir_cf25_44100[25] __attribute__((aligned)); +static sIIRCoefficients iir_cf25_48000[25] __attribute__((aligned)); +static sIIRCoefficients iir_cf31_44100[31] __attribute__((aligned)); +static sIIRCoefficients iir_cf31_48000[31] __attribute__((aligned)); + +/****************************************************************** + * Definitions and data structures to calculate the coefficients + ******************************************************************/ +static const double band_f011k[] = +{ 31, 62, 125, 250, 500, 1000, 2000, 3000, 4000, 5500 +}; +static const double band_f022k[] = +{ 31, 62, 125, 250, 500, 1000, 2000, 4000, 8000, 11000 +}; +static const double band_f010[] = +{ 31, 62, 125, 250, 500, 1000, 2000, 4000, 8000, 16000 +}; +static const double band_original_f010[] = +{ 60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000 +}; +static const double band_f015[] = +{ 25,40,63,100,160,250,400,630,1000,1600,2500,4000,6300,10000,16000 +}; +static const double band_f025[] = +{ 20,31.5,40,50,80,100,125,160,250,315,400,500,800, + 1000,1250,1600,2500,3150,4000,5000,8000,10000,12500,16000,20000 +}; +static const double band_f031[] = +{ 20,25,31.5,40,50,63,80,100,125,160,200,250,315,400,500,630,800, + 1000,1250,1600,2000,2500,3150,4000,5000,6300,8000,10000,12500,16000,20000 +}; + +#define GAIN_F0 1.0 +#define GAIN_F1 GAIN_F0 / M_SQRT2 + +#define SAMPLING_FREQ 44100.0 +#define TETA(f) (2*M_PI*(double)f/bands[n].sfreq) +#define TWOPOWER(value) (value * value) + +#define BETA2(tf0, tf) \ +(TWOPOWER(GAIN_F1)*TWOPOWER(cos(tf0)) \ + - 2.0 * TWOPOWER(GAIN_F1) * cos(tf) * cos(tf0) \ + + TWOPOWER(GAIN_F1) \ + - TWOPOWER(GAIN_F0) * TWOPOWER(sin(tf))) +#define BETA1(tf0, tf) \ + (2.0 * TWOPOWER(GAIN_F1) * TWOPOWER(cos(tf)) \ + + TWOPOWER(GAIN_F1) * TWOPOWER(cos(tf0)) \ + - 2.0 * TWOPOWER(GAIN_F1) * cos(tf) * cos(tf0) \ + - TWOPOWER(GAIN_F1) + TWOPOWER(GAIN_F0) * TWOPOWER(sin(tf))) +#define BETA0(tf0, tf) \ + (0.25 * TWOPOWER(GAIN_F1) * TWOPOWER(cos(tf0)) \ + - 0.5 * TWOPOWER(GAIN_F1) * cos(tf) * cos(tf0) \ + + 0.25 * TWOPOWER(GAIN_F1) \ + - 0.25 * TWOPOWER(GAIN_F0) * TWOPOWER(sin(tf))) + +#define GAMMA(beta, tf0) ((0.5 + beta) * cos(tf0)) +#define ALPHA(beta) ((0.5 - beta)/2.0) + +struct { + sIIRCoefficients *coeffs; + const double *cfs; + double octave; + int band_count; + double sfreq; +} bands[] = { + { iir_cf10_11k_11025, band_f011k, 1.0, 10, 11025.0 }, + { iir_cf10_22k_22050, band_f022k, 1.0, 10, 22050.0 }, + { iir_cforiginal10_44100, band_original_f010, 1.0, 10, 44100.0 }, + { iir_cforiginal10_48000, band_original_f010, 1.0, 10, 48000.0 }, + { iir_cf10_44100, band_f010, 1.0, 10, 44100.0 }, + { iir_cf10_48000, band_f010, 1.0, 10, 48000.0 }, + { iir_cf15_44100, band_f015, 2.0/3.0, 15, 44100.0 }, + { iir_cf15_48000, band_f015, 2.0/3.0, 15, 48000.0 }, + { iir_cf25_44100, band_f025, 1.0/3.0, 25, 44100.0 }, + { iir_cf25_48000, band_f025, 1.0/3.0, 25, 48000.0 }, + { iir_cf31_44100, band_f031, 1.0/3.0, 31, 44100.0 }, + { iir_cf31_48000, band_f031, 1.0/3.0, 31, 48000.0 }, + { 0, 0, 0, 0, 0 } +}; + +/************* + * Functions * + *************/ + +/* Get the coeffs for a given number of bands and sampling frequency */ +sIIRCoefficients* get_coeffs(int *bands, int sfreq) +{ + sIIRCoefficients *iir_cf = 0; + switch(sfreq) + { + case 11025: iir_cf = iir_cf10_11k_11025; + *bands = 10; + break; + case 22050: iir_cf = iir_cf10_22k_22050; + *bands = 10; + break; + case 48000: + switch(*bands) + { + case 31: iir_cf = iir_cf31_48000; break; + case 25: iir_cf = iir_cf25_48000; break; + case 15: iir_cf = iir_cf15_48000; break; + default: + /*iir_cf = use_xmms_original_freqs ? + iir_cforiginal10_48000 : + iir_cf10_48000;*/ + iir_cf = iir_cforiginal10_48000; + break; + } + break; + default: + switch(*bands) + { + case 31: iir_cf = iir_cf31_44100; break; + case 25: iir_cf = iir_cf25_44100; break; + case 15: iir_cf = iir_cf15_44100; break; + default: + /*iir_cf = use_xmms_original_freqs ? + iir_cforiginal10_44100 : + iir_cf10_44100;*/ + iir_cf = iir_cforiginal10_44100; + break; + } + break; + } + return iir_cf; +} + +/* Get the freqs at both sides of F0. These will be cut at -3dB */ +static void find_f1_and_f2(double f0, double octave_percent, double *f1, double *f2) +{ + double octave_factor = pow(2.0, octave_percent/2.0); + *f1 = f0/octave_factor; + *f2 = f0*octave_factor; +} + +/* Find the quadratic root + * Always return the smallest root */ +static int find_root(double a, double b, double c, double *x0) { + double k = c-((b*b)/(4.*a)); + double h = -(b/(2.*a)); + double x1 = 0.; + if (-(k/a) < 0.) + return -1; + *x0 = h - sqrt(-(k/a)); + x1 = h + sqrt(-(k/a)); + if (x1 < *x0) + *x0 = x1; + return 0; +} + +/* Calculate all the coefficients as specified in the bands[] array */ +void calc_coeffs() +{ + int i, n; + double f1, f2; + double x0; + + n = 0; + for (; bands[n].cfs; n++) { + double *freqs = (double *)bands[n].cfs; + for (i=0; i + * + * This program is free software; 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. + * + * $Id: iir_cfs.h,v 1.1 2005/10/17 01:57:59 liebremx Exp $ + */ +#ifndef IIR_CFS_H +#define IIR_CFS_H + +//#include + +/* Coefficients entry */ +typedef struct +{ + float beta; + float alpha; + float gamma; + float dummy; // Word alignment +}sIIRCoefficients; + +sIIRCoefficients* get_coeffs(int *bands, int sfreq); //, bool use_xmms_original_freqs); +void calc_coeffs(); + +#endif diff --git a/src/qmmp/equ/iir_fpu.c b/src/qmmp/equ/iir_fpu.c new file mode 100644 index 000000000..ae0051fdf --- /dev/null +++ b/src/qmmp/equ/iir_fpu.c @@ -0,0 +1,210 @@ +/* + * PCM time-domain equalizer + * + * Copyright (C) 2002-2005 Felipe Rivera + * + * This program is free software; 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. + * + * $Id: iir_fpu.c,v 1.3 2005/11/13 20:02:58 lisanet Exp $ + */ + +#include +#include +//#include +#include "iir.h" +#include "iir_fpu.h" + +static sXYData data_history[EQ_MAX_BANDS][EQ_CHANNELS] __attribute__((aligned)); +static sXYData data_history2[EQ_MAX_BANDS][EQ_CHANNELS] __attribute__((aligned)); +float gain[EQ_MAX_BANDS][EQ_CHANNELS] __attribute__((aligned)); +/* random noise */ +sample_t dither[256]; +int di; + +void set_gain(int index, int chn, float val) +{ + gain[index][chn] = val; +} + +void clean_history() +{ + int n; + /* Zero the history arrays */ + bzero(data_history, sizeof(sXYData) * EQ_MAX_BANDS * EQ_CHANNELS); + bzero(data_history2, sizeof(sXYData) * EQ_MAX_BANDS * EQ_CHANNELS); + /* this is only needed if we use fpu code and there's no other place for + the moment to init the dither array*/ + for (n = 0; n < 256; n++) { + dither[n] = (rand() % 4) - 2; + } + di = 0; +} + +__inline__ int iir(void * d, int length, int nch) +{ +/* FTZ_ON; */ + short *data = (short *) d; + /* Indexes for the history arrays + * These have to be kept between calls to this function + * hence they are static */ + static int i = 2, j = 1, k = 0; + + int index, band, channel; + int tempgint, halflength; + sample_t out[EQ_CHANNELS], pcm[EQ_CHANNELS]; + +#if 0 + /* Load the correct filter table according to the sampling rate if needed */ + if (srate != rate) + { + band_count = eqcfg.band_num; + rate = srate; + iir_cf = get_coeffs(&band_count, rate, eqcfg.use_xmms_original_freqs); + clean_history(); + } +#endif + +#ifdef BENCHMARK + start_counter(); +#endif /* BENCHMARK */ + + /** + * IIR filter equation is + * y[n] = 2 * (alpha*(x[n]-x[n-2]) + gamma*y[n-1] - beta*y[n-2]) + * + * NOTE: The 2 factor was introduced in the coefficients to save + * a multiplication + * + * This algorithm cascades two filters to get nice filtering + * at the expense of extra CPU cycles + */ + /* 16bit, 2 bytes per sample, so divide by two the length of + * the buffer (length is in bytes) + */ + halflength = (length >> 1); + for (index = 0; index < halflength; index+=nch) + { + /* For each channel */ + for (channel = 0; channel < nch; channel++) + { + pcm[channel] = data[index+channel] * 4; + /* Preamp gain */ + pcm[channel] *= (preamp[channel] / 2); + + /* add random noise */ + pcm[channel] += dither[di]; + + out[channel] = 0.0; + /* For each band */ + for (band = 0; band < band_count; band++) + { + /* Store Xi(n) */ + data_history[band][channel].x[i] = pcm[channel]; + /* Calculate and store Yi(n) */ + data_history[band][channel].y[i] = + ( + /* = alpha * [x(n)-x(n-2)] */ + iir_cf[band].alpha * ( data_history[band][channel].x[i] + - data_history[band][channel].x[k]) + /* + gamma * y(n-1) */ + + iir_cf[band].gamma * data_history[band][channel].y[j] + /* - beta * y(n-2) */ + - iir_cf[band].beta * data_history[band][channel].y[k] + ); + /* + * The multiplication by 2.0 was 'moved' into the coefficients to save + * CPU cycles here */ + /* Apply the gain */ + out[channel] += data_history[band][channel].y[i]*gain[band][channel]; /* * 2.0; */ + } /* For each band */ + + //if (cfg.eq_extra_filtering) + { + /* Filter the sample again */ + for (band = 0; band < band_count; band++) + { + /* Store Xi(n) */ + data_history2[band][channel].x[i] = out[channel]; + /* Calculate and store Yi(n) */ + data_history2[band][channel].y[i] = + ( + /* y(n) = alpha * [x(n)-x(n-2)] */ + iir_cf[band].alpha * (data_history2[band][channel].x[i] + - data_history2[band][channel].x[k]) + /* + gamma * y(n-1) */ + + iir_cf[band].gamma * data_history2[band][channel].y[j] + /* - beta * y(n-2) */ + - iir_cf[band].beta * data_history2[band][channel].y[k] + ); + /* Apply the gain */ + out[channel] += data_history2[band][channel].y[i]*gain[band][channel]; + } /* For each band */ + } + + /* Volume stuff + Scale down original PCM sample and add it to the filters + output. This substitutes the multiplication by 0.25 + Go back to use the floating point multiplication before the + conversion to give more dynamic range + */ + out[channel] += pcm[channel]*0.25; + + /* remove random noise */ + out[channel] -= dither[di]*0.25; + + /* Round and convert to integer */ +#ifdef ARCH_PPC + tempgint = round_ppc(out[channel]); +#else +#ifdef ARCH_X86 + tempgint = round_trick(out[channel]); +#else + tempgint = (int)out[channel]; +#endif +#endif + + /* Limit the output */ + if (tempgint < -32768) + data[index+channel] = -32768; + else if (tempgint > 32767) + data[index+channel] = 32767; + else + data[index+channel] = tempgint; + } /* For each channel */ + + /* Wrap around the indexes */ + i = (i+1)%3; + j = (j+1)%3; + k = (k+1)%3; + /* random noise index */ + di = (di + 1) % 256; + + }/* For each pair of samples */ + +#ifdef BENCHMARK + timex += get_counter(); + blength += length; + if (count++ == 1024) + { + printf("FLOATING POINT: %f %d\n",timex/1024.0, blength/1024); + blength = 0; + timex = 0.; + count = 0; + } +#endif /* BENCHMARK */ + +/* FTZ_OFF; */ + return length; +} diff --git a/src/qmmp/equ/iir_fpu.h b/src/qmmp/equ/iir_fpu.h new file mode 100644 index 000000000..990eebf97 --- /dev/null +++ b/src/qmmp/equ/iir_fpu.h @@ -0,0 +1,39 @@ +/* + * PCM time-domain equalizer + * + * Copyright (C) 2002-2005 Felipe Rivera + * + * This program is free software; 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. + * + * $Id: iir_fpu.h,v 1.2 2005/11/01 15:59:20 lisanet Exp $$ + */ +#ifndef IIR_FPU_H +#define IIR_FPU_H + +#define sample_t double + +/* + * Normal FPU implementation data structures + */ +/* Coefficient history for the IIR filter */ +typedef struct +{ + sample_t x[3]; /* x[n], x[n-1], x[n-2] */ + sample_t y[3]; /* y[n], y[n-1], y[n-2] */ + sample_t dummy1; // Word alignment + sample_t dummy2; +}sXYData; + +#endif diff --git a/src/qmmp/filetag.cpp b/src/qmmp/filetag.cpp new file mode 100644 index 000000000..3ce3b505a --- /dev/null +++ b/src/qmmp/filetag.cpp @@ -0,0 +1,100 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "filetag.h" + +FileTag::FileTag() +{} + +FileTag::FileTag(const FileTag &other) +{ + *this = other; +} + +FileTag::~FileTag() +{} + +void FileTag::operator=(const FileTag &tag) +{ + setValue(TITLE,tag.title ()); + setValue(ARTIST,tag.artist ()); + setValue(ALBUM,tag.album ()); + setValue(COMMENT,tag.comment ()); + setValue(GENRE,tag.genre ()); + setValue(YEAR,tag.year ()); + setValue(TRACK,tag.track ()); + setValue(LENGTH,tag.length ()); +} + +void FileTag::setValue(uint name, const QString &value) +{ + if (!value.isEmpty()) + m_strValues.insert (name, value); +} + +void FileTag::setValue(uint name, const uint &value) +{ + if (value > 0) + m_numValues.insert (name, value); +} + +const QString FileTag::title () const +{ + return m_strValues[TITLE]; +} + +const QString FileTag::artist () const +{ + return m_strValues[ARTIST]; +} + +const QString FileTag::album () const +{ + return m_strValues[ALBUM]; +} + +const QString FileTag::comment () const +{ + return m_strValues[COMMENT]; +} + +const QString FileTag::genre () const +{ + return m_strValues[GENRE]; +} + +const uint FileTag::year () const +{ + return m_numValues[YEAR]; +} + +const uint FileTag::track () const +{ + return m_numValues[TRACK]; +} + +const uint FileTag::length () const +{ + return m_numValues[LENGTH]; +} + +const bool FileTag::isEmpty () const +{ + return m_strValues.isEmpty(); +} diff --git a/src/qmmp/filetag.h b/src/qmmp/filetag.h new file mode 100644 index 000000000..f75facfa0 --- /dev/null +++ b/src/qmmp/filetag.h @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef FILETAG_H +#define FILETAG_H + +#include +#include + +/** + @author Ilya Kotov +*/ +class FileTag +{ +public: + FileTag(); + FileTag(const FileTag &other); + + ~FileTag(); + + enum Type + { + TITLE = 0, + ARTIST, + ALBUM, + COMMENT, + GENRE, + YEAR, + TRACK, + LENGTH + }; + + void operator=(const FileTag &tag); + void setValue(uint name, const QString &value); + void setValue(uint name, const uint &value); + const QString title () const; + const QString artist () const; + const QString album () const; + const QString comment () const; + const QString genre () const; + const uint year () const; + const uint track () const; + const uint length () const; + const bool isEmpty () const; + +private: + QMap m_strValues; + QMap m_numValues; +}; + +#endif diff --git a/src/qmmp/output.cpp b/src/qmmp/output.cpp new file mode 100644 index 000000000..50136608a --- /dev/null +++ b/src/qmmp/output.cpp @@ -0,0 +1,269 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#include +#include +#include +#include +#include + +#include "constants.h" +#include "output.h" + +#include + +// static methods + +static QList *factories = 0; +static QStringList files; +static QTimer *timer = 0; + +static void checkFactories() +{ + if ( ! factories ) + { + files.clear(); + factories = new QList; + + QDir pluginsDir ( qApp->applicationDirPath() ); + pluginsDir.cdUp(); + pluginsDir.cd ( "./"LIB_DIR"/qmmp/Output" ); + foreach ( QString fileName, pluginsDir.entryList ( QDir::Files ) ) + { + QPluginLoader loader ( pluginsDir.absoluteFilePath ( fileName ) ); + QObject *plugin = loader.instance(); + if ( loader.isLoaded() ) + { + qDebug ( "Output: plugin loaded - %s", qPrintable ( fileName ) ); + } + OutputFactory *factory = 0; + if ( plugin ) + factory = qobject_cast ( plugin ); + + if ( factory ) + { + Output::registerFactory ( factory ); + files << pluginsDir.absoluteFilePath(fileName); + } + } + } +} + +void Output::registerFactory ( OutputFactory *fact ) +{ + factories->append ( fact ); +} + +Output *Output::create (QObject *parent) +{ + Output *output = 0; + + checkFactories(); + if (factories->isEmpty ()) + { + qDebug("Output: unable to find output plugins"); + return output; + } + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + QString pluginFileName = + settings.value("Output/plugin_file","libalsa.so").toString(); + int j = 0; + for (int i = 0; i < factories->size(); ++i) + { + if (files.at(i).section('/',-1) == pluginFileName) + j = i; + } + OutputFactory *fact = factories->at (j); + bool useVolume = !settings.value("Volume/software_volume", FALSE).toBool(); + if (fact) + { + output = fact->create (parent, useVolume); + if (useVolume) + { + timer = new QTimer(output); + connect(timer, SIGNAL(timeout()), output, SLOT(checkVolume())); + timer->start(125); + } + else + { + QTimer::singleShot(125, output, SLOT(checkSoftwareVolume())); + } + } + return output; +} + +QList *Output::outputFactories() +{ + checkFactories(); + return factories; +} + +QStringList Output::outputFiles() +{ + checkFactories(); + return files; +} + +Output::Output (QObject* parent) : QThread (parent), r (stackSize()) +{ + qRegisterMetaType("OutputState"); + m_bl = -1; + m_br = -1; +} + + +Output::~Output() +{ + qDebug("Output::~Output()"); + Visual *visual = 0; + foreach(visual, m_vis_map.values ()) + { + visual->close(); + } + //m_vis_map.clear(); +} + +void Output::error ( const QString &e ) +{ + emit stateChanged ( OutputState ( e ) ); +} + + +void Output::addVisual ( Visual *v ) +{ + if (visuals.indexOf (v) == -1) + { + visuals.append (v); + v->setOutput(this); + qDebug("Output: added external visualization"); + } +} + + +void Output::removeVisual (Visual *v) +{ + visuals.removeAll (v); + if (m_vis_map.key(v)) + { + VisualFactory *factory = m_vis_map.key(v); + m_vis_map.remove(factory); + //Visual::setEnabled(factory, FALSE); + } +} + +void Output::addVisual(VisualFactory *factory, QWidget *parent) +{ + if (m_vis_map.value(factory)) + return; + Visual::setEnabled(factory, TRUE); + Visual* visual = factory->create(parent); + visual->setWindowFlags(Qt::Window); + if (visual) + { + visual->setOutput(this); + qDebug("Output: added visual factory: %s", + qPrintable(factory->properties().name)); + m_vis_map.insert (factory, visual); + visual->show(); + } +} + +void Output::removeVisual(VisualFactory *factory) +{ + if (m_vis_map.value(factory)) + { + m_vis_map.value(factory)->close(); + m_vis_map.remove (factory); + } + Visual::setEnabled(factory, FALSE); +} + +void Output::dispatchVisual ( Buffer *buffer, unsigned long written, + int chan, int prec ) +{ + if ( ! buffer || !visuals.size()) + return; + Visual* visual = 0; + foreach (visual , visuals) //external + { + visual->mutex()->lock (); + visual->add ( buffer, written, chan, prec ); + visual->mutex()->unlock(); + } + foreach (visual , m_vis_map.values ()) //internal + { + visual->mutex()->lock (); + visual->add ( buffer, written, chan, prec ); + visual->mutex()->unlock(); + } +} + + +void Output::clearVisuals() +{ + Visual *visual = 0; + foreach (visual, visuals ) + { + visual->mutex()->lock (); + visual->clear(); + visual->mutex()->unlock(); + } + foreach(visual, m_vis_map.values ()) + { + visual->mutex()->lock (); + visual->clear(); + visual->mutex()->unlock(); + } +} + +void Output::dispatch(OutputState::Type st) +{ + if (st == OutputState::Stopped) + clearVisuals(); + emit stateChanged ( OutputState(st) ); +} + +void Output::dispatch(long s, unsigned long w, int b, int f, int p, int c) +{ + emit stateChanged ( OutputState(s, w, b, f, p, c) ); +} + +void Output::dispatch ( const OutputState &st ) +{ + if (st.type() == OutputState::Stopped) + clearVisuals(); + emit stateChanged ( st ); +} + +void Output::dispatchVolume(int L, int R) +{ + emit stateChanged ( OutputState(L, R) ); +} + +void Output::checkVolume() +{ + int ll = 0, lr = 0; + volume(&ll,&lr); + ll = (ll > 100) ? 100 : ll; + lr = (lr > 100) ? 100 : lr; + ll = (ll < 0) ? 0 : ll; + lr = (lr < 0) ? 0 : lr; + if (m_bl!=ll || m_br!=lr) + { + m_bl = ll; + m_br = lr; + dispatchVolume(ll,lr); + } +} + +void Output::checkSoftwareVolume() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + int L = settings.value("Volume/left", 80).toInt(); + int R = settings.value("Volume/right", 80).toInt(); + dispatchVolume(L, R); +} + diff --git a/src/qmmp/output.h b/src/qmmp/output.h new file mode 100644 index 000000000..1a8ec3bd9 --- /dev/null +++ b/src/qmmp/output.h @@ -0,0 +1,208 @@ + +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#ifndef OUTPUT_H +#define OUTPUT_H + +class Output; + +#include +#include +#include +#include +#include +#include "visual.h" +#include "outputfactory.h" +#include "visualfactory.h" + +#include "recycler.h" + +class QTimer; + + +class OutputState +{ +public: + + enum Type { Playing, Buffering, Info, Paused, Stopped, Volume, Error }; + + OutputState() + : m_type(Stopped), m_error_msg(0), m_elasped_seconds(0), + m_written_bytes(0), m_brate(0), m_freq(0), m_prec(0), m_chan(0), + m_left(0), m_right(0) + {} + OutputState(const OutputState &st) + : m_type(Stopped), m_error_msg(0), m_elasped_seconds(0), + m_written_bytes(0), m_brate(0), m_freq(0), m_prec(0), m_chan(0), + m_left(0), m_right(0) + { + m_type = st.type(); + if (m_type == Info) + { + m_elasped_seconds = st.elapsedSeconds(); + m_written_bytes = st.writtenBytes(); + m_brate = st.bitrate(); + m_freq = st.frequency(); + m_prec = st.precision(); + m_chan = st.channels(); + m_left = st.leftVolume(); + m_right = st.rightVolume(); + } + else if (m_type == Error) + m_error_msg = new QString(*st.errorMessage()); + } + + OutputState(Type t) + : m_type(t), m_error_msg(0), m_elasped_seconds(0), + m_written_bytes(0), m_brate(0), m_freq(0), m_prec(0), m_chan(0), + m_left(0), m_right(0) +{} + OutputState(long s, unsigned long w, int b, int f, int p, int c) + : m_type(Info), m_error_msg(0), m_elasped_seconds(s), + m_written_bytes(w), m_brate(b), m_freq(f), m_prec(p), m_chan(c), + m_left(0), m_right(0) + {} + OutputState(int L, int R) + : m_type(Volume), m_error_msg(0), m_elasped_seconds(0), + m_written_bytes(0), m_brate(0), m_freq(0), m_prec(0), m_chan(0), + m_left(L), m_right(R) + {} + OutputState(const QString &e) + : m_type(Error), m_elasped_seconds(0), m_written_bytes(0), + m_brate(0), m_freq(0), m_prec(0), m_chan(0), + m_left(0), m_right(0) + { + m_error_msg = new QString(e); + } + ~OutputState() + { + if (m_error_msg) + delete m_error_msg; + } + + const QString *errorMessage() const + { + return m_error_msg; + } + + const long &elapsedSeconds() const + { + return m_elasped_seconds; + } + const unsigned long &writtenBytes() const + { + return m_written_bytes; + } + const int &bitrate() const + { + return m_brate; + } + const int &frequency() const + { + return m_freq; + } + const int &precision() const + { + return m_prec; + } + const int &channels() const + { + return m_chan; + } + const Type &type() const + { + return m_type; + } + const int leftVolume() const + { + return m_left; + } + const int rightVolume() const + { + return m_right; + } + +private: + Type m_type; + QString *m_error_msg; + long m_elasped_seconds; + unsigned long m_written_bytes; + int m_brate, m_freq, m_prec, m_chan; + int m_left, m_right; //volume +}; + + + + +class Output : public QThread +{ + Q_OBJECT +public: + + Output(QObject * parent = 0); + ~Output(); + + Recycler *recycler() + { + return &r; + } + + QMutex *mutex() + { + return &mtx; + } + + //visualization + void addVisual(Visual*); + void removeVisual(Visual*); + void addVisual(VisualFactory *factory, QWidget *parent); + void removeVisual(VisualFactory *factory); + + // abstract + virtual bool isInitialized() const = 0; + virtual bool initialize() = 0; + virtual void uninitialize() = 0; + virtual void configure(long, int, int, int) = 0; + virtual void pause() = 0; + virtual void stop() = 0; + virtual long written() = 0; + virtual long latency() = 0; + virtual void seek(long) = 0; + virtual void setVolume(int, int){}; + virtual void volume(int*, int*){}; + + static void registerFactory(OutputFactory *); + static Output *create(QObject *); + static QList *outputFactories(); + static QStringList outputFiles(); + +public slots: + void checkVolume(); + void checkSoftwareVolume(); + +signals: + void stateChanged(const OutputState&); + +protected: + void dispatch(OutputState::Type); + void dispatch(long s, unsigned long w, int b, int f, int p, int c); + void dispatch(const OutputState&); + void dispatchVolume(int L, int R); + void error(const QString &e); + void dispatchVisual(Buffer *, unsigned long, int, int); + void clearVisuals(); + +private: + QMutex mtx; + Recycler r; + QList visuals; //external visualization + QMap m_vis_map; //internal visualization + int m_bl, m_br; +}; + + +#endif // OUTPUT_H diff --git a/src/qmmp/outputfactory.h b/src/qmmp/outputfactory.h new file mode 100644 index 000000000..2a5513759 --- /dev/null +++ b/src/qmmp/outputfactory.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef OUTPUTFACTORY_H +#define OUTPUTFACTORY_H + +class QObject; +class QString; +class QIODevice; +class QWidget; +class QTranslator; + +class Decoder; +class Output; + +struct OutputProperties +{ + QString name; + bool hasAbout; + bool hasSettings; +}; + +class OutputFactory +{ +public: + virtual ~OutputFactory() {} + virtual const OutputProperties properties() const = 0; + virtual Output *create(QObject *, bool) = 0; + virtual void showSettings(QWidget *parent) = 0; + virtual void showAbout(QWidget *parent) = 0; + virtual QTranslator *createTranslator(QObject *parent) = 0; +}; + +Q_DECLARE_INTERFACE(OutputFactory, "OutputFactory/1.0") + +#endif diff --git a/src/qmmp/qmmp.pro b/src/qmmp/qmmp.pro new file mode 100644 index 000000000..a583cd45b --- /dev/null +++ b/src/qmmp/qmmp.pro @@ -0,0 +1,66 @@ +# ???? ?????? ? KDevelop ?????????? qmake. +# ------------------------------------------- +# ?????????? ???????????? ???????? ???????? ???????: ./libs +# ???? - ??????????: nnp + +include(../../qmmp.pri) + +HEADERS += recycler.h \ + buffer.h \ + constants.h \ + decoder.h \ + output.h \ + filetag.h \ + outputfactory.h \ + equ\iir_cfs.h \ + equ\iir_fpu.h \ + equ\iir.h \ + decoderfactory.h \ + soundcore.h \ + streamreader.h \ + downloader.h \ + visual.h \ + visualfactory.h \ + effect.h \ + effectfactory.h +SOURCES += recycler.cpp \ + decoder.cpp \ + output.cpp \ + equ\iir.c \ + equ\iir_cfs.c \ + equ\iir_fpu.c \ + soundcore.cpp \ + streamreader.cpp \ + downloader.cpp \ + filetag.cpp \ + visual.cpp \ + effect.cpp + +TARGET = ../../lib/qmmp +CONFIG += release \ +warn_on \ +qt \ +thread \ +link_pkgconfig + +TEMPLATE = lib +PKGCONFIG += libcurl + +isEmpty(LIB_DIR){ + LIB_DIR = /lib +} + +unix { + LINE1 = $$sprintf(echo \"%1ifndef CONFIG_H\" > ./config.h, $$LITERAL_HASH) + LINE2 = $$sprintf(echo \"%1define CONFIG_H\" >> ./config.h, $$LITERAL_HASH) + LINE3 = $$sprintf(echo \"%1define LIB_DIR \\\"%2\\\"\" >> ./config.h, $$LITERAL_HASH, $$LIB_DIR) + LINE4 = $$sprintf(echo \"%1endif\" >> ./config.h, $$LITERAL_HASH) + system($$LINE1) + system($$LINE2) + system($$LINE3) + system($$LINE4) + QMAKE_CLEAN = ./config.h +} + +target.path = $$LIB_DIR +INSTALLS += target diff --git a/src/qmmp/recycler.cpp b/src/qmmp/recycler.cpp new file mode 100644 index 000000000..15d2234a6 --- /dev/null +++ b/src/qmmp/recycler.cpp @@ -0,0 +1,120 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#include "recycler.h" +#include "constants.h" +#include "buffer.h" + + +Recycler::Recycler ( unsigned int sz ) + : add_index ( 0 ), done_index ( 0 ), current_count ( 0 ) +{ + buffer_count = ( sz / Buffer::size() ); + if ( buffer_count < 1 ) + { + buffer_count = 1; + } + + buffers = new Buffer*[buffer_count]; + + for ( unsigned int i = 0; i < buffer_count; i ++ ) + { + buffers[i] = new Buffer; + } +} + + +Recycler::~Recycler() +{ + for ( unsigned int i = 0; i < buffer_count; i++ ) + { + delete buffers[i]; + buffers[i] = 0; + } + + delete [] buffers; +} + + +bool Recycler::full() const +{ + return current_count == buffer_count; +} + + +bool Recycler::empty() const +{ + return current_count == 0; +} + + +int Recycler::available() const +{ + return buffer_count - current_count; +} + +int Recycler::used() const +{ + return current_count; +} + + +Buffer *Recycler::get(unsigned long size) +{ + if (full()) + return 0; + if(size > Buffer::size() + buffers[add_index]->exceeding) + { + delete buffers[add_index]->data; + buffers[add_index]->data = new unsigned char[size]; + buffers[add_index]->exceeding = size - Buffer::size(); + //qDebug("new size = %d, index = %d", size, add_index); + } + + return buffers[add_index]; +} + + +void Recycler::add() +{ + add_index = ++add_index % buffer_count; + current_count++; +} + + +Buffer *Recycler::next() +{ + return buffers[done_index]; +} + + +void Recycler::done() +{ + done_index = ++done_index % buffer_count; + current_count--; +} + + +void Recycler::clear() +{ + add_index = done_index = current_count = 0; + /*for ( unsigned int i = 0; i < buffer_count; i ++ ) + { + if(buffers[i]->exceeding > 0) + { + delete buffers[i]->data; + buffers[i]->data = new unsigned char[Buffer::size()]; + buffers[i]->exceeding = 0; + buffers[i]->nbytes = 0; + } + }*/ +} + + +unsigned int Recycler::size() const +{ + return buffer_count * Buffer::size(); +} diff --git a/src/qmmp/recycler.h b/src/qmmp/recycler.h new file mode 100644 index 000000000..6bb80375d --- /dev/null +++ b/src/qmmp/recycler.h @@ -0,0 +1,49 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#ifndef __recycler_h +#define __recycler_h + +#include +#include + +class Buffer; + + +class Recycler +{ +public: + Recycler(unsigned int sz); // sz = size in bytes + ~Recycler(); + + bool full() const; + bool empty() const; + + int available() const; + int used() const; + + Buffer *next(); // get next in queue + Buffer *get(unsigned long size); // get next in recycle + + void add(); // add to queue + void done(); // add to recycle + + void clear(); // clear queue + + unsigned int size() const; // size in bytes + + QMutex *mutex() { return &mtx; } + QWaitCondition *cond() { return &cnd; } + + +private: + unsigned int buffer_count, add_index, done_index, current_count; + Buffer **buffers; + QMutex mtx; + QWaitCondition cnd; +}; + +#endif // __recycler_h diff --git a/src/qmmp/soundcore.cpp b/src/qmmp/soundcore.cpp new file mode 100644 index 000000000..019b4c78e --- /dev/null +++ b/src/qmmp/soundcore.cpp @@ -0,0 +1,440 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include "decoderfactory.h" +#include "constants.h" +#include "streamreader.h" +#include "effect.h" + +#include "soundcore.h" + + +SoundCore *SoundCore::m_instance = 0; + +SoundCore::SoundCore(QObject *parent) + : QObject(parent) +{ + m_instance = this; + m_decoder = 0; + m_output = 0; + m_input = 0; + m_paused = FALSE; + m_useEQ = FALSE; + m_update = FALSE; + m_block = FALSE; + m_preamp = 0; + m_vis = 0; + m_parentWidget = 0; + for (int i = 1; i < 10; ++i) + m_bands[i] = 0; + m_error = NoError; + m_output = Output::create(this); + if (!m_output) + { + m_error = DecoderError; + qWarning("SoundCore: unable to create output"); + } + connect(m_output, SIGNAL(stateChanged(const OutputState&)), + SIGNAL(outputStateChanged(const OutputState&))); + + QList *outputFactories = Output::outputFactories(); + foreach(OutputFactory* of, *outputFactories) + qApp->installTranslator(of->createTranslator(this)); + + QList *decoderFactories = Decoder::decoderFactories(); + foreach(DecoderFactory* df, *decoderFactories) + qApp->installTranslator(df->createTranslator(this)); + + Effect::effectFactories(); +} + + +SoundCore::~SoundCore() +{} + +bool SoundCore::play(const QString &source) +{ + stop(); + if (source.isEmpty()) + { + m_error = DecoderError; + return FALSE; + } + if (source.left(4) == "http") + { + m_input = new StreamReader(source, this); + connect(m_input, SIGNAL(titleChanged(const QString&)), + SIGNAL(titleChanged(const QString&))); + connect(m_input, SIGNAL(readyRead()),SLOT(decode())); + } + else + m_input = new QFile(source); + + m_error = OutputError; + if (!m_output) + { + m_output = Output::create(this); + if (!m_output) + { + qWarning("SoundCore: unable to create output"); + return FALSE; + } + connect(m_output, SIGNAL(stateChanged(const OutputState&)), + SIGNAL(outputStateChanged(const OutputState&))); + connect(m_input, SIGNAL(readyRead()),SLOT(read())); + } + if (! m_output->initialize()) + return FALSE; + + m_error = DecoderError; + + Visual *visual = 0; + foreach(visual, m_visuals) + m_output->addVisual(visual); + + VisualFactory* factory; + foreach(factory, *Visual::visualFactories()) + { + if (Visual::isEnabled(factory)) + m_output->addVisual(factory, m_parentWidget); + } + + m_source = source; + if (source.left(4) != "http") + return decode(); + else + qobject_cast(m_input)->downloadFile(); + return TRUE; + +} + +uint SoundCore::error() +{ + return m_error; +} + +void SoundCore::stop() +{ + if (m_block) + return; + m_paused = FALSE; + if (m_decoder && m_decoder->isRunning()) + { + m_decoder->mutex()->lock (); + m_decoder->stop(); + m_decoder->mutex()->unlock(); + } + if (m_output) + { + m_output->mutex()->lock (); + m_output->stop(); + m_output->mutex()->unlock(); + } + + // wake up threads + if (m_decoder) + { + m_decoder->mutex()->lock (); + m_decoder->cond()->wakeAll(); + m_decoder->mutex()->unlock(); + } + if (m_output) + { + m_output->recycler()->mutex()->lock (); + m_output->recycler()->cond()->wakeAll(); + m_output->recycler()->mutex()->unlock(); + } + if (m_decoder) + m_decoder->wait(); + if (m_output) + m_output->wait(); + if (m_output && m_output->isInitialized()) + { + m_output->uninitialize(); + } + + //display->setTime(0); + if (m_decoder) + { + delete m_decoder; + m_decoder = 0; + } + if (m_input) + { + delete m_input; + m_input = 0; + } + // recreate output + if (m_update && m_output) + { + delete m_output; + m_output = 0; + m_update = FALSE; + m_output = Output::create(this); + if (!m_output) + { + qWarning("SoundCore: unable to create output"); + } + VisualFactory* factory; + foreach(factory, *Visual::visualFactories()) + { + if (Visual::isEnabled(factory)) + m_output->addVisual(factory, m_parentWidget); + } + connect(m_output, SIGNAL(stateChanged(const OutputState&)), + SIGNAL(outputStateChanged(const OutputState&))); + } +} + +void SoundCore::pause() +{ + if (m_output) + { + m_output->mutex()->lock (); + m_output->pause(); + m_output->mutex()->unlock(); + } + + // wake up threads + if (m_decoder) + { + m_paused = !m_paused; + m_decoder->mutex()->lock (); + m_decoder->cond()->wakeAll(); + m_decoder->mutex()->unlock(); + } + + if (m_output) + { + m_output->recycler()->mutex()->lock (); + m_output->recycler()->cond()->wakeAll(); + m_output->recycler()->mutex()->unlock(); + } +} + +void SoundCore::seek(int pos) +{ + if (m_output && m_output->isRunning()) + { + m_output->recycler()->mutex()->lock (); + m_output->recycler()->clear (); + m_output->recycler()->mutex()->unlock (); + m_output->mutex()->lock (); + m_output->seek(pos); + m_output->mutex()->unlock(); + if (m_decoder && m_decoder->isRunning()) + { + m_decoder->mutex()->lock (); + m_decoder->seek(pos); + m_decoder->mutex()->unlock(); + } + } +} + +int SoundCore::length() +{ + if (m_decoder) + return int(m_decoder->lengthInSeconds()); + return 0; +} + +bool SoundCore::isInitialized() +{ + if (m_decoder) + return TRUE; + return FALSE; +} + +bool SoundCore::isPaused() +{ + return m_paused; +} + +void SoundCore::setEQ(int bands[10], const int &preamp) +{ + for (int i = 0; i < 10; ++i) + m_bands[i] = bands[i]; + m_preamp = preamp; + if (m_decoder) + { + m_decoder->mutex()->lock (); + m_decoder->setEQ(m_bands, m_preamp); + m_decoder->setEQEnabled(m_useEQ); + m_decoder->mutex()->unlock(); + } +} + +void SoundCore::setEQEnabled(bool on) +{ + m_useEQ = on; + if (m_decoder) + { + m_decoder->mutex()->lock (); + m_decoder->setEQ(m_bands, m_preamp); + m_decoder->setEQEnabled(on); + m_decoder->mutex()->unlock(); + } +} + +void SoundCore::setVolume(int L, int R) +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + bool sofVolume = settings.value("Volume/software_volume", FALSE).toBool(); + if (sofVolume) + { + L = qMin(L,100); + R = qMin(R,100); + L = qMax(L,0); + R = qMax(R,0); + settings.setValue("Volume/left", L); + settings.setValue("Volume/right", R); + if (m_decoder) + m_decoder->setVolume(L,R); + if (m_output) + m_output->checkSoftwareVolume(); + } + else if (m_output) + m_output->setVolume(L,R); +} + +void SoundCore::volume(int *left, int *right) +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + bool sofVolume = settings.value("Volume/software_volume", FALSE).toBool(); + if (sofVolume) + { + *left = settings.value("Volume/left", 0).toInt(); + *right = settings.value("Volume/right", 0).toInt(); + } + else if (m_output) + m_output->volume(left,right); + return; +} + +void SoundCore::updateConfig() +{ + m_update = TRUE; + if (isInitialized()) + return; + stop(); +} + +void SoundCore::addVisualization(Visual *visual) +{ + if (m_visuals.indexOf (visual) == -1) + { + m_visuals.append(visual); + if (m_output) + m_output->addVisual(visual); + } +} + +bool SoundCore::decode() +{ + if (! m_decoder) + { + m_block = TRUE; + qDebug ("SoundCore: creating decoder"); + m_decoder = Decoder::create(this, m_source, m_input, m_output); + + if (! m_decoder) + { + qWarning("SoundCore: unsupported fileformat"); + m_block = FALSE; + stop(); + emit decoderStateChanged(DecoderState(DecoderState::Error)); + return FALSE; + } + qDebug ("ok"); + m_decoder->setBlockSize(globalBlockSize); + connect(m_decoder, SIGNAL(stateChanged(const DecoderState&)), + SIGNAL(decoderStateChanged(const DecoderState&))); + setEQ(m_bands, m_preamp); + setEQEnabled(m_useEQ); + } + qDebug("SoundCore: decoder was created successfully"); + + if (m_decoder->initialize()) + { + m_output->start(); + m_decoder->start(); + m_error = NoError; + m_block = FALSE; + return TRUE; + } + stop(); + m_block = FALSE; + return FALSE; +} + +void SoundCore::showVisualization(QWidget *parent) +{ + if (!m_parentWidget) + { + m_parentWidget = parent; + if (!m_output) + return; + VisualFactory* factory; + foreach(factory, *Visual::visualFactories()) + { + if (Visual::isEnabled(factory)) + m_output->addVisual(factory, m_parentWidget); + } + } +} + +void SoundCore::addVisual(VisualFactory *factory, QWidget *parent) +{ + if (m_output) + m_output->addVisual(factory, parent); + else + Visual::setEnabled(factory, TRUE); +} + +void SoundCore::removeVisual(VisualFactory *factory) +{ + if (m_output) + m_output->removeVisual(factory); + else + Visual::setEnabled(factory, FALSE); +} + +void SoundCore::removeVisual(Visual *visual) +{ + if (m_visuals.indexOf (visual) != -1) + { + m_visuals.removeAll(visual); + if (m_output) + m_output->removeVisual(visual); + } +} + +SoundCore* SoundCore::instance() +{ + return m_instance; +} + + diff --git a/src/qmmp/soundcore.h b/src/qmmp/soundcore.h new file mode 100644 index 000000000..3fa785a2a --- /dev/null +++ b/src/qmmp/soundcore.h @@ -0,0 +1,208 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SOUNDCORE_H +#define SOUNDCORE_H + + +#include +#include + +#include "decoder.h" +#include "output.h" +#include "visual.h" + +/** + @author Ilya Kotov +*/ + +class QIODevice; + +class SoundCore : public QObject +{ + Q_OBJECT +public: + + /*! This enum describes the errors that may be returned by the error() function. + * Available values is: + * \b SoundCore:NoError - no error occurred, + * \b SoundCore:DecoderError - an error occurred when creating decoder, + * \b SoundCore:OutputError - an error occurred when creating output. + */ + enum ErrorType { NoError = 0, DecoderError, OutputError }; + + SoundCore(QObject *parent = 0); + + ~SoundCore(); + + + //control + + /*! + * This function plays file with given path, returns \b TRUE if all is OK, otherwise \b FALSE + */ + bool play(const QString &source); + + /*! + * Returns the playback error status. + * For example, if play() returns false, this function can be called to find out + * the reason why the operation failed. + */ + uint error(); + + /*! + * Stops playing + */ + void stop(); + + /*! + * Pauses/resumes playing + */ + void pause(); + + /*! + *This function sets the current play position to \b pos + */ + void seek(int pos); + + // properties + + /*! + * Returns length in seconds + */ + int length(); + + /*! + * Returns \b TRUE if \b play() called successful, otherwise \b FALSE. + */ + bool isReady(); + + /*! + * Returns \b TRUE if \b play() called successful, otherwise \b FALSE. + * Also this function returns \b FALSE if \b stop() called before + */ + bool isInitialized(); + + /*! + * Returns \b TRUE if plugins in pause mode, otherwise \b FALSE. + */ + bool isPaused(); + + //equalizer + + /*! + * Sets equalizer settings. Each item of \b bands[] and \b reamp should be + * \b -100..100 + */ + void setEQ(int bands[10], const int &preamp); + + /*! + * Enables equalizer if on is \b TRUE or disables it if on is \b FALSE + */ + void setEQEnabled(bool on); + + //volume + + /*! + * Sets volume. \b L - volume of left channel. \b R - volume of right channel. + * \b L and \b R should be 0..100 + */ + void setVolume(int L, int R); + + void volume(int*, int*); + + //config + + /*! + * updates configuration + */ + void updateConfig(); + + //visualization + /*! + * adds visualization \b visual + */ + void addVisualization(Visual *visual); + + /*! + * shows enabled visualization with parent widget \b parent + */ + void showVisualization(QWidget *parent); + + /*! + * adds visualization by factory \b factory + */ + void addVisual(VisualFactory *factory, QWidget *parent); + + /*! + * removes visualization by factory \b factory + */ + void removeVisual(VisualFactory *factory); + + /*! + * removes visualization \b visual + */ + void removeVisual(Visual *visual); + + static SoundCore* instance(); + +signals: + + /*! + * This signal is emited when the state of the decoder changes. + * The argument \b state is the new state of the decoder + */ + void decoderStateChanged(const DecoderState& state); + + /*! + * This signal is emited when the state of the output changes. + * The argument \b state is the new state of the output + */ + void outputStateChanged(const OutputState& state); + + /*! + * This signal is emited when the title of the stream changes. + * The argument \b title is the new title of the stream. + * Signal emits with the shoutcast server stream only. + * For another servers use decoderStateChanged() + */ + void titleChanged(const QString& title); + +private slots: + bool decode(); + +private: + Decoder* m_decoder; + Output* m_output; + QIODevice* m_input; + uint m_error; + bool m_paused; + bool m_useEQ; + bool m_update; + bool m_block; + int m_preamp; + int m_bands[10]; + Visual *m_vis; + QList m_visuals; + QString m_source; + QWidget *m_parentWidget; + static SoundCore* m_instance; +}; + +#endif diff --git a/src/qmmp/streamreader.cpp b/src/qmmp/streamreader.cpp new file mode 100644 index 000000000..30bb9c3a7 --- /dev/null +++ b/src/qmmp/streamreader.cpp @@ -0,0 +1,139 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +#include "downloader.h" +#include "streamreader.h" + +StreamReader::StreamReader(const QString &name, QObject *parent) + : QIODevice(parent) +{ + m_downloader = new Downloader(this, name); + connect(m_downloader, SIGNAL(titleChanged()),SLOT(updateTitle())); + connect(m_downloader, SIGNAL(readyRead()), SIGNAL(readyRead())); +} + +StreamReader::~StreamReader() +{ + m_downloader->abort(); + qDebug("StreamReader::~StreamReader()"); +} + +bool StreamReader::atEnd () const +{ + return FALSE; +} + +qint64 StreamReader::bytesAvailable () const +{ + return m_downloader->bytesAvailable (); +} + +qint64 StreamReader::bytesToWrite () const +{ + return -1; +} + +bool StreamReader::canReadLine () const +{ + return FALSE; +} + +void StreamReader::close () +{ + m_downloader->abort(); +} + +bool StreamReader::isSequential () const +{ + return TRUE; +} + +bool StreamReader::open ( OpenMode mode ) +{ + if (mode != QIODevice::ReadOnly) + return FALSE; + //downloadFile(); + setOpenMode(QIODevice::ReadOnly); + if (m_downloader->isRunning() && m_downloader->isReady()) + return TRUE; + else + return FALSE; +} + +bool StreamReader::reset () +{ + QIODevice::reset(); + return TRUE; +} + +bool StreamReader::seek ( qint64 pos ) +{ + QIODevice::seek(pos); + return FALSE; +} + +qint64 StreamReader::size () const +{ + return bytesAvailable (); +} + +bool StreamReader::waitForBytesWritten ( int msecs ) +{ + usleep(msecs*1000); + return TRUE; +} + +bool StreamReader::waitForReadyRead ( int msecs ) +{ + usleep(msecs*1000); + return TRUE; +} + +qint64 StreamReader::readData(char* data, qint64 maxlen) +{ + return m_downloader->read (data, maxlen); +} + +qint64 StreamReader::writeData(const char*, qint64) +{ + return 0; +} + +void StreamReader::downloadFile() +{ + m_downloader->start(); +} + +void StreamReader::updateTitle() +{ + emit titleChanged(m_downloader->title()); +} + +const QString &StreamReader::contentType() +{ + m_downloader->mutex()->lock (); + m_contentType = m_downloader->contentType(); + m_downloader->mutex()->unlock(); + qApp->processEvents(); + qDebug("StreamReader: content type: %s", qPrintable(m_contentType)); + return m_contentType; +} diff --git a/src/qmmp/streamreader.h b/src/qmmp/streamreader.h new file mode 100644 index 000000000..c8182153a --- /dev/null +++ b/src/qmmp/streamreader.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef STREAMREADER_H +#define STREAMREADER_H + +#include +#include +#include + +class QFileInfo; + +class Downloader; + +/** + @author Ilya Kotov +*/ +class StreamReader : public QIODevice +{ + Q_OBJECT +public: + StreamReader(const QString &name, QObject *parent = 0); + + ~StreamReader(); + + /** + * QIODevice API + */ + bool atEnd () const; + qint64 bytesAvailable () const; + qint64 bytesToWrite () const; + bool canReadLine () const; + void close (); + bool isSequential () const; + bool open ( OpenMode mode ); + //qint64 pos () const; + bool reset (); + bool seek ( qint64 pos ); + qint64 size () const; + bool waitForBytesWritten ( int msecs ); + bool waitForReadyRead ( int msecs ); + + /** + * returns content type of a stream + */ + const QString &contentType(); + void downloadFile(); + +signals: + void titleChanged(const QString&); + void readyRead(); + +protected: + qint64 readData(char*, qint64); + qint64 writeData(const char*, qint64); + + +private slots: + void updateTitle(); + +private: + //void downloadFile(); + void fillBuffer(); + QUrl m_url; + QString m_contentType; + Downloader *m_downloader; +}; + +#endif diff --git a/src/qmmp/visual.cpp b/src/qmmp/visual.cpp new file mode 100644 index 000000000..ce5e8a982 --- /dev/null +++ b/src/qmmp/visual.cpp @@ -0,0 +1,151 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "visualfactory.h" +#include "constants.h" +#include "output.h" + +#include "visual.h" + + +static QList *factories = 0; +static QStringList files; + +static void checkFactories() +{ + if (! factories) + { + files.clear(); + factories = new QList; + + QDir pluginsDir (qApp->applicationDirPath()); + pluginsDir.cdUp(); + pluginsDir.cd("./"LIB_DIR"/qmmp/Visual"); + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) + { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (loader.isLoaded()) + { + qDebug("Visual: plugin loaded - %s", qPrintable(fileName)); + } + VisualFactory *factory = 0; + if (plugin) + factory = qobject_cast(plugin); + + if (factory) + { + factories->append(factory); + files << pluginsDir.absoluteFilePath(fileName); + } + } + } +} + + +Visual::Visual(QWidget *parent) : QWidget(parent) +{ + setAttribute(Qt::WA_DeleteOnClose, TRUE); + setAttribute(Qt::WA_QuitOnClose, FALSE); +} + +Visual::~Visual() +{ + qDebug("Visual::~Visual()"); +} + +Decoder *Visual::decoder() const +{ + return m_decoder; +} + +void Visual::setDecoder(Decoder *decoder) +{ + m_decoder = decoder; +} + +Output *Visual::output() const +{ + return m_output; +} + +void Visual::setOutput(Output *output) +{ + m_output = output; +} + +QMutex *Visual::mutex() +{ + return &m_mutex; +} + +QList *Visual::visualFactories() +{ + checkFactories(); + return factories; +} + +QStringList Visual::visualFiles() +{ + checkFactories(); + return files; +} + +void Visual::setEnabled(VisualFactory* factory, bool enable) +{ + checkFactories(); + if(!factories->contains(factory)) + return; + + QString name = files.at(factories->indexOf(factory)).section('/',-1); + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + QStringList visList = settings.value("Visualization/plugin_files").toStringList(); + + if(enable) + { + if (!visList.contains(name)) + visList << name; + } + else + visList.removeAll(name); + settings.setValue("Visualization/plugin_files", visList); +} + +bool Visual::isEnabled(VisualFactory* factory) +{ + checkFactories(); + if(!factories->contains(factory)) + return FALSE; + QString name = files.at(factories->indexOf(factory)).section('/',-1); + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + QStringList visList = settings.value("Visualization/plugin_files").toStringList(); + return visList.contains(name); +} + +void Visual::closeEvent (QCloseEvent *event) +{ + m_output->removeVisual(this); + QWidget::closeEvent(event); +} diff --git a/src/qmmp/visual.h b/src/qmmp/visual.h new file mode 100644 index 000000000..ef663bb37 --- /dev/null +++ b/src/qmmp/visual.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef VISUAL_H +#define VISUAL_H + +/** + @author Ilya Kotov +*/ + +#include +#include +#include +#include + +class Buffer; +class Decoder; +class Output; +class VisualFactory; + +class Visual : public QWidget +{ + Q_OBJECT +public: + Visual(QWidget *parent); + + virtual ~Visual(); + + virtual void add(Buffer *, unsigned long, int, int) = 0; + virtual void clear() = 0; + + Decoder *decoder() const; + void setDecoder(Decoder *decoder); + Output *output() const; + void setOutput(Output *output); + QMutex *mutex(); + + //static methods + static QList *visualFactories(); + static QStringList visualFiles(); + static void setEnabled(VisualFactory* factory, bool enable = TRUE); + static bool isEnabled(VisualFactory* factory); + +protected: + virtual void closeEvent (QCloseEvent *); + +private: + Decoder *m_decoder; + Output *m_output; + QMutex m_mutex; +}; + +#endif diff --git a/src/qmmp/visualfactory.h b/src/qmmp/visualfactory.h new file mode 100644 index 000000000..6862032bb --- /dev/null +++ b/src/qmmp/visualfactory.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef VISUALFACTORY_H +#define VISUALFACTORY_H + +class QObject; +class QWidget; +class QTranslator; + +class Visual; + +struct VisualProperties +{ + QString name; + bool hasAbout; + bool hasSettings; +}; + +class VisualFactory +{ +public: + virtual ~VisualFactory() {} + virtual const VisualProperties properties() const = 0; + virtual Visual *create(QWidget *parent) = 0; + virtual void showSettings(QWidget *parent) = 0; + virtual void showAbout(QWidget *parent) = 0; + virtual QTranslator *createTranslator(QObject *parent) = 0; +}; + +Q_DECLARE_INTERFACE(VisualFactory, "VisualFactory/1.0"); + +#endif diff --git a/src/qmmpstarter.cpp b/src/qmmpstarter.cpp deleted file mode 100644 index 56b1773b7..000000000 --- a/src/qmmpstarter.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -#include "unixdomainsocket.h" -#include - -#include "mainwindow.h" -#include "version.h" -#include "qmmpstarter.h" - -#define MAXCOMMANDSIZE 1024 - -QMMPStarter::QMMPStarter(int argc,char ** argv,QObject* parent) : QObject(parent),mw(NULL) -{ - QStringList tmp; - for(int i = 1;i < argc;i++) - tmp << QString::fromLocal8Bit(argv[i]); - - argString = tmp.join("\n"); - - if(argString == "--help") - { - printUsage(); - exit(0); - } - else if(argString == "--version") - { - printVersion(); - exit(0); - } - - if(argString.startsWith("--") && // command? - argString != "--play" && - argString != "--previous" && - argString != "--next" && - argString != "--stop" && - argString != "--pause" && - argString != "--play-pause" - ) - { - qFatal("QMMP: Unknown command..."); - exit(1); - } - - m_sock = new UnixDomainSocket(this); - if(m_sock->bind(UDS_PATH)) - { - startMainWindow(); - } - else if(!m_sock->alive(UDS_PATH)){ - // Socket is present but not connectable - application was terminated previously??? - unlink(UDS_PATH); - if(m_sock->bind(UDS_PATH)) - { - startMainWindow(); - } - else - { - qDebug("Fatal socket error, exiting"); - exit(1); - } - } - else // socket is alive, qmmp application is already running. passing command to it! - writeCommand(); -} - -QMMPStarter::~ QMMPStarter() -{ - qWarning("QMMPStarter::~ QMMPStarter()"); - if(mw) delete mw; -} - -void QMMPStarter::startMainWindow() -{ - connect(m_sock, SIGNAL(readyRead()),this, SLOT(readCommand())); - QStringList arg_l = argString.split("\n", QString::SkipEmptyParts); - mw = new MainWindow(arg_l,0); -} - -void QMMPStarter::writeCommand() -{ - if(!argString.isEmpty()) - { - char buf[PATH_MAX + 1]; - QString workingDir = QString(getcwd(buf,PATH_MAX)) + "\n"; - - QByteArray barray; - barray.append(workingDir); - barray.append(argString); - m_sock->writeDatagram ( barray.data(),UDS_PATH); - } - else - { - printUsage(); - } - - exit(0); -} - -void QMMPStarter::readCommand() -{ - QByteArray inputArray; - inputArray.resize(MAXCOMMANDSIZE); - bzero(inputArray.data(),inputArray.size()); - m_sock->readDatagram(inputArray.data(), inputArray.size()); - QStringList slist = QString(inputArray).split("\n",QString::SkipEmptyParts); - QString cwd = slist.takeAt(0); - if(mw) - { - mw->processCommandArgs(slist,cwd); - } - -} - -void QMMPStarter::printUsage() -{ - qWarning( - "Usage: qmmp [options] [files] \n" - "Options:\n" - "--------\n" - "--help Display this text and exit.\n" - "--previous Skip backwards in playlist\n" - "--play Start playing current playlist\n" - "--pause Pause current song\n" - "--play-pause Pause if playing, play otherwise\n" - "--stop Stop current song\n" - "--next Skip forward in playlist\n" - "--version Print version number and exit.\n\n" - "Ideas, patches, bugreports send to forkotov02@hotmail.ru\n" - ); -} - -void QMMPStarter::printVersion() -{ - qWarning("QMMP version: %s",QMMP_STR_VERSION); -} - - - diff --git a/src/qmmpstarter.h b/src/qmmpstarter.h deleted file mode 100644 index c859496cf..000000000 --- a/src/qmmpstarter.h +++ /dev/null @@ -1,72 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ - -#ifndef _QMMPSTARTER_H -#define _QMMPSTARTER_H - -#include -#include -#include - -class UnixDomainSocket; -class MainWindow; - - -/*! - * QMMPStarter represents wrapper object that is responsible - * for proper QMMP initialization(only one instance of running - * MainWindow) and passing command line args to application. - * @author Vladimir Kuznetsov - */ -class QMMPStarter : public QObject -{ -Q_OBJECT -public: - QMMPStarter(int argc,char ** argv,QObject* parent = 0); - ~QMMPStarter(); -protected slots: - - /*! - * Passes command args to the running application - */ - void writeCommand(); - - void readCommand(); -private: - /*! - * Prints usage - */ - void printUsage(); - - /*! - * Prints version of program - */ - void printVersion(); - - void startMainWindow(); -private: - MainWindow* mw; - UnixDomainSocket* m_sock; - QString argString; -}; - -#endif - - diff --git a/src/qmmpui/general.cpp b/src/qmmpui/general.cpp new file mode 100644 index 000000000..aebd06647 --- /dev/null +++ b/src/qmmpui/general.cpp @@ -0,0 +1,157 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "config.h" +#include "general.h" + + +static QList *factories = 0; +static QStringList files; + +static void checkFactories() +{ + if (! factories) + { + files.clear(); + factories = new QList; + + QDir pluginsDir (qApp->applicationDirPath()); + pluginsDir.cdUp(); + pluginsDir.cd("./"LIB_DIR"/qmmp/General"); + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) + { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (loader.isLoaded()) + { + qDebug("General: plugin loaded - %s", qPrintable(fileName)); + } + GeneralFactory *factory = 0; + if (plugin) + factory = qobject_cast(plugin); + + if (factory) + { + factories->append(factory); + files << pluginsDir.absoluteFilePath(fileName); + } + } + } +} + +General::General(QObject *parent) + : QObject(parent) +{ +} + + +General::~General() +{ +} + +void General::setState(const uint&) +{} + +void General::setSongInfo(const SongInfo &song) +{} + + +QList *General::generalFactories() +{ + checkFactories(); + return factories; +} + +QStringList General::generalFiles() +{ + checkFactories(); + return files; +} + +void General::setEnabled(GeneralFactory* factory, bool enable) +{ + checkFactories(); + if(!factories->contains(factory)) + return; + + QString name = files.at(factories->indexOf(factory)).section('/',-1); + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + QStringList genList = settings.value("General/plugin_files").toStringList(); + + if(enable) + { + if (!genList.contains(name)) + genList << name; + } + else + genList.removeAll(name); + settings.setValue("General/plugin_files", genList); +} + +bool General::isEnabled(GeneralFactory* factory) +{ + checkFactories(); + if(!factories->contains(factory)) + return FALSE; + QString name = files.at(factories->indexOf(factory)).section('/',-1); + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + QStringList genList = settings.value("General/plugin_files").toStringList(); + return genList.contains(name); +} + +void General::play() +{ + emit commandCalled(Play); +} + +void General::pause() +{ + emit commandCalled(Pause); +} + +void General::stop() +{ + emit commandCalled(Stop); +} + +void General::next() +{ + emit commandCalled(Next); +} + +void General::previous() +{ + emit commandCalled(Previous); +} + +void General::exit() +{ + emit commandCalled(Exit); +} + +void General::toggleVisibility() +{ + emit commandCalled(ToggleVisibility); +} diff --git a/src/qmmpui/general.h b/src/qmmpui/general.h new file mode 100644 index 000000000..a7cc0e142 --- /dev/null +++ b/src/qmmpui/general.h @@ -0,0 +1,86 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef GENERAL_H +#define GENERAL_H + +#include +#include +#include + +#include "songinfo.h" +#include "generalfactory.h" + +/** + @author Ilya Kotov +*/ +class General : public QObject +{ + Q_OBJECT +public: + General(QObject *parent = 0); + + ~General(); + + enum State + { + Playing = 0, + Paused, + Stopped + }; + + enum Command + { + Play = 0, + Stop, + Pause, + Previous, + Next, + Exit, + ToggleVisibility + }; + + virtual void setState(const uint &state); + virtual void setSongInfo(const SongInfo &song); + + //static methods + static QList *generalFactories(); + static QStringList generalFiles(); + static void setEnabled(GeneralFactory* factory, bool enable = TRUE); + static bool isEnabled(GeneralFactory* factory); + +signals: + void commandCalled(uint command); + +public slots: + void play(); + void pause(); + void stop(); + void next(); + void previous(); + void exit(); + void toggleVisibility(); + +private: + QMap m_strValues; + QMap m_numValues; + +}; + +#endif diff --git a/src/qmmpui/generalfactory.h b/src/qmmpui/generalfactory.h new file mode 100644 index 000000000..3038b597c --- /dev/null +++ b/src/qmmpui/generalfactory.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef GENERALFACTORY_H +#define GENERALFACTORY_H + +/** + @author Ilya Kotov +*/ +class QObject; +class QTranslator; + +class General; + +struct GeneralProperties +{ + QString name; + bool hasAbout; + bool hasSettings; +}; + +class GeneralFactory +{ +public: + virtual ~GeneralFactory() {} + virtual const GeneralProperties properties() const = 0; + virtual General *create(QObject *parent) = 0; + virtual void showSettings(QWidget *parent) = 0; + virtual void showAbout(QWidget *parent) = 0; + virtual QTranslator *createTranslator(QObject *parent) = 0; +}; + +Q_DECLARE_INTERFACE(GeneralFactory, "GeneralFactory/1.0"); + + +#endif diff --git a/src/qmmpui/generalhandler.cpp b/src/qmmpui/generalhandler.cpp new file mode 100644 index 000000000..dc29f281a --- /dev/null +++ b/src/qmmpui/generalhandler.cpp @@ -0,0 +1,143 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "general.h" +#include "generalfactory.h" + +#include "generalhandler.h" + +GeneralHandler *GeneralHandler::m_instance = 0; + +GeneralHandler::GeneralHandler(QObject *parent) + : QObject(parent) +{ + m_instance = this; + m_state = General::Stopped; + GeneralFactory* factory; + foreach(factory, *General::generalFactories()) + { + if (General::isEnabled(factory)) + { + General *general = factory->create(parent); + connect(general, SIGNAL(commandCalled(uint)), SLOT(processCommand(uint))); + m_generals.append(general); + } + } +} + +GeneralHandler::~GeneralHandler() +{} + +void GeneralHandler::setState(uint state) +{ + if (state == m_state) + return; + m_state = state; + General *general; + if (state == General::Stopped) + m_songInfo.clear(); + + foreach(general, m_generals) + { + general->setState(state); + } +} + +void GeneralHandler::setSongInfo(const SongInfo &info) +{ + if (m_state == General::Stopped) + return; + if (m_songInfo != info) + { + m_songInfo = info; + General *general; + foreach(general, m_generals) + { + general->setSongInfo(m_songInfo); + } + } +} + +void GeneralHandler::updateConfig() +{ + while (!m_generals.isEmpty()) + delete m_generals.takeFirst(); + + GeneralFactory* factory; + foreach(factory, *General::generalFactories()) + { + if (General::isEnabled(factory)) + { + General *general = factory->create(parent()); + connect(general, SIGNAL(commandCalled(uint)), SLOT(processCommand(uint))); + m_generals.append(general); + general->setState(m_state); + if (m_state != General::Stopped) + general->setSongInfo(m_songInfo); + } + } +} + +GeneralHandler* GeneralHandler::instance() +{ + return m_instance; +} + +void GeneralHandler::processCommand(uint command) +{ + switch ((uint) command) + { + case General::Play: + { + emit playCalled(); + break; + } + case General::Stop: + { + emit stopCalled(); + break; + } + case General::Pause: + { + emit pauseCalled(); + break; + } + case General::Previous: + { + emit previousCalled(); + break; + } + case General::Next: + { + emit nextCalled(); + break; + } + case General::Exit: + { + emit exitCalled(); + break; + } + case General::ToggleVisibility: + { + emit toggleVisibilityCalled(); + break; + } + } +} diff --git a/src/qmmpui/generalhandler.h b/src/qmmpui/generalhandler.h new file mode 100644 index 000000000..308a0a694 --- /dev/null +++ b/src/qmmpui/generalhandler.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef GENERALHANDLER_H +#define GENERALHANDLER_H + +#include + +#include "songinfo.h" + +class General; +class GeneralFactory; + +/** + @author Ilya Kotov +*/ +class GeneralHandler : public QObject +{ + Q_OBJECT +public: + GeneralHandler(QObject *parent = 0); + + ~GeneralHandler(); + + void setSongInfo(const SongInfo &info); + void updateConfig(); + static GeneralHandler* instance(); + +signals: + void playCalled(); + void pauseCalled(); + void stopCalled(); + void nextCalled(); + void previousCalled(); + void exitCalled(); + void toggleVisibilityCalled(); + +public slots: + void setState(uint state); + +private slots: + void processCommand(uint command); + +private: + void connectSignals(General*); + QList m_generals; + SongInfo m_songInfo; + uint m_state; + static GeneralHandler* m_instance; + +}; + +#endif diff --git a/src/qmmpui/qmmpui.pro b/src/qmmpui/qmmpui.pro new file mode 100644 index 000000000..88c60a0da --- /dev/null +++ b/src/qmmpui/qmmpui.pro @@ -0,0 +1,38 @@ +include(../../qmmp.pri) + +TARGET = ../../lib/qmmpui +CONFIG += release \ +warn_on \ +qt \ +thread + +TEMPLATE = lib + + +isEmpty(LIB_DIR){ + LIB_DIR = /lib +} + +unix { + LINE1 = $$sprintf(echo \"%1ifndef CONFIG_H\" > ./config.h, $$LITERAL_HASH) + LINE2 = $$sprintf(echo \"%1define CONFIG_H\" >> ./config.h, $$LITERAL_HASH) + LINE3 = $$sprintf(echo \"%1define LIB_DIR \\\"%2\\\"\" >> ./config.h, $$LITERAL_HASH, $$LIB_DIR) + LINE4 = $$sprintf(echo \"%1endif\" >> ./config.h, $$LITERAL_HASH) + system($$LINE1) + system($$LINE2) + system($$LINE3) + system($$LINE4) + QMAKE_CLEAN = ./config.h +} + + +target.path = $$LIB_DIR +INSTALLS += target +HEADERS += general.h \ +generalfactory.h \ + generalhandler.h \ + songinfo.h +SOURCES += general.cpp \ + generalhandler.cpp \ + songinfo.cpp + diff --git a/src/qmmpui/songinfo.cpp b/src/qmmpui/songinfo.cpp new file mode 100644 index 000000000..6fa1e831e --- /dev/null +++ b/src/qmmpui/songinfo.cpp @@ -0,0 +1,137 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "songinfo.h" + +SongInfo::SongInfo() +{} + +SongInfo::SongInfo(const SongInfo &other) +{ + *this = other; +} + +SongInfo::~SongInfo() +{} + +void SongInfo::operator=(const SongInfo &info) +{ + setValue(TITLE,info.title ()); + setValue(ARTIST,info.artist ()); + setValue(ALBUM,info.album ()); + setValue(COMMENT,info.comment ()); + setValue(GENRE,info.genre ()); + setValue(YEAR,info.year ()); + setValue(TRACK,info.track ()); + setValue(LENGTH,info.length ()); + setValue(STREAM,info.isStream()); +} + +bool SongInfo::operator==(const SongInfo &info) +{ + return title() == info.title() && + artist() == info.artist() && + album() == info.album() && + comment() == info.comment() && + genre() == info.genre() && + track() == info.track() && + year() == info.year() && + isStream() == info.isStream(); +} + +bool SongInfo::operator!=(const SongInfo &info) +{ + return !operator==(info); +} + +void SongInfo::setValue(uint name, const QString &value) +{ + if (!value.isEmpty()) + m_strValues.insert (name, value); +} + +void SongInfo::setValue(uint name, const uint &value) +{ + if (value > 0) + m_numValues.insert (name, value); +} + +void SongInfo::setValue(uint name, const bool &value) +{ + if(name == STREAM) + m_stream = value; +} + +const QString SongInfo::title () const +{ + return m_strValues[TITLE]; +} + +const QString SongInfo::artist () const +{ + return m_strValues[ARTIST]; +} + +const QString SongInfo::album () const +{ + return m_strValues[ALBUM]; +} + +const QString SongInfo::comment () const +{ + return m_strValues[COMMENT]; +} + +const QString SongInfo::genre () const +{ + return m_strValues[GENRE]; +} + +const uint SongInfo::year () const +{ + return m_numValues[YEAR]; +} + +const uint SongInfo::track () const +{ + return m_numValues[TRACK]; +} + +const uint SongInfo::length () const +{ + return m_numValues[LENGTH]; +} + +const bool SongInfo::isEmpty () const +{ + return m_strValues.isEmpty(); +} + +void SongInfo::clear () +{ + m_strValues.clear(); + m_numValues.clear(); + m_stream = FALSE; +} + +const bool SongInfo::isStream () const +{ + return m_stream; +} + diff --git a/src/qmmpui/songinfo.h b/src/qmmpui/songinfo.h new file mode 100644 index 000000000..7bc43381d --- /dev/null +++ b/src/qmmpui/songinfo.h @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SONGINFO_H +#define SONGINFO_H + +#include +#include + +/** + @author Ilya Kotov +*/ + +class SongInfo{ +public: + public: + SongInfo(); + SongInfo(const SongInfo &other); + + ~SongInfo(); + + enum Type + { + TITLE = 0, + ARTIST, + ALBUM, + COMMENT, + GENRE, + YEAR, + TRACK, + LENGTH, + STREAM + }; + + void operator=(const SongInfo &info); + bool operator==(const SongInfo &info); + bool operator!=(const SongInfo &info); + void setValue(uint name, const QString &value); + void setValue(uint name, const uint &value); + void setValue(uint name, const bool &value); + const QString title () const; + const QString artist () const; + const QString album () const; + const QString comment () const; + const QString genre () const; + const uint year () const; + const uint track () const; + const uint length () const; + const bool isEmpty () const; + const bool isStream () const; + void clear(); + +private: + QMap m_strValues; + QMap m_numValues; + bool m_stream; + +}; + +#endif diff --git a/src/shadedbar.cpp b/src/shadedbar.cpp deleted file mode 100644 index 63b2017c0..000000000 --- a/src/shadedbar.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include -#include - -#include "skin.h" - -#include "shadedbar.h" - -ShadedBar::ShadedBar(QWidget *parent, uint slider1, uint slider2, uint slider3) - : QWidget(parent) -{ - m_slider1 = slider1; - m_slider2 = slider2; - m_slider3 = slider3; - setFixedSize(97,7); - //setAutoFillBackground (TRUE); - m_skin = Skin::getPointer(); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); - m_moving = FALSE; - m_min = 0; - m_max = 100; - m_old = m_value = 0; - draw(); -} - - -ShadedBar::~ShadedBar() -{ -} - -void ShadedBar::mousePressEvent(QMouseEvent *e) -{ - - m_moving = TRUE; - press_pos = e->x(); - if(m_posx() && e->x()x()-m_pos; - } - else - { - m_value = convert(qMax(qMin(width()-3,e->x()-1),0)); - press_pos = 1; - if (m_value!=m_old) - { - emit sliderMoved(m_value); - } - } - draw(); -} - -void ShadedBar::mouseMoveEvent (QMouseEvent *e) -{ - if(m_moving) - { - int po = e->x(); - po = po - press_pos; - - if(0<=po && po<=width()-3) - { - m_value = convert(po); - draw(); - emit sliderMoved(m_value); - qDebug("%d", m_value); - } - } -} - -void ShadedBar::mouseReleaseEvent(QMouseEvent*) -{ - m_moving = FALSE; - draw(); - m_old = m_value; -} - -void ShadedBar::setValue(int v) -{ - if (m_moving || m_max == 0) - return; - m_value = v; - draw(); -} - -void ShadedBar::setRange(int min, int max) -{ - m_max = max; - m_min = min; - draw(); -} - -void ShadedBar::updateSkin() -{ - draw(); -} - -void ShadedBar::draw() -{ - if (m_value <= m_min + (m_max - m_min)/3) - m_pixmap = m_skin->getEqPart(m_slider1); - else if(m_min + (m_max - m_min)/3 < m_value && m_value <= m_min + 2*(m_max - m_min)/3) - m_pixmap = m_skin->getEqPart(m_slider2); - else - m_pixmap = m_skin->getEqPart(m_slider3); - m_pos = int(ceil(double(m_value-m_min)*(width()-3)/(m_max-m_min))); - update(); -} - -int ShadedBar::convert(int p) -{ - return int(ceil(double(m_max-m_min)*(p)/(width()-3)+m_min)); -} - -void ShadedBar::paintEvent(QPaintEvent*) -{ - QPainter paint(this); - paint.drawPixmap(m_pos,0,m_pixmap); -} - diff --git a/src/shadedbar.h b/src/shadedbar.h deleted file mode 100644 index 4ea8c871f..000000000 --- a/src/shadedbar.h +++ /dev/null @@ -1,77 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef SHADEDBAR_H -#define SHADEDBAR_H - -#include - -class QMouseEvent; -class QPaintEvent; - -class Skin; - - -/** - @author Ilya Kotov -*/ -class ShadedBar : public QWidget -{ - Q_OBJECT -public: - ShadedBar(QWidget *parent = 0, uint slider1 = 0, uint slider2 = 0, uint slider3 = 0); - - ~ShadedBar(); - int value() - { - return m_value; - }; - int isPressed() - { - return m_moving; - } - void setRange(int min, int max); - -public slots: - void setValue(int); - -signals: - void sliderMoved (int); - -private slots: - void updateSkin(); - -private: - Skin *m_skin; - bool m_moving; - int press_pos; - int m_max, m_min, m_pos, m_value, m_old, m_x; - QPixmap m_pixmap; - int convert(int); // value = convert(position); - void draw(); - uint m_slider1, m_slider2, m_slider3; - -protected: - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); - void paintEvent(QPaintEvent*); -}; - -#endif diff --git a/src/shadedvisual.cpp b/src/shadedvisual.cpp deleted file mode 100644 index 2dea3d419..000000000 --- a/src/shadedvisual.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include "skin.h" -#include "mainvisual.h" -#include "inlines.h" - - -#include "shadedvisual.h" - -ShadedVisual::ShadedVisual(QWidget *parent) - : Visual(parent) -{ - setFixedSize(38,5); - m_pixmap = QPixmap (38,5); - m_skin = Skin::getPointer(); - m_timer = new QTimer(this); - connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout())); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); - m_timer->setInterval(50); - m_timer->start(); - clear(); -} - - -ShadedVisual::~ShadedVisual() -{} - -void ShadedVisual::add(Buffer *b, unsigned long w, int c, int p) -{ - if (!m_timer->isActive ()) - return; - long len = b->nbytes, cnt; - short *l = 0, *r = 0; - - len /= c; - len /= ( p / 8 ); - if ( len > 512 ) - len = 512; - cnt = len; - - if ( c == 2 ) - { - l = new short[len]; - r = new short[len]; - - if ( p == 8 ) - stereo16_from_stereopcm8 ( l, r, b->data, cnt ); - else if ( p == 16 ) - stereo16_from_stereopcm16 ( l, r, ( short * ) b->data, cnt ); - } - else if ( c == 1 ) - { - l = new short[len]; - - if ( p == 8 ) - mono16_from_monopcm8 ( l, b->data, cnt ); - else if ( p == 16 ) - mono16_from_monopcm16 ( l, ( short * ) b->data, cnt ); - } - else - len = 0; - - if (len) - m_nodes.append (new VisualNode (l, r, len, w)); -} - -void ShadedVisual::clear() -{ - while (!m_nodes.isEmpty()) - m_nodes.removeFirst(); - m_l = 0; - m_r = 0; - m_pixmap.fill(m_skin->getVisColor(0)); - update(); -}; - -void ShadedVisual::timeout() -{ - VisualNode *node = 0; - m_pixmap.fill(m_skin->getVisColor(0)); - - if ( /*playing &&*/ output()) - { - //output()->mutex()->lock (); - //long olat = output()->latency(); - //long owrt = output()->written(); - //output()->mutex()->unlock(); - - //long synctime = owrt < olat ? 0 : owrt - olat; - - mutex()->lock (); - VisualNode *prev = 0; - while ((!m_nodes.isEmpty())) - { - node = m_nodes.takeFirst(); - /*if ( node->offset > synctime ) - break;*/ - - if (prev) - delete prev; - prev = node; - } - mutex()->unlock(); - node = prev; - } - - if (!node) - return; - process (node); - delete node; - QPainter p(&m_pixmap); - draw (&p); - update(); -} - -void ShadedVisual::process (VisualNode *node) -{ - if (!node) - return; - - int step = (node->length << 8)/74; - int pos = 0; - int l = 0; - int r = 0; - int j_l = 0, j_r = 0; - - for (int i = 0; i < 75; ++i) - { - pos += step; - - if (node->left) - { - j_l = abs((node->left[pos >> 8] >> 12)); - - if (j_l > 15) - j_l = 15; - l = qMax(l, j_l); - } - if (node->right) - { - j_r = abs((node->right[pos >> 8] >> 12)); - if (j_r > 15) - j_r = 15; - r = qMax(r, j_r); - } - } - m_l -= 0.5; - m_l = m_l > l ? m_l : l; - m_r -= 0.5; - m_r = m_r > r ? m_r : r; -} - -void ShadedVisual::draw (QPainter *p) -{ - for (int i = 0; i < m_l; ++i) - { - p->fillRect (i*3, 0, 3, 2, QBrush(m_skin->getVisColor (17-i))); - } - for (int i = 0; i < m_r; ++i) - { - p->fillRect (i*3, 3, 3, 2, QBrush(m_skin->getVisColor (17-i))); - } -} - -void ShadedVisual::paintEvent (QPaintEvent *) -{ - QPainter painter (this); - painter.drawPixmap (0,0,m_pixmap); -} - -void ShadedVisual::hideEvent (QHideEvent *) -{ - m_timer->stop(); -} - -void ShadedVisual::showEvent (QShowEvent *) -{ - m_timer->start(); -} - -void ShadedVisual::updateSkin() -{ - clear(); -} - diff --git a/src/shadedvisual.h b/src/shadedvisual.h deleted file mode 100644 index e46331ecb..000000000 --- a/src/shadedvisual.h +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef SHADEDVISUAL_H -#define SHADEDVISUAL_H - - -#include -#include -#include - -class QTimer; -class QPixmap; - -class Skin; -class VisualNode; - -/** - @author Ilya Kotov -*/ -class ShadedVisual : public Visual -{ - Q_OBJECT -public: - ShadedVisual(QWidget *parent = 0); - - ~ShadedVisual(); - - void add(Buffer *, unsigned long, int, int); - void clear(); - - void paintEvent (QPaintEvent *); - void hideEvent (QHideEvent *); - void showEvent (QShowEvent *); - -public slots: - void timeout(); - -private slots: - void updateSkin(); - -private: - void process (VisualNode *node); - void draw (QPainter *); - Skin *m_skin; - QTimer *m_timer; - QPixmap m_pixmap; - QList m_nodes; - double m_l, m_r; - -}; - -#endif diff --git a/src/skin.cpp b/src/skin.cpp deleted file mode 100644 index 8bb4a63ad..000000000 --- a/src/skin.cpp +++ /dev/null @@ -1,771 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include -#include -#include -#include - -#include "skin.h" - -Skin *Skin::pointer = 0; - -Skin *Skin::getPointer() -{ - if ( !pointer ) - pointer = new Skin(); - return pointer; -} - -QPixmap Skin::getPixmap ( const QString& name, QDir dir ) -{ - dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); - QFileInfoList f = dir.entryInfoList(); - for ( int j = 0; j < f.size(); ++j ) - { - QFileInfo fileInfo = f.at ( j ); - QString fn = fileInfo.fileName().toLower(); - if ( fn.section ( ".",0,0 ) == name ) - { - return QPixmap ( fileInfo.filePath() ); - } - } - return QPixmap(); -} - -Skin::Skin ( QObject *parent ) - : QObject ( parent ) -{ - pointer = this; - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - QString path = settings.value("skin_path","").toString(); - if (path.isEmpty() || !QDir(path).exists ()) - path = ":/default"; - setSkin (QDir::cleanPath(path)); - /* skin directory */ - QDir skinDir(QDir::homePath()+"/.qmmp"); - skinDir.mkdir ("skins"); -} - - -Skin::~Skin() -{} - -void Skin::setSkin ( const QString& path ) -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - settings.setValue("skin_path",path); - - qDebug ( path.toAscii() ); //TODO don't clear lists - m_skin_dir = QDir ( path ); - - m_pledit_txt.clear(); - loadPLEdit(); - loadMain(); - buttons.clear(); - loadButtons(); - loadShufRep(); - titlebar.clear(); - loadTitleBar(); - loadPosBar(); - m_numbers.clear(); - loadNumbers(); - m_pl_parts.clear(); - loadPlayList(); - m_eq_parts.clear(); - loadEq_ex(); - m_eq_bar.clear(); - m_eq_spline.clear(); - loadEqMain(); - m_vis_colors.clear(); - loadVisColor(); - loadLetters(); - loadMonoSter(); - loadVolume(); - loadBalance(); - loadRegion(); - loadColors(); - - emit skinChanged(); -} - -void Skin::loadMain() -{ - QPixmap *pixmap = getPixmap ("main"); - if (!pixmap) - pixmap = getDummyPixmap("main"); - - m_main = pixmap->copy ( 0,0,275,116 ); - delete pixmap; -} - -void Skin::loadButtons() -{ - - QPixmap *pixmap = getPixmap ("cbuttons"); - - if (!pixmap) - pixmap = getDummyPixmap("cbuttons"); - - buttons[BT_PREVIOUS_N] = pixmap->copy ( 0, 0,23,18 ); - buttons[BT_PREVIOUS_P] = pixmap->copy ( 0,18,23,18 ); - - buttons[BT_PLAY_N] = pixmap->copy ( 23, 0,23,18 ); - buttons[BT_PLAY_P] = pixmap->copy ( 23,18,23,18 ); - - buttons[BT_PAUSE_N] = pixmap->copy ( 46, 0,23,18 ); - buttons[BT_PAUSE_P] = pixmap->copy ( 46,18,23,18 ); - - buttons[BT_STOP_N] = pixmap->copy ( 69, 0,23,18 ); - buttons[BT_STOP_P] = pixmap->copy ( 69,18,23,18 ); - - buttons[BT_NEXT_N] = pixmap->copy ( 92, 0,22,18 ); - buttons[BT_NEXT_P] = pixmap->copy ( 92,16,22,18 ); - - buttons[BT_EJECT_N] = pixmap->copy ( 114, 0,22,16 ); - buttons[BT_EJECT_P] = pixmap->copy ( 114,16,22,16 ); - delete pixmap; - -} - -void Skin::loadTitleBar() -{ - - QPixmap *pixmap = getPixmap ("titlebar"); - - if (!pixmap) - pixmap = getDummyPixmap("titlebar"); - - buttons[BT_MENU_N] = pixmap->copy ( 0,0,9,9 ); - buttons[BT_MENU_P] = pixmap->copy ( 0,9,9,9 ); - buttons[BT_MINIMIZE_N] = pixmap->copy ( 9,0,9,9 ); - buttons[BT_MINIMIZE_P] = pixmap->copy ( 9,9,9,9 ); - buttons[BT_CLOSE_N] = pixmap->copy ( 18,0,9,9 ); - buttons[BT_CLOSE_P] = pixmap->copy ( 18,9,9,9 ); - buttons[BT_SHADE1_N] = pixmap->copy ( 0,18,9,9 ); - buttons[BT_SHADE1_P] = pixmap->copy ( 9,18,9,9 ); - buttons[BT_SHADE2_N] = pixmap->copy ( 0,27,9,9 ); - buttons[BT_SHADE2_P] = pixmap->copy ( 9,27,9,9 ); - titlebar[TITLEBAR_A] = pixmap->copy ( 27, 0,275,14 ); - titlebar[TITLEBAR_I] = pixmap->copy ( 27,15,275,14 ); - titlebar[TITLEBAR_SHADED_A] = pixmap->copy ( 27,29,275,14 ); - titlebar[TITLEBAR_SHADED_I] = pixmap->copy ( 27,42,275,14 ); - delete pixmap; - -} - -void Skin::loadPosBar() -{ - - QPixmap *pixmap = getPixmap ("posbar"); - - if (!pixmap) - pixmap = getDummyPixmap("posbar"); - - if (pixmap->width() > 249) - { - buttons[BT_POSBAR_N] = pixmap->copy ( 248,0,29, pixmap->height()); - buttons[BT_POSBAR_P] = pixmap->copy ( 278,0,29, pixmap->height()); - } - else - { - QPixmap dummy(29, pixmap->height()); - dummy.fill(Qt::transparent); - buttons[BT_POSBAR_N] = dummy; - buttons[BT_POSBAR_P] = dummy; - } - posbar = pixmap->copy ( 0,0,248,pixmap->height() ); - delete pixmap; - -} - -void Skin::loadNumbers() -{ - QPixmap *pixmap = getPixmap ( "numbers" ); - if ( !pixmap ) - { - pixmap = getPixmap ( "nums_ex" ); - } - for ( uint i = 0; i < 10; i++ ) - { - m_numbers << pixmap->copy ( i*9, 0, 9, 13 ); - } - if (pixmap->width() > 107) - { - m_numbers << pixmap->copy(99, 0, 9,13 ); - } - else - { // We didn't find "-" symbol. So we have to extract it from "2". - // Winamp uses this method too. - QPixmap pix = pixmap->copy(90,0,9,13); - QPixmap minus = pixmap->copy(18,6,9,1); - QPainter paint(&pix); - paint.drawPixmap(0,6, minus); - m_numbers << pix; - } - delete pixmap; -} - -void Skin::loadPlayList() -{ - - QPixmap *pixmap = getPixmap ("pledit"); - - if (!pixmap) - pixmap = getDummyPixmap("pledit"); - - m_pl_parts[PL_CORNER_UL_A] = pixmap->copy ( 0,0,25,20 ); - m_pl_parts[PL_CORNER_UL_I] = pixmap->copy ( 0,21,25,20 ); - - m_pl_parts[PL_CORNER_UR_A] = pixmap->copy ( 153,0,25,20 ); - m_pl_parts[PL_CORNER_UR_I] = pixmap->copy ( 153,21,25,20 ); - - m_pl_parts[PL_TITLEBAR_A] = pixmap->copy ( 26,0,100,20 ); - m_pl_parts[PL_TITLEBAR_I] = pixmap->copy ( 26,21,100,20 ); - - m_pl_parts[PL_TFILL1_A] = pixmap->copy ( 127,0,25,20 ); - m_pl_parts[PL_TFILL1_I] = pixmap->copy ( 127,21,25,20 ); - - //m_pl_parts[PL_TFILL2_A] = pixmap->copy();//FIXME: ����� - //m_pl_parts[PL_TFILL2_I] = pixmap->copy(); - - m_pl_parts[PL_LFILL] = pixmap->copy ( 0,42,12,29 ); - m_pl_parts[PL_RFILL] = pixmap->copy ( 31,42,20,29 ); //??? - - m_pl_parts[PL_LSBAR] = pixmap->copy ( 0,72,125,38 ); - m_pl_parts[PL_RSBAR] = pixmap->copy ( 126,72,150,38 ); - m_pl_parts[PL_SFILL1] = pixmap->copy ( 179,0,25,38 ); - m_pl_parts[PL_SFILL2] = pixmap->copy ( 250,21,75,38 ); - m_pl_parts[PL_TITLEBAR_SHADED1_A] = pixmap->copy ( 99,42,50,14 ); - m_pl_parts[PL_TITLEBAR_SHADED1_I] = pixmap->copy ( 99,57,50,14 ); - m_pl_parts[PL_TITLEBAR_SHADED2] = pixmap->copy ( 72,42,25,14 ); - m_pl_parts[PL_TFILL_SHADED] = pixmap->copy ( 72,57,25,14 ); - - m_pl_parts[PL_CONTROL] = pixmap->copy(129,94,60,8); - - buttons[PL_BT_ADD] = pixmap->copy ( 11,80,25,18 ); - buttons[PL_BT_SUB] = pixmap->copy ( 40,80,25,18 ); - buttons[PL_BT_SEL] = pixmap->copy ( 70,80,25,18 ); - buttons[PL_BT_SORT] = pixmap->copy ( 99,80,25,18 ); - buttons[PL_BT_LST] = pixmap->copy(229, 80, 25, 18); - buttons[PL_BT_SCROLL_N] = pixmap->copy ( 52,53,8,18 ); - buttons[PL_BT_SCROLL_P] = pixmap->copy ( 61,53,8,18 ); - - buttons[PL_BT_CLOSE_N] = pixmap->copy (167,3,9,9); - buttons[PL_BT_CLOSE_P] = pixmap->copy (52,42,9,9); - buttons[PL_BT_SHADE1_N] = pixmap->copy (158,3,9,9); - buttons[PL_BT_SHADE1_P] = pixmap->copy (62,42,9,9); - buttons[PL_BT_SHADE2_N] = pixmap->copy (129,45,9,9); - buttons[PL_BT_SHADE2_P] = pixmap->copy (150,42,9,9); - -} - -QPixmap *Skin::getPixmap ( const QString& name ) -{ - m_skin_dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); - QFileInfoList f = m_skin_dir.entryInfoList(); - for ( int j = 0; j < f.size(); ++j ) - { - QFileInfo fileInfo = f.at ( j ); - QString fn = fileInfo.fileName().toLower(); - if ( fn.section ( ".",0,0 ) == name ) - { - return new QPixmap ( fileInfo.filePath() ); - } - } - return 0; -} - -void Skin::loadPLEdit() -{ - m_skin_dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); - QString path; - QFileInfoList list = m_skin_dir.entryInfoList(); - for ( int i = 0; i < list.size(); ++i ) - { - QFileInfo fileInfo = list.at ( i ); - if ( fileInfo.fileName().toLower() == "pledit.txt" ) - { - path = fileInfo.filePath (); - break; - } - } - - if ( path.isNull () ) - { - qDebug ( "Skin: Cannot find pledit.txt" ); - return; - } - - - QFile file ( path ); - - if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) ) - return; - - while ( !file.atEnd () ) - { - QByteArray line = file.readLine (); - QList l = line.split ( '=' ); - if ( l.count () == 2 ) - { - m_pledit_txt[l[0].toLower () ] = l[1].trimmed(); - } - else if ( line.length() == 0 ) - { - break; - } - } - -} - -void Skin::loadEqMain() -{ - QPixmap *pixmap = getPixmap ("eqmain"); - - if (!pixmap) - pixmap = getDummyPixmap("eqmain"); - - m_eq_parts[ EQ_MAIN ] = pixmap->copy ( 0,0,275,116 ); - m_eq_parts[ EQ_TITLEBAR_A ] = pixmap->copy ( 0,134,275,14 ); - m_eq_parts[ EQ_TITLEBAR_I ] = pixmap->copy ( 0,149,275,14 ); - m_eq_parts[ EQ_GRAPH ] = pixmap->copy ( 0,294,113,19 ); - for ( int i = 0; i < 14; ++i ) - { - m_eq_bar << pixmap->copy ( 13 + i*15,164,14,63 ); - } - for ( int i = 0; i < 14; ++i ) - { - m_eq_bar << pixmap->copy ( 13 + i*15,229,14,63 ); - } - buttons[ EQ_BT_BAR_N ] = pixmap->copy ( 0,164,11,11 ); - buttons[ EQ_BT_BAR_P ] = pixmap->copy ( 0,164+12,11,11 ); - - buttons[ EQ_BT_ON_N ] = pixmap->copy ( 69,119,28,12 ); - buttons[ EQ_BT_ON_P ] = pixmap->copy ( 128,119,28,12 ); - buttons[ EQ_BT_OFF_N ] = pixmap->copy ( 10, 119,28,12 ); - buttons[ EQ_BT_OFF_P ] = pixmap->copy ( 187,119,28,12 ); - - buttons[ EQ_BT_PRESETS_N ] = pixmap->copy ( 224,164,44,12 ); - buttons[ EQ_BT_PRESETS_P ] = pixmap->copy ( 224,176,44,12 ); - - buttons[ EQ_BT_AUTO_1_N ] = pixmap->copy ( 94,119,33,12 ); - buttons[ EQ_BT_AUTO_1_P ] = pixmap->copy ( 153,119,33,12 ); - buttons[ EQ_BT_AUTO_0_N ] = pixmap->copy ( 35, 119,33,12 ); - buttons[ EQ_BT_AUTO_0_P ] = pixmap->copy ( 212,119,33,12 ); - - buttons[ EQ_BT_CLOSE_N ] = pixmap->copy ( 0,116,9,9 ); - buttons[ EQ_BT_CLOSE_P ] = pixmap->copy ( 0,125,9,9 ); - buttons[ EQ_BT_SHADE1_N ] = pixmap->copy ( 254,137,9,9 ); - - for ( int i = 0; i < 19; ++i ) - { - m_eq_spline << pixmap->copy ( 115, 294+i, 1, 1 ); - } - delete pixmap; - -} - -void Skin::loadEq_ex() -{ - QPixmap *pixmap = getPixmap ("eq_ex"); - - if (!pixmap) - pixmap = getDummyPixmap("eq_ex"); - - buttons[ EQ_BT_SHADE1_P ] = pixmap->copy (1,38,9,9); - buttons[ EQ_BT_SHADE2_N ] = pixmap->copy (254,3,9,9); - buttons[ EQ_BT_SHADE2_P ] = pixmap->copy (1,47,9,9); - m_eq_parts[ EQ_TITLEBAR_SHADED_A ] = pixmap->copy(0,0,275,14); - m_eq_parts[ EQ_TITLEBAR_SHADED_I ] = pixmap->copy(0,15,275,14); - m_eq_parts[ EQ_VOLUME1 ] = pixmap->copy(1,30,3,8); - m_eq_parts[ EQ_VOLUME2 ] = pixmap->copy(4,30,3,8); - m_eq_parts[ EQ_VOLUME3 ] = pixmap->copy(7,30,3,8); - m_eq_parts[ EQ_BALANCE1 ] = pixmap->copy(11,30,3,8); - m_eq_parts[ EQ_BALANCE2 ] = pixmap->copy(14,30,3,8); - m_eq_parts[ EQ_BALANCE3 ] = pixmap->copy(17,30,3,8); - - delete pixmap; -} - -void Skin::loadVisColor() -{ - //QList colors; - m_skin_dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); - QString path; - QFileInfoList list = m_skin_dir.entryInfoList(); - for ( int i = 0; i < list.size(); ++i ) - { - QFileInfo fileInfo = list.at ( i ); - if ( fileInfo.fileName().toLower() == "viscolor.txt" ) - { - path = fileInfo.filePath (); - break; - } - } - - if ( path.isNull () ) - { - qDebug ( "Skin: Cannot find viscolor.txt" ); - return; - } - - - QFile file ( path ); - - if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) ) - return; - - int j = 0; - while ( !file.atEnd () && j<24 ) - { - j++; - QByteArray line = file.readLine (); - QString tmp = QString::fromAscii ( line ); - tmp = tmp.trimmed (); - int i = tmp.indexOf ( "//" ); - if ( i>0 ) - tmp.truncate ( tmp.indexOf ( "//" ) ); - QStringList list = tmp.split ( "," ); - if ( list.count () >= 3 ) - { - //colors - int r = list.at ( 0 ).toInt(); - int g = list.at ( 1 ).toInt(); - int b = list.at ( 2 ).toInt(); - m_vis_colors << QColor ( r,g,b ); - } - else if ( line.length() == 0 ) - { - break; - } - } - if (m_vis_colors.size() < 24) - { - qWarning ( "Skin: cannot parse viscolor.txt" ); - while (m_vis_colors.size() < 24) - m_vis_colors << QColor (0,0,0); - } -} - -void Skin::loadShufRep() -{ - QPixmap *pixmap = getPixmap ("shufrep"); - - if (!pixmap) - pixmap = getDummyPixmap("shufrep"); - - buttons[ BT_EQ_ON_N ] = pixmap->copy ( 0,73,23,12 ); - buttons[ BT_EQ_ON_P ] = pixmap->copy ( 46,73,23,12 ); - buttons[ BT_EQ_OFF_N ] = pixmap->copy ( 0,61,23,12 ); - buttons[ BT_EQ_OFF_P ] = pixmap->copy ( 46,61,23,12 ); - - buttons[ BT_PL_ON_N ] = pixmap->copy ( 23,73,23,12 ); - buttons[ BT_PL_ON_P ] = pixmap->copy ( 69,73,23,12 ); - buttons[ BT_PL_OFF_N ] = pixmap->copy ( 23,61,23,12 ); - buttons[ BT_PL_OFF_P ] = pixmap->copy ( 69,61,23,12 ); - - //buttons[ BT_PL_CLOSE_N ] = pixmap->copy (); - //buttons[ BT_PL_CLOSE_P ] = pixmap->copy (); - - buttons[REPEAT_ON_N] = pixmap->copy ( 0,30, 28, 15 ); - buttons[REPEAT_ON_P] = pixmap->copy ( 0,45, 28, 15 ); - - buttons[REPEAT_OFF_N] = pixmap->copy ( 0, 0,28,15 ); - buttons[REPEAT_OFF_P] = pixmap->copy ( 0,15,28,15 ); - - buttons[SHUFFLE_ON_N] = pixmap->copy ( 28,30,46,15 ); - buttons[SHUFFLE_ON_P] = pixmap->copy ( 28,45,46,15 ); - - buttons[SHUFFLE_OFF_N] = pixmap->copy ( 28, 0,46,15 ); - buttons[SHUFFLE_OFF_P] = pixmap->copy ( 28,15,46,15 ); - - delete pixmap; - -} - -void Skin::loadLetters( void ) -{ - QPixmap *img = getPixmap("text"); - - if (!img) - img = getDummyPixmap("text"); - - QList > ( letters ); - for ( int i = 0; i < 3; i++ ) - { - QList ( l ); - for ( int j = 0; j < 31; j++ ) - { - l.append ( img->copy ( j*5, i*6, 5, 6 ) ); - } - letters.append ( l ); - } - - delete img; - - - /* alphabet */ - for ( uint i = 97; i < 123; i++ ) - { - m_letters.insert(i, letters[0][i-97]); - } - - /* digits */ - for ( uint i = 0; i <= 9; i++ ) - { - m_letters.insert ( i+48, letters[1][i] ); - } - - /* special characters */ - m_letters.insert('"', letters[0][27]); - m_letters.insert('@', letters[0][28]); - m_letters.insert(':', letters[1][12]); - m_letters.insert('(', letters[1][13]); - m_letters.insert(')', letters[1][14]); - m_letters.insert('-', letters[1][15]); - m_letters.insert('\'', letters[1][16]); - m_letters.insert('`', letters[1][16]); - m_letters.insert('!', letters[1][17]); - m_letters.insert('_', letters[1][18]); - m_letters.insert('+', letters[1][19]); - m_letters.insert('\\', letters[1][20]); - m_letters.insert('/', letters[1][21]); - m_letters.insert('[', letters[1][22]); - m_letters.insert(']', letters[1][23]); - m_letters.insert('^', letters[1][24]); - m_letters.insert('&', letters[1][25]); - m_letters.insert('%', letters[1][26]); - m_letters.insert('.', letters[1][27]); - m_letters.insert(',', letters[1][27]); - m_letters.insert('=', letters[1][28]); - m_letters.insert('$', letters[1][29]); - m_letters.insert('#', letters[1][30]); - - m_letters.insert(229, letters[2][0]); - m_letters.insert(246, letters[2][1]); - m_letters.insert(228, letters[2][2]); - m_letters.insert('?', letters[2][3]); - m_letters.insert('*', letters[2][4]); - m_letters.insert(' ', letters[2][5]); - - /* text background */ - //m_items->insert (TEXTBG, letters[2][6]); -} - -void Skin::loadMonoSter() -{ - QPixmap *pixmap = getPixmap("monoster"); - - if (!pixmap) - pixmap = getDummyPixmap("monoster"); - - m_ms_parts.clear(); - m_ms_parts[ MONO_A ] = pixmap->copy ( 29,0,27,12 ); - m_ms_parts[ MONO_I ] = pixmap->copy ( 29,12,27,12 ); - m_ms_parts[ STEREO_A ] = pixmap->copy ( 0,0,27,12 ); - m_ms_parts[ STEREO_I ] = pixmap->copy ( 0,12,27,12 ); - - delete pixmap; - - m_parts.clear(); - QPainter paint; - pixmap = getPixmap("playpaus"); - - if (!pixmap) - pixmap = getDummyPixmap("playpaus"); - - QPixmap part(11, 9); - paint.begin(&part); - paint.drawPixmap (0, 0, 3, 9, *pixmap, 36, 0, 3, 9); - paint.drawPixmap (3, 0, 8, 9, *pixmap, 1, 0, 8, 9); - paint.end(); - m_parts [PLAY] = part.copy(); - - part = QPixmap(11, 9); - paint.begin(&part); - paint.drawPixmap (0, 0, 2, 9, *pixmap, 27, 0, 2, 9); - paint.drawPixmap (2, 0, 9, 9, *pixmap, 9, 0, 9, 9); - paint.end(); - m_parts [PAUSE] = part.copy(); - - part = QPixmap(11, 9); - paint.begin(&part); - paint.drawPixmap (0, 0, 2, 9, *pixmap, 27, 0, 2, 9); - paint.drawPixmap (2, 0, 9, 9, *pixmap, 18, 0, 9, 9); - paint.end(); - m_parts [STOP] = part.copy(); - - delete pixmap; -} - -void Skin::loadVolume() -{ - QPixmap *pixmap = getPixmap("volume"); - - if (!pixmap) - pixmap = getDummyPixmap("volume"); - - m_volume.clear(); - for (int i = 0; i < 28; ++i) - m_volume.append(pixmap->copy ( 0,i*15,66,13 )); - if (pixmap->height() > 425) - { - buttons [BT_VOL_N] = pixmap->copy (15,422,14, pixmap->height() - 422); - buttons [BT_VOL_P] = pixmap->copy (0, 422,14, pixmap->height() - 422); - } - else - { - buttons [BT_VOL_N] = QPixmap(); - buttons [BT_VOL_P] = QPixmap(); - } - delete pixmap; -} - -void Skin::loadBalance() -{ - QPixmap *pixmap = getPixmap ( "balance" ); - if (!pixmap) - pixmap = getPixmap ( "volume" ); - - if (!pixmap) - pixmap = getDummyPixmap("balance"); - - m_balance.clear(); - for (int i = 0; i < 28; ++i) - m_balance.append(pixmap->copy ( 9,i*15,38,13 )); - if (pixmap->height() > 427) - { - buttons [BT_BAL_N] = pixmap->copy (15, 422,14,pixmap->height()-422); - buttons [BT_BAL_P] = pixmap->copy (0,422,14,pixmap->height()-422); - } - else - { - buttons [BT_BAL_N] = QPixmap(); - buttons [BT_BAL_P] = QPixmap(); - } - delete pixmap; -} - -void Skin::loadRegion() -{ - m_mwRegion = QRegion(); - m_plRegion = QRegion(); - m_skin_dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); - QString path; - QFileInfoList list = m_skin_dir.entryInfoList(); - for ( int i = 0; i < list.size(); ++i ) - { - QFileInfo fileInfo = list.at ( i ); - if ( fileInfo.fileName().toLower() == "region.txt" ) - { - path = fileInfo.filePath (); - break; - } - } - - if ( path.isNull () ) - { - qDebug ( "Skin: cannot find region.txt. Transparenty disabled" ); - return; - } - m_mwRegion = createRegion(path, "Normal"); - m_plRegion = createRegion(path, "Equalizer"); -} - -QRegion Skin::createRegion(const QString &path, const QString &key) -{ - QRegion region; - QSettings settings(path, QSettings::IniFormat); - QStringList numPoints = settings.value(key+"/NumPoints").toStringList(); - QStringList value = settings.value(key+"/PointList").toStringList(); - QStringList numbers; - foreach(QString str, value) - numbers << str.split(" ", QString::SkipEmptyParts); - - QList regions; - - QList::iterator n; - n = numbers.begin(); - for (int i = 0; i < numPoints.size(); ++i) - { - QList lp; - for (int j = 0; j < numPoints.at(i).toInt()*2; j++) - { - lp << n->toInt(); - n ++; - } - QVector points; - - for (int l = 0; l < lp.size(); l+=2) - { - points << QPoint(lp.at(l), lp.at(l+1)); - } - region = region.united(QRegion(QPolygon(points))); - } - return region; -} - -QPixmap * Skin::getDummyPixmap(const QString& name) -{ - QDir dir (":/default"); - dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); - QFileInfoList f = dir.entryInfoList(); - for ( int j = 0; j < f.size(); ++j ) - { - QFileInfo fileInfo = f.at ( j ); - QString fn = fileInfo.fileName().toLower(); - if ( fn.section ( ".",0,0 ) == name ) - { - return new QPixmap ( fileInfo.filePath() ); - } - } - qFatal("Skin:: default skin corrupted"); - return 0; -} - -void Skin::loadColors() -{ - //extract color from image - QPixmap pix = m_letters['*']; - QImage img = pix.toImage(); - img = img.convertToFormat(QImage::Format_Indexed8); - - QPixmap pix2 = m_letters[' ']; - QImage img2 = pix2.toImage(); - img2 = img2.convertToFormat(QImage::Format_Indexed8); - QVector c1 = img.colorTable (); - QVector c2 = img2.colorTable (); - //qDebug("%d -- %d", img.numColors (), img2.numColors ()); - QColor color; - color.setNamedColor(getPLValue("normal")); - - for (int i = 0; i < c1.size(); ++i) - { - if (c2.indexOf(c1[i]) == -1) - { - if(img.numColors () == img2.numColors () + 1) - color = QColor(c1[i]); - break; - } - } - m_scroller_color = color; -} diff --git a/src/skin.h b/src/skin.h deleted file mode 100644 index d981c4613..000000000 --- a/src/skin.h +++ /dev/null @@ -1,340 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef SKIN_H -#define SKIN_H - -#include -#include -#include -#include -#include - -/* - @author Ilya Kotov -*/ - - -class Skin : public QObject -{ - Q_OBJECT -public: - Skin(QObject *parent = 0); - - ~Skin(); - - static Skin *getPointer(); - static QPixmap getPixmap(const QString&, QDir); - void setSkin(const QString& path); - const QPixmap getMain() const - { - return m_main; - }; - const QPixmap getButton(uint bt) const - { - return buttons[bt]; - }; - const QPixmap getTitleBar(uint tb) const - { - return titlebar[tb]; - }; - const QPixmap getPosBar() const - { - return posbar; - }; - const QPixmap getNumber(uint n) const - { - return m_numbers[n]; - }; - /*! - * Returns count of numbers in number list. - * We need this to check if we have "-" in pixmaps. - * if no we should draw it manually. - */ - const uint getNumCount(void) const - { - return m_numbers.count(); - } - const QPixmap getPlPart(uint p) const - { - return m_pl_parts[p]; - }; - const QPixmap getEqPart(uint p) const - { - return m_eq_parts[p]; - }; - const QPixmap getEqSlider(uint n) const - { - return m_eq_bar[n]; - }; - const QPixmap getEqSpline(uint n) const - { - return m_eq_spline[n]; - }; - const QPixmap getMSPart(uint n) const - { - return m_ms_parts[n]; - }; - const QPixmap getLetter(const QChar& ch) - { - return m_letters[ch]; - }; - const QPixmap getItem(uint n) const - { - return m_parts[n]; - }; - const QPixmap getVolumeBar(int n) const - { - return m_volume[n]; - }; - const QPixmap getBalanceBar(int n) const - { - return m_balance[n]; - }; - const QByteArray getPLValue (QByteArray c) const - { - return m_pledit_txt[c]; - }; - const QColor getVisColor(int n) const - { - return m_vis_colors[n]; - }; - const QRegion getMWRegion() const - { - return m_mwRegion; - }; - const QRegion getPLRegion() const - { - return m_plRegion; - }; - const QColor scrollerTextColor() const - { - return m_scroller_color; - }; - - enum Buttons - { - BT_PREVIOUS_N = 0, - BT_PREVIOUS_P, - BT_PLAY_N, - BT_PLAY_P, - BT_PAUSE_N, - BT_PAUSE_P, - BT_STOP_N, - BT_STOP_P, - BT_NEXT_N, - BT_NEXT_P, - BT_EJECT_N, - BT_EJECT_P, - /*titlebar.* */ - BT_MENU_N, - BT_MENU_P, - BT_MINIMIZE_N, - BT_MINIMIZE_P, - BT_CLOSE_N, - BT_CLOSE_P, - BT_SHADE1_N, - BT_SHADE1_P, - BT_SHADE2_N, - BT_SHADE2_P, - BT_CLOSE_SHADED_N, - BT_CLOSE_SHADED_P, - - /* posbar.* */ - BT_POSBAR_N, - BT_POSBAR_P, - /* pledit.* */ - PL_BT_ADD, - PL_BT_SUB, - PL_BT_SEL, - PL_BT_SORT, - PL_BT_LST, - PL_BT_SCROLL_N, - PL_BT_SCROLL_P, - PL_BT_CLOSE_N, - PL_BT_CLOSE_P, - PL_BT_SHADE1_N, - PL_BT_SHADE1_P, - PL_BT_SHADE2_N, - PL_BT_SHADE2_P, - - /* eqmain.* */ - EQ_BT_BAR_N, - EQ_BT_BAR_P, - EQ_BT_ON_N, - EQ_BT_ON_P, - EQ_BT_OFF_N, - EQ_BT_OFF_P, - EQ_BT_PRESETS_N, - EQ_BT_PRESETS_P, - EQ_BT_AUTO_1_N, - EQ_BT_AUTO_1_P, - EQ_BT_AUTO_0_N, - EQ_BT_AUTO_0_P, - EQ_BT_CLOSE_N, - EQ_BT_CLOSE_P, - EQ_BT_SHADE1_N, - - /* eq_ex.* */ - EQ_BT_SHADE1_P, - EQ_BT_SHADE2_N, - EQ_BT_SHADE2_P, - - /* shufrep.* */ - BT_EQ_ON_N, - BT_EQ_ON_P, - BT_EQ_OFF_N, - BT_EQ_OFF_P, - BT_PL_ON_N, - BT_PL_ON_P, - BT_PL_OFF_N, - BT_PL_OFF_P, - BT_PL_CLOSE_N, - BT_PL_CLOSE_P, - REPEAT_ON_N, - REPEAT_ON_P, - REPEAT_OFF_N, - REPEAT_OFF_P, - SHUFFLE_ON_N, - SHUFFLE_ON_P, - SHUFFLE_OFF_N, - SHUFFLE_OFF_P, - /* volume.* */ - BT_VOL_N, - BT_VOL_P, - /* balance.* */ - BT_BAL_N, - BT_BAL_P, - }; - enum TitleBar - { - TITLEBAR_A = 0, - TITLEBAR_I, - TITLEBAR_SHADED_A, - TITLEBAR_SHADED_I, - }; - enum PlayList - { - PL_CORNER_UL_A = 0, - PL_CORNER_UL_I, - PL_CORNER_UR_A, - PL_CORNER_UR_I, - PL_TITLEBAR_A, - PL_TITLEBAR_I, - PL_TFILL1_A, - PL_TFILL1_I, - PL_TFILL2_A, - PL_TFILL2_I, - PL_LFILL, - PL_RFILL, - PL_LSBAR, - PL_RSBAR, - PL_SFILL1, - PL_SFILL2, - PL_CONTROL, - PL_TITLEBAR_SHADED1_A, - PL_TITLEBAR_SHADED1_I, - PL_TITLEBAR_SHADED2, - PL_TFILL_SHADED, - }; - enum Equalizer - { - EQ_MAIN = 0, - EQ_TITLEBAR_A, - EQ_TITLEBAR_I, - EQ_GRAPH, - EQ_TITLEBAR_SHADED_A, - EQ_TITLEBAR_SHADED_I, - EQ_VOLUME1, - EQ_VOLUME2, - EQ_VOLUME3, - EQ_BALANCE1, - EQ_BALANCE2, - EQ_BALANCE3, - }; - enum MonoSter - { - MONO_A = 0, - MONO_I, - STEREO_A, - STEREO_I, - }; - enum OtherParts - { - PLAY = 0, - PAUSE, - STOP, - }; -signals: - void skinChanged(); - -private: - QPixmap *getPixmap(const QString&); - - /*! - * As far as there is no standard in skin making we cannot be sure - * that all needful images we can find in skin :( This will cause - * segfaults and asserts. So to prevent this we need such method - * to load pixmap from default skin. - */ - QPixmap *getDummyPixmap(const QString&); - static Skin *pointer; - QDir m_skin_dir; - QMap buttons; - QMap titlebar; - QMap m_pl_parts; - QMap m_eq_parts; - QMap m_ms_parts; - QMap m_parts; - QMap m_letters; - QMap m_pledit_txt; - QColor m_scroller_color; - QPixmap m_main; - QPixmap posbar; - QList m_numbers; - QList m_eq_bar; - QList m_eq_spline; - QList m_volume; - QList m_balance; - QList m_vis_colors; - QRegion m_mwRegion; - QRegion m_plRegion; - - void loadMain(); - void loadButtons(); - void loadTitleBar(); - void loadPosBar(); - void loadNumbers(); - void loadPlayList(); - void loadPLEdit(); - void loadEqMain(); - void loadEq_ex(); - void loadVisColor(); - void loadShufRep(); - void loadLetters(); - void loadMonoSter(); - void loadVolume(); - void loadBalance(); - void loadRegion(); - void loadColors(); - QRegion createRegion(const QString &path, const QString &key); - -}; - -#endif diff --git a/src/skinreader.cpp b/src/skinreader.cpp deleted file mode 100644 index 64e0aacc9..000000000 --- a/src/skinreader.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "skinreader.h" - -SkinReader::SkinReader(QObject *parent) - : QObject(parent) -{ - m_process = new QProcess(this); - //create cache dir - QDir dir(QDir::homePath() +"/.qmmp/"); - dir.mkdir("cache"); - dir.cd("cache"); - dir.mkdir("skins"); -} - - -SkinReader::~SkinReader() -{} - -void SkinReader::updateCache() -{ - QDir dir(QDir::homePath() +"/.qmmp/skins"); - dir.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks); - QFileInfoList f = dir.entryInfoList(); - //clear removed skins from cache - QDir cache_dir(QDir::homePath() +"/.qmmp/cache/skins"); - cache_dir.setFilter(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot); - QFileInfoList d = cache_dir.entryInfoList(); - - foreach(QFileInfo dirInfo, d) - { - bool del = TRUE; - foreach(QFileInfo fileInfo, f) - { - if (fileInfo.baseName () == dirInfo.fileName ()) - { - del = FALSE; - break; - } - } - if (del) - { - qDebug("SkinReader: deleting %s from cache", - qPrintable(dirInfo.fileName ())); - - cache_dir.cd(dirInfo.fileName ()); - cache_dir.setFilter(QDir::Files | QDir::Hidden); - QFileInfoList removeList = cache_dir.entryInfoList(); - foreach(QFileInfo to_remove, removeList) - cache_dir.remove(to_remove.fileName ()); - cache_dir.cdUp(); - cache_dir.rmdir(dirInfo.fileName ()); - } - } - //add new skins to cache - foreach(QFileInfo fileInfo, f) - { - bool create = TRUE; - foreach(QFileInfo dirInfo, d) - { - if (fileInfo.baseName () == dirInfo.fileName ()) - { - create = FALSE; - break; - } - } - if (create) - { - qDebug("SkinReader: adding %s to cache", - qPrintable(fileInfo.fileName ())); - cache_dir.mkdir(fileInfo.baseName ()); - QString name = fileInfo.fileName ().toLower(); - - if (name.endsWith(".tgz") || name.endsWith(".tar.gz")) - untar(fileInfo.filePath (), cache_dir.absolutePath ()+"/"+ - fileInfo.baseName ()); - if (name.endsWith(".zip") || name.endsWith(".wsz")) - unzip(fileInfo.filePath (), cache_dir.absolutePath ()+"/"+ - fileInfo.baseName ()); - } - } -} - -void SkinReader::untar(const QString &from, const QString &to) -{ - QByteArray array; - QStringList args; - //list archive - args << "tf" <start("tar", args); - m_process->waitForFinished(); - array = m_process->readAllStandardOutput (); - QString str = QString(array); - QStringList outputList = str.split("\n",QString::SkipEmptyParts); - foreach(QString str, outputList) - { - str = str.trimmed(); - args.clear(); - args << "xvfk" << from << "-O" << str; - m_process->start("tar", args); - m_process->waitForFinished(); - array = m_process->readAllStandardOutput (); - QString name = str.right(str.size() - str.indexOf("/",Qt::CaseInsensitive) - 1).trimmed().toLower(); - - QFile file(to+"/"+name); - file.open(QIODevice::WriteOnly); - file.write(array); - file.close(); - } -} - -void SkinReader::unzip(const QString &from, const QString &to) -{ - QStringList args; - args << "-j" << "-o" << "-d" << to << from; - m_process->start("unzip", args); - m_process->waitForFinished(); -} - diff --git a/src/skinreader.h b/src/skinreader.h deleted file mode 100644 index c6db283fa..000000000 --- a/src/skinreader.h +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef SKINREADER_H -#define SKINREADER_H - -#include - -/** - @author Ilya Kotov -*/ -class QProcess; - -class SkinReader : public QObject -{ - Q_OBJECT -public: - SkinReader(QObject *parent = 0); - - ~SkinReader(); - - void updateCache(); - -private: - QProcess *m_process; - void untar(const QString &from, const QString &to); - void unzip(const QString &from, const QString &to); -}; - -#endif diff --git a/src/src.pro b/src/src.pro deleted file mode 100644 index 47708ec48..000000000 --- a/src/src.pro +++ /dev/null @@ -1,152 +0,0 @@ -# ???? ?????? ? KDevelop ?????????? qmake. -# ------------------------------------------- -# ?????????? ???????????? ???????? ???????? ???????: ./src -# ???? - ??????????: ../bin/mp3player - -include(../qmmp.pri) - -FORMS += configdialog.ui \ - preseteditor.ui \ - jumptotrackdialog.ui \ - aboutdialog.ui - -HEADERS += mainwindow.h \ - fileloader.h \ - button.h \ - display.h \ - skin.h \ - titlebar.h \ - positionbar.h \ - number.h \ - playlist.h \ - mediafile.h \ - listwidget.h \ - playlistmodel.h \ - pixmapwidget.h \ - playlisttitlebar.h \ - configdialog.h \ - playlistslider.h \ - dock.h \ - eqwidget.h \ - eqtitlebar.h \ - eqslider.h \ - togglebutton.h \ - eqgraph.h \ - mainvisual.h \ - inlines.h \ - fft.h \ - logscale.h \ - textscroller.h \ - monostereo.h \ - playstatus.h \ - pluginitem.h \ - volumebar.h \ - balancebar.h \ - playstate.h \ - symboldisplay.h \ - playlistformat.h \ - playlistcontrol.h \ - version.h \ - qmmpstarter.h \ - eqpreset.h \ - preseteditor.h \ - jumptotrackdialog.h \ - aboutdialog.h \ - timeindicator.h \ - keyboardmanager.h \ - filedialog.h \ - unixdomainsocket.h - - -SOURCES += mainwindow.cpp \ - mp3player.cpp \ - fileloader.cpp \ - button.cpp \ - display.cpp \ - skin.cpp \ - titlebar.cpp \ - positionbar.cpp \ - number.cpp \ - playlist.cpp \ - mediafile.cpp \ - listwidget.cpp \ - playlistmodel.cpp \ - pixmapwidget.cpp \ - playlisttitlebar.cpp \ - configdialog.cpp \ - playlistslider.cpp \ - dock.cpp \ - eqwidget.cpp \ - eqtitlebar.cpp \ - eqslider.cpp \ - togglebutton.cpp \ - eqgraph.cpp \ - mainvisual.cpp \ - fft.c \ - logscale.cpp \ - textscroller.cpp \ - monostereo.cpp \ - playstatus.cpp \ - pluginitem.cpp \ - volumebar.cpp \ - balancebar.cpp \ - playstate.cpp \ - symboldisplay.cpp \ - playlistformat.cpp \ - playlistcontrol.cpp \ - qmmpstarter.cpp \ - eqpreset.cpp \ - preseteditor.cpp \ - jumptotrackdialog.cpp \ - aboutdialog.cpp \ - timeindicator.cpp \ - keyboardmanager.cpp \ - filedialog.cpp \ - unixdomainsocket.cpp - - - -contains(CONFIG,XSPF_PLUGIN){ - message(*********************************************) - message(* XSPF support will be compiled as plugin *) - message(*********************************************) - DEFINES += XSPF_PLUGIN -}else { - DEFINES -= XSPF_PLUGIN - message(*******************************************) - message(* XSPF support will be compiled in QMMP *) - message(*******************************************) - QT += xml -} - -QT += network -TARGET = ../bin/qmmp -CONFIG += thread release \ -warn_on -QMAKE_LIBDIR += ../lib -LIBS += -Wl,-rpath,../lib -lqmmp -INCLUDEPATH += ../lib -RESOURCES = images/images.qrc \ - stuff.qrc -# translations/qmmp_locales.qrc - -#TRANSLATIONS = translations/qmmp_ru.ts \ -# translations/qmmp_tr.ts \ -# translations/qmmp_zh_CN.ts -TEMPLATE = app -target.path = /bin -INSTALLS += target - -HEADERS += addurldialog.h \ - skinreader.h \ - visualmenu.h \ - titlebarcontrol.h \ - shadedvisual.h \ - shadedbar.h -SOURCES += addurldialog.cpp \ - skinreader.cpp \ - visualmenu.cpp \ - titlebarcontrol.cpp \ - shadedvisual.cpp \ - shadedbar.cpp -FORMS += addurldialog.ui diff --git a/src/stuff.qrc b/src/stuff.qrc deleted file mode 100644 index dfffed67d..000000000 --- a/src/stuff.qrc +++ /dev/null @@ -1,28 +0,0 @@ - - - - ../COPYING - html/about_en.html - html/about_ru.html - html/authors_en.txt - html/thanks_en.txt - html/authors_ru.txt - html/thanks_ru.txt - default/balance.png - default/eqmain.png - default/numbers.png - default/pledit.txt - default/text.png - default/volume.png - default/cbuttons.png - default/main.png - default/playpaus.png - default/posbar.png - default/titlebar.png - default/eq_ex.png - default/monoster.png - default/pledit.png - default/shufrep.png - default/viscolor.txt - - diff --git a/src/symboldisplay.cpp b/src/symboldisplay.cpp deleted file mode 100644 index b3942a6bb..000000000 --- a/src/symboldisplay.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include - -#include "skin.h" - -#include "symboldisplay.h" - -SymbolDisplay::SymbolDisplay ( QWidget *parent, int digits ) - : PixmapWidget ( parent ), m_digits ( digits ), m_text(), m_max(0) -{ - m_alignment = Qt::AlignRight; - m_skin = Skin::getPointer(); - connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT (draw())); - draw(); - for (int i=0; igetLetter ( ' ' ); - int w = bg.size().width(); - int h = bg.size().height(); - QPixmap tmp ( m_digits*w,h ); - QPainter paint ( &tmp ); - int j; - for ( int i = 0; i < m_digits; ++i ) - { - if (m_alignment == Qt::AlignRight) // TODO: add align Center - { - j = str.size() -1 - i; - if ( j >= 0 ) - paint.drawPixmap ( ( m_digits-1-i ) *w,0,m_skin->getLetter ( str.at ( j ) ) ); - else - paint.drawPixmap ( ( m_digits-1-i ) *w,0,m_skin->getLetter ( ' ' ) ); - } - else - { - if (i < str.size()) - paint.drawPixmap ( i * w,0,m_skin->getLetter ( str.at ( i ) ) ); - else - paint.drawPixmap ( i * w,0,m_skin->getLetter ( ' ' ) ); - ; - } - } - setPixmap(tmp); -} - -void SymbolDisplay::display(int val) -{ - if (val < m_max) - display(QString::number(val)); - else - display(QString("%1h").arg(val/100)); -} - diff --git a/src/symboldisplay.h b/src/symboldisplay.h deleted file mode 100644 index 065579b7a..000000000 --- a/src/symboldisplay.h +++ /dev/null @@ -1,64 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef SYMBOLDISPLAY_H -#define SYMBOLDISPLAY_H - -#include - -#include "pixmapwidget.h" - -/** - @author Vladimir Kuznetsov - */ - -class Skin; - -class SymbolDisplay : public PixmapWidget -{ - Q_OBJECT -public: - SymbolDisplay(QWidget *parent = 0, int digits = 3); - - ~SymbolDisplay(); - void display(const QString&); - void display(int); - void setAlignment(Qt::Alignment a) - { - m_alignment = a; - } - Qt::Alignment alignment()const - { - return m_alignment; - } - -private slots: - void draw(); - -private: - Skin* m_skin; - QPixmap m_pixmap; - int m_digits; - QString m_text; - Qt::Alignment m_alignment; - int m_max; - -}; - -#endif diff --git a/src/textscroller.cpp b/src/textscroller.cpp deleted file mode 100644 index 35e4ed4eb..000000000 --- a/src/textscroller.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include - -#include "skin.h" -#include "textscroller.h" -#include "version.h" - -TextScroller *TextScroller::pointer = 0; - -TextScroller *TextScroller::getPointer() -{ - return pointer; -} - - -TextScroller::TextScroller ( QWidget *parent ) - : PixmapWidget ( parent ) -{ - pointer = this; - m_skin = Skin::getPointer(); - m_pixmap = QPixmap ( 154,15 ); - x = 0; - m_text = "Qt-based Multimedia Player (Qmmp " + QString(QMMP_STR_VERSION) + ")"; - m_update = FALSE; - readSettings(); - m_timer = new QTimer ( this ); - connect ( m_timer, SIGNAL ( timeout() ),SLOT ( addOffset() ) ); - m_timer->setInterval(50); - m_timer->start(); - updateSkin(); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); -} - - -TextScroller::~TextScroller() -{} - -void TextScroller::addOffset() -{ - m_pixmap.fill ( Qt::transparent ); - QPainter paint ( &m_pixmap ); - x--; - paint.setPen(m_color); - paint.setFont(m_font); - paint.drawText ( 154+x,12, m_text ); - paint.drawText ( 154+x+m_metrics->width ( m_text ) + 15,12, m_text ); - if ( 154 + x < - m_metrics->width ( m_text ) - 15 +1) - { - x=-154; - } - setPixmap ( m_pixmap ); -} - -void TextScroller::setText(const QString& text) -{ - if (m_text != text) - { - m_text = text; - x = -50; - } -} - -void TextScroller::updateSkin() -{ - m_color.setNamedColor(m_skin->getPLValue("normal")); -} - -void TextScroller::readSettings() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - QString fontname = settings.value("MainWindow/Font","").toString(); - if (fontname.isEmpty ()) - fontname = QFont("Helvetica [Cronyx]", 9).toString(); - m_font.fromString(fontname); - - if (m_update) - { - delete m_metrics; - m_metrics = new QFontMetrics(m_font); - } - else - { - m_update = TRUE; - m_metrics = new QFontMetrics(m_font); - } -} - -void TextScroller::hideEvent ( QHideEvent *) -{ - m_timer->stop(); -} - -void TextScroller::showEvent ( QShowEvent *) -{ - m_timer->start(); -} diff --git a/src/textscroller.h b/src/textscroller.h deleted file mode 100644 index 7346ce29a..000000000 --- a/src/textscroller.h +++ /dev/null @@ -1,66 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef TEXTSCROLLER_H -#define TEXTSCROLLER_H - -#include - -/** - @author Ilya Kotov -*/ - -class QTimer; - -class Skin; - -class TextScroller : public PixmapWidget -{ -Q_OBJECT -public: - TextScroller(QWidget *parent = 0); - - ~TextScroller(); - - static TextScroller *getPointer(); - void setText(const QString&); - void readSettings(); - -private slots: - void addOffset(); - void updateSkin(); - -protected: - void hideEvent ( QHideEvent *); - void showEvent ( QShowEvent *); - -private: - bool m_update; - static TextScroller *pointer; - QPixmap m_pixmap; - int x; - QFont m_font; - QFontMetrics *m_metrics; - QString m_text; - Skin *m_skin; - QColor m_color; - QTimer *m_timer; -}; - -#endif diff --git a/src/timeindicator.cpp b/src/timeindicator.cpp deleted file mode 100644 index 9b81ba040..000000000 --- a/src/timeindicator.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include -#include -#include - -#include "skin.h" -#include "timeindicator.h" - -TimeIndicator::TimeIndicator ( QWidget *parent ) - : PixmapWidget ( parent ) -{ - m_skin = Skin::getPointer(); - m_pixmap = QPixmap ( 65,13 ); - m_elapsed = true; - m_time = m_songDuration = 0; - readSettings(); - m_needToShowTime = false; - updateSkin(); - reset(); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); -} - -void TimeIndicator::setTime ( int t ) -{ - m_time = t; - m_pixmap.fill ( Qt::transparent ); - QPainter paint ( &m_pixmap ); - - if (!m_elapsed) - { - t = m_songDuration - t; - paint.drawPixmap(QPoint(2,0),m_skin->getNumber( 10 )); - } - if(t < 0) - t = 0; - - paint.drawPixmap(QPoint(13,0),m_skin->getNumber( t/600%10 )); - paint.drawPixmap(QPoint(26,0),m_skin->getNumber( t/60%10 )); - paint.drawPixmap(QPoint(43,0),m_skin->getNumber( t%60/10 )); - paint.drawPixmap(QPoint(56,0),m_skin->getNumber( t%60%10 )); - - setPixmap ( m_pixmap ); - -} - -void TimeIndicator::reset() -{ - m_pixmap.fill ( Qt::transparent ); - QPainter paint ( &m_pixmap ); - setPixmap ( m_pixmap ); -} - -void TimeIndicator::mousePressEvent(QMouseEvent* e ) -{ - if (m_needToShowTime && e->button() & Qt::LeftButton) - { - m_elapsed = m_elapsed ? false : true; - setTime(m_time); - } - PixmapWidget::mousePressEvent(e); -} - -void TimeIndicator::setSongDuration(int d) -{ - m_songDuration = d; -} - -TimeIndicator::~TimeIndicator() -{ - writeSettings(); -} - - -void TimeIndicator::updateSkin() -{ - if (m_needToShowTime) - setTime(m_time); -} - -void TimeIndicator::readSettings() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - settings.beginGroup("Display"); - m_elapsed = settings.value("Elapsed",true).toBool(); - settings.endGroup(); -} - - -void TimeIndicator::writeSettings() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - settings.beginGroup("Display"); - settings.setValue("Elapsed",m_elapsed); - settings.endGroup(); -} - - -void TimeIndicator::setNeedToShowTime(bool need) -{ - m_needToShowTime = need; - if (!need) reset(); -} - -void TimeIndicator::mouseMoveEvent(QMouseEvent *) -{} - -void TimeIndicator::mouseReleaseEvent(QMouseEvent *) -{} - diff --git a/src/timeindicator.h b/src/timeindicator.h deleted file mode 100644 index 19981a4b3..000000000 --- a/src/timeindicator.h +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef TIMEINDICATOR_H -#define TIMEINDICATOR_H - -#include - -class QMouseEvent; - -class Skin; - - -/** Class TimeIndicator - * @author Vladimir Kuznetsov - * - * Represents time indicator in the main display. Can show elapsed - * and rest time of song (mouse press on indicator changes mode) - */ -class TimeIndicator : public PixmapWidget -{ - Q_OBJECT -public: - TimeIndicator(QWidget *parent = 0); - ~TimeIndicator(); - void setTime ( int t ); - void setSongDuration(int); - void setNeedToShowTime(bool); -protected: - virtual void mousePressEvent(QMouseEvent*); - virtual void mouseMoveEvent(QMouseEvent*); - virtual void mouseReleaseEvent(QMouseEvent*); - void writeSettings(); - void readSettings(); - void reset(); -private slots: - void updateSkin(); -private: - QPixmap m_pixmap; - Skin *m_skin; - int m_time; - int m_songDuration; - bool m_elapsed; - bool m_needToShowTime; -}; - -#endif diff --git a/src/titlebar.cpp b/src/titlebar.cpp deleted file mode 100644 index bdbd86b2e..000000000 --- a/src/titlebar.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include -#include -#include - -#include -#include "symboldisplay.h" -#include "skin.h" -#include "button.h" -#include "dock.h" -#include "titlebarcontrol.h" -#include "shadedvisual.h" -#include "titlebar.h" - -TitleBar::TitleBar(QWidget *parent) - : PixmapWidget(parent) -{ - m_align = FALSE; - m_skin = Skin::getPointer(); - setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_A)); - m_mw = qobject_cast(parent); - m_shaded = FALSE; - m_currentTime = 0; - //buttons - m_menu = new Button(this,Skin::BT_MENU_N,Skin::BT_MENU_P); - connect(m_menu,SIGNAL(clicked()),this,SLOT(showMainMenu())); - m_menu->move(6,3); - m_minimize = new Button(this,Skin::BT_MINIMIZE_N,Skin::BT_MINIMIZE_P); - m_minimize->move(244,3); - connect(m_minimize, SIGNAL(clicked()), m_mw, SLOT(showMinimized())); - m_shade = new Button(this,Skin::BT_SHADE1_N,Skin::BT_SHADE1_P); - m_shade->move(254,3); - connect(m_shade, SIGNAL(clicked()), SLOT(shade())); - m_close = new Button(this,Skin::BT_CLOSE_N,Skin::BT_CLOSE_P); - m_close->move(264,3); - connect(m_close, SIGNAL(clicked()), m_mw, SLOT(handleCloseRequest())); - setActive(FALSE); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); - - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - if (settings.value("Display/shaded", FALSE).toBool()) - shade(); - m_align = TRUE; -} - - -TitleBar::~TitleBar() -{ - QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); - settings.setValue("Display/shaded", m_shaded); -} - -void TitleBar::mousePressEvent(QMouseEvent* event) -{ - switch ((int) event->button ()) - { - case Qt::LeftButton: - { - m_pos = event->pos(); - Dock::getPointer()->calculateDistances(); - break; - } - case Qt::RightButton: - { - m_mw->menu()->exec(event->globalPos()); - } - } -} - -void TitleBar::mouseReleaseEvent(QMouseEvent*) -{ - Dock::getPointer()->updateDock(); -} -void TitleBar::mouseMoveEvent(QMouseEvent* event) -{ - QPoint npos = (event->globalPos()-m_pos); - Dock::getPointer()->move(m_mw, npos); -} - -void TitleBar::setActive(bool a) -{ - if (a) - { - if (m_shaded) - { - setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_SHADED_A)); - m_shade2->show(); - } - else - { - setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_A)); - m_shade->show(); - } - m_menu->show(); - m_minimize->show(); - m_close->show(); - } - else - { - if (m_shaded) - { - setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_SHADED_I)); - m_shade2->hide(); - } - else - { - setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_I)); - m_shade->hide(); - } - m_menu->hide(); - m_minimize->hide(); - m_close->hide(); - } -} - -void TitleBar::updateSkin() -{ - setActive(FALSE); -} - -void TitleBar::showMainMenu() -{ - m_mw->menu()->exec(m_menu->mapToGlobal(m_menu->pos())); -} - -void TitleBar::shade() -{ - m_shaded = !m_shaded; - - if (m_shaded) - { - m_mw->setFixedSize(275,14); - setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_SHADED_A)); - m_shade->hide(); - m_shade2 = new Button(this,Skin::BT_SHADE2_N, Skin::BT_SHADE2_P); - m_shade2->move(254,3); - connect(m_shade2, SIGNAL(clicked()), SLOT(shade())); - m_shade2->show(); - m_currentTime = new SymbolDisplay(this, 6); - m_currentTime->move(127,4); - m_currentTime->show(); - m_currentTime->display("--:--"); - m_control = new TitleBarControl(this); - m_control->move(168,2); - m_control->show(); - connect (m_control, SIGNAL (nextClicked()), parent(), SLOT (next())); - connect (m_control, SIGNAL (previousClicked()), parent(), SLOT (previous())); - connect (m_control, SIGNAL (playClicked()), parent(), SLOT (play())); - connect (m_control, SIGNAL (pauseClicked()), parent(), SLOT (pause())); - connect (m_control, SIGNAL (stopClicked()), parent(), SLOT (stop())); - connect (m_control, SIGNAL (ejectClicked()), parent(), SLOT (addFile())); - m_visual = new ShadedVisual(this); - SoundCore::instance()->addVisualization(m_visual); - m_visual->show(); - m_visual->move(79,5); - } - else - { - m_mw->setFixedSize(275,116); - setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_A)); - delete m_shade2; - delete m_currentTime; - delete m_control; - SoundCore::instance()->removeVisual(m_visual); - delete m_visual; - m_shade2 = 0; - m_currentTime = 0; - m_shade->show(); - } - if(m_align) - Dock::getPointer()->align(m_mw, m_shaded? -102: 102); -} - -QString TitleBar::formatTime ( int sec ) -{ - int minutes = sec / 60; - int seconds = sec % 60; - - QString str_minutes = QString::number ( minutes ); - QString str_seconds = QString::number ( seconds ); - - if ( minutes < 10 ) str_minutes.prepend ( "0" ); - if ( seconds < 10 ) str_seconds.prepend ( "0" ); - - return str_minutes + ":" + str_seconds; -} - -void TitleBar::setInfo(const OutputState &st) -{ - if (!m_currentTime) - return; - switch ( ( int ) st.type() ) - { - case OutputState::Info: - { - m_currentTime->display(formatTime(st.elapsedSeconds())); - break; - } - case OutputState::Stopped: - { - m_currentTime->display("--:--"); - break; - } - } -} diff --git a/src/titlebar.h b/src/titlebar.h deleted file mode 100644 index 4428a188c..000000000 --- a/src/titlebar.h +++ /dev/null @@ -1,82 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef TITLEBAR_H -#define TITLEBAR_H - -#include -#include - -#include "pixmapwidget.h" -#include "playlist.h" -#include "mainwindow.h" - -/** - @author Ilya Kotov -*/ -class MainWindow; -class QMouseEvent; - -class Skin; -class Button; -class SymbolDisplay; -class TitleBarControl; -class ShadedVisual; - -class TitleBar : public PixmapWidget -{ -Q_OBJECT -public: - TitleBar(QWidget *parent = 0); - - ~TitleBar(); - - void setActive(bool); - void setInfo(const OutputState &st); - -private slots: - void updateSkin(); - void showMainMenu(); - void shade(); - -private: - Skin *m_skin; - QPoint m_pos; - MainWindow *m_mw; - Button *m_menu; - Button *m_minimize; - Button *m_shade; - Button *m_shade2; - Button *m_close; - SymbolDisplay *m_currentTime; - QString formatTime (int); - bool m_shaded; - bool m_align; - TitleBarControl *m_control; - ShadedVisual *m_visual; - -protected: - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); -}; - - - -#endif diff --git a/src/titlebarcontrol.cpp b/src/titlebarcontrol.cpp deleted file mode 100644 index 8238c287a..000000000 --- a/src/titlebarcontrol.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -#include "titlebarcontrol.h" - -TitleBarControl::TitleBarControl(QWidget *parent) - : QWidget(parent) -{ - //setAutoFillBackground(TRUE); - setFixedSize(57,10); -} - - -TitleBarControl::~TitleBarControl() -{ -} - -void TitleBarControl::mousePressEvent (QMouseEvent *) -{} - -void TitleBarControl::mouseReleaseEvent (QMouseEvent * event) -{ - QPoint pt = event->pos(); - if(QRect(0,0,8,10).contains(pt)) - emit previousClicked(); - else if(QRect(8,0,11,10).contains(pt)) - emit playClicked(); - else if(QRect(19,0,10,10).contains(pt)) - emit pauseClicked(); - else if(QRect(29,0,8,10).contains(pt)) - emit stopClicked(); - else if(QRect(37,0,10,10).contains(pt)) - emit nextClicked(); - else if(QRect(47,0,10,10).contains(pt)) - emit ejectClicked(); -} - -void TitleBarControl::mouseMoveEvent(QMouseEvent*) -{} diff --git a/src/titlebarcontrol.h b/src/titlebarcontrol.h deleted file mode 100644 index c368b2186..000000000 --- a/src/titlebarcontrol.h +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef TITLEBARCONTROL_H -#define TITLEBARCONTROL_H - -#include - -class QMouseEvent; - -/** - @author Ilya Kotov -*/ -class TitleBarControl : public QWidget -{ -Q_OBJECT -public: - TitleBarControl(QWidget *parent = 0); - ~TitleBarControl(); - -signals: - void previousClicked(); - void nextClicked(); - void pauseClicked(); - void playClicked(); - void stopClicked(); - void ejectClicked(); - -protected: - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); - - - -}; - -#endif diff --git a/src/togglebutton.cpp b/src/togglebutton.cpp deleted file mode 100644 index 86b809ef2..000000000 --- a/src/togglebutton.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include "skin.h" -#include "togglebutton.h" - - -ToggleButton::ToggleButton ( QWidget *parent,uint on_n,uint on_p,uint off_n,uint off_p ) - : PixmapWidget ( parent ) -{ - m_on_n = on_n; - m_on_p = on_p; - m_off_n = off_n; - m_off_p = off_p; - m_on = FALSE; - skin = Skin::getPointer(); - setON ( FALSE ); - connect ( skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); -} - - -ToggleButton::~ToggleButton() -{} - -bool ToggleButton::isChecked() -{ - return m_on; -} - -void ToggleButton::updateSkin() -{ - //setPixmap ( skin->getButton ( name_normal ) ); - setON ( m_on ); -} - -void ToggleButton::click() -{ - m_on = !m_on; - setON (m_on); - emit clicked(m_on); -} - -void ToggleButton::setON ( bool on ) -{ - m_on = on; - if ( on ) - setPixmap ( skin->getButton ( m_on_n ) ); - else - setPixmap ( skin->getButton ( m_off_n ) ); -} -void ToggleButton::mousePressEvent ( QMouseEvent* ) -{ - if ( m_on ) - setPixmap ( skin->getButton ( m_off_p ) ); - else - setPixmap ( skin->getButton ( m_on_p ) ); -} - -void ToggleButton::mouseReleaseEvent ( QMouseEvent* ) -{ - m_on = !m_on; - setON ( m_on ); - emit clicked( m_on ); -} diff --git a/src/togglebutton.h b/src/togglebutton.h deleted file mode 100644 index a15d7476f..000000000 --- a/src/togglebutton.h +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef TOGGLEBUTTON_H -#define TOGGLEBUTTON_H - -#include - -/** - @author Ilya Kotov -*/ -class Skin; - -class ToggleButton : public PixmapWidget -{ -Q_OBJECT -public: - ToggleButton( QWidget *parent, uint on_n, uint on_p, uint off_n, uint off_p ); - - ~ToggleButton(); - - bool isChecked(); - void setON(bool); - -signals: - void clicked(bool); - -public slots: - void click(); - -private slots: - void updateSkin(); - -private: - Skin *skin; - uint m_on_n, m_on_p, m_off_n, m_off_p; - bool m_on; - -protected: - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); -}; - - -#endif diff --git a/src/translations/qmmp_cs.ts b/src/translations/qmmp_cs.ts deleted file mode 100644 index faba9c1b9..000000000 --- a/src/translations/qmmp_cs.ts +++ /dev/null @@ -1,716 +0,0 @@ - - - - - AboutDialog - - - :/html/about_en.html - :/html/about_cs.html - - - - :/html/authors_en.txt - :/html/authors_cs.txt - - - - :/html/thanks_en.txt - :/html/thanks_cs.txt - - - - About Qmmp - O Qmmp - - - - About - O aplikaci - - - - Authors - Autoři - - - - Thanks To - Poděkování - - - - License Agreement - Licence - - - - AddUrlDialog - - - Enter URL to add - Přidat URL - - - - ConfigDialog - - - Enabled - Povoleno - - - - Description - Popis - - - - Filename - Soubor - - - - Artist - Umělec - - - - Album - Album - - - - Title - Název - - - - Tracknumber - Číslo stopy - - - - Genre - Žánr - - - - Filepath - Soubor - - - - Date - Datum - - - - Year - Rok - - - - Comment - Komentář - - - - Qmmp Settings - Nastavení Qmmp - - - - Appearance - Vzhled - - - - Playlist - Seznam skladeb - - - - Plugins - Moduly - - - - Advanced - Pokročilé - - - - Skins - Témata - - - - Fonts - Písma - - - - Player: - Přehrávač: - - - - Playlist: - Seznam skladeb: - - - - ??? - ??? - - - - ... - ... - - - - Metadata - Metadata - - - - Load metadata from files - Číst ze souborů metadata - - - - Song Display - Zobrazení skladby - - - - Title format: - Formát titulku: - - - - Preferences - Nastavení - - - - Information - Informace - - - - Input - Vstup - - - - Output - Výstup - - - - Tray Icon - Ikona v doku - - - - Show tooltip - Zobrazovat tooltip - - - - Show message - Zobrazovat zprávy - - - - Message delay, ms: - Doba zobrazení zpráv, v ms: - - - - Show tray icon - Zobrazovat ikonu v doku - - - - Action On Close - Při zavření okna - - - - Hide to tray - Schovat do doku - - - - Quit - Ukončit - - - - Close - Zavřít - - - - Connectivity - Síť - - - - File Dialog - Souborový dialog - - - - Proxy - Proxy - - - - Enable proxy usage - Povolit používání proxy - - - - Proxy host name: - Adresa proxy: - - - - Proxy port: - Port proxy: - - - - Use authentication with proxy - Použít autorizaci pro proxy - - - - Proxy user name: - Uživatelské jméno: - - - - Proxy password: - Heslo: - - - - Decoder - - - All Supported Bitstreams ( - Všechny podporované formáty ( - - - - EqWidget - - - preset - předvolba - - - - &Load/Delete - &Načíst/Odstranit - - - - &Save Preset - &Uložit předvolbu - - - - &Save Auto-load Preset - Uložit &automatickou předvolbu - - - - &Import - &Importovat - - - - &Clear - &Vynulovat - - - - Saving Preset - Uložení předvolby - - - - Preset name: - Název předvolby: - - - - preset # - předvolba # - - - - Import Preset - Importovat předvolbu - - - - JumpToTrackDialog - - - Unqueue - Vyřadit - - - - Queue - Zařadit - - - - Jump To Track - Přeskočit na skladbu - - - - Filter - Filtr - - - - Refresh - Načíst znovu - - - - Jump To - Přeskočit na - - - - Close - Zavřít - - - - MainWindow - - - Default - Seznam - - - - Now Playing - Nyní se přehrává - - - - Choose a directory - Výběr adresáře - - - - Select one or more files to open - Vyberte jeden či více souborů k otevření - - - - &Play - Pře&hrát - - - - X - X - - - - &Pause - Pau&za - - - - C - C - - - - &Stop - &Stop - - - - V - V - - - - &Previous - &Předchozí - - - - Z - Z - - - - &Next - &Další - - - - B - B - - - - &Queue - &Fronta - - - - Q - Q - - - - &Jump To File - Přeskočit na soubo&r - - - - J - J - - - - &Settings - &Nastavení - - - - Ctrl+P - Ctrl+P - - - - &About - O &aplikaci - - - - &Exit - U&končit - - - - Ctrl+Q - Ctrl+Q - - - - Playlist Files - Seznamy skladeb - - - - Open Playlist - Načíst seznam skladeb - - - - Save Playlist - Uložit seznam skladeb - - - - PlayList - - - &Add File - Přidat &soubor - - - - F - F - - - - &Add Directory - Přidat &adresář - - - - D - D - - - - &Remove Selected - &Odstranit vybrané - - - - Del - Del - - - - &Remove All - Odstranit &vše - - - - &Remove Unselected - Odstranit &nevybrané - - - - &View Track Details - Zobrazit &informace o skladbě - - - - Alt+I - Alt+I - - - - Sort List - Seřadit seznam - - - - By Title - Podle názvu skladby - - - - By Filename - Podle názvu souboru - - - - By Path + Filename - Podle cesty a názvu souboru - - - - By Date - Podle data - - - - Sort Selection - Seřadit výběr - - - - Randomize List - Zamíchat seznam - - - - Reverse List - Obrátit pořadí seznamu - - - - Invert Selection - Invertovat výběr - - - - &Select None - &Zrušit výběr - - - - &Select All - &Vybrat vše - - - - Ctrl+A - Ctrl+A - - - - &New List - &Nový seznam - - - - Shift+N - Shift+N - - - - &Load List - Načíst &seznam - - - - O - O - - - - &Save List - &Uložit seznam - - - - Shift+S - Shift+S - - - - &Add Url - Přidat &URL - - - - U - U - - - - PresetEditor - - - Preset Editor - Editor předvoleb - - - - Load - Načíst - - - - Delete - Odstranit - - - - Preset - Předvolba - - - - Auto-preset - Automatická předvolba - - - diff --git a/src/translations/qmmp_locales.qrc b/src/translations/qmmp_locales.qrc deleted file mode 100644 index 64ac204fa..000000000 --- a/src/translations/qmmp_locales.qrc +++ /dev/null @@ -1,8 +0,0 @@ - - - - qmmp_ru.qm - qmmp_tr.qm - qmmp_zh_CN.qm - - diff --git a/src/translations/qmmp_ru.qm b/src/translations/qmmp_ru.qm deleted file mode 100644 index 38c82d0e8..000000000 Binary files a/src/translations/qmmp_ru.qm and /dev/null differ diff --git a/src/translations/qmmp_ru.ts b/src/translations/qmmp_ru.ts deleted file mode 100644 index 32fdd757d..000000000 --- a/src/translations/qmmp_ru.ts +++ /dev/null @@ -1,645 +0,0 @@ - - - - - AboutDialog - - - About Qmmp - О Qmmp - - - - About - О программе - - - - License Agreement - Лицензия - - - - :/html/about_en.html - :/html/about_ru.html - - - - :/html/authors_en.txt - :/html/authors_ru.txt - - - - :/html/thanks_en.txt - :/html/thanks_ru.txt - - - - Authors - Авторы - - - - Thanks To - Благодарности - - - - ConfigDialog - - - Enabled - Включён - - - - Description - Описание - - - - Filename - Имя файла - - - - Artist - Исполнитель - - - - Album - Альбом - - - - Title - Название - - - - Tracknumber - Номер трека - - - - Genre - Жанр - - - - Filepath - Путь к файлу - - - - Date - Дата - - - - Year - Год - - - - Comment - Комментарий - - - - Qmmp Settings - Настройки Qmmp - - - - Skins - Обложки - - - - Fonts - Шрифты - - - - Player: - Плеер: - - - - Playlist: - Список: - - - - ??? - ??? - - - - ... - ... - - - - Metadata - Метаданные - - - - Load metadata from files - Считывать метаданные из файлов - - - - Song Display - Список песен - - - - Title format: - Формат названия: - - - - Input - Ввод - - - - Output - Вывод - - - - Preferences - Настройки - - - - Information - Информация - - - - Tray Icon - Системный значок - - - - Show tooltip - Всплывающая подсказка - - - - Show message - Показывать сообщение - - - - Message delay, ms: - Задержка сообщения, мс: - - - - Show tray icon - Показывать системный значок - - - - Appearance - Внешний вид - - - - Playlist - Список - - - - Plugins - Модули - - - - Advanced - Дополнительно - - - - Close - Закрыть - - - - Action On Close - Реакция на закрытие - - - - Hide to tray - Свернуть в системный лоток - - - - Quit - Выход - - - - EqWidget - - - preset - предустановка - - - - &Load/Delete - &Загрузить/Удалить - - - - &Save Preset - &Сохранить предустановку - - - - &Save Auto-load Preset - &Сохранить авто-предустановку - - - - &Clear - &Очистить - - - - Saving Preset - Сохранение предустановки - - - - Preset name: - Имя предустановки: - - - - preset # - предустановка # - - - - &Import - &Импортировать - - - - Import Preset - Импорт предустановки - - - - JumpToTrackDialog - - - Unqueue - Снять с очереди - - - - Queue - В очередь - - - - Jump To Track - Перейти к треку - - - - Filter - Фильтр - - - - Refresh - Обновить - - - - Jump To - Перейти к - - - - Close - Закрыть - - - - MainWindow - - - Default - - - - - Now Playing - Сейчас играет - - - - Choose a directory - Выберите директорию - - - - Select one or more files to open - Выберите один или несколько файлов - - - - &Play - &Воспроизвести - - - - X - - - - - &Pause - &Приостановить - - - - C - - - - - &Stop - &Стоп - - - - V - - - - - &Previous - &Назад - - - - Z - - - - - &Next - &Вперёд - - - - B - - - - - &Queue - &В очередь - - - - Q - - - - - &Jump To File - &Перейти к файлу - - - - J - - - - - &Settings - &Настройки - - - - Ctrl+P - - - - - &Exit - &Выход - - - - Ctrl+Q - - - - - Open Playlist - Открыть список - - - - Save Playlist - Сохранить список - - - - &About - &О программе - - - - Playlist Files - Файлы списков - - - - PlayList - - - F - - - - - D - - - - - Alt+I - - - - - Ctrl+A - - - - - O - - - - - &Add File - &Добавить файл - - - - &Add Directory - &Добавить директорию - - - - &Remove Selected - &Удалить выделенное - - - - &Remove All - &Удалить всё - - - - &Remove Unselected - &Удалить невыделенное - - - - &View Track Details - &Информация - - - - Sort List - Сортировать - - - - By Title - По названию - - - - By Filename - По имени файла - - - - By Path + Filename - По пути и файлу - - - - By Date - По дате - - - - Sort Selection - Сортировать выделенное - - - - Randomize List - Перемешать - - - - Reverse List - Перевернуть - - - - Invert Selection - Инвертировать выделение - - - - &Select None - &Снять выделение - - - - &Select All - &Выделить всё - - - - &New List - &Новый лист - - - - Shift+N - - - - - &Load List - &Загрузить лист - - - - &Save List - &Сохранить лист - - - - Shift+S - - - - - Del - - - - - PresetEditor - - - Preset Editor - Редактор предустановок - - - - Load - Загрузить - - - - Delete - Удалить - - - - Preset - Предустановка - - - - Auto-preset - Авто-предустановка - - - diff --git a/src/translations/qmmp_tr.qm b/src/translations/qmmp_tr.qm deleted file mode 100644 index 1180e41d5..000000000 Binary files a/src/translations/qmmp_tr.qm and /dev/null differ diff --git a/src/translations/qmmp_tr.ts b/src/translations/qmmp_tr.ts deleted file mode 100644 index 73f8206d6..000000000 --- a/src/translations/qmmp_tr.ts +++ /dev/null @@ -1,644 +0,0 @@ - - - - AboutDialog - - - About Qmmp - Qmmp Hakkında - - - - About - Hakkında - - - - License Agreement - Lisans Anlaşması - - - - :/html/about_en.html - :/html/about_en.html - - - - :/html/authors_en.txt - :/html/authors_en.txt - - - - :/html/thanks_en.txt - :/html/thanks_en.txt - - - - Authors - Yazarlar - - - - Thanks To - Teşekkürler - - - - ConfigDialog - - - Enabled - Etkinleştirildi - - - - Description - Açıklama - - - - Filename - Dosya adı - - - - Artist - Sanatçı - - - - Album - Albüm - - - - Title - Başlık - - - - Tracknumber - Parça Numarası - - - - Genre - Tarz - - - - Filepath - Dosya yolu - - - - Date - Tarih - - - - Year - Yıl - - - - Comment - Yorum - - - - Qmmp Settings - Qmmp Ayarları - - - - Skins - Kabuklar - - - - Fonts - Fontlar - - - - Player: - Oynatıcı: - - - - Playlist: - Çalma Listesi: - - - - ??? - ??? - - - - ... - ... - - - - Metadata - Veri bilgisi - - - - Load metadata from files - Veri bilgisini dosyadan yükle - - - - Song Display - Şarkı Göstergesi - - - - Title format: - Başlık formatı: - - - - Input - Giriş - - - - Output - Çıkış - - - - Preferences - Tercihler - - - - Information - Bilgi - - - - Tray Icon - Sistem Çekmecesi Simgesi - - - - Show tooltip - İpuçlarını göster - - - - Show message - Mesaj göster - - - - Message delay, ms: - Mesaj görüntü süresi, ms: - - - - Show tray icon - Sistem çekmecesi simgesini göster - - - - Appearance - Görünüm - - - - Playlist - Çalma Listesi - - - - Plugins - Eklentiler - - - - Advanced - Gelişmiş - - - - Close - Kapat - - - - Action On Close - - - - - Hide to tray - - - - - Quit - - - - - EqWidget - - - preset - tanımlanmış ayar - - - - &Load/Delete - &Yükle/Sil - - - - &Save Preset - Tanımlanmış &Ayarları Kaydet - - - - &Save Auto-load Preset - &Otomatik Tanımlanmış Ayarları Kaydet - - - - &Clear - &Temizle - - - - Saving Preset - Tanımlanmış Ayarla Kaydediliyor - - - - Preset name: - Tanımlanmış ayar adı: - - - - preset # - tanımlanmış ayar # - - - - &Import - &İçe Aktar - - - - Import Preset - Tanımlanmış Ayarları Al - - - - JumpToTrackDialog - - - Unqueue - Kuyrukta Değil - - - - Queue - Kuyruk - - - - Jump To Track - Parçaya Git - - - - Filter - Filtre - - - - Refresh - Yenile - - - - Jump To - Git - - - - Close - Kapat - - - - MainWindow - - - Default - Öntanımlı - - - - Now Playing - Şimdi Çalınıyor - - - - Choose a directory - Bir dizin seçin - - - - Select one or more files to open - Açmak için bir yada daha çok dosya seçin - - - - &Play - &Çal - - - - X - X - - - - &Pause - &Duraklat - - - - C - C - - - - &Stop - &Durdur - - - - V - V - - - - &Previous - &Önceki - - - - Z - Z - - - - &Next - &Sonraki - - - - B - B - - - - &Queue - &Kuyruğa ekle - - - - Q - Q - - - - &Jump To File - &Parçaya Git - - - - J - J - - - - &Settings - &Ayarlar - - - - Ctrl+P - Ctrl+P - - - - &Exit - &Çıkış - - - - Ctrl+Q - Ctrl+Q - - - - Open Playlist - Çalma Listesini Aç - - - - Save Playlist - Çalma Listesini Kaydet - - - - &About - &Hakkında - - - - Playlist Files - Çalma Listesi Dosyaları - - - - PlayList - - - F - F - - - - D - D - - - - Alt+I - Alt+I - - - - Ctrl+A - Ctrl+A - - - - O - O - - - - &Add File - &Dosya Ekle - - - - &Add Directory - &Dizin Ekle - - - - &Remove Selected - &Seçileni Kaldır - - - - &Remove All - &Hepsini Kaldır - - - - &Remove Unselected - &Seçilmemişleri Kaldır - - - - &View Track Details - &Parça Detaylarını Göster - - - - Sort List - Listeyi Sınıflandır - - - - By Title - Başlığa Göre - - - - By Filename - Dosya Adına Göre - - - - By Path + Filename - Dosya Yolu + Dosya Adına Göre - - - - By Date - Tarihe Göre - - - - Sort Selection - Seçilenleri Sınıflandır - - - - Randomize List - Rastgele Listele - - - - Reverse List - Listeyi Ters Çevir - - - - Invert Selection - Seçimi Tersine Çevir - - - - &Select None - &Hiçbirini Seçme - - - - &Select All - &Tümünü Seç - - - - &New List - &Yeni Liste - - - - Shift+N - Shift+N - - - - &Load List - &Liste Yükle - - - - &Save List - &Listeyi Kaydet - - - - Shift+S - Shift+S - - - - Del - - - - - PresetEditor - - - Preset Editor - Tanımlanmış Ayar Düzenleyici - - - - Load - Yükle - - - - Delete - Sil - - - - Preset - Tanımlanmış Ayar - - - - Auto-preset - Ayarları Otomatik Tanımla - - - diff --git a/src/translations/qmmp_zh_CN.qm b/src/translations/qmmp_zh_CN.qm deleted file mode 100644 index 2e3e3f2ea..000000000 Binary files a/src/translations/qmmp_zh_CN.qm and /dev/null differ diff --git a/src/translations/qmmp_zh_CN.ts b/src/translations/qmmp_zh_CN.ts deleted file mode 100644 index 3aeefd569..000000000 --- a/src/translations/qmmp_zh_CN.ts +++ /dev/null @@ -1,507 +0,0 @@ - - - AboutDialog - - About Qmmp - 关于 Qmmp - - - About - 关于 - - - License Agreement - 许可协议 - - - :/html/about_en.html - :/html/about_zh_CN.html - - - :/html/authors_en.txt - :/html/authors_zh_CN.txt - - - :/html/thanks_en.txt - :/html/thanks_zh_CN.txt - - - Authors - 作者 - - - Thanks To - 感谢 - - - - ConfigDialog - - Enabled - 启用 - - - Description - 描述 - - - Filename - 文件名 - - - Artist - 艺术家 - - - Album - 专辑 - - - Title - 标题 - - - Tracknumber - 轨迹 - - - Genre - 流派 - - - Filepath - 文件路径 - - - Date - 日期 - - - Year - - - - Comment - 注释 - - - Qmmp Settings - Qmmp 设置 - - - Skins - 皮肤 - - - Fonts - 字体 - - - Player: - 播放器: - - - Playlist: - 播放列表: - - - ??? - ??? - - - ... - ... - - - Metadata - 元数据 - - - Load metadata from files - 从文件载入元数据 - - - Song Display - 显示歌曲 - - - Title format: - 标题格式: - - - Input - 输入 - - - Output - 输出 - - - Preferences - 参数设置 - - - Information - 信息 - - - Tray Icon - 托盘图标 - - - Show tooltip - 显示工具栏 - - - Show message - 显示通知 - - - Message delay, ms: - 消息延迟,毫秒: - - - Show tray icon - 显示托盘图标 - - - Appearance - 外观 - - - Playlist - 播放列表 - - - Plugins - 插件 - - - Advanced - 高级 - - - Close - 关闭 - - - - EqWidget - - preset - 预设 - - - &Load/Delete - 载入/删除(&L) - - - &Save Preset - 保存预设(&S) - - - &Save Auto-load Preset - 保存自动载入预设(&S) - - - &Clear - 清除(&C) - - - Saving Preset - 保存预设 - - - Preset name: - 预设名字: - - - preset # - 预设 # - - - &Import - 导入(&I) - - - Import Preset - 导入预设 - - - - JumpToTrackDialog - - Unqueue - 移出队列 - - - Queue - 加入队列 - - - Jump To Track - 跳跃至音轨 - - - Filter - 过滤 - - - Refresh - 刷新 - - - Jump To - 跳跃至 - - - Close - 关闭 - - - - MainWindow - - Default - 默认 - - - Now Playing - 正在播放 - - - Choose a directory - 选择一个目录 - - - Select one or more files to open - 选择打开一个或更多文件 - - - &Play - 播放(&P) - - - X - X - - - &Pause - 暂停(&P) - - - C - C - - - &Stop - 停止(&S) - - - V - V - - - &Previous - 上一个(&P) - - - Z - Z - - - &Next - 下一个(&N) - - - B - B - - - &Queue - 队列&Q) - - - Q - Q - - - &Jump To File - 跳跃至文件(&J) - - - J - J - - - &Settings - 设置(&S) - - - Ctrl+P - Ctrl+P - - - &Exit - 退出(&E) - - - Ctrl+Q - Q - - - Open Playlist - 打开播放列表 - - - Save Playlist - 保存播放列表 - - - &About - 关于(&A) - - - Playlist Files - 播放列表文件 - - - - PlayList - - F - F - - - D - D - - - Delete - 删除 - - - Alt+I - Alt+I - - - Ctrl+A - Ctrl+A - - - O - O - - - &Add File - 添加文件(&A) - - - &Add Directory - 添加文件夹(&A) - - - &Remove Selected - 移除所选(&R) - - - &Remove All - 移除全部(&R) - - - &Remove Unselected - 移除未选(&R) - - - &View Track Details - 查看音轨详细信息(&V) - - - Sort List - 列表排序 - - - By Title - 按标题 - - - By Filename - 按文件名 - - - By Path + Filename - 按路径+文件名 - - - By Date - 按日期 - - - Sort Selection - 选择排序 - - - Randomize List - 随机产生列表 - - - Reverse List - 逆序列表 - - - Invert Selection - 反选 - - - &Select None - 选择无(&S) - - - &Select All - 全选(&S) - - - &New List - 新建列表(&N) - - - Shift+N - Shift+N - - - &Load List - 载入列表(&L) - - - &Save List - 保存列表(&S) - - - Shift+S - Shift+S - - - - PresetEditor - - Preset Editor - 预设编辑器 - - - Load - 装入 - - - Delete - 删除 - - - Preset - 预设 - - - Auto-preset - 预设自动 - - - diff --git a/src/ui/aboutdialog.cpp b/src/ui/aboutdialog.cpp new file mode 100644 index 000000000..a8b80e6cd --- /dev/null +++ b/src/ui/aboutdialog.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** +* Copyright (C) 2006 by Ilya Kotov * +* forkotov02@hotmail.ru * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ + + +#include "aboutdialog.h" + +#include +#include + +static QString getstringFromResource(const QString& res_file) +{ + QString ret_string; + QFile file(res_file); + if (file.open(QIODevice::ReadOnly)) + { + QTextStream ts(&file); + ts.setCodec("UTF-8"); + ret_string = ts.readAll(); + file.close(); + } + return ret_string; +} + +AboutDialog::AboutDialog(QWidget* parent, Qt::WFlags fl) + : QDialog( parent, fl ) +{ + setupUi(this); + setAttribute(Qt::WA_QuitOnClose, FALSE); + licenseTextEdit->setPlainText(getstringFromResource(":COPYING")); + aboutTextEdit->setHtml(getstringFromResource(tr(":/html/about_en.html"))); + authorsTextEdit->setPlainText(getstringFromResource(tr(":/html/authors_en.txt"))); + thanksToTextEdit->setPlainText(getstringFromResource(tr(":/html/thanks_en.txt"))); +} + +AboutDialog::~AboutDialog() +{} + +/*$SPECIALIZATION$*/ +void AboutDialog::accept() +{ + QDialog::accept(); +} + + + + diff --git a/src/ui/aboutdialog.h b/src/ui/aboutdialog.h new file mode 100644 index 000000000..10dcde4a5 --- /dev/null +++ b/src/ui/aboutdialog.h @@ -0,0 +1,44 @@ +/*************************************************************************** +* Copyright (C) 2006 by Ilya Kotov * +* forkotov02@hotmail.ru * +* * +* This program is free software; 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. * +***************************************************************************/ + +#ifndef ABOUTDIALOG_H +#define ABOUTDIALOG_H + +#include +#include "ui_aboutdialog.h" + +/** + @author Vladimir Kuznetsov + */ + +class AboutDialog : public QDialog, private Ui::AboutDialog +{ + Q_OBJECT +public: + AboutDialog(QWidget* parent = 0, Qt::WFlags fl = 0 ); + ~AboutDialog(); + +protected slots: + virtual void accept(); + +}; + +#endif + diff --git a/src/ui/addurldialog.cpp b/src/ui/addurldialog.cpp new file mode 100644 index 000000000..6746a2de1 --- /dev/null +++ b/src/ui/addurldialog.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "addurldialog.h" + +#include "playlistmodel.h" + +AddUrlDialog::AddUrlDialog( QWidget * parent, Qt::WindowFlags f) : QDialog(parent,f) +{ + setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); +} + +AddUrlDialog::~AddUrlDialog() +{} + + + +QPointer AddUrlDialog::instance = 0; + +void AddUrlDialog::popup(QWidget* parent,PlayListModel* model ) +{ + if(!instance) + { + instance = new AddUrlDialog(parent); + instance->setModel(model); + } + + instance->show(); + instance->raise(); +} + +void AddUrlDialog::accept( ) +{ + if(!urlComboBox->currentText().isEmpty()) + { + QString s = urlComboBox->currentText(); + if(!s.startsWith("http://")) + s.prepend("http://"); + + m_model->addFile(s); + } + + QDialog::accept(); +} + +void AddUrlDialog::setModel( PlayListModel *m ) +{ + m_model = m; +} diff --git a/src/ui/addurldialog.h b/src/ui/addurldialog.h new file mode 100644 index 000000000..86a065703 --- /dev/null +++ b/src/ui/addurldialog.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef ADDURLDIALOG_H +#define ADDURLDIALOG_H + +#include "ui_addurldialog.h" +#include +#include + + +class PlayListModel; + +/** + @author Vladimir Kuznetsov + */ + +class AddUrlDialog : public QDialog , private Ui::AddUrlDialog +{ + Q_OBJECT +public: + static void popup(QWidget* parent ,PlayListModel*); +protected: + AddUrlDialog( QWidget * parent = 0, Qt::WindowFlags f = 0 ); + ~AddUrlDialog(); +protected slots: + virtual void accept(); +private: + void setModel(PlayListModel*); + static QPointer instance; + PlayListModel* m_model; + +}; +#endif //ADDURLDIALOG_H diff --git a/src/ui/balancebar.cpp b/src/ui/balancebar.cpp new file mode 100644 index 000000000..3089e0cbd --- /dev/null +++ b/src/ui/balancebar.cpp @@ -0,0 +1,132 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include "skin.h" +#include "button.h" +#include "mainwindow.h" + +#include "balancebar.h" + + +BalanceBar::BalanceBar(QWidget *parent) + : PixmapWidget(parent) +{ + m_skin = Skin::getPointer(); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); + setPixmap(m_skin->getBalanceBar(0)); + m_moving = FALSE; + m_min = -100; + m_max = 100; + m_old = m_value = 0; + draw(FALSE); +} + + +BalanceBar::~BalanceBar() +{} + +void BalanceBar::mousePressEvent(QMouseEvent *e) +{ + + m_moving = TRUE; + press_pos = e->x(); + if(m_posx() && e->x()x()-m_pos; + } + else + { + m_value = convert(qMax(qMin(width()-18,e->x()-6),0)); + press_pos = 6; + if (m_value!=m_old) + { + emit sliderMoved(m_value); + + } + } + draw(); +} + +void BalanceBar::mouseMoveEvent (QMouseEvent *e) +{ + if(m_moving) + { + int po = e->x(); + po = po - press_pos; + + if(0<=po && po<=width()-13) + { + m_value = convert(po); + draw(); + emit sliderMoved(m_value); + } + } +} + +void BalanceBar::mouseReleaseEvent(QMouseEvent*) +{ + m_moving = FALSE; + draw(FALSE); + m_old = m_value; +} + +void BalanceBar::setValue(int v) +{ + if (m_moving || m_max == 0) + return; + m_value = v; + draw(FALSE); +} + +void BalanceBar::setMax(int max) +{ + m_max = max; + draw(FALSE); +} + +void BalanceBar::updateSkin() +{ + draw(FALSE); +} + +void BalanceBar::draw(bool pressed) +{ + if(abs(m_value)<6) + m_value = 0; + int p=int(ceil(double(m_value-m_min)*(width()-13)/(m_max-m_min))); + m_pixmap = m_skin->getBalanceBar(abs(27*m_value/m_max)); + QPainter paint(&m_pixmap); + if(pressed) + paint.drawPixmap(p,1,m_skin->getButton(Skin::BT_BAL_P)); + else + paint.drawPixmap(p,1,m_skin->getButton(Skin::BT_BAL_N)); + setPixmap(m_pixmap); + m_pos = p; +} + +int BalanceBar::convert(int p) +{ + return int(ceil(double(m_max-m_min)*(p)/(width()-13)+m_min)); +} + diff --git a/src/ui/balancebar.h b/src/ui/balancebar.h new file mode 100644 index 000000000..6704671f9 --- /dev/null +++ b/src/ui/balancebar.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef BALANCEBAR_H +#define BALANCEBAR_H + +#include + +class Skin; + +/** + @author Ilya Kotov +*/ +class BalanceBar : public PixmapWidget +{ +Q_OBJECT +public: + BalanceBar(QWidget *parent = 0); + + ~BalanceBar(); + + int value() {return m_value; }; + +public slots: + void setValue(int); + void setMax(int); + +signals: + void sliderMoved (int); + +private slots: + void updateSkin(); + +private: + Skin *m_skin; + bool m_moving; + int press_pos; + int m_max, m_min, m_pos, m_value, m_old; + QPixmap m_pixmap; + int convert(int); // value = convert(position); + void draw(bool pressed = TRUE); + +protected: + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + +}; + +#endif diff --git a/src/ui/button.cpp b/src/ui/button.cpp new file mode 100644 index 000000000..8bd006ed3 --- /dev/null +++ b/src/ui/button.cpp @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "button.h" +#include "skin.h" + +Button::Button ( QWidget *parent, uint normal, uint pressed ) + : PixmapWidget ( parent ) +{ + name_normal = normal; + name_pressed = pressed; + skin = Skin::getPointer(); + setON ( FALSE ); + connect ( skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); +} + + +Button::~Button() +{} + +void Button::updateSkin() +{ + setPixmap ( skin->getButton ( name_normal ) ); +} + +void Button::setON ( bool on ) +{ + if ( on ) + setPixmap ( skin->getButton ( name_pressed ) ); + else + setPixmap ( skin->getButton ( name_normal ) ); +} +void Button::mousePressEvent ( QMouseEvent* ) +{ + setON ( TRUE ); +} + +void Button::mouseReleaseEvent ( QMouseEvent* ) +{ + setON ( FALSE ); + emit clicked(); +} diff --git a/src/ui/button.h b/src/ui/button.h new file mode 100644 index 000000000..7f2d8f314 --- /dev/null +++ b/src/ui/button.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef BUTTON_H +#define BUTTON_H + +#include "pixmapwidget.h" + +class Skin; + +/** + @author Ilya Kotov +*/ +class Button : public PixmapWidget +{ +Q_OBJECT +public: + Button(QWidget *parent, uint normal, uint pressed); + + ~Button(); + +signals: + void clicked(); + +private slots: + void updateSkin(); + +private: + Skin *skin; + void setON(bool); + uint name_normal, name_pressed; + +protected: + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); +}; + +#endif diff --git a/src/ui/commandlineoption.cpp b/src/ui/commandlineoption.cpp new file mode 100644 index 000000000..ca9e8d398 --- /dev/null +++ b/src/ui/commandlineoption.cpp @@ -0,0 +1,216 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include "commandlineoption.h" +#include "mainwindow.h" +#include + + +// Command option manager methods +CommandLineOptionManager::CommandLineOptionManager() +{ + this->registerBuiltingCommandLineOptions(); + this->registerExternalCommandLineOptions(); +} + +bool CommandLineOptionManager::hasOption(const QString &opt) +{ + for(int i = 0; i < m_options.count(); i++) + { + if(m_options[i]->identify(opt)) + { + return true; + } + } + return false; +} + +void CommandLineOptionManager::executeCommand(const QString &opt, MainWindow *mw) +{ + for(int i = 0; i < m_options.count(); i++) + { + if(m_options[i]->identify(opt)) + { + m_options[i]->executeCommand(opt,mw); + } + } +} + +CommandLineOption * CommandLineOptionManager::operator [](int index) +{ + return m_options[index]; +} + +int CommandLineOptionManager::count() const +{ + return m_options.count(); +} + + +void CommandLineOptionManager::registerBuiltingCommandLineOptions() +{ + m_options.append(new BuiltinCommandLineOption()); +} + + +void CommandLineOptionManager::registerExternalCommandLineOptions() +{ + QDir pluginsDir (QDir::homePath()+"/.qmmp/plugins/CommandLineOptions"); + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) + { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (loader.isLoaded()) + qDebug("CommandLineOption: plugin loaded - %s", qPrintable(fileName)); + else + qWarning(qPrintable(loader.errorString())); + + CommandLineOption *cmd_option = 0; + if (plugin) + cmd_option = qobject_cast(plugin); + + if (cmd_option) + { + foreach(CommandLineOption* opt,m_options) + { + if (opt->name() == cmd_option->name()) + { + qDebug("CommandLineOption: Plugin with name %s is already registered...", + qPrintable(cmd_option->name())); + return; + } + } + m_options.append(cmd_option); + } + } +} + +/////////////////////////////////////////////////////////////////// + + +// BuiltinCommandLineOption methods implementation +bool BuiltinCommandLineOption::identify(const QString & str) const +{ + if( + str == QString("--help") || + str == QString("--next") || + str == QString("--previous") || + str == QString("--play") || + str == QString("--pause") || + str == QString("--play-pause") || + str == QString("--stop") || + str.startsWith("--volume") || + str.startsWith("--jump-to-file") || + str.startsWith("--toggle-visibility") || + str.startsWith("--add-file") + ) + { + return TRUE; + } + + return FALSE; +} + +const QString BuiltinCommandLineOption::helpString() const +{ + return QString( + "--next Skip forward in playlist\n" + "--previous Skip backwards in playlist\n" + "--play Start playing current song\n" + "--pause Pause current song\n" + "--play-pause Pause if playing, play otherwise\n" + "--stop Stop current song\n" + "--next Skip forward in playlist\n" + "--volume Set playback volume(example: qmmp --volume20, qmmp --volume100)\n" + "--jump-to-file Display Jump to File dialog\n" + "--toggle-visibility Show/hide application\n" + "--add-file Display Add File dialog" + ); +} + +void BuiltinCommandLineOption::executeCommand(const QString & option_string, MainWindow *mw) +{ + if (option_string == "--play") + { + mw->play(); + } + else if (option_string == "--stop") + { + mw->stop(); + mw->mainDisplay()->hideTimeDisplay(); + } + else if (option_string == "--pause") + { + mw->pause(); + } + else if (option_string == "--next") + { + mw->next(); + if(!mw->soundCore()->isInitialized()) + mw->play(); + } + else if (option_string == "--previous") + { + mw->previous(); + if(!mw->soundCore()->isInitialized()) + mw->play(); + } + else if (option_string == "--play-pause") + { + mw->playPause(); + } + else if (option_string == "--jump-to-file") + { + mw->jumpToFile(); + } + else if (option_string == "--toggle-visibility") + { + mw->toggleVisibility(); + } + else if (option_string == "--add-file") + { + mw->addFile(); + } + else if (option_string.startsWith("--volume")) + { + QString vol_str(option_string); + vol_str.remove("--volume"); + bool ok = FALSE; + int volume = vol_str.toUInt(&ok); + if(ok) + { + mw->soundCore()->setVolume(volume,volume); + } + } +} + +const QString BuiltinCommandLineOption::name() const +{ + return "BuiltinCommandLineOption"; +} + + + + + + diff --git a/src/ui/commandlineoption.h b/src/ui/commandlineoption.h new file mode 100644 index 000000000..f5bc78ecf --- /dev/null +++ b/src/ui/commandlineoption.h @@ -0,0 +1,94 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef CommandLineOption_H +#define CommandLineOption_H + +#include +#include +#include + +class MainWindow; + +/** + @author Vladimir Kuznetsov + */ +class CommandLineOption +{ +public: + /*! + * Returns \b true if \b opt_str string can be processed, + * otherise \b false + */ + virtual bool identify(const QString& opt_str)const = 0; + + /*! + * Command line option name + */ + virtual const QString name()const = 0; + + /*! + * Help string. + */ + virtual const QString helpString()const = 0; + + /*! + * Parses \b opt_str args(if needed), executes command. + */ + virtual void executeCommand(const QString& opt_str,MainWindow* mw) = 0; + virtual ~CommandLineOption(){;} +}; + +Q_DECLARE_INTERFACE(CommandLineOption,"CommandLineOptionInterface/1.0"); + + + +typedef QList CommandLineOptionList; + +class CommandLineOptionManager +{ +public: + CommandLineOptionManager(); + bool hasOption(const QString& ); + void executeCommand(const QString&,MainWindow* = NULL); + CommandLineOption* operator[](int); + int count()const; +protected: + void registerBuiltingCommandLineOptions(); + void registerExternalCommandLineOptions(); +private: + void _register(CommandLineOption*); +private: + CommandLineOptionList m_options; +}; + +/*! + * Represens command line option handling for standard operations. + */ +class BuiltinCommandLineOption : public CommandLineOption +{ + virtual bool identify(const QString& str)const; + virtual const QString helpString()const; + virtual void executeCommand(const QString& option,MainWindow* = NULL); + virtual const QString name()const; + virtual ~BuiltinCommandLineOption(){;} +}; + +#endif diff --git a/src/ui/configdialog.cpp b/src/ui/configdialog.cpp new file mode 100644 index 000000000..808c1ac94 --- /dev/null +++ b/src/ui/configdialog.cpp @@ -0,0 +1,509 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "skin.h" +#include "filedialog.h" +#include "pluginitem.h" +#include "configdialog.h" +#include "skinreader.h" + +ConfigDialog::ConfigDialog ( QWidget *parent ) + : QDialog ( parent ) +{ + ui.setupUi ( this ); + setAttribute(Qt::WA_QuitOnClose, FALSE); + setAttribute(Qt::WA_DeleteOnClose, FALSE); + connect ( ui. contentsWidget, + SIGNAL ( currentItemChanged ( QListWidgetItem *, QListWidgetItem * ) ), + this, SLOT ( changePage ( QListWidgetItem *, QListWidgetItem* ) ) ); + connect ( ui.mainFontButton, SIGNAL ( clicked() ), SLOT ( setMainFont() ) ); + connect ( ui.plFontButton, SIGNAL ( clicked() ), SLOT ( setPlFont() ) ); + connect ( ui.preferencesButton, SIGNAL ( clicked() ), SLOT (showPluginSettings())); + connect ( ui.informationButton, SIGNAL ( clicked() ), SLOT (showPluginInfo())); + connect ( this, SIGNAL(accepted()),SLOT(saveSettings())); + ui.listWidget->setIconSize ( QSize ( 69,29 ) ); + m_skin = Skin::getPointer(); + ui.fileDialogComboBox->insertItems(0,FileDialog::registeredFactories()); + readSettings(); + SkinReader reader; + reader.updateCache(); + loadSkins(); + loadPluginsInfo(); + loadFonts(); + createMenus(); +} + +ConfigDialog::~ConfigDialog() +{ + while (!m_outputPluginItems.isEmpty()) + delete m_outputPluginItems.takeFirst(); + while (!m_inputPluginItems.isEmpty()) + delete m_outputPluginItems.takeFirst(); + while (!m_visualPluginItems.isEmpty()) + delete m_visualPluginItems.takeFirst(); + while (!m_effectPluginItems.isEmpty()) + delete m_effectPluginItems.takeFirst(); +} + +void ConfigDialog::readSettings() +{ + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + ui.formatLineEdit->setText( + settings.value ( "PlayList/title_format", "%p - %t").toString()); + ui.metadataCheckBox->setChecked( + settings.value ( "PlayList/load_metadata", TRUE).toBool()); + QString f_dialogName = + settings.value("FileDialog",QtFileDialogFactory::QtFileDialogFactoryName).toString(); + + int ind = FileDialog::registeredFactories().indexOf(f_dialogName); + if (ind != -1) + ui.fileDialogComboBox->setCurrentIndex(ind); + else + ui.fileDialogComboBox->setCurrentIndex(0); + + //proxy settings + ui.enableProxyCheckBox->setChecked( + settings.value ("Proxy/use_proxy", FALSE).toBool()); + ui.authProxyCheckBox->setChecked( + settings.value ("Proxy/authentication", FALSE).toBool()); + + ui.hostLineEdit->setText(settings.value("Proxy/host").toString()); + ui.portLineEdit->setText(settings.value("Proxy/port").toString()); + ui.proxyUserLineEdit->setText(settings.value("Proxy/user").toString()); + ui.proxyPasswLineEdit->setText(settings.value("Proxy/passw").toString()); + + ui.hostLineEdit->setEnabled(ui.enableProxyCheckBox->isChecked()); + ui.portLineEdit->setEnabled(ui.enableProxyCheckBox->isChecked()); + ui.proxyUserLineEdit->setEnabled(ui.authProxyCheckBox->isChecked()); + ui.proxyPasswLineEdit->setEnabled(ui.authProxyCheckBox->isChecked()); + + ui.softVolumeCheckBox->setChecked(settings.value("Volume/software_volume", FALSE).toBool()); +} + +void ConfigDialog::changePage ( QListWidgetItem *current, QListWidgetItem *previous ) +{ + if ( !current ) + current = previous; + ui.stackedWidget->setCurrentIndex ( ui.contentsWidget->row ( current ) ); +} + +void ConfigDialog::changeSkin() +{ + int row = ui.listWidget->currentRow(); + QString path = m_skinList.at ( row ).canonicalFilePath(); + m_skin->setSkin ( path ); +} + +void ConfigDialog::loadSkins() +{ + m_skinList.clear(); + //findSkins(":/"); + + QFileInfo fileInfo (":/default"); + QPixmap preview = Skin::getPixmap ("main", QDir (fileInfo.filePath())); + QListWidgetItem *item = new QListWidgetItem (fileInfo.fileName ()); + item->setIcon ( preview ); + ui.listWidget->addItem ( item ); + m_skinList << fileInfo; + + findSkins(QDir::homePath() +"/.qmmp/skins"); + findSkins(QDir::homePath() +"/.qmmp/cache/skins"); + findSkins(qApp->applicationDirPath()+"/../share/qmmp/skins"); + connect ( ui.listWidget, SIGNAL ( itemClicked ( QListWidgetItem* ) ), + this, SLOT ( changeSkin() ) ); +} + +void ConfigDialog::findSkins(const QString &path) +{ + QDir dir(path); + dir.setFilter ( QDir::Dirs | QDir::NoDotAndDotDot); + QList fileList = dir.entryInfoList(); + if ( fileList.count() == 0 ) + return; + foreach (QFileInfo fileInfo, fileList) + { + QPixmap preview = Skin::getPixmap ( "main", QDir ( fileInfo.filePath() ) ); + if ( !preview.isNull() ) + { + QListWidgetItem *item = new QListWidgetItem ( fileInfo.fileName () ); + item->setIcon ( preview ); + ui.listWidget->addItem ( item ); + m_skinList << fileInfo; + } + } +} + +void ConfigDialog::loadPluginsInfo() +{ + /* + load input plugins information + */ + QList *decoders = 0; + decoders = Decoder::decoderFactories(); + QStringList files = Decoder::decoderFiles(); + ui.inputPluginTable->setColumnCount ( 3 ); + ui.inputPluginTable->verticalHeader()->hide(); + ui.inputPluginTable->setHorizontalHeaderLabels ( QStringList() + << tr ( "Enabled" ) << tr ( "Description" ) << tr ( "Filename" ) ); + ui.inputPluginTable->setRowCount ( decoders->count () ); + for ( int i = 0; i < decoders->count (); ++i ) + { + InputPluginItem *item = new InputPluginItem(this,decoders->at(i),files.at(i)); + QCheckBox* checkBox = new QCheckBox ( ui.inputPluginTable ); + connect(checkBox, SIGNAL(toggled(bool)), item, SLOT(setSelected(bool))); + checkBox->setChecked(item->isSelected()); + ui.inputPluginTable->setCellWidget ( i, 0, checkBox ); + ui.inputPluginTable->setItem ( i,1, + new QTableWidgetItem (item->factory()->properties().name) ); + ui.inputPluginTable->setItem ( i,2, new QTableWidgetItem (files.at (i)) ); + ui.inputPluginTable->item(i,1)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + ui.inputPluginTable->item(i,2)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + } + ui.inputPluginTable->resizeColumnToContents ( 0 ); + ui.inputPluginTable->resizeColumnToContents ( 1 ); + ui.inputPluginTable->resizeRowsToContents (); + /* + load output plugins information + */ + QList *outputs = 0; + outputs = Output::outputFactories(); + files = Output::outputFiles(); + ui.outputPluginTable->setColumnCount ( 3 ); + ui.outputPluginTable->verticalHeader()->hide(); + ui.outputPluginTable->setHorizontalHeaderLabels ( QStringList() + << tr ( "Enabled" ) << tr ( "Description" ) << tr ( "Filename" ) ); + ui.outputPluginTable->setRowCount ( outputs->count () ); + + for ( int i = 0; i < outputs->count (); ++i ) + { + OutputPluginItem *item = new OutputPluginItem(this,outputs->at(i),files.at(i)); + m_outputPluginItems.append(item); + QRadioButton* button = new QRadioButton ( ui.outputPluginTable ); + connect(button, SIGNAL(pressed ()), item, SLOT(select())); + button->setChecked ( item->isSelected() ); + ui.outputPluginTable->setCellWidget ( i, 0, button ); + ui.outputPluginTable->setItem (i,1, + new QTableWidgetItem (item->factory()->properties().name)); + ui.outputPluginTable->setItem (i,2, new QTableWidgetItem (files.at(i))); + ui.outputPluginTable->item(i,1)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + ui.outputPluginTable->item(i,2)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + } + + ui.outputPluginTable->resizeColumnToContents ( 0 ); + ui.outputPluginTable->resizeColumnToContents ( 1 ); + ui.outputPluginTable->resizeRowsToContents (); + /* + load visual plugin information + */ + QList *visuals = 0; + visuals = Visual::visualFactories(); + files = Visual::visualFiles(); + ui.visualPluginTable->setColumnCount ( 3 ); + ui.visualPluginTable->verticalHeader()->hide(); + ui.visualPluginTable->setHorizontalHeaderLabels ( QStringList() + << tr ( "Enabled" ) << tr ( "Description" ) << tr ( "Filename" ) ); + ui.visualPluginTable->setRowCount ( visuals->count () ); + + for ( int i = 0; i < visuals->count (); ++i ) + { + VisualPluginItem *item = new VisualPluginItem(this,visuals->at(i),files.at(i)); + m_visualPluginItems.append(item); + QCheckBox* button = new QCheckBox (ui.visualPluginTable); + connect(button, SIGNAL(clicked (bool)), item, SLOT(select(bool))); + button->setChecked (item->isSelected()); + ui.visualPluginTable->setCellWidget ( i, 0, button ); + ui.visualPluginTable->setItem (i,1, + new QTableWidgetItem (item->factory()->properties().name)); + ui.visualPluginTable->setItem (i,2, new QTableWidgetItem (files.at(i))); + ui.visualPluginTable->item(i,1)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + ui.visualPluginTable->item(i,2)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + } + + ui.visualPluginTable->resizeColumnToContents ( 0 ); + ui.visualPluginTable->resizeColumnToContents ( 1 ); + ui.visualPluginTable->resizeRowsToContents (); + + /* + load effect plugin information + */ + QList *effects = 0; + effects = Effect::effectFactories(); + files = Effect::effectFiles(); + ui.effectPluginTable->setColumnCount ( 3 ); + ui.effectPluginTable->verticalHeader()->hide(); + ui.effectPluginTable->setHorizontalHeaderLabels ( QStringList() + << tr ( "Enabled" ) << tr ( "Description" ) << tr ( "Filename" ) ); + ui.effectPluginTable->setRowCount ( visuals->count () ); + + for ( int i = 0; i < effects->count (); ++i ) + { + EffectPluginItem *item = new EffectPluginItem(this,effects->at(i),files.at(i)); + m_effectPluginItems.append(item); + QCheckBox* button = new QCheckBox (ui.effectPluginTable); + connect(button, SIGNAL(clicked (bool)), item, SLOT(select(bool))); + button->setChecked (item->isSelected()); + ui.effectPluginTable->setCellWidget ( i, 0, button ); + ui.effectPluginTable->setItem (i,1, + new QTableWidgetItem (item->factory()->properties().name)); + ui.effectPluginTable->setItem (i,2, new QTableWidgetItem (files.at(i))); + ui.effectPluginTable->item(i,1)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + ui.effectPluginTable->item(i,2)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + } + + ui.effectPluginTable->resizeColumnToContents ( 0 ); + ui.effectPluginTable->resizeColumnToContents ( 1 ); + ui.effectPluginTable->resizeRowsToContents (); + + /* + load general plugin information + */ + QList *generals = 0; + generals = General::generalFactories(); + files = General::generalFiles(); + ui.generalPluginTable->setColumnCount ( 3 ); + ui.generalPluginTable->verticalHeader()->hide(); + ui.generalPluginTable->setHorizontalHeaderLabels ( QStringList() + << tr ( "Enabled" ) << tr ( "Description" ) << tr ( "Filename" ) ); + ui.generalPluginTable->setRowCount ( generals->count () ); + + for ( int i = 0; i < generals->count (); ++i ) + { + GeneralPluginItem *item = new GeneralPluginItem(this,generals->at(i),files.at(i)); + m_generalPluginItems.append(item); + QCheckBox* button = new QCheckBox (ui.generalPluginTable); + connect(button, SIGNAL(clicked (bool)), item, SLOT(select(bool))); + button->setChecked (item->isSelected()); + ui.generalPluginTable->setCellWidget ( i, 0, button ); + ui.generalPluginTable->setItem (i,1, + new QTableWidgetItem (item->factory()->properties().name)); + ui.generalPluginTable->setItem (i,2, new QTableWidgetItem (files.at(i))); + ui.generalPluginTable->item(i,1)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + ui.generalPluginTable->item(i,2)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + } + + ui.generalPluginTable->resizeColumnToContents ( 0 ); + ui.generalPluginTable->resizeColumnToContents ( 1 ); + ui.generalPluginTable->resizeRowsToContents (); +} + + +void ConfigDialog::loadFonts() +{ + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + QString fontname = settings.value ( "PlayList/Font","" ).toString(); + if ( fontname.isEmpty () ) + fontname = QFont ( "Helvetica [Cronyx]", 10 ).toString(); + ui.plFontLabel -> setText ( fontname ); + + fontname = settings.value ( "MainWindow/Font","" ).toString(); + if ( fontname.isEmpty () ) + fontname = QFont ( "Helvetica [Cronyx]", 9 ).toString(); + ui.mainFontLabel -> setText ( fontname ); +} + +void ConfigDialog::setPlFont() +{ + bool ok; + QFont font; + font.fromString ( ui.plFontLabel->text() ); + font = QFontDialog::getFont ( &ok, font, this ); + if ( ok ) + { + ui.plFontLabel -> setText ( font.toString () ); + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + settings.setValue ( "PlayList/Font", font.toString() ); + } +} + +void ConfigDialog::setMainFont() +{ + bool ok; + QFont font; + font.fromString ( ui.plFontLabel->text() ); + font = QFontDialog::getFont ( &ok, font, this ); + if ( ok ) + { + ui.mainFontLabel -> setText ( font.toString () ); + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + settings.setValue ( "MainWindow/Font", font.toString() ); + } +} + +void ConfigDialog::showPluginSettings() +{ + switch ( ( int ) ui.pluginsTab -> currentIndex () ) + { + case 0: + { + QList *decoders = 0; + decoders = Decoder::decoderFactories(); + int row = ui.inputPluginTable->currentRow (); + if ( !decoders || row<0 ) + return; + + decoders->at ( row )->showSettings ( this ); + break; + } + case 1: + { + int row = ui.outputPluginTable->currentRow (); + if ( m_outputPluginItems.isEmpty() || row < 0 ) + return; + m_outputPluginItems.at(row)->factory()->showSettings ( this ); + break; + } + case 2: + { + int row = ui.visualPluginTable->currentRow (); + if ( m_visualPluginItems.isEmpty() || row < 0 ) + return; + m_visualPluginItems.at(row)->factory()->showSettings ( this ); + break; + } + case 3: + { + int row = ui.effectPluginTable->currentRow (); + if ( m_effectPluginItems.isEmpty() || row < 0 ) + return; + m_effectPluginItems.at(row)->factory()->showSettings ( this ); + break; + } + case 4: + { + int row = ui.generalPluginTable->currentRow (); + if ( m_generalPluginItems.isEmpty() || row < 0 ) + return; + m_generalPluginItems.at(row)->factory()->showSettings ( this ); + break; + } + } +} + +void ConfigDialog::showPluginInfo() +{ + switch ( ( int ) ui.pluginsTab -> currentIndex () ) + { + case 0: + { + QList *decoders = 0; + decoders = Decoder::decoderFactories(); + int row = ui.inputPluginTable->currentRow (); + if ( !decoders || row<0 ) + return; + + decoders->at ( row )->showAbout ( this ); + break; + } + case 1: + { + int row = ui.outputPluginTable->currentRow (); + if ( m_outputPluginItems.isEmpty() || row < 0 ) + return; + m_outputPluginItems.at(row)->factory()->showAbout ( this ); + break; + } + case 2: + { + int row = ui.visualPluginTable->currentRow (); + if ( m_visualPluginItems.isEmpty() || row < 0 ) + return; + m_visualPluginItems.at(row)->factory()->showAbout ( this ); + break; + } + case 3: + { + int row = ui.effectPluginTable->currentRow (); + if ( m_effectPluginItems.isEmpty() || row < 0 ) + return; + m_effectPluginItems.at(row)->factory()->showAbout ( this ); + break; + } + case 4: + { + int row = ui.generalPluginTable->currentRow (); + if ( m_generalPluginItems.isEmpty() || row < 0 ) + return; + m_generalPluginItems.at(row)->factory()->showAbout ( this ); + break; + } + } +} + +void ConfigDialog::createMenus() +{ + QMenu *menu = new QMenu(this); + + menu->addAction(tr("Artist"))->setData("%p"); + menu->addAction(tr("Album"))->setData("%a"); + menu->addAction(tr("Title"))->setData("%t"); + menu->addAction(tr("Tracknumber"))->setData("%n"); + menu->addAction(tr("Genre"))->setData("%g"); + menu->addAction(tr("Filename"))->setData("%f"); + menu->addAction(tr("Filepath"))->setData("%F"); + menu->addAction(tr("Date"))->setData("%d"); + menu->addAction(tr("Year"))->setData("%y"); + menu->addAction(tr("Comment"))->setData("%c"); + ui.titleButton->setMenu(menu); + ui.titleButton->setPopupMode(QToolButton::InstantPopup); + connect( menu, SIGNAL(triggered ( QAction * )), SLOT(addTitleString( QAction * ))); +} + +void ConfigDialog::addTitleString( QAction * a) +{ + if (ui.formatLineEdit->cursorPosition () < 1) + ui.formatLineEdit->insert(a->data().toString()); + else + ui.formatLineEdit->insert(" - "+a->data().toString()); +} + +void ConfigDialog::saveSettings() +{ + QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); + settings.setValue ("PlayList/title_format", ui.formatLineEdit->text()); + settings.setValue ("PlayList/load_metadata", ui.metadataCheckBox->isChecked()); + settings.setValue ("FileDialog", ui.fileDialogComboBox->currentText()); + settings.setValue ("Proxy/use_proxy", ui.enableProxyCheckBox->isChecked()); + settings.setValue ("Proxy/authentication", ui.authProxyCheckBox->isChecked()); + settings.setValue ("Proxy/host",ui.hostLineEdit->text()); + settings.setValue ("Proxy/port",ui.portLineEdit->text()); + settings.setValue ("Proxy/user",ui.proxyUserLineEdit->text()); + settings.setValue ("Proxy/passw",ui.proxyPasswLineEdit->text()); + settings.setValue ("Volume/software_volume", ui.softVolumeCheckBox->isChecked()); +} + diff --git a/src/ui/configdialog.h b/src/ui/configdialog.h new file mode 100644 index 000000000..7b9b1fab2 --- /dev/null +++ b/src/ui/configdialog.h @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef CONFIGDIALOG_H +#define CONFIGDIALOG_H + +#include +#include + +#include "ui_configdialog.h" + + +/** + @author Ilya Kotov +*/ +class QFileInfo; + +class Skin; +class InputPluginItem; +class OutputPluginItem; +class VisualPluginItem; +class EffectPluginItem; +class GeneralPluginItem; + +class ConfigDialog : public QDialog +{ + Q_OBJECT +public: + ConfigDialog(QWidget *parent = 0); + + ~ConfigDialog(); + +private slots: + void changePage(QListWidgetItem *current, QListWidgetItem *previous); + void changeSkin(); + void setPlFont(); + void setMainFont(); + void showPluginSettings(); + void showPluginInfo(); + void addTitleString( QAction * ); + void saveSettings(); + +private: + void readSettings(); + void loadSkins(); + void findSkins(const QString &path); + void loadPluginsInfo(); + void loadFonts(); + void createMenus(); + + + QList m_skinList; + Ui::ConfigDialog ui; + Skin *m_skin; + QPixmap pixmap; + + QList m_inputPluginItems; + QList m_outputPluginItems; + QList m_visualPluginItems; + QList m_effectPluginItems; + QList m_generalPluginItems; +}; + +#endif diff --git a/src/ui/default/balance.png b/src/ui/default/balance.png new file mode 100644 index 000000000..5fa10cce8 Binary files /dev/null and b/src/ui/default/balance.png differ diff --git a/src/ui/default/cbuttons.png b/src/ui/default/cbuttons.png new file mode 100644 index 000000000..7a1369b59 Binary files /dev/null and b/src/ui/default/cbuttons.png differ diff --git a/src/ui/default/eq_ex.png b/src/ui/default/eq_ex.png new file mode 100644 index 000000000..974004590 Binary files /dev/null and b/src/ui/default/eq_ex.png differ diff --git a/src/ui/default/eqmain.png b/src/ui/default/eqmain.png new file mode 100644 index 000000000..b28b818de Binary files /dev/null and b/src/ui/default/eqmain.png differ diff --git a/src/ui/default/main.png b/src/ui/default/main.png new file mode 100644 index 000000000..6b7c8597a Binary files /dev/null and b/src/ui/default/main.png differ diff --git a/src/ui/default/monoster.png b/src/ui/default/monoster.png new file mode 100644 index 000000000..7ddb9d0e5 Binary files /dev/null and b/src/ui/default/monoster.png differ diff --git a/src/ui/default/numbers.png b/src/ui/default/numbers.png new file mode 100644 index 000000000..46f1e1f63 Binary files /dev/null and b/src/ui/default/numbers.png differ diff --git a/src/ui/default/playpaus.png b/src/ui/default/playpaus.png new file mode 100644 index 000000000..0cfbd6835 Binary files /dev/null and b/src/ui/default/playpaus.png differ diff --git a/src/ui/default/pledit.png b/src/ui/default/pledit.png new file mode 100644 index 000000000..3c2943cea Binary files /dev/null and b/src/ui/default/pledit.png differ diff --git a/src/ui/default/pledit.txt b/src/ui/default/pledit.txt new file mode 100644 index 000000000..549a81ad1 --- /dev/null +++ b/src/ui/default/pledit.txt @@ -0,0 +1,6 @@ +[Text] +Normal=#C0C0C0 +Current=#8080FF +NormalBG=#000080 +SelectedBG=#408080 +Font=Tahoma Bold \ No newline at end of file diff --git a/src/ui/default/posbar.png b/src/ui/default/posbar.png new file mode 100644 index 000000000..271106557 Binary files /dev/null and b/src/ui/default/posbar.png differ diff --git a/src/ui/default/shufrep.png b/src/ui/default/shufrep.png new file mode 100644 index 000000000..107fd50bb Binary files /dev/null and b/src/ui/default/shufrep.png differ diff --git a/src/ui/default/text.png b/src/ui/default/text.png new file mode 100644 index 000000000..d37241405 Binary files /dev/null and b/src/ui/default/text.png differ diff --git a/src/ui/default/titlebar.png b/src/ui/default/titlebar.png new file mode 100644 index 000000000..c1e7818cd Binary files /dev/null and b/src/ui/default/titlebar.png differ diff --git a/src/ui/default/viscolor.txt b/src/ui/default/viscolor.txt new file mode 100644 index 000000000..9fbb3f64d --- /dev/null +++ b/src/ui/default/viscolor.txt @@ -0,0 +1,24 @@ +0,64,128 +0,64,128 +55,105,155 +63,111,159 +71,117,163 +79,123,167 +87,129,171 +95,135,175 +103,141,179 +111,147,183 +119,153,187 +127,159,191 +135,165,195 +143,171,199 +151,177,203 +159,183,207 +167,189,211 +175,195,215 +255,255,255 +167,189,211 +135,165,195 +119,153,187 +87,129,171 +114,223,229 diff --git a/src/ui/default/volume.png b/src/ui/default/volume.png new file mode 100644 index 000000000..b4f457453 Binary files /dev/null and b/src/ui/default/volume.png differ diff --git a/src/ui/display.cpp b/src/ui/display.cpp new file mode 100644 index 000000000..d2cce8165 --- /dev/null +++ b/src/ui/display.cpp @@ -0,0 +1,290 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include +#include "skin.h" +#include "mainvisual.h" +#include "button.h" +#include "titlebar.h" +#include "positionbar.h" +#include "number.h" +#include "togglebutton.h" +#include "symboldisplay.h" +#include "textscroller.h" +#include "monostereo.h" +#include "playstatus.h" +#include "volumebar.h" +#include "balancebar.h" +#include "mainwindow.h" +#include "timeindicator.h" + +#include "display.h" + +MainDisplay::MainDisplay ( QWidget *parent ) + : PixmapWidget ( parent ) +{ + m_skin = Skin::getPointer(); + setPixmap ( m_skin->getMain() ); + setMaximumSize ( QSize ( 275,116 ) ); + setMinimumSize ( QSize ( 275,116 ) ); + + m_mw = qobject_cast(parent); + + Button *previous = new Button ( this, + Skin::BT_PREVIOUS_N, Skin::BT_PREVIOUS_P ); + previous->move ( 16, 88 ); + connect ( previous,SIGNAL ( clicked() ),parent,SLOT ( previous() ) ); + Button *play = new Button ( this, + Skin::BT_PLAY_N, Skin::BT_PLAY_P ); + play->move ( 39, 88 ); + connect ( play,SIGNAL ( clicked() ),parent,SLOT ( play() ) ); + Button *pause = new Button ( this, Skin::BT_PAUSE_N,Skin::BT_PAUSE_P ); + pause->move ( 62, 88 ); + connect ( pause,SIGNAL ( clicked() ),parent,SLOT ( pause() ) ); + Button *stop = new Button ( this, Skin::BT_STOP_N,Skin::BT_STOP_P ); + stop->move ( 85, 88 ); + connect ( stop,SIGNAL ( clicked() ),parent,SLOT ( stop() ) ); + connect ( stop,SIGNAL ( clicked() ),this,SLOT ( hideTimeDisplay() ) ); + Button *next = new Button ( this, Skin::BT_NEXT_N,Skin::BT_NEXT_P ); + next->move ( 108, 88 ); + connect ( next,SIGNAL ( clicked() ),parent,SLOT ( next() ) ); + Button *eject = new Button ( this, Skin::BT_EJECT_N,Skin::BT_EJECT_P ); + eject->move ( 136, 89 ); + connect ( eject,SIGNAL ( clicked() ),parent,SLOT ( addFile() ) ); + connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); + posbar = new PositionBar ( this ); + posbar->move ( 16,72 ); + //connect(posbar, SIGNAL(sliderMoved(int)), SLOT(setTime(int))); + MainVisual* vis = new MainVisual (this); + vis->move(24,39); + vis->show(); + + m_eqButton = new ToggleButton ( this,Skin::BT_EQ_ON_N,Skin::BT_EQ_ON_P, + Skin::BT_EQ_OFF_N,Skin::BT_EQ_OFF_P ); + m_eqButton->move ( 219,58 ); + m_eqButton->show(); + m_plButton = new ToggleButton ( this,Skin::BT_PL_ON_N,Skin::BT_PL_ON_P, + Skin::BT_PL_OFF_N,Skin::BT_PL_OFF_P ); + m_plButton->move ( 241,58 ); + m_plButton->show(); + + m_repeatButton = new ToggleButton ( this,Skin::REPEAT_ON_N,Skin::REPEAT_ON_P, + Skin::REPEAT_OFF_N,Skin::REPEAT_OFF_P ); + connect(m_repeatButton,SIGNAL(clicked(bool)),this,SIGNAL(repeatableToggled(bool))); + + m_repeatButton->move ( 210,89 ); + m_repeatButton->show(); + + m_shuffleButton = new ToggleButton ( this,Skin::SHUFFLE_ON_N,Skin::SHUFFLE_ON_P, + Skin::SHUFFLE_OFF_N,Skin::SHUFFLE_OFF_P ); + connect(m_shuffleButton,SIGNAL(clicked(bool)),this,SIGNAL(shuffleToggled(bool))); + m_shuffleButton->move ( 164,89 ); + m_shuffleButton->show(); + + m_kbps = new SymbolDisplay( this,3 ); + m_kbps -> move ( 111,43 ); + m_kbps -> show(); + + m_freq = new SymbolDisplay( this,2 ); + m_freq -> move ( 156,43 ); + m_freq -> show(); + + TextScroller *m_text = new TextScroller ( this ); + m_text->resize ( 154,15 ); + m_text->move ( 109,23 ); + m_text->show(); + + m_monoster = new MonoStereo ( this ); + m_monoster->move ( 212,41 ); + m_monoster->show(); + + m_playstatus = new PlayStatus(this); + m_playstatus->move(24,28); + m_playstatus->show(); + + m_volumeBar = new VolumeBar(this); + connect(m_volumeBar, SIGNAL(sliderMoved(int)),SLOT(updateVolume())); + m_volumeBar->move(107,57); + m_volumeBar->show(); + + m_balanceBar = new BalanceBar(this); + connect(m_balanceBar, SIGNAL(sliderMoved(int)),SLOT(updateVolume())); + m_balanceBar->move(177,57); + m_balanceBar->show(); + m_timeIndicator = new TimeIndicator(this); + m_timeIndicator->move(34,26); + m_timeIndicator->show(); +} + + +MainDisplay::~MainDisplay() +{ + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + settings.setValue ( "Playlist/visible",m_plButton->isChecked() ); + settings.setValue ( "Equalizer/visible",m_eqButton->isChecked() ); +} + +void MainDisplay::setTime ( int t ) +{ + posbar->setValue ( t ); + m_timeIndicator->setTime(t); +} +void MainDisplay::setMaxTime ( long mt ) // TODO: should be removed +{ + posbar->setMax ( mt ); + m_timeIndicator->setSongDuration(mt); +} + + +void MainDisplay::updateSkin() +{ + setPixmap ( m_skin->getMain() ); +} + +void MainDisplay::setEQ ( QWidget* w ) +{ + m_equlizer = w; + m_eqButton->setON ( m_equlizer->isVisible() ); + connect (m_eqButton, SIGNAL (clicked(bool)), m_equlizer, SLOT (setVisible (bool))); + connect (m_equlizer, SIGNAL (closed ()), m_eqButton, SLOT (click())); +} + +void MainDisplay::setPL ( QWidget* w ) +{ + m_playlist = w; + m_plButton->setON ( m_playlist->isVisible() ); + connect (m_plButton, SIGNAL (clicked (bool)), m_playlist, SLOT (setVisible (bool))); + connect (m_playlist, SIGNAL (closed ()), m_plButton, SLOT (click())); +} + +void MainDisplay::setInfo(const OutputState &st) +{ + + + switch ( ( int ) st.type() ) + { + case OutputState::Info: + { + //if ( seeking ) + // break; + setTime ( st.elapsedSeconds() ); + m_kbps->display ( st.bitrate() ); + m_freq->display ( st.frequency() /1000 ); + m_monoster->setChannels ( st.channels() ); + update(); + break; + } + case OutputState::Playing: + { + m_playstatus->setStatus(PlayStatus::PLAY); + m_timeIndicator->setNeedToShowTime(true); + break; + } + case OutputState::Buffering: + { + //ui.label->setText("Buffering"); + break; + } + case OutputState::Paused: + { + m_playstatus->setStatus(PlayStatus::PAUSE); + break; + } + case OutputState::Stopped: + { + m_playstatus->setStatus(PlayStatus::STOP); + m_monoster->setChannels (0); + //m_timeIndicator->setNeedToShowTime(false); + break; + } + case OutputState::Volume: + //qDebug("volume %d, %d", st.rightVolume(), st.leftVolume()); + int maxVol = qMax(st.leftVolume(),st.rightVolume()); + m_volumeBar->setValue(maxVol); + if (maxVol && !m_volumeBar->isPressed()) + m_balanceBar->setValue((st.rightVolume()-st.leftVolume())*100/maxVol); + break; + + } +} + +bool MainDisplay::isPlaylistVisible() const +{ + return m_plButton->isChecked(); +} + +bool MainDisplay::isEqualizerVisible() const +{ + return m_eqButton->isChecked(); +} + +void MainDisplay::updateVolume() +{ + m_mw->setVolume(m_volumeBar->value(), m_balanceBar->value()); +} + +void MainDisplay::wheelEvent (QWheelEvent *e) +{ + m_mw->setVolume(m_volumeBar->value()+e->delta()/10, m_balanceBar->value()); +} + +bool MainDisplay::isRepeatable() const +{ + return m_repeatButton->isChecked(); +} + +bool MainDisplay::isShuffle() const +{ + return m_shuffleButton->isChecked(); +} + +void MainDisplay::setIsRepeatable(bool yes) +{ + m_repeatButton->setON(yes); +} + +void MainDisplay::setIsShuffle(bool yes) +{ + m_shuffleButton->setON(yes); +} + + +void MainDisplay::hideTimeDisplay() +{ + m_timeIndicator->setNeedToShowTime(false); +} + + +void MainDisplay::mousePressEvent(QMouseEvent *e) +{ + if ( e->button() == Qt::RightButton) + { + m_mw->menu()->exec(e->globalPos()); + } + PixmapWidget::mousePressEvent(e); +} + + diff --git a/src/ui/display.h b/src/ui/display.h new file mode 100644 index 000000000..15e0111d6 --- /dev/null +++ b/src/ui/display.h @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include + +class TimeIndicator; + + +#include "pixmapwidget.h" + +/** + @author Ilya Kotov +*/ +class QPushButton; +class QLabel; + +class TitleBar; +class PositionBar; +class Number; +class Skin; +class ToggleButton; +class OutputState; +class NumberDisplay; +class SymbolDisplay; +class MonoStereo; +class PlayStatus; +class VolumeBar; +class BalanceBar; +class MainWindow; + +class MainDisplay : public PixmapWidget +{ + Q_OBJECT +public: + MainDisplay(QWidget *parent = 0); + + ~MainDisplay(); + + void setMaxTime(long); + void setEQ(QWidget*); + void setPL(QWidget*); + void setInfo(const OutputState &st); + bool isEqualizerVisible()const; + bool isPlaylistVisible()const; + bool isRepeatable()const; + bool isShuffle()const; + void setIsRepeatable(bool); + void setIsShuffle(bool); + +public slots: + void setTime(int); + void hideTimeDisplay(); +signals: + void repeatableToggled(bool); + void shuffleToggled(bool); +protected: + void wheelEvent(QWheelEvent *); + void mousePressEvent(QMouseEvent*); + +private slots: + void updateSkin(); + void updateVolume(); + +private: + QWidget* m_equlizer; + QWidget* m_playlist; + QPixmap pixmap; + QPushButton *button; + QLabel *label; + Skin *m_skin; + TitleBar *titleBar; + PositionBar *posbar; + ToggleButton *m_eqButton; + ToggleButton *m_plButton; + ToggleButton *m_shuffleButton; + ToggleButton *m_repeatButton; + SymbolDisplay* m_kbps; + SymbolDisplay* m_freq; + MonoStereo* m_monoster; + PlayStatus* m_playstatus; + VolumeBar* m_volumeBar; + BalanceBar* m_balanceBar; + MainWindow* m_mw; + TimeIndicator* m_timeIndicator; +}; + +#endif diff --git a/src/ui/dock.cpp b/src/ui/dock.cpp new file mode 100644 index 000000000..2a755a9b9 --- /dev/null +++ b/src/ui/dock.cpp @@ -0,0 +1,257 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "dock.h" + + +Dock *Dock::pointer = 0; + +Dock *Dock::getPointer() +{ + if ( !pointer ) + pointer = new Dock(); + return pointer; +} + +Dock::Dock ( QObject *parent ) + : QObject ( parent ) +{ + pointer = this; + m_mainWidget = 0; +} + +Dock::~Dock() +{} + +void Dock::setMainWidget ( QWidget *widget ) +{ + m_mainWidget = widget; + m_widgetList.prepend ( widget ); + m_dockedList.prepend ( FALSE ); +} + + +QPoint Dock::snap ( QPoint npos, QWidget* mv, QWidget* st ) +{ + int nx = npos.x() - st->x(); + int ny = abs ( npos.y() - st->y() + mv->height() ); + + if ( abs ( nx ) < 13 && ny < 13 ) //above + npos.rx() = st->x(); + if ( ny < 13 && nx > -mv->width() && nx < st->width() ) + npos.ry() = st->y() - mv->height(); + nx = abs ( npos.x() + mv->width() - st->x() - st->width() ); + if ( nx < 13 && ny < 13 ) + npos.rx() = st->x() + st->width() - mv->width(); + + /***********/ + nx = npos.x() - st->x(); + ny = abs ( npos.y() - st->y() - st->height() ); + + if ( abs ( nx ) < 13 && ny < 13 ) //near + npos.rx() = st->x(); + if ( ny < 13 && nx > -mv->width() && nx < st->width() ) + npos.ry() = st->y() + st->height(); + nx = abs ( npos.x() + mv->width() - st->x() - st->width() ); + if ( nx < 13 && ny < 13 ) + npos.rx() = st->x() + st->width() - mv->width(); + /**************/ + nx = abs ( npos.x() - st->x() + mv->width() ); + ny = npos.y() - st->y(); + + if ( nx < 13 && abs ( ny ) < 13 ) //left + npos.ry() = st->y(); + if ( nx < 13 && ny > -mv->height() && ny < st->height() ) + npos.rx() = st->x() - mv->width(); + + ny = abs ( npos.y() + mv->height() - st->y() - st->height() ); + if ( nx < 13 && ny < 13 ) + npos.ry() = st->y() + st->height() - mv->height(); + /*****************/ + nx = abs ( npos.x() - st->x() - st->width() ); + ny = npos.y() - st->y(); + + if ( nx < 13 && abs ( ny ) < 13 ) //right + npos.ry() = st->y(); + if ( nx < 13 && ny > -mv->height() && ny < st->height() ) + npos.rx() = st->x() + st->width(); + + ny = abs ( npos.y() + mv->height() - st->y() - st->height() ); + if ( nx < 13 && ny < 13 ) + npos.ry() = st->y() + st->height() - mv->height(); + + return ( npos ); +} + +void Dock::addWidget ( QWidget *widget ) +{ + m_widgetList.append ( widget ); + m_dockedList.append ( FALSE ); + widget->addActions(m_actions); + +} + +void Dock::move ( QWidget* mv, QPoint npos ) +{ + if ( mv == m_mainWidget ) + { + + for ( int i = 1; iisVisible() ) + npos = snap ( npos, mv, m_widgetList.at ( i ) ); + + } + else + { + QPoint pos = QPoint ( npos.x() + x_list.at ( i ), + npos.y() + y_list.at ( i ) ); + for ( int j = 1; jisVisible() ) + { + pos = snap ( pos, m_widgetList.at ( i ), m_widgetList.at ( j ) ); + npos = QPoint ( pos.x() - x_list.at ( i ), + pos.y() - y_list.at ( i ) ); + } + } + } + } + mv->move ( npos ); + for ( int i = 1; imove ( npos.x() + x_list.at ( i ), + npos.y() + y_list.at ( i ) ); + } + } + else + { + for ( int i = 0; iisVisible() ) + { + npos = snap ( npos, mv, m_widgetList.at ( i ) ); + } + } + mv->move ( npos ); + } +} + +void Dock::calculateDistances() +{ + x_list.clear(); + y_list.clear(); + foreach ( QWidget *w, m_widgetList ) + { + if ( w!=m_mainWidget ) + { + x_list.append ( - m_mainWidget->x() + w->x() ); + y_list.append ( - m_mainWidget->y() + w->y() ); + } + else + { + x_list.prepend ( 0 ); + y_list.prepend ( 0 ); + } + } +} + +void Dock::updateDock() +{ + QWidget *mv = m_widgetList.at ( 0 ); + for ( int j = 1; jx() - st->x(); + int ny = abs ( mv->y() - st->y() + mv->height() ); + if ( ny < 2 && nx > -mv->width() && nx < st->width() ) //above + return TRUE; + + /***********/ + nx = mv->x() - st->x(); + ny = abs ( mv->y() - st->y() - st->height() ); + if ( ny < 2 && nx > -mv->width() && nx < st->width() ) //near + return TRUE; + + /**************/ + nx = abs ( mv->x() - st->x() + mv->width() ); + ny = mv->y() - st->y(); + if ( nx < 2 && ny > -mv->height() && ny < st->height() ) //left + return TRUE; + + /*****************/ + nx = abs ( mv->x() - st->x() - st->width() ); + ny = mv->y() - st->y(); + if ( nx < 2 && ny > -mv->height() && ny < st->height() ) //right + return TRUE; + return FALSE; +} + +void Dock::addActions ( QList actions ) +{ + m_actions << actions; + for ( int i = 0; iaddActions ( actions ); +} + +bool Dock::isUnder(QWidget* upper, QWidget* nether, int dy) +{ + int nx = upper->x() - nether->x(); + return abs (upper->y() + upper->height() -dy - nether->y()) < 2 && + nx > -upper->width() && nx < nether->width(); +} + +void Dock::align(QWidget* w, int dy) +{ + for (int i = 0; imove(m_widgetList.at(i)->x(), m_widgetList.at(i)->y()+dy); + align(m_widgetList.at(i), dy); + } + } +} diff --git a/src/ui/dock.h b/src/ui/dock.h new file mode 100644 index 000000000..b4b62dda2 --- /dev/null +++ b/src/ui/dock.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef DOCK_H +#define DOCK_H + +#include +#include +#include + +/** + @author Ilya Kotov +*/ + +class QAction; + +class Dock : public QObject +{ + Q_OBJECT +public: + Dock(QObject *parent = 0); + + ~Dock(); + + static Dock *getPointer(); + void setMainWidget(QWidget*); + void addWidget(QWidget *); + void move(QWidget*, QPoint); + void calculateDistances(); + void updateDock(); + QPoint snap(QPoint, QWidget*, QWidget*); + void addActions(QList actions); + void align(QWidget*, int dy); + +private: + bool isDocked(QWidget*, QWidget*); + bool isUnder(QWidget*, QWidget*, int); + static Dock *pointer; + QWidget *m_mainWidget; + QList m_widgetList; + QList m_dockedList; + QList x_list; + QList y_list; + QList m_actions; +}; + +#endif diff --git a/src/ui/eqgraph.cpp b/src/ui/eqgraph.cpp new file mode 100644 index 000000000..314e504d9 --- /dev/null +++ b/src/ui/eqgraph.cpp @@ -0,0 +1,163 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include + +#include "skin.h" +#include "eqgraph.h" + +EQGraph::EQGraph ( QWidget *parent ) + : PixmapWidget ( parent ) +{ + m_skin = Skin::getPointer(); + setPixmap ( m_skin->getEqPart ( Skin::EQ_GRAPH ) ); + clear(); + draw(); + connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); +} + + +EQGraph::~EQGraph() +{} + +void EQGraph::addValue ( int value ) +{ + if ( m_values.size() >= 10 ) + return; + m_values.append ( value ); + if ( m_values.size() == 10 ) + { + draw(); + } +} + +void EQGraph::clear () +{ + m_values.clear(); + update(); +} + +void EQGraph::init_spline ( double * x, double * y, int n, double * y2 ) +{ + int i, k; + double p, qn, sig, un, *u; + + //u = ( gfloat * ) g_malloc ( n * sizeof ( gfloat ) ); + u = new double[n]; + + 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 ); + delete[] u; +} + +double EQGraph::eval_spline ( double xa[], double ya[], 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 ); +} + +void EQGraph::draw() +{ + if(m_values.size()!=10) + { + setPixmap ( m_skin->getEqPart ( Skin::EQ_GRAPH ) ); + return; + } + + int i, y, ymin, ymax, py = 0; + double x[] = { 0, 11, 23, 35, 47, 59, 71, 83, 97, 109 }, yf[10]; + double *bands = new double[10]; + + for ( int i = 0; i<10; ++i ) + { + bands[i] = m_values.at ( i ); + } + QPixmap pixmap = m_skin->getEqPart ( Skin::EQ_GRAPH ); + + init_spline ( x, bands, 10, yf ); + for ( i = 0; i < 109; i++ ) + { + y = 9 - + ( int ) ( ( eval_spline ( x, bands, yf, 10, i ) * + 9.0 ) / 20.0 ); + if ( y < 0 ) + y = 0; + if ( y > 18 ) + y = 18; + if ( !i ) + py = y; + if ( y < py ) + { + ymin = y; + ymax = py; + } + else + { + ymin = py; + ymax = y; + } + py = y; + + QPainter paint ( &pixmap ); + paint.drawPixmap ( i, y, m_skin->getEqSpline ( y ) ) ; + + + } + setPixmap ( pixmap ); + delete [] bands; +} + +void EQGraph::updateSkin() +{ + draw(); +} + diff --git a/src/ui/eqgraph.h b/src/ui/eqgraph.h new file mode 100644 index 000000000..4f6bf1882 --- /dev/null +++ b/src/ui/eqgraph.h @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef EQGRAPH_H +#define EQGRAPH_H + +#include "pixmapwidget.h" + +/** + @author Ilya Kotov +*/ + +class Skin; + +class EQGraph : public PixmapWidget +{ + Q_OBJECT +public: + EQGraph ( QWidget *parent = 0 ); + + ~EQGraph(); + + void addValue ( int ); + void clear(); + +/*protected: + void paintEvent ( QPaintEvent * );*/ +private slots: + void updateSkin(); + +private: + QList m_values; + Skin *m_skin; + void init_spline ( double * x, double * y, int n, double * y2 ); + double eval_spline ( double xa[], double ya[], double y2a[], int n, double x ); + void draw(); + +}; + +#endif diff --git a/src/ui/eqpreset.cpp b/src/ui/eqpreset.cpp new file mode 100644 index 000000000..760dea9d2 --- /dev/null +++ b/src/ui/eqpreset.cpp @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "eqpreset.h" + +EQPreset::EQPreset() + : QListWidgetItem() +{ + m_preamp = 0; + for(int i = 0; i < 10; ++i) + m_bands[i] = 0; +} + + +EQPreset::~EQPreset() +{} + +void EQPreset::setGain(int n, int value) +{ + if(n > 9 || n < 0) + return; + m_bands[n] = value; +} + +void EQPreset::setPreamp(int preamp) +{ + m_preamp = preamp; +} + +int EQPreset::gain(int n) +{ + if(n > 9 || n < 0) + return 0; + return m_bands[n]; +} + +int EQPreset::preamp() +{ + return m_preamp; +} diff --git a/src/ui/eqpreset.h b/src/ui/eqpreset.h new file mode 100644 index 000000000..80f31747e --- /dev/null +++ b/src/ui/eqpreset.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef EQPRESET_H +#define EQPRESET_H + +#include + +/** + @author Ilya Kotov +*/ +class EQPreset : public QListWidgetItem +{ +public: + EQPreset(); + + ~EQPreset(); + + void setGain(int n, int value); + void setPreamp(int); + + int gain(int n); + int preamp(); + +private: + int m_bands[10]; + int m_preamp; + +}; + +#endif diff --git a/src/ui/eqslider.cpp b/src/ui/eqslider.cpp new file mode 100644 index 000000000..bdc4ec4e2 --- /dev/null +++ b/src/ui/eqslider.cpp @@ -0,0 +1,147 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include + +#include "skin.h" + +#include "eqslider.h" + + +EqSlider::EqSlider(QWidget *parent) + : PixmapWidget(parent) +{ + m_skin = Skin::getPointer(); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); + setPixmap(m_skin->getEqSlider(0)); + m_moving = FALSE; + m_min = -20; + m_max = 20; + m_old = m_value = 0; + draw(FALSE); +} + + +EqSlider::~EqSlider() +{} + +void EqSlider::mousePressEvent(QMouseEvent *e) +{ + m_moving = TRUE; + press_pos = e->y(); + if (m_posy() && e->y()y()-m_pos; + } + else + { + m_value = convert(qMax(qMin(height()-12,e->y()-6),0)); + press_pos = 6; + if (m_value!=m_old) + { + emit sliderMoved(m_value); + m_old = m_value; + //qDebug ("%d",m_value); + } + } + draw(); +} + +void EqSlider::mouseReleaseEvent(QMouseEvent*) +{ + m_moving = FALSE; + draw(FALSE); +} + +void EqSlider::mouseMoveEvent(QMouseEvent* e) +{ + if (m_moving) + { + int po = e->y(); + po = po - press_pos; + + if (0<=po && po<=height()-12) + { + m_value = convert(po); + draw(); + if (m_value!=m_old) + { + + m_old = m_value; + //qDebug ("%d",-m_value); + emit sliderMoved(-m_value); + } + } + } +} + +int EqSlider::value() +{ + return -m_value; +} + +void EqSlider::setValue(int p) +{ + if (m_moving) + return; + m_value = -p; + draw(FALSE); +} + +void EqSlider::setMax(int m) +{ + m_max = m; + draw(FALSE); +} + +void EqSlider::updateSkin() +{ + draw(FALSE); +} + +void EqSlider::draw(bool pressed) +{ + int p=int(ceil(double(m_value-m_min)*(height()-12)/(m_max-m_min))); + m_pixmap = m_skin->getEqSlider(27-27*(m_value-m_min)/(m_max-m_min)); + QPainter paint(&m_pixmap); + if (pressed) + paint.drawPixmap(1,p,m_skin->getButton(Skin::EQ_BT_BAR_P)); + else + paint.drawPixmap(1,p,m_skin->getButton(Skin::EQ_BT_BAR_N)); + setPixmap(m_pixmap); + m_pos = p; +} + +int EqSlider::convert(int p) +{ + return int(ceil(double(m_max-m_min)*(p)/(height()-12)+m_min)); +} + +void EqSlider::wheelEvent(QWheelEvent *e) +{ + m_value -= e->delta()/60; + m_value = m_value > m_max ? m_max : m_value; + m_value = m_value < m_min ? m_min : m_value; + draw(FALSE); + emit sliderMoved(m_value); +} + diff --git a/src/ui/eqslider.h b/src/ui/eqslider.h new file mode 100644 index 000000000..54dc9f285 --- /dev/null +++ b/src/ui/eqslider.h @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef EQSLIDER_H +#define EQSLIDER_H + +#include + +/** + @author Ilya Kotov +*/ +class QMouseEvent; +class QWheelEvent; + +class Skin; + +class EqSlider : public PixmapWidget +{ +Q_OBJECT +public: + EqSlider(QWidget *parent = 0); + + ~EqSlider(); + + int value(); + +public slots: + void setValue(int); + void setMax(int); + +signals: + void sliderMoved (int); + +private slots: + void updateSkin(); + +private: + Skin *m_skin; + bool m_moving; + int press_pos; + int m_max, m_min, m_pos, m_value, m_old; + QPixmap m_pixmap; + int convert(int); // value = convert(position); + void draw(bool pressed = TRUE); + +protected: + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + void wheelEvent(QWheelEvent *); + + +}; + +#endif diff --git a/src/ui/eqtitlebar.cpp b/src/ui/eqtitlebar.cpp new file mode 100644 index 000000000..5420831f8 --- /dev/null +++ b/src/ui/eqtitlebar.cpp @@ -0,0 +1,182 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "skin.h" +#include "shadedbar.h" +#include "dock.h" +#include "mainwindow.h" +#include "button.h" + +#include "eqtitlebar.h" + +EqTitleBar::EqTitleBar(QWidget *parent) + : PixmapWidget(parent) +{ + m_volumeBar = 0; + m_balanceBar = 0; + m_shade2 = 0; + m_left = 0; + m_right = 0; + m_shaded = FALSE; + m_align = FALSE; + m_skin = Skin::getPointer(); + m_eq = parentWidget(); + m_mw = qobject_cast(m_eq->parent()); + m_close = new Button(this, Skin::EQ_BT_CLOSE_N, Skin::EQ_BT_CLOSE_P); + connect(m_close, SIGNAL(clicked()),m_eq, SIGNAL(closed())); + m_close->move(264,3); + m_shade = new Button(this, Skin::EQ_BT_SHADE1_N, Skin::EQ_BT_SHADE1_P); + connect(m_shade, SIGNAL(clicked()), SLOT(shade())); + m_shade->move(254,3); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + if (settings.value("Equalizer/shaded", FALSE).toBool()) + shade(); + m_align = TRUE; + setActive(FALSE); +} + + +EqTitleBar::~EqTitleBar() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.setValue("Equalizer/shaded", m_shaded); +} + +void EqTitleBar::setActive(bool active) +{ + if (active) + { + if (m_shaded) + { + setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_SHADED_A)); + m_shade2->show(); + } + else + { + setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_A)); + m_shade->show(); + } + m_close->show(); + } + else + { + if (m_shaded) + { + setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_SHADED_I)); + m_shade2->hide(); + } + else + { + setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_I)); + m_shade->hide(); + } + m_close->hide(); + } +} + +void EqTitleBar::setVolume(int left, int right) +{ + m_left = left; + m_right = right; + if (m_volumeBar && m_balanceBar) + { + int maxVol = qMax(left, right); + m_volumeBar->setValue(maxVol); + if (maxVol && !m_volumeBar->isPressed()) + m_balanceBar->setValue((right - left)*100/maxVol); + } +} + +void EqTitleBar::mousePressEvent(QMouseEvent* event) +{ + switch ((int) event->button ()) + { + case Qt::LeftButton: + { + m_pos = event->pos(); + break; + } + case Qt::RightButton: + { + m_mw->menu()->exec(event->globalPos()); + } + } +} + +void EqTitleBar::mouseMoveEvent(QMouseEvent* event) +{ + QPoint npos = (event->globalPos()-m_pos); + Dock::getPointer()->move(m_eq, npos); +} + +void EqTitleBar::mouseReleaseEvent(QMouseEvent*) +{ + Dock::getPointer()->updateDock(); +} + +void EqTitleBar::shade() +{ + m_shaded = !m_shaded; + + if (m_shaded) + { + m_eq->setFixedSize(275,14); + setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_SHADED_A)); + m_shade->hide(); + m_shade2 = new Button(this, Skin::EQ_BT_SHADE2_N, Skin::EQ_BT_SHADE2_P); + m_shade2->move(254,3); + connect(m_shade2, SIGNAL(clicked()), SLOT(shade())); + m_shade2->show(); + m_volumeBar = new ShadedBar(this, Skin::EQ_VOLUME1, Skin::EQ_VOLUME2, Skin::EQ_VOLUME3); + m_volumeBar->move(61,4); + m_volumeBar->show(); + connect(m_volumeBar, SIGNAL(sliderMoved(int)),SLOT(updateVolume())); + m_balanceBar = new ShadedBar(this, Skin::EQ_BALANCE1, Skin::EQ_BALANCE2, Skin::EQ_BALANCE3); + m_balanceBar->move(164,4); + m_balanceBar->setFixedSize(42,7); + m_balanceBar->setRange(-100,100); + m_balanceBar->show(); + connect(m_balanceBar, SIGNAL(sliderMoved(int)),SLOT(updateVolume())); + setVolume(m_left, m_right); //show current volume and balance + } + else + { + m_eq->setFixedSize(275,116); + setPixmap(m_skin->getEqPart(Skin::EQ_TITLEBAR_A)); + delete m_shade2; + delete m_volumeBar; + delete m_balanceBar; + m_volumeBar = 0; + m_balanceBar = 0; + m_shade2 = 0; + m_shade->show(); + } + if (m_align) + Dock::getPointer()->align(m_eq, m_shaded? -102: 102); +} + +void EqTitleBar::updateVolume() +{ + m_mw->setVolume(m_volumeBar->value(), m_balanceBar->value()); +} + diff --git a/src/ui/eqtitlebar.h b/src/ui/eqtitlebar.h new file mode 100644 index 000000000..d3e9a0452 --- /dev/null +++ b/src/ui/eqtitlebar.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef EQTITLEBAR_H +#define EQTITLEBAR_H + +#include + +/** + @author Ilya Kotov +*/ + +class QMouseEvent; + +class Skin; +class MainWindow; +class Button; +class ShadedBar; + +class EqTitleBar : public PixmapWidget +{ +Q_OBJECT +public: + EqTitleBar(QWidget *parent = 0); + + ~EqTitleBar(); + + void setActive(bool); + void setVolume(int left, int right); + +private slots: + void shade(); + void updateVolume(); + +private: + Skin* m_skin; + bool m_active; + int m_left; + int m_right; + QPoint m_pos; + QWidget* m_eq; + MainWindow* m_mw; + Button* m_close; + Button* m_shade; + Button* m_shade2; + bool m_shaded, m_align; + ShadedBar* m_volumeBar; + ShadedBar* m_balanceBar; + +protected: + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + +}; + +#endif diff --git a/src/ui/eqwidget.cpp b/src/ui/eqwidget.cpp new file mode 100644 index 000000000..d86ab45d2 --- /dev/null +++ b/src/ui/eqwidget.cpp @@ -0,0 +1,417 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include + +#include "filedialog.h" +#include "skin.h" +#include "eqslider.h" +#include "eqtitlebar.h" +#include "togglebutton.h" +#include "eqgraph.h" +#include "button.h" +#include "eqpreset.h" +#include "preseteditor.h" +#include "mainwindow.h" +#include "playlist.h" +#include "eqwidget.h" + + + +EqWidget::EqWidget ( QWidget *parent ) + : PixmapWidget ( parent ) +{ + m_skin = Skin::getPointer(); + setWindowFlags ( Qt::Dialog | Qt::FramelessWindowHint ); + setPixmap ( m_skin->getEqPart ( Skin::EQ_MAIN ) ); + //setPixmap(QPixmap(275,116)); + m_titleBar = new EqTitleBar ( this ); + m_titleBar -> move ( 0,0 ); + m_titleBar -> show(); + connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); + + m_preamp = new EqSlider ( this ); + m_preamp->show(); + m_preamp->move ( 21,38 ); + connect ( m_preamp,SIGNAL ( sliderMoved ( int ) ),SLOT ( setPreamp () ) ); + + m_on = new ToggleButton ( this,Skin::EQ_BT_ON_N,Skin::EQ_BT_ON_P, + Skin::EQ_BT_OFF_N,Skin::EQ_BT_OFF_P ); + m_on->show(); + m_on->move ( 14,18 ); + connect (m_on, SIGNAL (clicked(bool)), SIGNAL(valueChanged())); + + m_autoButton = new ToggleButton(this, Skin::EQ_BT_AUTO_1_N, Skin::EQ_BT_AUTO_1_P, + Skin::EQ_BT_AUTO_0_N, Skin::EQ_BT_AUTO_0_P); + m_autoButton->move(39, 18); + m_autoButton->show(); + + m_eqg = new EQGraph(this); + m_eqg->move(87,17); + m_eqg->show(); + + m_presetsMenu = new QMenu(this); + + m_presetButton = new Button ( this, Skin::EQ_BT_PRESETS_N, Skin::EQ_BT_PRESETS_P); + m_presetButton->move(217,18); + m_presetButton->show(); + + connect(m_presetButton, SIGNAL(clicked()), SLOT(showPresetsMenu())); + + for ( int i = 0; i<10; ++i ) + { + m_sliders << new EqSlider ( this ); + m_sliders.at ( i )->move ( 78+i*18,38 ); + m_sliders.at ( i )->show(); + connect (m_sliders.at (i), SIGNAL ( sliderMoved (int) ),SLOT (setGain())); + } + readSettings(); + createActions(); +} + +EqWidget::~EqWidget() +{ + while (!m_presets.isEmpty()) + delete m_presets.takeFirst(); + while (!m_autoPresets.isEmpty()) + delete m_autoPresets.takeFirst(); +} + +int EqWidget::preamp() +{ + return m_preamp->value(); +} + +int EqWidget::gain ( int g ) +{ + return m_sliders.at ( g )->value(); +} + +void EqWidget::changeEvent ( QEvent * event ) +{ + if (event->type() == QEvent::ActivationChange) + { + m_titleBar->setActive(isActiveWindow()); + } +} + +void EqWidget::closeEvent ( QCloseEvent* ) +{ + writeSettings(); +} + +void EqWidget::updateSkin() +{ + m_titleBar->setActive ( FALSE ); + setPixmap ( m_skin->getEqPart ( Skin::EQ_MAIN ) ); +} + +void EqWidget::readSettings() +{ + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + settings.beginGroup ( "Equalizer" ); + //geometry + move ( settings.value ( "pos", QPoint ( 100, 216 ) ).toPoint() ); + //equalizer + for (int i = 0; i < m_sliders.size(); ++i) + m_sliders.at(i)->setValue(settings.value("band_"+ + QString("%1").arg(i), 0).toInt()); + m_preamp->setValue(settings.value("preamp", 0).toInt()); + m_on->setON(settings.value("enabled", FALSE).toBool()); + settings.endGroup(); + setGain(); + //equalizer presets + QSettings eq_preset (QDir::homePath() +"/.qmmp/eq.preset", QSettings::IniFormat ); + for (int i = 1; TRUE; ++i) + { + if (eq_preset.contains("Presets/Preset"+QString("%1").arg(i))) + { + QString name = eq_preset.value("Presets/Preset"+QString("%1").arg(i), + tr("preset")).toString(); + EQPreset *preset = new EQPreset(); + preset->setText(name); + eq_preset.beginGroup(name); + for (int j = 0; j < 10; ++j) + { + preset->setGain(j,eq_preset.value("Band"+QString("%1").arg(j), + 0).toInt()); + } + preset->setPreamp(eq_preset.value("Preamp",0).toInt()); + m_presets.append(preset); + eq_preset.endGroup(); + } + else + break; + } + //equalizer auto-load presets + QSettings eq_auto (QDir::homePath() +"/.qmmp/eq.auto_preset", QSettings::IniFormat ); + for (int i = 1; TRUE; ++i) + { + if (eq_auto.contains("Presets/Preset"+QString("%1").arg(i))) + { + QString name = eq_auto.value("Presets/Preset"+QString("%1").arg(i), + tr("preset")).toString(); + EQPreset *preset = new EQPreset(); + preset->setText(name); + eq_auto.beginGroup(name); + for (int j = 0; j < 10; ++j) + { + preset->setGain(j,eq_auto.value("Band"+QString("%1").arg(j), + 0).toInt()); + } + preset->setPreamp(eq_auto.value("Preamp",0).toInt()); + m_autoPresets.append(preset); + eq_auto.endGroup(); + } + else + break; + } +} + +void EqWidget::writeSettings() +{ + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + settings.beginGroup ( "Equalizer" ); + //geometry + settings.setValue ( "pos", this->pos() ); + //equalizer + for (int i = 0; i < m_sliders.size(); ++i) + settings.setValue("band_"+QString("%1").arg(i), m_sliders.at(i)->value()); + settings.setValue("preamp", m_preamp->value()); + settings.setValue("enabled",m_on->isChecked()); + settings.endGroup(); + //equalizer presets + QSettings eq_preset (QDir::homePath() +"/.qmmp/eq.preset", QSettings::IniFormat ); + eq_preset.clear (); + for (int i = 0; i < m_presets.size(); ++i) + { + eq_preset.setValue("Presets/Preset"+QString("%1").arg(i+1), + m_presets.at(i)->text()); + eq_preset.beginGroup(m_presets.at(i)->text()); + for (int j = 0; j < 10; ++j) + { + eq_preset.setValue("Band"+QString("%1").arg(j),m_presets.at(i)->gain(j)); + } + eq_preset.setValue("Preamp",m_presets.at(i)->preamp()); + eq_preset.endGroup(); + } + //equalizer auto-load presets + QSettings eq_auto (QDir::homePath() +"/.qmmp/eq.auto_preset", + QSettings::IniFormat ); + eq_auto.clear(); + for (int i = 0; i < m_autoPresets.size(); ++i) + { + eq_auto.setValue("Presets/Preset"+QString("%1").arg(i+1), + m_autoPresets.at(i)->text()); + eq_auto.beginGroup(m_autoPresets.at(i)->text()); + for (int j = 0; j < 10; ++j) + { + eq_auto.setValue("Band"+QString("%1").arg(j),m_autoPresets.at(i)->gain(j)); + } + eq_auto.setValue("Preamp",m_autoPresets.at(i)->preamp()); + eq_auto.endGroup(); + } +} + +void EqWidget::setPreamp () +{ + emit valueChanged(); +} + +void EqWidget::setGain() +{ + m_eqg->clear(); + for (int i=0; i<10; ++i) + { + int value = m_sliders.at(i)->value(); + m_eqg->addValue(value); + } + emit valueChanged(); +} + +bool EqWidget::isEQEnabled() +{ + return m_on->isChecked(); +} + +void EqWidget::createActions() +{ + m_presetsMenu->addAction(tr("&Load/Delete"),this, SLOT(showEditor())); + m_presetsMenu->addSeparator(); + m_presetsMenu->addAction(tr("&Save Preset"),this,SLOT(savePreset())); + m_presetsMenu->addAction(tr("&Save Auto-load Preset"),this,SLOT(saveAutoPreset())); + m_presetsMenu->addAction(tr("&Import"),this,SLOT(importWinampEQF())); + m_presetsMenu->addSeparator(); + m_presetsMenu->addAction(tr("&Clear"),this, SLOT(reset())); +} + +void EqWidget::showPresetsMenu() +{ + m_presetsMenu->exec(m_presetButton->mapToGlobal(QPoint(0, 0))); +} + +void EqWidget::reset() +{ + for (int i = 0; i < m_sliders.size(); ++i) + m_sliders.at(i)->setValue(0); + m_preamp->setValue(0); + setGain(); +} + +void EqWidget::showEditor() +{ + PresetEditor *editor = new PresetEditor(this); + editor->addPresets(m_presets); + editor->addAutoPresets(m_autoPresets); + connect (editor, SIGNAL(presetLoaded(EQPreset*)), SLOT(setPreset(EQPreset*))); + connect (editor, SIGNAL(presetDeleted(EQPreset*)), SLOT(deletePreset(EQPreset*))); + editor->show(); +} + +void EqWidget::savePreset() +{ + bool ok; + QString text = QInputDialog::getText(this, tr("Saving Preset"), + tr("Preset name:"), QLineEdit::Normal, + tr("preset #")+QString("%1").arg(m_presets.size()+1), &ok); + if (ok) + { + EQPreset* preset = new EQPreset; + preset->setText(text); + preset->setPreamp(m_preamp->value()); + for (int i = 0; i<10; ++i) + { + preset->setGain(i, m_sliders.at (i)->value()); + } + m_presets.append(preset); + } +} + +void EqWidget::saveAutoPreset() +{ + PlayList* playlist = qobject_cast(parent())->getPLPointer(); + if (!playlist->currentItem()) + return; + //delete preset if it already exists + EQPreset* preset = findPreset(playlist->currentItem()->fileName()); + if (preset) + deletePreset(preset); + //create new preset + preset = new EQPreset(); + preset->setText(playlist->currentItem()->fileName()); + preset->setPreamp(m_preamp->value()); + for (int i = 0; i<10; ++i) + { + preset->setGain(i, m_sliders.at (i)->value()); + } + m_autoPresets.append(preset); +} + +void EqWidget::setPreset(EQPreset* preset) +{ + for (int i = 0; i<10; ++i) + m_sliders.at(i)->setValue(preset->gain(i)); + m_preamp->setValue(preset->preamp()); + setGain(); +} + +void EqWidget::deletePreset(EQPreset* preset) +{ + int p = m_presets.indexOf(preset); + if (p != -1) + { + delete m_presets.takeAt(p); + return; + } + p = m_autoPresets.indexOf(preset); + if (p != -1) + { + delete m_autoPresets.takeAt(p); + return; + } +} + +void EqWidget::loadPreset(const QString &name) +{ + if (m_autoButton->isChecked()) + { + EQPreset *preset = findPreset(name); + if (preset) + setPreset(preset); + else + reset(); + } +} + +void EqWidget::setInfo(const OutputState &st) +{ + if (st.type() == OutputState::Volume) + { + m_titleBar->setVolume(st.leftVolume(),st.rightVolume()); + + } +} + +EQPreset *EqWidget::findPreset(const QString &name) +{ + foreach(EQPreset *preset, m_autoPresets) + { + if (preset->text() == name) + return preset; + } + return 0; +} + +void EqWidget::importWinampEQF() +{ + char header[31]; + char name[257]; + char bands[11]; + QString path = FileDialog::getOpenFileName(this, tr("Import Preset"), + "/home", + QString("Winamp EQF (*.q1)"),NULL,true); + + QFile file(path); + file.open(QIODevice::ReadOnly); + file.read ( header, 31); + if (QString::fromAscii(header).contains("Winamp EQ library file v1.1")) + { + + while (file.read ( name, 257)) + { + EQPreset* preset = new EQPreset; + preset->setText(QString::fromAscii(name)); + + file.read(bands,11); + + for (int i = 0; i<10; ++i) + { + preset->setGain(i, 20 - bands[i]*40/64); + } + preset->setPreamp(20 - bands[10]*40/64); + m_presets.append(preset); + } + + } + file.close(); + +} diff --git a/src/ui/eqwidget.h b/src/ui/eqwidget.h new file mode 100644 index 000000000..94cd564d5 --- /dev/null +++ b/src/ui/eqwidget.h @@ -0,0 +1,103 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef EQWIDGET_H +#define EQWIDGET_H + +#include +#include + +/** + @author Ilya Kotov +*/ + +class QMenu; +class Skin; +class EqTitleBar; +class EqSlider; +class ToggleButton; +class EQGraph; +class Button; +class EQPreset; +class MediaFile; + +class EqWidget : public PixmapWidget +{ + Q_OBJECT +public: + EqWidget(QWidget *parent = 0); + + ~EqWidget(); + + int preamp(); + int gain(int); + bool isEQEnabled(); + /*! + * necessary for auto-load presets + */ + void loadPreset(const QString &name); + + /*! + * shows output volume and balance. Necessare for the shaded mode + */ + void setInfo(const OutputState &st); + +signals: + void valueChanged(); + void closed(); + +private slots: + void updateSkin(); + void setPreamp(); + void setGain(); + void showPresetsMenu(); + void reset(); + void showEditor(); + void savePreset(); + void saveAutoPreset(); + void setPreset(EQPreset*); + void deletePreset(EQPreset*); + void importWinampEQF(); + +private: + void readSettings(); + void writeSettings(); + void createActions(); + EQPreset *findPreset(const QString &name); + Skin *m_skin; + EqTitleBar *m_titleBar; + EqSlider *m_preamp; + Button *m_presetButton; + QList m_sliders; + QPoint m_pos; + ToggleButton *m_on; + ToggleButton *m_autoButton; + EQGraph *m_eqg; + QMenu *m_presetsMenu; + QList m_presets; + QList m_autoPresets; + QString m_autoName; + +protected: + virtual void changeEvent(QEvent*); + virtual void closeEvent(QCloseEvent*); + +}; + +#endif diff --git a/src/ui/fft.c b/src/ui/fft.c new file mode 100644 index 000000000..7ca1978a5 --- /dev/null +++ b/src/ui/fft.c @@ -0,0 +1,296 @@ +/* fft.c: Iterative implementation of a FFT + * Copyright (C) 1999 Richard Boulton + * Convolution stuff by Ralph Loader + * + * This program is free software; 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. + */ + +/* + * TODO + * Remove compiling in of FFT_BUFFER_SIZE? (Might slow things down, but would + * be nice to be able to change size at runtime.) + * Finish making / checking thread-safety. + * More optimisations. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "fft.h" + +//#include +#include +#include +#ifndef PI +#ifdef M_PI +#define PI M_PI +#else +#define PI 3.14159265358979323846 /* pi */ +#endif +#endif + +/* ########### */ +/* # Structs # */ +/* ########### */ + +struct _struct_fft_state { + /* Temporary data stores to perform FFT in. */ + float real[FFT_BUFFER_SIZE]; + float imag[FFT_BUFFER_SIZE]; +}; + +/* ############################# */ +/* # Local function prototypes # */ +/* ############################# */ + +static void fft_prepare(const sound_sample * input, float *re, float *im); +static void fft_calculate(float *re, float *im); +static void fft_output(const float *re, const float *im, float *output); +static int reverseBits(unsigned int initial); + +/* #################### */ +/* # Global variables # */ +/* #################### */ + +/* Table to speed up bit reverse copy */ +static unsigned int bitReverse[FFT_BUFFER_SIZE]; + +/* The next two tables could be made to use less space in memory, since they + * overlap hugely, but hey. */ +static float sintable[FFT_BUFFER_SIZE / 2]; +static float costable[FFT_BUFFER_SIZE / 2]; + +/* ############################## */ +/* # Externally called routines # */ +/* ############################## */ + +/* --------- */ +/* FFT stuff */ +/* --------- */ + +/* + * Initialisation routine - sets up tables and space to work in. + * Returns a pointer to internal state, to be used when performing calls. + * On error, returns NULL. + * The pointer should be freed when it is finished with, by fft_close(). + */ +fft_state * +fft_init(void) +{ + fft_state *state; + unsigned int i; + + state = (fft_state *) malloc(sizeof(fft_state)); + if (!state) + return NULL; + + for (i = 0; i < FFT_BUFFER_SIZE; i++) { + bitReverse[i] = reverseBits(i); + } + for (i = 0; i < FFT_BUFFER_SIZE / 2; i++) { + float j = 2 * PI * i / FFT_BUFFER_SIZE; + costable[i] = cos(j); + sintable[i] = sin(j); + } + + return state; +} + +/* + * Do all the steps of the FFT, taking as input sound data (as described in + * sound.h) and returning the intensities of each frequency as floats in the + * range 0 to ((FFT_BUFFER_SIZE / 2) * 32768) ^ 2 + * + * FIXME - the above range assumes no frequencies present have an amplitude + * larger than that of the sample variation. But this is false: we could have + * a wave such that its maximums are always between samples, and it's just + * inside the representable range at the places samples get taken. + * Question: what _is_ the maximum value possible. Twice that value? Root + * two times that value? Hmmm. Think it depends on the frequency, too. + * + * The input array is assumed to have FFT_BUFFER_SIZE elements, + * and the output array is assumed to have (FFT_BUFFER_SIZE / 2 + 1) elements. + * state is a (non-NULL) pointer returned by fft_init. + */ +void +fft_perform(const sound_sample * input, float *output, fft_state * state) +{ + /* Convert data from sound format to be ready for FFT */ + fft_prepare(input, state->real, state->imag); + + /* Do the actual FFT */ + fft_calculate(state->real, state->imag); + + /* Convert the FFT output into intensities */ + fft_output(state->real, state->imag, output); +} + +/* + * Free the state. + */ +void +fft_close(fft_state * state) +{ + if (state) + free(state); +} + +/* ########################### */ +/* # Locally called routines # */ +/* ########################### */ + +/* + * Prepare data to perform an FFT on + */ +static void +fft_prepare(const sound_sample * input, float *re, float *im) +{ + unsigned int i; + float *realptr = re; + float *imagptr = im; + + /* Get input, in reverse bit order */ + for (i = 0; i < FFT_BUFFER_SIZE; i++) { + *realptr++ = input[bitReverse[i]]; + *imagptr++ = 0; + } +} + +/* + * Take result of an FFT and calculate the intensities of each frequency + * Note: only produces half as many data points as the input had. + * This is roughly a consequence of the Nyquist sampling theorm thingy. + * (FIXME - make this comment better, and helpful.) + * + * The two divisions by 4 are also a consequence of this: the contributions + * returned for each frequency are split into two parts, one at i in the + * table, and the other at FFT_BUFFER_SIZE - i, except for i = 0 and + * FFT_BUFFER_SIZE which would otherwise get float (and then 4* when squared) + * the contributions. + */ +static void +fft_output(const float *re, const float *im, float *output) +{ + float *outputptr = output; + const float *realptr = re; + const float *imagptr = im; + float *endptr = output + FFT_BUFFER_SIZE / 2; + +#ifdef DEBUG + unsigned int i, j; +#endif + + while (outputptr <= endptr) { + *outputptr = (*realptr * *realptr) + (*imagptr * *imagptr); + outputptr++; + realptr++; + imagptr++; + } + /* Do divisions to keep the constant and highest frequency terms in scale + * with the other terms. */ + *output /= 4; + *endptr /= 4; + +#ifdef DEBUG + printf("Recalculated input:\n"); + for (i = 0; i < FFT_BUFFER_SIZE; i++) { + float val_real = 0; + float val_imag = 0; + for (j = 0; j < FFT_BUFFER_SIZE; j++) { + float fact_real = cos(-2 * j * i * PI / FFT_BUFFER_SIZE); + float fact_imag = sin(-2 * j * i * PI / FFT_BUFFER_SIZE); + val_real += fact_real * re[j] - fact_imag * im[j]; + val_imag += fact_real * im[j] + fact_imag * re[j]; + } + printf("%5d = %8f + i * %8f\n", i, + val_real / FFT_BUFFER_SIZE, val_imag / FFT_BUFFER_SIZE); + } + printf("\n"); +#endif +} + +/* + * Actually perform the FFT + */ +static void +fft_calculate(float *re, float *im) +{ + unsigned int i, j, k; + unsigned int exchanges; + float fact_real, fact_imag; + float tmp_real, tmp_imag; + unsigned int factfact; + + /* Set up some variables to reduce calculation in the loops */ + exchanges = 1; + factfact = FFT_BUFFER_SIZE / 2; + + /* Loop through the divide and conquer steps */ + for (i = FFT_BUFFER_SIZE_LOG; i != 0; i--) { + /* In this step, we have 2 ^ (i - 1) exchange groups, each with + * 2 ^ (FFT_BUFFER_SIZE_LOG - i) exchanges + */ + /* Loop through the exchanges in a group */ + for (j = 0; j != exchanges; j++) { + /* Work out factor for this exchange + * factor ^ (exchanges) = -1 + * So, real = cos(j * PI / exchanges), + * imag = sin(j * PI / exchanges) + */ + fact_real = costable[j * factfact]; + fact_imag = sintable[j * factfact]; + + /* Loop through all the exchange groups */ + for (k = j; k < FFT_BUFFER_SIZE; k += exchanges << 1) { + int k1 = k + exchanges; + /* newval[k] := val[k] + factor * val[k1] + * newval[k1] := val[k] - factor * val[k1] + **/ +#ifdef DEBUG + printf("%d %d %d\n", i, j, k); + printf("Exchange %d with %d\n", k, k1); + printf("Factor %9f + i * %8f\n", fact_real, fact_imag); +#endif + /* FIXME - potential scope for more optimization here? */ + tmp_real = fact_real * re[k1] - fact_imag * im[k1]; + tmp_imag = fact_real * im[k1] + fact_imag * re[k1]; + re[k1] = re[k] - tmp_real; + im[k1] = im[k] - tmp_imag; + re[k] += tmp_real; + im[k] += tmp_imag; +#ifdef DEBUG + for (k1 = 0; k1 < FFT_BUFFER_SIZE; k1++) { + printf("%5d = %8f + i * %8f\n", k1, real[k1], imag[k1]); + } +#endif + } + } + exchanges <<= 1; + factfact >>= 1; + } +} + +static int +reverseBits(unsigned int initial) +{ + unsigned int reversed = 0, loop; + for (loop = 0; loop < FFT_BUFFER_SIZE_LOG; loop++) { + reversed <<= 1; + reversed += (initial & 1); + initial >>= 1; + } + return reversed; +} diff --git a/src/ui/fft.h b/src/ui/fft.h new file mode 100644 index 000000000..431afa365 --- /dev/null +++ b/src/ui/fft.h @@ -0,0 +1,45 @@ +/* fft.h: Header for iterative implementation of a FFT + * Copyright (C) 1999 Richard Boulton + * + * This program is free software; 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. + */ + +#ifndef _FFT_H_ +#define _FFT_H_ + +#define FFT_BUFFER_SIZE_LOG 9 + +#define FFT_BUFFER_SIZE (1 << FFT_BUFFER_SIZE_LOG) + +/* sound sample - should be an signed 16 bit value */ +typedef short int sound_sample; + +#ifdef __cplusplus +extern "C" { +#endif + +/* FFT library */ + typedef struct _struct_fft_state fft_state; + fft_state *fft_init(void); + void fft_perform(const sound_sample * input, float *output, + fft_state * state); + void fft_close(fft_state * state); + + + +#ifdef __cplusplus +} +#endif +#endif /* _FFT_H_ */ diff --git a/src/ui/filedialog.cpp b/src/ui/filedialog.cpp new file mode 100644 index 000000000..fb7ecbdaf --- /dev/null +++ b/src/ui/filedialog.cpp @@ -0,0 +1,296 @@ +#include "filedialog.h" + +#include + + +#include +#include + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +#include "playlistmodel.h" + +FileDialog* FileDialog::_instance = 0; + +QMap FileDialog::factories = QMap(); + +FileDialog::FileDialog() : QObject(), m_initialized(false) +{ +} + + +bool FileDialog::isModal() +{ + return instance()->modal(); +} + + +void FileDialog::init(QObject* o) +{ + if(!m_initialized && !instance()->modal()) + { + PlayListModel* model = NULL; + if( ( model = qobject_cast(o)) ) + { + connect(this,SIGNAL(filesAdded(const QStringList&)),model,SLOT(addFileList(const QStringList&))); + m_initialized = true; + } + } +} + + + +QString FileDialog::getExistingDirectory( QWidget * parent, const QString & caption, const QString & dir,bool def) +{ + QString s; + if(def) + s = defaultInstance()->existingDirectory(parent,caption,dir); + else + s = instance()->existingDirectory(parent,caption,dir); + delete _instance; + _instance = 0; + return s; +} + +QString FileDialog::getOpenFileName(QWidget * parent, + const QString & caption, + const QString & dir, + const QString & filter, + QString * selectedFilter,bool def) +{ + QString s; + if(def) + s = defaultInstance()->openFileName(parent,caption,dir,filter,selectedFilter); + else + s = instance()->openFileName(parent,caption,dir,filter,selectedFilter); + delete _instance; + _instance = 0; + return s; +} + +QStringList FileDialog::getOpenFileNames(QWidget * parent, const QString & caption , const QString & dir , + const QString & filter, QString * selectedFilter,bool def) +{ + QStringList sl; + if(def) + sl = defaultInstance()->openFileNames(parent,caption ,dir ,filter, selectedFilter); + else + sl = instance()->openFileNames(parent,caption,dir,filter,selectedFilter); + delete _instance; + _instance = 0; + return sl; +} + +QString FileDialog::getSaveFileName ( QWidget * parent, const QString & caption, + const QString & dir, const QString & filter, QString * selectedFilter,bool def) +{ + QString s; + if(def) + s = defaultInstance()->saveFileName(parent,caption,dir,filter,selectedFilter); + else + s = instance()->saveFileName(parent,caption,dir,filter,selectedFilter); + delete _instance; + _instance = 0; + return s; +} + + +QString FileDialog::existingDirectory(QWidget *, const QString &, const QString &) +{ + return QString(); +} + +QString FileDialog::openFileName(QWidget *, const QString &, const QString &, const QString &, QString *) +{ + return QString(); +} + +QStringList FileDialog::openFileNames(QWidget *, const QString &, const QString &, const QString &, QString *) +{ + return QStringList(); +} + +QString FileDialog::saveFileName(QWidget *, const QString &, const QString &, const QString &, QString *) +{ + return QString(); +} + + +void FileDialog::registerBuiltinFactories() +{ + registerFactory(new QtFileDialogFactory()); + //registerFactory(new QmmpFileDialogFactory()); +} + +void FileDialog::registerExternalFactories() +{ + QDir pluginsDir (QDir::homePath()+"/.qmmp/plugins/FileDialogs"); + + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) + { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (loader.isLoaded()) + qDebug("FileDialog: plugin loaded - %s", qPrintable(fileName)); + else + qDebug("FileDialog: %s",qPrintable(loader.errorString())); + + FileDialogFactory *fct = 0; + if (plugin) + fct = qobject_cast(plugin); + + if (fct) + if (!registerFactory(fct)) + qDebug("Warning: Plugin with name %s is already registered...", + qPrintable(fct->name())); + } +} + +bool FileDialog::registerFactory(FileDialogFactory *f) +{ + QString name = f->name(); + if (!factories.contains(name)) + { + factories.insert(name,f); + return true; + } + return false; +} + +QString FileDialog::m_current_factory = QString(); + +FileDialog* FileDialog::instance() +{ + if(_instance && _instance->modal()) + { + delete _instance; + _instance = 0; + } + + if(factories.isEmpty()) + { + registerBuiltinFactories(); + registerExternalFactories(); + } + + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + QString f_dialogName = + settings.value("FileDialog",QtFileDialogFactory::QtFileDialogFactoryName).toString(); + + QStringList names = factories.keys(); + + if(m_current_factory != f_dialogName || !_instance) + { + if(_instance) + delete _instance; + + foreach(QString name,names) + { + if(name == f_dialogName) + { + _instance = factories[name]->create(); + m_current_factory = f_dialogName; + break; + } + } + + if(!_instance) + _instance = factories[QtFileDialogFactory::QtFileDialogFactoryName]->create(); + } + //else if(!_instance->modal()) + //return _instance; + // _instance->raise(); + return _instance; + +} + +FileDialog* FileDialog::defaultInstance() +{ + if(_instance) + { + delete _instance; + _instance = 0; + } + + if(factories.isEmpty()) + { + registerBuiltinFactories(); + registerExternalFactories(); + } + + _instance = factories[QtFileDialogFactory::QtFileDialogFactoryName]->create(); + + return _instance; +} + +QStringList FileDialog::registeredFactories() +{ + if(factories.isEmpty()) + { + registerBuiltinFactories(); + registerExternalFactories(); + } + return factories.keys(); +} + + +void FileDialog::popup(QObject* o,const QString& d,Mode m,const QStringList& f) +{ + FileDialog* inst = instance(); + inst->init(o); + inst->raise(d,m,f); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + +QtFileDialog::~QtFileDialog() +{ + qWarning("QtFileDialog::~QtFileDialog()"); +} + +QString QtFileDialog::existingDirectory(QWidget * parent, const QString & caption, const QString & dir) +{ + return QFileDialog::getExistingDirectory(parent,caption,dir,QFileDialog::DontResolveSymlinks | QFileDialog::ShowDirsOnly); +} + +QString QtFileDialog::openFileName(QWidget * parent,const QString & caption,const QString & dir,const QString & filter, + QString * selectedFilter) +{ + return QFileDialog::getOpenFileName(parent,caption,dir,filter,selectedFilter); +} + +QStringList QtFileDialog::openFileNames(QWidget * parent, const QString & caption , const QString & dir , + const QString & filter, QString * selectedFilter) +{ + return QFileDialog::getOpenFileNames(parent,caption,dir,filter,selectedFilter); +} + + QString QtFileDialog::saveFileName ( QWidget * parent, const QString & caption, + const QString & dir, const QString & filter, QString * selectedFilter) +{ + return QFileDialog::getSaveFileName(parent,caption,dir,filter,selectedFilter); +} + + + + + + +FileDialog* QtFileDialogFactory::create() +{ + return new QtFileDialog(); +} + +QString QtFileDialogFactory::name() +{ + return QtFileDialogFactoryName; +} + +QString QtFileDialogFactory::QtFileDialogFactoryName = "Qt File Dialog"; + + diff --git a/src/ui/filedialog.h b/src/ui/filedialog.h new file mode 100644 index 000000000..f8e6c4f93 --- /dev/null +++ b/src/ui/filedialog.h @@ -0,0 +1,109 @@ +#ifndef FILEDIALOG_H +#define FILEDIALOG_H + +#include +#include + +#include +#include + +#define interface struct + +interface FileDialogFactory; + + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////// FILE DIALOG ////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class FileDialog : public QObject +{ +Q_OBJECT + public: + enum Mode{AddFiles,AddDirs,SaveFiles}; + static QString getExistingDirectory( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(),bool = FALSE); + static QString getOpenFileName(QWidget * parent = 0,const QString & caption = QString(),const QString & dir = QString(),const QString & filter = QString(), + QString * selectedFilter = 0,bool = FALSE); + static QStringList getOpenFileNames( QWidget * parent = 0, const QString & caption = QString(), const QString & dir = QString(), + const QString & filter = QString(), QString * selectedFilter = 0,bool = FALSE); + static QString getSaveFileName ( QWidget * parent = 0, const QString & caption = QString(), + const QString & dir = QString(), const QString & filter = QString(), QString * selectedFilter = 0,bool = FALSE); + static QStringList registeredFactories(); + + static bool isModal(); + static void popup(QObject* ,const QString& = QString(),Mode = AddFiles,const QStringList& nameFilters = QStringList()); + signals: + void filesAdded(const QStringList&); + protected: + FileDialog(); + virtual QString existingDirectory( QWidget* , const QString& , const QString& ); + virtual QString openFileName( QWidget* ,const QString& ,const QString& ,const QString& , QString* ); + virtual QStringList openFileNames( QWidget* , const QString& , const QString& ,const QString& , QString* ); + virtual QString saveFileName ( QWidget* , const QString& ,const QString& , const QString& , QString* ); + virtual bool modal()const{ return TRUE;} + virtual ~FileDialog(){;} + void init(QObject*); + virtual void raise(const QString& = QString(),Mode = AddFiles,const QStringList& = QStringList()){;} + + static bool registerFactory(FileDialogFactory*); + public: + static void registerBuiltinFactories(); + static void registerExternalFactories(); + protected: + static FileDialog* instance(); + static FileDialog* defaultInstance(); + private: + static QMap factories; + static FileDialog* _instance; + static QString m_current_factory; + bool m_initialized; +}; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + +interface FileDialogFactory +{ + virtual FileDialog* create() = 0; + virtual QString name() = 0; + virtual ~FileDialogFactory(){;} +}; + +Q_DECLARE_INTERFACE(FileDialogFactory, "FileDialogFactory/1.0"); + + +//////////////////////////////////////////// QT FILE DIALOG //////////////////////////////////////////////////////////////////// + +class QtFileDialog : public FileDialog +{ + public: + virtual ~QtFileDialog(); + virtual QString existingDirectory(QWidget * parent , const QString & , const QString & dir); + virtual QString openFileName(QWidget * parent,const QString & caption,const QString & dir,const QString & filter, + QString * selectedFilter); + virtual QStringList openFileNames(QWidget * parent, const QString & caption , const QString & dir , + const QString & filter, QString * selectedFilter); + virtual QString saveFileName ( QWidget * parent, const QString & caption, + const QString & dir, const QString & filter, QString * selectedFilter); +}; + + +class QtFileDialogFactory : public QObject, public FileDialogFactory +{ + Q_OBJECT + Q_INTERFACES(FileDialogFactory); + public: + virtual FileDialog* create(); + virtual QString name(); + virtual ~QtFileDialogFactory(){;} + static QString QtFileDialogFactoryName; +}; + + +#endif + + diff --git a/src/ui/fileloader.cpp b/src/ui/fileloader.cpp new file mode 100644 index 000000000..fda8efdc1 --- /dev/null +++ b/src/ui/fileloader.cpp @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include + +#include "fileloader.h" +#include "mediafile.h" + +FileLoader::FileLoader(QObject *parent) + : QThread(parent),m_files_to_load(),m_directory() +{ + m_filters = Decoder::nameFilters(); + m_finished = false; +} + + +FileLoader::~FileLoader() +{ + qWarning("FileLoader::~FileLoader()"); +} + + +void FileLoader::addFiles(const QStringList &files) +{ + if (files.isEmpty ()) + return; + + foreach(QString s, files) + { + if (Decoder::supports(s)) + emit newMediaFile(new MediaFile(s)); + if(m_finished) return; + } +} + + +void FileLoader::addDirectory(const QString& s) +{ + QDir dir(s); + dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); + dir.setSorting(QDir::Name); + QFileInfoList l = dir.entryInfoList(m_filters); + for (int i = 0; i < l.size(); ++i) + { + QFileInfo fileInfo = l.at(i); + QString suff = fileInfo.completeSuffix(); + list << fileInfo; + + if (Decoder::supports(fileInfo.absoluteFilePath ())) + emit newMediaFile(new MediaFile(fileInfo.absoluteFilePath ())); + if(m_finished) return; + } + dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); + dir.setSorting(QDir::Name); + l.clear(); + l = dir.entryInfoList(); + if (l.size() > 0) + for (int i = 0; i < l.size(); ++i) + { + QFileInfo fileInfo = l.at(i); + addDirectory(fileInfo.absoluteFilePath ()); + if(m_finished) return; + } +} + + +void FileLoader::run() +{ + if(!m_files_to_load.isEmpty()) + addFiles(m_files_to_load); + else if(!m_directory.isEmpty()) + addDirectory(m_directory); +} + + + +void FileLoader::setFilesToLoad(const QStringList & l) +{ + m_files_to_load = l; + m_directory = QString(); +} + +void FileLoader::setDirectoryToLoad(const QString & d) +{ + m_directory = d; + m_files_to_load.clear(); +} + +void FileLoader::finish() +{ + m_finished = true; +} diff --git a/src/ui/fileloader.h b/src/ui/fileloader.h new file mode 100644 index 000000000..c23d1ed35 --- /dev/null +++ b/src/ui/fileloader.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef FILELOADER_H +#define FILELOADER_H + +#include +#include +#include + +class MediaFile; + +/*! + * This class represents fileloader object that + * processes file list in separate thread and emits + * \b newMediaFile(MediaFile*) signal for every newly + * created media file. + @author Ilya Kotov +*/ +class FileLoader : public QThread +{ +Q_OBJECT +public: + FileLoader(QObject *parent = 0); + + ~FileLoader(); + virtual void run(); + + /*! + * Call this method when you want to notify the thread about finishing + */ + void finish(); + + /*! + * Sets filelist to load( directory to load will be cleaned ) + */ + void setFilesToLoad(const QStringList&); + + /*! + * Sets directory to load( filelist to load will be cleaned ) + */ + void setDirectoryToLoad(const QString&); +signals: + void newMediaFile(MediaFile*); +protected: + void addFiles(const QStringList &files); + void addDirectory(const QString& s); +private: + QFileInfoList list; + QStringList m_filters; + QStringList m_files_to_load; + QString m_directory; + bool m_finished; +}; + +#endif diff --git a/src/ui/forms/aboutdialog.ui b/src/ui/forms/aboutdialog.ui new file mode 100644 index 000000000..56fbef9c5 --- /dev/null +++ b/src/ui/forms/aboutdialog.ui @@ -0,0 +1,174 @@ + + AboutDialog + + + + 0 + 0 + 518 + 414 + + + + About Qmmp + + + + 9 + + + 6 + + + + + + + + :/logo-qmmp.png + + + Qt::AlignCenter + + + + + + + 0 + + + + About + + + + 9 + + + 6 + + + + + true + + + + + + + + Authors + + + + 9 + + + 6 + + + + + true + + + + + + + + Thanks To + + + + 9 + + + 6 + + + + + true + + + + + + + + License Agreement + + + + 9 + + + 6 + + + + + true + + + true + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + AboutDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AboutDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/ui/forms/addurldialog.ui b/src/ui/forms/addurldialog.ui new file mode 100644 index 000000000..46031b849 --- /dev/null +++ b/src/ui/forms/addurldialog.ui @@ -0,0 +1,76 @@ + + AddUrlDialog + + + + 0 + 0 + 394 + 80 + + + + Enter URL to add + + + + 9 + + + 6 + + + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + AddUrlDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AddUrlDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/ui/forms/configdialog.ui b/src/ui/forms/configdialog.ui new file mode 100644 index 000000000..530786ab4 --- /dev/null +++ b/src/ui/forms/configdialog.ui @@ -0,0 +1,944 @@ + + ConfigDialog + + + + 0 + 0 + 601 + 409 + + + + Qmmp Settings + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 170 + 16777215 + + + + + 38 + 38 + + + + QListView::Static + + + QListView::TopToBottom + + + false + + + QListView::Adjust + + + 2 + + + QListView::ListMode + + + false + + + 100 + + + false + + + -1 + + + + Appearance + + + :/interface.png + + + + + Playlist + + + :/playlist.png + + + + + Plugins + + + :/plugins.png + + + + + Advanced + + + :/advanced.png + + + + + Connectivity + + + :/network.png + + + + + + + + + 0 + 0 + + + + QFrame::Raised + + + 0 + + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Skins + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + QListView::Static + + + QListView::TopToBottom + + + QListView::ListMode + + + 0 + + + + + + + + + + Fonts + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + 6 + + + + + + 80 + 16777215 + + + + Player: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 80 + 16777215 + + + + Playlist: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + QFrame::Panel + + + QFrame::Sunken + + + ??? + + + + + + + ... + + + + + + + QFrame::Panel + + + QFrame::Sunken + + + ??? + + + + + + + ... + + + + + + + + + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + 6 + + + + + Metadata + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + 6 + + + + + Load metadata from files + + + + + + + + + + Song Display + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + Title format: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + ... + + + + + + + + + + Qt::Vertical + + + + 20 + 121 + + + + + + + + + + 9 + + + 9 + + + 9 + + + 9 + + + 6 + + + 6 + + + + + Preferences + + + + + + + Information + + + + + + + Qt::Horizontal + + + + 101 + 20 + + + + + + + + QTabWidget::North + + + QTabWidget::Rounded + + + 0 + + + + Input + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + 0 + + + 0 + + + + + + + + Output + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + + + + + Visualization + + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + + + + + + Effects + + + + + + QAbstractItemView::SelectRows + + + + + + + + General + + + + + + QAbstractItemView::SelectRows + + + + + + + + File Dialog + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + + + Audio + + + + + + Use software volume control + + + + + + + + + + Qt::Vertical + + + + 20 + 251 + + + + + + + + + + + + Proxy + + + false + + + false + + + + + + Enable proxy usage + + + + + + + Proxy host name: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Proxy port: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Use authentication with proxy + + + + + + + Proxy user name: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Proxy password: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + QLineEdit::Password + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + Qt::Horizontal + + + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 341 + 20 + + + + + + + + Close + + + + + + + + + + + + + closeButton + clicked() + ConfigDialog + accept() + + + 590 + 364 + + + 316 + 340 + + + + + enableProxyCheckBox + toggled(bool) + hostLineEdit + setEnabled(bool) + + + 305 + 52 + + + 424 + 82 + + + + + enableProxyCheckBox + toggled(bool) + portLineEdit + setEnabled(bool) + + + 506 + 56 + + + 506 + 116 + + + + + authProxyCheckBox + toggled(bool) + proxyUserLineEdit + setEnabled(bool) + + + 318 + 142 + + + 326 + 163 + + + + + authProxyCheckBox + toggled(bool) + proxyPasswLineEdit + setEnabled(bool) + + + 264 + 138 + + + 334 + 204 + + + + + diff --git a/src/ui/forms/jumptotrackdialog.ui b/src/ui/forms/jumptotrackdialog.ui new file mode 100644 index 000000000..1418c54fd --- /dev/null +++ b/src/ui/forms/jumptotrackdialog.ui @@ -0,0 +1,110 @@ + + JumpToTrackDialog + + + + 0 + 0 + 487 + 315 + + + + Jump To Track + + + + 9 + + + 6 + + + + + 0 + + + 6 + + + + + Filter + + + + + + + + + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::SelectRows + + + + + + + 0 + + + 6 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Queue + + + + + + + Refresh + + + + + + + Jump To + + + + + + + Close + + + + + + + + + + diff --git a/src/ui/forms/preseteditor.ui b/src/ui/forms/preseteditor.ui new file mode 100644 index 000000000..2f88d6d53 --- /dev/null +++ b/src/ui/forms/preseteditor.ui @@ -0,0 +1,88 @@ + + PresetEditor + + + + 0 + 0 + 225 + 248 + + + + Preset Editor + + + false + + + + 9 + + + 6 + + + + + Load + + + + + + + Delete + + + + + + + 0 + + + + Preset + + + + 9 + + + 6 + + + + + + + + + Auto-preset + + + + 9 + + + 6 + + + + + QAbstractItemView::NoEditTriggers + + + + + + + + + + + qPixmapFromMimeSource + + + diff --git a/src/ui/html/about_cs.html b/src/ui/html/about_cs.html new file mode 100644 index 000000000..84bd2b42a --- /dev/null +++ b/src/ui/html/about_cs.html @@ -0,0 +1,81 @@ + + + + Qt-based Multimedia Player + +
+

+ Qt-based Multimedia Player (Qmmp) +

+
+

+ Qmmp je přehrávač zvuku založený na knihovně Qt. +

+

+ Klíčové vlastnosti: +

+
    +
  • + podpora témat programu Winamp; +
  • +
  • + podpora zásuvných modulů (plugin); +
  • +
  • + podpora MPEG1 layer 1/2/3; +
  • +
  • + podpora Ogg-Vorbis; +
  • +
  • + podpora FLAC; +
  • +
  • + podpora Musepack; +
  • +
  • + podpora WMA; +
  • +
  • + zvukový výstup ALSA; +
  • +
  • + zvukový výstup JACK. +
  • +
+

+ Požadavky: +

+ diff --git a/src/ui/html/about_en.html b/src/ui/html/about_en.html new file mode 100644 index 000000000..d03691cf6 --- /dev/null +++ b/src/ui/html/about_en.html @@ -0,0 +1,81 @@ + + + + Qt-based Multimedia Player + +
+

+ Qt-based Multimedia Player (Qmmp) +

+
+

+ This program is an audio-player, written with help of Qt library. +

+

+ Main opportunities: +

+
    +
  • + unpacked winamp skins support; +
  • +
  • + plugins support; +
  • +
  • + MPEG1 layer 1/2/3 support; +
  • +
  • + Ogg Vorbis support; +
  • +
  • + native FLAC support; +
  • +
  • + Musepack support; +
  • +
  • + WMA support; +
  • +
  • + ALSA sound output; +
  • +
  • + JACK sound output. +
  • +
+

+ Requirements: +

+ diff --git a/src/ui/html/about_ru.html b/src/ui/html/about_ru.html new file mode 100644 index 000000000..26e5b9906 --- /dev/null +++ b/src/ui/html/about_ru.html @@ -0,0 +1,81 @@ + + + + Qt-based Multimedia Player + +
+

+ Qt-based Multimedia Player (Qmmp) +

+
+

+ Данная программа является аудио-плеером, написанным с использованием библиотеки Qt. Программа имеет интерфейс, аналогичный winamp или xmms. +

+

+ Основные возможности программы: +

+
    +
  • + поддержка тем winamp в распакованном виде; +
  • +
  • + поддержка модулей (плагинов); +
  • +
  • + поддержка файлов MPEG1 layer 1/2/3; +
  • +
  • + поддержка файлов Ogg Vorbis; +
  • +
  • + поддержка файлов Native FLAC; +
  • +
  • + поддержка файлов Musepack; +
  • +
  • + поддержка файлов WMA; +
  • +
  • + вывод звука через ALSA; +
  • +
  • + вывод звука через Jack. +
  • +
+

+ Для работы необходимы: +

+
    +
  • + операционная система GNU Linux; +
  • +
  • + Qt версии >= 4.2; +
  • +
  • + MAD; +
  • +
  • + Ogg Vorbis; +
  • +
  • + FLAC версии >= 1.1.3; +
  • +
  • + ALSA версии >= 1.0.1; +
  • +
  • + TagLib версии >= 1.4. +
  • +
  • + libmpcdec версии >= 1.2.6 +
  • +
  • + Jack версии >= 0.102.5 +
  • +
  • + FFmpeg версии >= 0.4.9-pre1 +
  • +
diff --git a/src/ui/html/about_zh_CN.html b/src/ui/html/about_zh_CN.html new file mode 100644 index 000000000..eadc7f78d --- /dev/null +++ b/src/ui/html/about_zh_CN.html @@ -0,0 +1,81 @@ + + + + 基于Qt的多媒体播放器 + +
+

+ 基于Qt的多媒体播放器(Qmmp)。 +

+
+

+ 此程序是一个音乐播放器,程序的编写基于Qt库。 +

+

+ 主要功能: +

+
    +
  • + 未压缩的winamp皮肤支持; +
  • +
  • + 插件支持; +
  • +
  • + MPEG1 1/2/3 层支持; +
  • +
  • + Ogg Vorbis 支持; +
  • +
  • + native FLAC 支持; +
  • +
  • + Musepack 支持; +
  • +
  • + WMA 支持; +
  • +
  • + ALSA 声音输出; +
  • +
  • + JACK 声音输出。 +
  • +
+

+ 要求: +

+ diff --git a/src/ui/html/authors_cs.txt b/src/ui/html/authors_cs.txt new file mode 100644 index 000000000..89d585c24 --- /dev/null +++ b/src/ui/html/authors_cs.txt @@ -0,0 +1,12 @@ +Vývojáři programu: + + Илья Котов (Ilja Kotov) (nápad a základní kód) + Владимир Кузнецов (Vladimír Kuzněcov) (vzhled a mnoho vylepšení) + +Vývojáři zásuvných modulů: + + Юрий Журавлёв (Jurij Žuravljov) (jack plugin) + +Český překlad: + + Karel Volný diff --git a/src/ui/html/authors_en.txt b/src/ui/html/authors_en.txt new file mode 100644 index 000000000..6c11ebd5e --- /dev/null +++ b/src/ui/html/authors_en.txt @@ -0,0 +1,12 @@ +Core Developers: + + Ilya Kotov (idea and base code) + Vladimir Kuznetsov (look&feel and many improvements) + +Plugin Developers: + + Yuriy Zhuravlev (jack plugin) + +Turkish translation: + + Mustafa GUNAY diff --git a/src/ui/html/authors_ru.txt b/src/ui/html/authors_ru.txt new file mode 100644 index 000000000..b95c3887e --- /dev/null +++ b/src/ui/html/authors_ru.txt @@ -0,0 +1,9 @@ +Разработчики ядра: + + Владимир Кузнецов (внешний вид и множество улучшений) + Илья Котов (идея и основной код) + +Разработчики модулей: + + Юрий Журавлёв (модуль jack) + diff --git a/src/ui/html/authors_zh_CN.txt b/src/ui/html/authors_zh_CN.txt new file mode 100644 index 000000000..f2d8892fd --- /dev/null +++ b/src/ui/html/authors_zh_CN.txt @@ -0,0 +1,16 @@ +核心开发: + + Ilya Kotov (idea and base code) + Vladimir Kuznetsov (look&feel and many improvements) + +插件开发: + + Yuriy Zhuravlev (jack plugin) + +土耳其语翻译: + + Mustafa GUNAY + +简体中文翻译: + + 李红昆 \ No newline at end of file diff --git a/src/ui/html/thanks_cs.txt b/src/ui/html/thanks_cs.txt new file mode 100644 index 000000000..9bc0388da --- /dev/null +++ b/src/ui/html/thanks_cs.txt @@ -0,0 +1,3 @@ +Poděkování patří: + + Вадим Калинников (Vadim Kalinnikov) (hosting projektu) diff --git a/src/ui/html/thanks_en.txt b/src/ui/html/thanks_en.txt new file mode 100644 index 000000000..3ed2fe5d5 --- /dev/null +++ b/src/ui/html/thanks_en.txt @@ -0,0 +1,3 @@ +Thanks to: + + Vadim Kalinnikov (project hosting) diff --git a/src/ui/html/thanks_ru.txt b/src/ui/html/thanks_ru.txt new file mode 100644 index 000000000..79acc177d --- /dev/null +++ b/src/ui/html/thanks_ru.txt @@ -0,0 +1,3 @@ +Благодарности: + + Вадиму Калинникову (хотстинг проекта) diff --git a/src/ui/html/thanks_zh_CN.txt b/src/ui/html/thanks_zh_CN.txt new file mode 100644 index 000000000..505d05c72 --- /dev/null +++ b/src/ui/html/thanks_zh_CN.txt @@ -0,0 +1,3 @@ +感谢: + + Vadim Kalinnikov (project hosting) diff --git a/src/ui/images/advanced.png b/src/ui/images/advanced.png new file mode 100644 index 000000000..25efaf35b Binary files /dev/null and b/src/ui/images/advanced.png differ diff --git a/src/ui/images/images.qrc b/src/ui/images/images.qrc new file mode 100644 index 000000000..acc7c26f0 --- /dev/null +++ b/src/ui/images/images.qrc @@ -0,0 +1,12 @@ + + + + qmmp.xpm + interface.png + playlist.png + advanced.png + plugins.png + network.png + logo-qmmp.png + + diff --git a/src/ui/images/interface.png b/src/ui/images/interface.png new file mode 100644 index 000000000..53174d71a Binary files /dev/null and b/src/ui/images/interface.png differ diff --git a/src/ui/images/logo-qmmp.png b/src/ui/images/logo-qmmp.png new file mode 100644 index 000000000..7a4d6ded4 Binary files /dev/null and b/src/ui/images/logo-qmmp.png differ diff --git a/src/ui/images/network.png b/src/ui/images/network.png new file mode 100644 index 000000000..5f47a5fe1 Binary files /dev/null and b/src/ui/images/network.png differ diff --git a/src/ui/images/playlist.png b/src/ui/images/playlist.png new file mode 100644 index 000000000..99923dea9 Binary files /dev/null and b/src/ui/images/playlist.png differ diff --git a/src/ui/images/plugins.png b/src/ui/images/plugins.png new file mode 100644 index 000000000..e9c744e64 Binary files /dev/null and b/src/ui/images/plugins.png differ diff --git a/src/ui/images/qmmp.xpm b/src/ui/images/qmmp.xpm new file mode 100644 index 000000000..85ea94fc1 --- /dev/null +++ b/src/ui/images/qmmp.xpm @@ -0,0 +1,278 @@ +/* XPM */ +static char *trayicon[]={ +"32 32 243 2", +"#N c None", +"Qt c None", +".# c #000000", +".a c #050d16", +".U c #060e16", +".L c #06101b", +"a9 c #091725", +"b. c #0a0b11", +"bU c #0b1826", +".c c #0c2034", +"bt c #0d1823", +"be c #0d2034", +"bb c #0f0f0f", +".A c #0f253c", +"a7 c #11263d", +".n c #112a45", +"a6 c #12273d", +"aL c #122f4c", +"bV c #131e29", +"bi c #141b23", +"bg c #14212e", +".b c #16385b", +".i c #16385c", +"#L c #191b2b", +"bW c #1a2b3e", +".d c #1a4169", +"aY c #1a416b", +"bm c #1a426b", +"aB c #1b1d2e", +"aZ c #1b1d2f", +".o c #1c1c1c", +"bl c #1c436b", +"aH c #1d436b", +"ah c #1e1f25", +"at c #1e4b7a", +"#o c #1f2236", +"#K c #1f272f", +"bO c #1f2e3e", +"aK c #1f4c7b", +"bk c #202a35", +"bh c #202e3e", +"au c #212331", +"as c #215489", +"a8 c #21548a", +".R c #223952", +"br c #233242", +"#J c #24303e", +".3 c #253647", +".T c #27507b", +".e c #292929", +"#O c #292a30", +"aM c #2967a7", +".x c #2968a9", +"bN c #2a598a", +"aJ c #2c69a9", +"ar c #2d71b7", +"ap c #2d71b8", +".M c #2e2e2e", +"bs c #2f4d6c", +"#w c #2f547b", +"#B c #303030", +"ag c #303453", +"bI c #30353a", +"bc c #30465d", +"bf c #307ac7", +"bP c #314253", +".K c #317bc7", +"#I c #323e4b", +"#p c #333333", +"#8 c #34353d", +"aq c #3484d6", +"aA c #3484d7", +"az c #35404c", +"#d c #363636", +"aN c #373b5e", +"bu c #387ec8", +".4 c #393939", +"a4 c #39414a", +"aI c #3a87d7", +"af c #3b3b3b", +"#j c #3b699a", +".V c #3c3c3c", +"#A c #3c4046", +"bn c #3c6a9a", +".m c #3c95f2", +".l c #3c95f3", +".k c #3c96f4", +".j c #3c96f5", +".z c #3c97f5", +".y c #3c97f6", +"bJ c #3f4954", +"aX c #3f99f6", +"bD c #408ad7", +".J c #419af6", +"aT c #4284c8", +"aW c #459cf6", +"bd c #46688c", +"#X c #474a60", +".I c #479df6", +"## c #48719b", +"bT c #4887c8", +"ba c #494949", +"aU c #4a97e7", +"bE c #4b81b9", +".S c #4b89c9", +"aV c #4b9ff6", +".1 c #4d4d4d", +".p c #545454", +"ay c #555555", +"#M c #555b91", +".2 c #57789c", +"#. c #585d61", +"a5 c #5897d9", +"bC c #59a6f7", +"bM c #5aa6f7", +".f c #606060", +"#G c #616161", +"bv c #62abf7", +"aC c #636785", +"#v c #646464", +"aF c #676767", +"bj c #6a8aac", +"bS c #6bb0f8", +"#a c #6f94bb", +"bB c #6fb2f8", +"aO c #707175", +"bL c #70b2f8", +"#b c #71879d", +"bo c #72b4f8", +"#6 c #747474", +"aR c #757575", +"#7 c #777777", +"bQ c #7798bb", +"#x c #77b6f8", +"#W c #787878", +"#t c #797979", +"#k c #7ab8f8", +".0 c #7b7b7b", +"ai c #7b7f9f", +"bF c #7bb9f8", +".h c #7e7e7e", +"#i c #808080", +"by c #808f9d", +"aG c #828282", +"#F c #838383", +"bR c #83bdf9", +".Q c #848484", +"av c #8487a4", +"#5 c #858585", +"bz c #86a8cb", +"ao c #878787", +"#9 c #878aa2", +"ac c #888888", +"bA c #89c0f9", +"#2 c #8a8a8a", +"bp c #8ac1f9", +".w c #8b8b8b", +".q c #8c8c8c", +"#3 c #8d8d8d", +"#H c #8e8e8e", +"#n c #90979e", +"#U c #919191", +"#Z c #9396ac", +"aS c #969696", +"bw c #96c7fa", +"#4 c #989898", +"bG c #98c8fa", +"ad c #9a9a9a", +"#T c #9b9b9b", +".g c #9c9c9c", +"#e c #9d9d9d", +"#y c #9dcafa", +"ae c #9f9f9f", +"#c c #9fbddc", +"aE c #a0a0a0", +"bH c #a1bedc", +".9 c #a2a2a2", +"a. c #a2a3ad", +"#l c #a3cefa", +"aD c #a4a4a4", +"#Y c #a4a5ad", +"#u c #a5a5a5", +"aw c #a7a7a7", +"al c #a8a8a8", +"#g c #a9a9a9", +"bK c #a9d1fb", +"bq c #aacaeb", +"#h c #acacac", +"am c #afafaf", +"#Q c #afb1bd", +"#1 c #b0b0b0", +".Z c #b1b1b1", +".8 c #b3b3b3", +"#P c #b3b3b9", +"ak c #b4b4b4", +"bx c #b5d7fb", +"#r c #b9b9b9", +"aj c #bababa", +"ax c #bbbbbb", +"a# c #bebebe", +"an c #bfbfbf", +".B c #c0c0c0", +".r c #c2c2c2", +"#R c #c2c3cb", +".6 c #c5c5c5", +"#z c #c5e0fc", +"aa c #c7c7c7", +".Y c #c8c8c8", +"#0 c #c9c9c9", +"#C c #cacaca", +"aP c #cbcbcb", +"#S c #cccccc", +"#E c #cecece", +"b# c #cfcfcf", +".X c #d0d0d0", +".7 c #d1d1d1", +"ab c #d2d2d2", +"#m c #d2e7fc", +"#q c #d5d5d5", +"#f c #d6d6d6", +"#D c #d6d7db", +"aQ c #d7d7d7", +"#s c #d9d9d9", +".t c #dbdbdb", +".s c #dcdcdc", +".5 c #dddddd", +".F c #dedede", +".E c #e0e0e0", +".D c #e1e1e1", +".C c #e3e3e3", +".u c #e5e5e5", +".G c #e6e6e6", +".P c #e7e7e7", +"#V c #eaeaea", +".v c #ebebeb", +".H c #ececec", +".O c #ededed", +"a3 c #eeeeee", +"a0 c #efefef", +"a2 c #f0f0f0", +"a1 c #f1f1f1", +".W c #f7f7f7", +".N c #f9f9f9", +"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQtQtQt.#.#QtQtQtQtQt.a.b.#.c.dQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQt.#.#.e.f.g.h.#QtQtQtQt.i.j.k.l.m.nQtQtQtQtQt", +"QtQtQtQtQtQtQt.#.o.p.q.r.s.t.u.v.w.#QtQtQt.x.y.z.k.k.AQtQtQtQtQt", +"QtQtQtQtQtQt.#.B.u.C.D.E.F.s.s.G.H.q.#Qt.#.I.J.K.c.#.LQtQtQtQtQt", +"QtQtQtQtQtQt.M.N.O.u.C.D.E.F.s.s.P.O.Q.#.R.S.T.UQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQt.V.W.N.O.u.C.F.X.r.Y.X.Z.0.1.2.3QtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQt.4.H.W.N.5.6.7.s.8.9#.###a#b#c.#QtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQt#d.D.H.W.Y#e#f#g#h#i#j#k#l#m#n#oQtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQt#p#q.D.H.X#r#s#t#u#v#w#x#y#z#AQtQtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQt#B#C#q#D#E#s.t#F#G#H.w#I#J#K#L#MQt#NQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQt#O#P#Q#R#S.s.F.r#T#U.w.F#V#WQt#MQtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQt#X#Y#Z#C#0.F#1#2#3#4#5#6.O#7Qt#MQtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQt#8#9a.a#aaabac.E.8adae.1.Eaf.##oQtagQtQtQtQtQtQtQtQt", +"QtQtQtQtQt#Nahaiajak.6al#5am#2an.q.paoap.zaqarasat.A.AQtQtQtQtQt", +"QtQtQtQtQtQtauavan#r.6#i#eawanaxay#4azaAapap.z.j.k.k.l.#QtQtQtQt", +"QtQtQtQtQtQtaBaC.ra##SaD.0aE#3ayaFaGaHaIaJaK.iaLaLataMQtQtQtQtQt", +"QtQtQtQtQtQtQtaNaOa#aPaQaR.1.paS.G.waTaUaVaWaX.y.y.zaYQtQtQtQtQt", +"QtQtQtQtQt#NQtQtaZaF#E#5a0a1a2a3ana4a5.#.#a6a7aKa8.za9QtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtb.#2.Hb#.Qbabb.#bcbdQtQtQtQtQtbebfQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQt.#.#.#.#bgbhbibjbkQtQtQtQtQtblbmQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQt.#bnbobp#lbq.#Qt.#brbsbtbua9QtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQt.#bv#kbwbxbyQt.#bzbAbBbCbD.#QtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQt.#bEbFbGbHbIQtbJbKbpbLbMbNQtQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQtQt.#bObP.#QtQt.#bQbRbSbTbUQtQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.#bVbW.#QtQtQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", +"QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt"}; diff --git a/src/ui/inlines.h b/src/ui/inlines.h new file mode 100644 index 000000000..3efccf0de --- /dev/null +++ b/src/ui/inlines.h @@ -0,0 +1,505 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#ifndef INLINES_H +#define INLINES_H + +#include "fft.h" + +// *fast* convenience functions +static inline void +calc_freq(short* dest, short *src) +{ + static fft_state *state = NULL; + float tmp_out[257]; + int i; + + if (!state) + state = fft_init(); + + fft_perform(src, tmp_out, state); + + for (i = 0; i < 256; i++) + dest[i] = ((int) sqrt(tmp_out[i + 1])) >> 8; +} + +static inline void +calc_mono_freq(short dest[2][256], short src[2][512], int nch) +{ + int i; + short *d, *sl, *sr, tmp[512]; + + if (nch == 1) + calc_freq(dest[0], src[0]); + else + { + d = tmp; + sl = src[0]; + sr = src[1]; + for (i = 0; i < 512; i++) + { + *(d++) = (*(sl++) + *(sr++)) >> 1; + } + calc_freq(dest[0], tmp); + } +} + +static inline void stereo16_from_stereopcm8(register short *l, + register short *r, + register uchar *c, + long cnt) +{ + while (cnt >= 4l) + { + l[0] = c[0]; + r[0] = c[1]; + l[1] = c[2]; + r[1] = c[3]; + l[2] = c[4]; + r[2] = c[5]; + l[3] = c[6]; + r[3] = c[7]; + l += 4; + r += 4; + c += 8; + cnt -= 4l; + } + + if (cnt > 0l) + { + l[0] = c[0]; + r[0] = c[1]; + if (cnt > 1l) + { + l[1] = c[2]; + r[1] = c[3]; + if (cnt > 2l) + { + l[2] = c[4]; + r[2] = c[5]; + } + } + } +} + + +static inline void stereo16_from_stereopcm16(register short *l, + register short *r, + register short *s, + long cnt) +{ + while (cnt >= 4l) + { + l[0] = s[0]; + r[0] = s[1]; + l[1] = s[2]; + r[1] = s[3]; + l[2] = s[4]; + r[2] = s[5]; + l[3] = s[6]; + r[3] = s[7]; + l += 4; + r += 4; + s += 8; + cnt -= 4l; + } + + if (cnt > 0l) + { + l[0] = s[0]; + r[0] = s[1]; + if (cnt > 1l) + { + l[1] = s[2]; + r[1] = s[3]; + if (cnt > 2l) + { + l[2] = s[4]; + r[2] = s[5]; + } + } + } +} + + +static inline void mono16_from_monopcm8(register short *l, + register uchar *c, + long cnt) +{ + while (cnt >= 4l) + { + l[0] = c[0]; + l[1] = c[1]; + l[2] = c[2]; + l[3] = c[3]; + l += 4; + c += 4; + cnt -= 4l; + } + + if (cnt > 0l) + { + l[0] = c[0]; + if (cnt > 1l) + { + l[1] = c[1]; + if (cnt > 2l) + { + l[2] = c[2]; + } + } + } +} + + +static inline void mono16_from_monopcm16(register short *l, + register short *s, + long cnt) +{ + while (cnt >= 4l) + { + l[0] = s[0]; + l[1] = s[1]; + l[2] = s[2]; + l[3] = s[3]; + l += 4; + s += 4; + cnt -= 4l; + } + + if (cnt > 0l) + { + l[0] = s[0]; + if (cnt > 1l) + { + l[1] = s[1]; + if (cnt > 2l) + { + l[2] = s[2]; + } + } + } +} + + +static inline void fast_short_set(register short *p, + short v, + long c) +{ + while (c >= 4l) + { + p[0] = v; + p[1] = v; + p[2] = v; + p[3] = v; + p += 4; + c -= 4l; + } + + if (c > 0l) + { + p[0] = v; + if (c > 1l) + { + p[1] = v; + if (c > 2l) + { + p[2] = v; + } + } + } +} + +#ifdef FFTW +static inline void fast_real_set(register fftw_real *p, + fftw_real v, + long c) +{ + while (c >= 4l) + { + p[0] = v; + p[1] = v; + p[2] = v; + p[3] = v; + p += 4; + c -= 4l; + } + + if (c > 0l) + { + p[0] = v; + if (c > 1l) + { + p[1] = v; + if (c > 2l) + { + p[2] = v; + } + } + } +} + +static inline void fast_complex_set(register fftw_complex *p, + fftw_complex v, + long c) +{ + while (c >= 4l) + { + p[0] = v; + p[1] = v; + p[2] = v; + p[3] = v; + p += 4; + c -= 4l; + } + + if (c > 0l) + { + p[0] = v; + if (c > 1l) + { + p[1] = v; + if (c > 2l) + { + p[2] = v; + } + } + } +} + + +static inline void fast_real_set_from_short(register fftw_real *d, + register short *s, + long c) +{ + while (c >= 4l) + { + d[0] = fftw_real(s[0]); + d[1] = fftw_real(s[1]); + d[2] = fftw_real(s[2]); + d[3] = fftw_real(s[3]); + d += 4; + s += 4; + c -= 4l; + } + + if (c > 0l) + { + d[0] = fftw_real(s[0]); + if (c > 1l) + { + d[1] = fftw_real(s[1]); + if (c > 2l) + { + d[2] = fftw_real(s[2]); + } + } + } +} + +static inline void fast_complex_set_from_short(register fftw_complex *d, + register short *s, + long c) +{ + while (c >= 4l) + { + d[0].re = fftw_real(s[0]); + d[0].im = 0; + d[1].re = fftw_real(s[1]); + d[1].im = 0; + d[2].re = fftw_real(s[2]); + d[2].im = 0; + d[3].re = fftw_real(s[3]); + d[3].im = 0; + d += 4; + s += 4; + c -= 4l; + } + + if (c > 0l) + { + d[0].re = fftw_real(s[0]); + d[0].im = 0; + if (c > 1l) + { + d[1].re = fftw_real(s[1]); + d[1].im = 0; + if (c > 2l) + { + d[2].re = fftw_real(s[2]); + d[2].im = 0; + } + } + } +} + + +static inline void fast_real_avg_from_shorts(register fftw_real *d, + register short *s1, + register short *s2, + long c) +{ + fftw_real t0, t1, t2, t3; + while (c >= 4l) + { + t0 = (s1[0] + s2[0]) / 2; + t1 = (s1[1] + s2[1]) / 2; + t2 = (s1[2] + s2[2]) / 2; + t3 = (s1[3] + s2[3]) / 2; + d[0] = t0; + d[1] = t1; + d[2] = t2; + d[3] = t3; + d += 4; + s1 += 4; + s2 += 4; + c -= 4l; + } + + if (c > 0l) + { + d[0] = fftw_real((s1[0] + s2[0]) / 2); + if (c > 1l) + { + d[1] = fftw_real((s1[1] + s2[1]) / 2); + if (c > 2l) + { + d[2] = fftw_real((s1[2] + s2[2]) / 2); + } + } + } +} + +static inline void fast_complex_avg_from_shorts(register fftw_complex *d, + register short *s1, + register short *s2, + long c) +{ + fftw_real t0, t1, t2, t3; + while (c >= 4l) + { + t0 = (s1[0] + s2[0]) / 2; + t1 = (s1[1] + s2[1]) / 2; + t2 = (s1[2] + s2[2]) / 2; + t3 = (s1[3] + s2[3]) / 2; + d[0].re = t0; + d[0].im = 0; + d[1].re = t1; + d[1].im = 0; + d[2].re = t2; + d[2].im = 0; + d[3].re = t3; + d[3].im = 0; + d += 4; + s1 += 4; + s2 += 4; + c -= 4l; + } + + if (c > 0l) + { + d[0].re = fftw_real((s1[0] + s2[0]) / 2); + d[0].im = 0; + if (c > 1l) + { + d[1].re = fftw_real((s1[1] + s2[1]) / 2); + d[1].im = 0; + if (c > 2l) + { + d[2].re = fftw_real((s1[2] + s2[2]) / 2); + d[2].im = 0; + } + } + } +} + + +static inline fftw_complex fftw_complex_from_real( fftw_real re ) +{ + fftw_complex c; + + c.re = re; + c.im = 0; + + return c; +} + +static inline void fast_reals_set(register fftw_real *p1, + register fftw_real *p2, + fftw_real v, + long c) +{ + while (c >= 4l) + { + p1[0] = v; + p1[1] = v; + p1[2] = v; + p1[3] = v; + p2[0] = v; + p2[1] = v; + p2[2] = v; + p2[3] = v; + p1 += 4; + p2 += 4; + c -= 4l; + } + + if (c > 0l) + { + p1[0] = v; + p2[0] = v; + if (c > 1l) + { + p1[1] = v; + p2[1] = v; + if (c > 2l) + { + p1[2] = v; + p2[2] = v; + } + } + } +} + +static inline void fast_complex_set(register fftw_complex *p1, + register fftw_complex *p2, + fftw_complex v, + long c) +{ + while (c >= 4l) + { + p1[0] = v; + p1[1] = v; + p1[2] = v; + p1[3] = v; + p2[0] = v; + p2[1] = v; + p2[2] = v; + p2[3] = v; + p1 += 4; + p2 += 4; + c -= 4l; + } + + if (c > 0l) + { + p1[0] = v; + p2[0] = v; + if (c > 1l) + { + p1[1] = v; + p2[1] = v; + if (c > 2l) + { + p1[2] = v; + p2[2] = v; + } + } + } +} +#endif // FFTW + +#endif // INLINES_H diff --git a/src/ui/jumptotrackdialog.cpp b/src/ui/jumptotrackdialog.cpp new file mode 100644 index 000000000..bcd0f308c --- /dev/null +++ b/src/ui/jumptotrackdialog.cpp @@ -0,0 +1,128 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "jumptotrackdialog.h" +#include "playlistmodel.h" + +#include +#include +#include +#include + +JumpToTrackDialog::JumpToTrackDialog(QWidget* parent, Qt::WFlags fl) +: QDialog( parent, fl ) +{ + setupUi(this); + setAttribute(Qt::WA_QuitOnClose, FALSE); + m_playListModel = 0; + m_listModel = new QStringListModel(this); + + m_proxyModel = new QSortFilterProxyModel; + m_proxyModel->setDynamicSortFilter(true); + m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); + m_proxyModel->setSourceModel(m_listModel); + songsListView->setModel(m_proxyModel); + + connect(songsListView,SIGNAL(doubleClicked(const QModelIndex &)), + this,SLOT(jumpTo(const QModelIndex&))); + + + connect(songsListView->selectionModel(), + SIGNAL(currentRowChanged(const QModelIndex&,const QModelIndex&)), + this,SLOT(queueUnqueue(const QModelIndex&,const QModelIndex&))); + + new QShortcut(QKeySequence("Q"),this,SLOT(on_queuePushButton_clicked())); + new QShortcut(QKeySequence("J"),this,SLOT(on_jumpToPushButton_clicked())); + new QShortcut(QKeySequence("F5"),this,SLOT(on_refreshPushButton_clicked())); +} + +JumpToTrackDialog::~JumpToTrackDialog() +{ +} + + +void JumpToTrackDialog::on_closePushButton_clicked() +{ + hide(); +} + +void JumpToTrackDialog::on_refreshPushButton_clicked() +{ + refresh(); +} + +void JumpToTrackDialog::on_queuePushButton_clicked() +{ + QModelIndexList mi_list = songsListView->selectionModel()->selectedRows(); + if(!mi_list.isEmpty()) + { + int selected = (m_proxyModel->mapToSource(mi_list.at(0))).row(); + m_playListModel->setQueued(m_playListModel->item(selected)); + if(m_playListModel->isQueued(m_playListModel->item(selected))) + queuePushButton->setText(tr("Unqueue")); + else + queuePushButton->setText(tr("Queue")); + } +} + +void JumpToTrackDialog::on_jumpToPushButton_clicked() +{ + QModelIndexList mi_list = songsListView->selectionModel()->selectedRows(); + if(!mi_list.isEmpty()) + { + jumpTo(mi_list.at(0)); + } +} + +void JumpToTrackDialog::refresh() +{ + filterLineEdit->clear(); + QStringList titles = m_playListModel->getTitles(0,m_playListModel->count()); + m_listModel->setStringList(titles); + filterLineEdit->setFocus(); +} + +void JumpToTrackDialog::setModel(PlayListModel * model) +{ + m_playListModel = model; +} + +void JumpToTrackDialog::on_filterLineEdit_textChanged(const QString &str) +{ + m_proxyModel->setFilterFixedString(str); +} + +void JumpToTrackDialog::jumpTo(const QModelIndex & index) +{ + int selected = (m_proxyModel->mapToSource(index)).row(); + m_playListModel->setCurrent(selected); + emit playRequest(); +} + +void JumpToTrackDialog::queueUnqueue(const QModelIndex& curr,const QModelIndex&) +{ + int row = m_proxyModel->mapToSource(curr).row(); + if(m_playListModel->isQueued(m_playListModel->item(row))) + queuePushButton->setText(tr("Unqueue")); + else + queuePushButton->setText(tr("Queue")); +} + + diff --git a/src/ui/jumptotrackdialog.h b/src/ui/jumptotrackdialog.h new file mode 100644 index 000000000..cfe629693 --- /dev/null +++ b/src/ui/jumptotrackdialog.h @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef JUMPTOTRACKDIALOG_H +#define JUMPTOTRACKDIALOG_H + +#include +#include "ui_jumptotrackdialog.h" + +/** + @author Vladimir Kuznetsov + */ + +class QStringListModel; +class PlayListModel; +class QSortFilterProxyModel; + + +class JumpToTrackDialog : public QDialog, private Ui::JumpToTrackDialog +{ + Q_OBJECT + +public: + JumpToTrackDialog(QWidget* parent = 0, Qt::WFlags fl = 0 ); + ~JumpToTrackDialog(); + void setModel(PlayListModel* model); + void refresh(); +protected slots: + void on_closePushButton_clicked(); + void on_refreshPushButton_clicked(); + void on_queuePushButton_clicked(); + void on_jumpToPushButton_clicked(); + void on_filterLineEdit_textChanged(const QString&); + void jumpTo(const QModelIndex&); + void queueUnqueue(const QModelIndex&,const QModelIndex&); +signals: + void playRequest(); +private: + PlayListModel* m_playListModel; + QStringListModel* m_listModel; + QSortFilterProxyModel* m_proxyModel; +}; + +#endif + diff --git a/src/ui/keyboardmanager.cpp b/src/ui/keyboardmanager.cpp new file mode 100644 index 000000000..5ad32fee7 --- /dev/null +++ b/src/ui/keyboardmanager.cpp @@ -0,0 +1,260 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +#include + +#include "playlist.h" +#include "playlistmodel.h" +#include "listwidget.h" +#include "keyboardmanager.h" +#include "mainwindow.h" + + +KeyboardManager::KeyboardManager ( PlayList* pl ) +{ + m_playlist = pl; +} + +bool KeyboardManager::handleKeyPress ( QKeyEvent* ke ) +{ + bool handled = TRUE; + switch ( ke->key() ) + { + case Qt::Key_Up: + keyUp ( ke ); + break; + case Qt::Key_Down: + keyDown ( ke ); + break; + case Qt::Key_PageUp: + keyPgUp ( ke ); + break; + case Qt::Key_PageDown: + keyPgDown ( ke ); + break; + case Qt::Key_Enter: + case Qt::Key_Return: + keyEnter ( ke ); + default: + handled = FALSE; + } + return handled; +} + +bool KeyboardManager::handleKeyRelease ( QKeyEvent* ) +{ + return FALSE; +} + + + +void KeyboardManager::setModel ( PlayListModel *m ) +{ + m_playListModel = m; +} + +void KeyboardManager::keyUp ( QKeyEvent * ke ) +{ + QList rows = m_playListModel->getSelectedRows(); + ListWidget* list_widget = m_playlist->listWidget(); + + if ( rows.count() > 0 ) + { + if(rows[0] == 0 && rows.count() == 1) + return; + + if ( ! ( ke->modifiers() & Qt::ShiftModifier || ke->modifiers() & Qt::AltModifier ) ) + { + m_playListModel->clearSelection(); + list_widget->setAnchorRow(-1); + } + + bool select_top = false; + int first_visible = list_widget->firstVisibleRow(); + int last_visible = list_widget->visibleRows() + first_visible - 1; + foreach ( int i, rows ) + { + if ( i > last_visible || i < first_visible ) + { + select_top = true; + break; + } + } + + if ( !select_top || ke->modifiers() & Qt::ShiftModifier || ke->modifiers() & Qt::AltModifier ) + { + if ( ke->modifiers() == Qt::AltModifier ) + { + m_playListModel->moveItems ( rows[0],rows[0] - 1 ); + list_widget->setAnchorRow ( list_widget->getAnchorRow() - 1 ); + } + else + { + if ( rows.last() > list_widget->getAnchorRow() && ke->modifiers() & Qt::ShiftModifier ) + { + m_playListModel->setSelected ( rows.last(),false ); + } + else if ( rows[0] > 0 ) + { + m_playListModel->setSelected ( rows[0] - 1,true ); + } + else + { + m_playListModel->setSelected ( rows[0],true ); + if(list_widget->getAnchorRow() == -1) + list_widget->setAnchorRow(rows[0]); + } + + if ( ! ( ke->modifiers() & Qt::ShiftModifier ) && rows[0] > 0 ) + list_widget->setAnchorRow ( rows[0] - 1 ); + } + } + else + { + m_playListModel->setSelected ( list_widget->firstVisibleRow(),true ); + list_widget->setAnchorRow(list_widget->firstVisibleRow()); + } + + rows = m_playListModel->getSelectedRows(); + + if ( rows[0] < list_widget->firstVisibleRow() && list_widget->firstVisibleRow() > 0 ) + { + int r = rows.last() > list_widget->getAnchorRow() ? rows.last(): rows.first(); + if(ke->modifiers() & Qt::ShiftModifier && (r >= list_widget->firstVisibleRow() )) + ; + else + list_widget->scroll ( list_widget->firstVisibleRow() - 1 ); + } + } + else + { + //if(list_widget->getAnchorRow() == -1) + list_widget->setAnchorRow(list_widget->firstVisibleRow()); + m_playListModel->setSelected ( list_widget->firstVisibleRow(),true ); + } +} + +void KeyboardManager::keyDown ( QKeyEvent * ke ) +{ + QList rows = m_playListModel->getSelectedRows(); + ListWidget* list_widget = m_playlist->listWidget(); + //qWarning("count: %d",rows.count()); + if ( rows.count() > 0 ) + { + if ( ! ( ke->modifiers() & Qt::ShiftModifier || ke->modifiers() & Qt::AltModifier ) ) + { + m_playListModel->clearSelection(); + list_widget->setAnchorRow(-1); + } + + bool select_top = false; + int first_visible = list_widget->firstVisibleRow(); + int last_visible = list_widget->visibleRows() + first_visible - 1; + foreach ( int i, rows ) + { + if ( i > last_visible || i < first_visible ) + { + select_top = true; + break; + } + } + + if ( !select_top || ke->modifiers() & Qt::ShiftModifier || ke->modifiers() & Qt::AltModifier ) + { + if ( ke->modifiers() == Qt::AltModifier ) + { + m_playListModel->moveItems ( rows.last(),rows.last() + 1 ); + list_widget->setAnchorRow ( list_widget->getAnchorRow() + 1 ); + } + else + { + //qWarning("list_widget %d",list_widget->getAnchorRow()); + //qWarning("model count: %d rows.last(): %d",m_playListModel->count(),rows.last()); + if ( rows[0] < list_widget->getAnchorRow() && ke->modifiers() & Qt::ShiftModifier ) + m_playListModel->setSelected ( rows[0],false ); + else if ( rows.last() < m_playListModel->count() - 1 ) + { + m_playListModel->setSelected ( rows.last() + 1,true ); + } + else + { + m_playListModel->setSelected ( rows.last(),true ); + if(list_widget->getAnchorRow() == -1) + list_widget->setAnchorRow(rows.last()); + } + + if ( ! ( ke->modifiers() & Qt::ShiftModifier ) && rows.last() < m_playListModel->count() - 1 ) + list_widget->setAnchorRow ( rows.last() + 1 ); + } + } + else + { + m_playListModel->setSelected ( list_widget->firstVisibleRow(),true ); + list_widget->setAnchorRow(list_widget->firstVisibleRow()); + } + + rows = m_playListModel->getSelectedRows(); + + if ( !rows.isEmpty() && rows.last() >= list_widget->visibleRows() + list_widget->firstVisibleRow() ) + { + int r = rows.first() < list_widget->getAnchorRow() ? rows.first(): rows.last(); + if(ke->modifiers() & Qt::ShiftModifier && + (r < list_widget->firstVisibleRow() + list_widget->visibleRows() )) + ; + else + list_widget->scroll ( list_widget->firstVisibleRow() + 1 ); + } + } + else + { + m_playListModel->setSelected ( list_widget->firstVisibleRow(),true ); + //if(list_widget->getAnchorRow() == -1) + list_widget->setAnchorRow(list_widget->firstVisibleRow()); + } +} + +void KeyboardManager::keyPgUp ( QKeyEvent * ) +{ + ListWidget* list_widget = m_playlist->listWidget(); + int page_size = list_widget->visibleRows(); + int offset= ( list_widget->firstVisibleRow()-page_size >= 0 ) ?list_widget->firstVisibleRow()-page_size:0; + list_widget->scroll ( offset ); +} + +void KeyboardManager::keyPgDown ( QKeyEvent * ) +{ + ListWidget* list_widget = m_playlist->listWidget(); + int page_size = list_widget->visibleRows(); + int offset = ( list_widget->firstVisibleRow() +page_size < m_playListModel->count() ) ? + list_widget->firstVisibleRow() +page_size:m_playListModel->count() - 1; + list_widget->scroll ( offset ); +} + +void KeyboardManager::keyEnter ( QKeyEvent * ) +{ + QList rows = m_playListModel->getSelectedRows(); + MainWindow* mw = qobject_cast ( m_playlist->parentWidget() ); + if ( mw && rows.count() > 0 ) + { + m_playListModel->setCurrent ( rows[0] ); + mw->replay(); + } +} diff --git a/src/ui/keyboardmanager.h b/src/ui/keyboardmanager.h new file mode 100644 index 000000000..2b33b5ef9 --- /dev/null +++ b/src/ui/keyboardmanager.h @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + + +#ifndef _KEYBOARDMANAGER_H +#define _KEYBOARDMANAGER_H + +class PlayList; +class PlayListModel; +class QKeyEvent; + + +/*! + * Class \b KeyboardManager represents key handler object that processes + * all key events passed to the \b PlayList + * @author Vladimir Kuznetsov + */ +class KeyboardManager +{ + public: + /*! + * Constructor. Takes \b PlayList object as an argument. + */ + KeyboardManager ( PlayList* ); + + /*! + * Handles key press events from \b PlayList object. Returns \b TRUE + * if the key was handled, otherwise \b FALSE. + */ + bool handleKeyPress ( QKeyEvent* ); + + /*! + * Handles key release events from \b PlayList object. Returns \b TRUE + * if the key was handled, otherwise \b FALSE. + */ + bool handleKeyRelease ( QKeyEvent* ); + + /*! + * Inits the \b KeyboardManager object with data model. + */ + void setModel ( PlayListModel* ); + protected: + void keyUp ( QKeyEvent* ke ); + void keyDown ( QKeyEvent* ke ); + void keyPgUp ( QKeyEvent* ke ); + void keyPgDown ( QKeyEvent* ke ); + void keyEnter ( QKeyEvent* ke ); + private: + PlayList* m_playlist; + PlayListModel* m_playListModel; +}; + +#endif + diff --git a/src/ui/listwidget.cpp b/src/ui/listwidget.cpp new file mode 100644 index 000000000..fb2173b33 --- /dev/null +++ b/src/ui/listwidget.cpp @@ -0,0 +1,482 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mediafile.h" +#include "textscroller.h" +#include "listwidget.h" +#include "skin.h" +#include "playlistmodel.h" +#include "playlist.h" + +#define INVALID_ROW -1 + +ListWidget::ListWidget(QWidget *parent) + : QWidget(parent) +{ + m_update = FALSE; + m_skin = Skin::getPointer(); + loadColors(); + setWindowFlags(Qt::FramelessWindowHint); + m_menu = new QMenu(this); + m_scroll_direction = NONE; + m_prev_y = 0; + m_anchor_row = INVALID_ROW; + + m_first = 0; + m_rows = 0; + m_scroll = FALSE; + m_select_on_release = FALSE; + readSettings(); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); + setAcceptDrops(true); +} + + +ListWidget::~ListWidget() +{} + +void ListWidget::readSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + QString fontname = settings.value("PlayList/Font","").toString(); + if (fontname.isEmpty ()) + fontname = QFont("Helvetica [Cronyx]", 10).toString(); + m_font.fromString(fontname); + + if (m_update) + { + delete m_metrics; + m_metrics = new QFontMetrics(m_font); + m_rows = (height() - 10) / m_metrics->ascent (); + updateList(); + } + else + { + m_update = TRUE; + m_metrics = new QFontMetrics(m_font); + } +} + +void ListWidget::loadColors() +{ + m_normal.setNamedColor(m_skin->getPLValue("normal")); + m_current.setNamedColor(m_skin->getPLValue("current")); + m_normal_bg.setNamedColor(m_skin->getPLValue("normalbg")); + m_selected_bg.setNamedColor(m_skin->getPLValue("selectedbg")); +} + +void ListWidget::paintEvent(QPaintEvent *) +{ + + QPainter m_painter(this); + //m_painter.setPen(Qt::white); + m_painter.setFont(m_font); + m_painter.setBrush(QBrush(m_normal_bg)); + m_painter.drawRect(-1,-1,width()+1,height()+1); + + + + for (int i=0; iisSelected(i + m_first)) + { + m_painter.setBrush(QBrush(m_selected_bg)); + m_painter.setPen(m_selected_bg); + m_painter.drawRect ( 6, 15+(i-1)*m_metrics->ascent(), + width() - 10, m_metrics->ascent()); + } + + if (m_model->currentRow() == i + m_first) + m_painter.setPen(m_current); + else + m_painter.setPen(m_normal); //243,58 + + m_painter.drawText(10,14+i*m_metrics->ascent(),m_titles.at(i)); + + if (m_model->isQueued(m_model->item(i + m_first))) + { + QString queue_string = "|" + + QString::number(1 + m_model->queuedIndex(m_model->item(m_first + i))) + "|"; + + int old_size = m_font.pointSize(); + m_font.setPointSize(old_size - 1 ); + m_painter.setFont(m_font); + + m_painter.drawText(width() - 10 - m_metrics->width(queue_string) - m_metrics->width(m_times.at(i)), 12+i*m_metrics->ascent (), queue_string); + + m_font.setPointSize(old_size); + m_painter.setFont(m_font); + + + m_painter.setBrush(QBrush(Qt::transparent)); + //m_painter.drawRect(width() - 10 - m_metrics->width(queue_string) - m_metrics->width(m_times.at(i)), + // /*14+*/i*m_metrics->ascent () + 3,10,12); + m_painter.setBrush(QBrush(m_normal_bg)); + } + + + m_painter.drawText(width() - 7 - m_metrics->width(m_times.at(i)), + 14+i*m_metrics->ascent (), m_times.at(i)); + + } + +} + +void ListWidget::mouseDoubleClickEvent (QMouseEvent *e) +{ + int y = e->y(); + int row = rowAt(y); + if (INVALID_ROW != row) + { + m_model->setCurrent(row); + emit selectionChanged(); + update(); + } +} + + +void ListWidget::mousePressEvent(QMouseEvent *e) +{ + m_scroll = TRUE; + int y = e->y(); + int row = rowAt(y); + + if (INVALID_ROW != row && m_model->count() > row) + { + if (!(Qt::ControlModifier & e->modifiers () || + Qt::ShiftModifier & e->modifiers () || + m_model->isSelected(row))) + m_model->clearSelection(); + + if (m_model->isSelected(row) && (e->modifiers() == Qt::NoModifier)) + m_select_on_release = TRUE; + + //qWarning("m_prev_clicked_row: %d",m_prev_clicked_row); + + m_pressed_row = row; + if ((Qt::ShiftModifier & e->modifiers())) + { + + if (m_pressed_row > m_anchor_row) + { + //int upper_selected = m_model->firstSelectedUpper(m_anchor_row); + //if (INVALID_ROW != upper_selected) + //{ + /*for (int j = upper_selected;j < m_anchor_row;j++) + { + m_model->setSelected(j, false); + }*/ + m_model->clearSelection(); + for (int j = m_anchor_row;j <= m_pressed_row;j++) + { + m_model->setSelected(j, true); + } + //} + } + else + { + m_model->clearSelection(); + for (int j = m_anchor_row;j >= m_pressed_row;j--) + { + m_model->setSelected(j, true); + } + } + + /* + int upper_selected = m_model->firstSelectedUpper(row); + int lower_selected = m_model->firstSelectedLower(row); + if (INVALID_ROW != upper_selected) + { + for (int j = upper_selected;j <= row;j++) + { + m_model->setSelected(j, true); + } + } + else if (INVALID_ROW != lower_selected) + { + for (int j = row;j <= lower_selected;j++) + { + m_model->setSelected(j, true); + } + } + else + m_model->setSelected(row, true); + */ + } + else + { + if (!m_model->isSelected(row) || (Qt::ControlModifier & e->modifiers())) + m_model->setSelected(row, !m_model->isSelected(row)); + } + + if (m_model->getSelection(m_pressed_row).count() == 1) + m_anchor_row = m_pressed_row; + //qWarning("m_anchor_row: %d",m_anchor_row); + + update(); + } + QWidget::mousePressEvent(e); +} + +void ListWidget::resizeEvent(QResizeEvent *e) +{ + m_rows = (e->size().height() - 10) / m_metrics->ascent (); + + m_scroll = TRUE; + + updateList(); + QWidget::resizeEvent(e); +} + +void ListWidget::wheelEvent (QWheelEvent *e) +{ + if (m_model->count() <= m_rows) + return; + if ((m_first == 0 && e->delta() > 0) || + ((m_first == m_model->count() - m_rows) && e->delta() < 0)) + return; + m_first -= e->delta()/40; //40*3 TODO: add step to config + if (m_first < 0) + m_first = 0; + + if (m_first > m_model->count() - m_rows) + m_first = m_model->count() - m_rows; + + m_scroll = FALSE; + updateList(); +} + +void ListWidget::updateList() +{ + if (m_model->count() < (m_rows+m_first+1) && m_rows< m_model->count()) + { + m_first = m_model->count() - m_rows; + } + if (m_model->count() < m_rows + 1) + { + m_first = 0; + emit positionChanged(0,0); + } + else + { + //int pos = m_first*99/(m_model->count() - m_rows); + //emit positionChanged(pos); + emit positionChanged(m_first, m_model->count() - m_rows); + } + if (m_model->count() <= m_first) + { + m_first = 0; + emit positionChanged(0, qMax(0, m_model->count() - m_rows)); + } + + m_titles = m_model->getTitles(m_first, m_rows ); + m_times = m_model->getTimes(m_first, m_rows ); + m_scroll = FALSE; + //add numbers + for (int i = 0; i < m_titles.size(); ++i) + { + QString title = m_titles.at(i); + m_titles.replace(i, title.prepend(QString("%1").arg(m_first+i+1)+". ")); + + } + if (m_model->currentItem()) + { + TextScroller::getPointer()->setText("*** "+m_model->currentItem()->title()); + parentWidget()->parentWidget()->setWindowTitle(m_model->currentItem()->title()); + } + cut(); + update(); +} + +void ListWidget::setModel(PlayListModel *model) +{ + m_model = model; + connect (m_model, SIGNAL(listChanged()), SLOT(updateList())); + connect (m_model, SIGNAL(currentChanged()), SLOT(recenterCurrent())); + updateList(); +} + +void ListWidget::scroll(int sc) +{ + if (m_model->count() <= m_rows) + return; + m_first = sc; //*(m_model->count() - m_rows)/99; + m_scroll = TRUE; + updateList(); +} + +void ListWidget::cut() +{ + bool cut; + for (int i=0; iisQueued(m_model->item(i + m_first))) + { + int index = m_model->queuedIndex(m_model->item(m_first + i)); + QString queue_string = "|"+QString::number(index)+"|"; + queue_number_space = m_metrics->width(queue_string); + } + while ( m_metrics->width(m_titles.at(i)) > (this->width() - 54 - queue_number_space)) + { + cut = TRUE; + name = m_titles.at(i); + m_titles.replace(i, name.left(name.length()-1) ); + } + if (cut) + { + m_titles.replace(i, name.left(name.length()-3).trimmed()+"..."); + + } + } +} + +void ListWidget::updateSkin() +{ + loadColors(); + update(); +} + +void ListWidget::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasFormat("text/uri-list")) + event->acceptProposedAction(); +} + + +void ListWidget::dropEvent(QDropEvent *event) +{ + if (event->mimeData()->hasUrls()) + { + QList list_urls = event->mimeData()->urls(); + event->acceptProposedAction(); + QApplication::restoreOverrideCursor(); + + foreach(QUrl u,list_urls) + { + QString add_string = u.toString(QUrl::RemoveScheme); + if (!add_string.isEmpty()) + processFileInfo(QFileInfo(add_string)); + } + } + +} + +void ListWidget::processFileInfo(const QFileInfo& info) +{ + if (info.isDir()) + { + m_model->addDirectory(info.absoluteFilePath()); + } + else + { + m_model->addFile(info.absoluteFilePath()); + } +} + +void ListWidget::mouseMoveEvent(QMouseEvent *e) +{ + m_scroll = true; + if (m_prev_y > e->y()) + m_scroll_direction = TOP; + else if (m_prev_y < e->y()) + m_scroll_direction = DOWN; + else + m_scroll_direction = NONE; + + int row = rowAt(e->y()); + + if (INVALID_ROW != row) + { + SimpleSelection sel = m_model->getSelection(m_pressed_row); + if ((sel.m_top == 0 && m_scroll_direction == TOP) && sel.count() > 1 || + (sel.m_bottom == m_model->count() - 1 && m_scroll_direction == DOWN && sel.count() > 1) + ) + return; + + if (row + 1 == m_first + m_rows && m_scroll_direction == DOWN) + (m_first + m_rows < m_model->count() ) ? m_first ++ : m_first; + else if (row == m_first && m_scroll_direction == TOP) + (m_first > 0) ? m_first -- : 0; + + m_model->moveItems(m_pressed_row,row); + m_prev_y = e->y(); + m_scroll = false; + m_pressed_row = row; + } +} + +void ListWidget::mouseReleaseEvent(QMouseEvent *e) +{ + if (FALSE != m_select_on_release) + { + m_model->clearSelection(); + m_model->setSelected(m_pressed_row,true); + //if(e->modifiers() != Qt::ShiftModifier) + m_anchor_row = m_pressed_row; + m_select_on_release = FALSE; + } + m_pressed_row = INVALID_ROW; + m_scroll_direction = NONE; + QWidget::mouseReleaseEvent(e); +} + +int ListWidget::rowAt( int y) const +{ + for (int i = 0; i < qMin(m_rows, m_model->count() - m_first); ++i ) + { + if ((y >= 2+i*m_metrics->ascent())&&(y < 2+(i+1)*m_metrics->ascent())) + return m_first + i; + } + return INVALID_ROW; +} + + +void ListWidget::contextMenuEvent(QContextMenuEvent * event) +{ + if (menu()) + menu()->exec(event->globalPos()); +} + +void ListWidget::recenterCurrent() +{ + if (!m_scroll) + { + if (m_first + m_rows < m_model->currentRow() + 1) + m_first = qMin(m_model->count() - m_rows, + m_model->currentRow() - m_rows/2 + 1); + else if (m_first > m_model->currentRow()) + m_first = qMax (m_model->currentRow() - m_rows/2 + 1, 0); + } +} + + diff --git a/src/ui/listwidget.h b/src/ui/listwidget.h new file mode 100644 index 000000000..2f20a3bf8 --- /dev/null +++ b/src/ui/listwidget.h @@ -0,0 +1,126 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef LISTWIDGET_H +#define LISTWIDGET_H + +#include +#include +#include + +/** + @author Ilya Kotov +*/ +class QFont; +class QFontMetrics; +class QMenu; +class QAction; + +class PlayList; +class PlayListModel; +class Skin; +class MediaFile; + +class ListWidget : public QWidget +{ + Q_OBJECT +public: + ListWidget(QWidget *parent = 0); + + ~ListWidget(); + + void setModel(PlayListModel *); + void readSettings(); + /*! + * Returns count of currently visible rows. + */ + int visibleRows()const{return m_rows;} + + /*! + * Returns number of first visible row. + */ + int firstVisibleRow()const{return m_first;} + + int getAnchorRow()const{return m_anchor_row;} + + void setAnchorRow(int r){m_anchor_row = r;} + +public slots: + void updateList(); + void scroll(int); //0-99 + void recenterCurrent(); + + QMenu *menu() + { + return m_menu; + }; + +signals: + void selectionChanged(); + void positionChanged(int, int); //current position, maximum value + +protected: + void paintEvent(QPaintEvent *); + void mouseDoubleClickEvent(QMouseEvent *); + void mousePressEvent(QMouseEvent *); + void mouseMoveEvent(QMouseEvent *); + void mouseReleaseEvent(QMouseEvent *); + void resizeEvent(QResizeEvent *); + void wheelEvent(QWheelEvent *); + int rowAt(int)const; + void dragEnterEvent(QDragEnterEvent *event); + void dropEvent(QDropEvent *event); + void contextMenuEvent ( QContextMenuEvent * event ); + +private slots: + void updateSkin(); + +private: + void cut(); + void loadColors(); + void processFileInfo(const QFileInfo&); + bool m_update; + bool m_scroll; + int m_pressed_row; + QMenu *m_menu; + PlayListModel *m_model; + int m_rows, m_first; + QList m_titles; + QList m_times; + PlayList *m_pl; + QFont m_font; + QFontMetrics *m_metrics; + Skin *m_skin; + QColor m_normal, m_current, m_normal_bg, m_selected_bg; + int m_anchor_row; + + enum ScrollDirection + { + NONE = 0,TOP,DOWN + }; + + /*! + * Scroll direction that is preforming in current moment. + */ + ScrollDirection m_scroll_direction; + int m_prev_y; + bool m_select_on_release; +}; + +#endif diff --git a/src/ui/logscale.cpp b/src/ui/logscale.cpp new file mode 100644 index 000000000..921004fd9 --- /dev/null +++ b/src/ui/logscale.cpp @@ -0,0 +1,74 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#include "logscale.h" + +#include +#include + + +LogScale::LogScale(int maxscale, int maxrange) + : indices(0), s(0), r(0) +{ + setMax(maxscale, maxrange); +} + + +LogScale::~LogScale() +{ + if (indices) + delete [] indices; +} + + +void LogScale::setMax(int maxscale, int maxrange) +{ + if (maxscale == 0 || maxrange == 0) + return; + + s = maxscale; + r = maxrange; + + if (indices) + delete [] indices; + + double alpha; + int i, scaled; + double domain = double(maxscale), + range = double(maxrange), + x = 1.0, + dx = 1.0, + y = 0.0, + yy = 0.0, + t = 0.0, + e4 = double(1.0E-8); + + indices = new int[maxrange]; + for (i = 0; i < maxrange; i++) + indices[i] = 0; + + // initialize log scale + while (fabs(dx) > e4) { + t = log((domain + x) / x); + y = (x * t) - range; + yy = t - (domain / (x + domain)); + dx = y / yy; + x -= dx; + } + + alpha = x; + for (i = 1; i < (int) domain; i++) { + scaled = (int) floor(0.5 + (alpha * log((double(i) + alpha) / alpha))); + if (indices[scaled - 1] < i) + indices[scaled - 1] = i; + } +} + + +int LogScale::operator[](int index) +{ + return indices[index]; +} diff --git a/src/ui/logscale.h b/src/ui/logscale.h new file mode 100644 index 000000000..d74d25207 --- /dev/null +++ b/src/ui/logscale.h @@ -0,0 +1,31 @@ +// Copyright (c) 2000-2001 Brad Hughes +// +// Use, modification and distribution is allowed without limitation, +// warranty, or liability of any kind. +// + +#ifndef __logscale_h +#define __logscale_h + + +class LogScale +{ +public: + LogScale(int = 0, int = 0); + ~LogScale(); + + int scale() const { return s; } + int range() const { return r; } + + void setMax(int, int); + + int operator[](int); + + +private: + int *indices; + int s, r; +}; + + +#endif // __logscale_h diff --git a/src/ui/mainvisual.cpp b/src/ui/mainvisual.cpp new file mode 100644 index 000000000..5bdcbf5cb --- /dev/null +++ b/src/ui/mainvisual.cpp @@ -0,0 +1,628 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "skin.h" +#include "fft.h" +#include "inlines.h" +#include "mainvisual.h" + + +MainVisual *MainVisual::pointer = 0; + +MainVisual *MainVisual::getPointer() +{ + if ( !pointer ) + qFatal ( "MainVisual: this object not created!" ); + return pointer; +} + +MainVisual::MainVisual (QWidget *parent) + : Visual (parent), m_vis (0), m_playing (FALSE) +{ + m_draw = TRUE; + m_skin = Skin::getPointer(); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSettings())); + resize(75,20); + m_pixmap = QPixmap (75,20); + m_timer = new QTimer (this); + connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout())); + m_nodes.clear(); + createMenu(); + readSettings(); + pointer = this; +} + +MainVisual::~MainVisual() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + if (m_vis) + { + settings.setValue("Visualization/type",m_vis->name()); + delete m_vis; + m_vis = 0; + } + else + settings.setValue("Visualization/type", "None"); + settings.setValue("Visualization/rate", 1000/m_timer->interval()); + while (!m_nodes.isEmpty()) + delete m_nodes.takeFirst(); +} + +void MainVisual::setVisual (VisualBase *newvis) +{ + m_timer->stop(); + if (m_vis) + delete m_vis; + m_vis = newvis; + if (m_vis) + m_timer->start(); + else + { + m_pixmap.fill (Qt::transparent); + update(); + } +} + +void MainVisual::clear() +{ + while (!m_nodes.isEmpty()) + delete m_nodes.takeFirst(); + if (m_vis) + m_vis->clear(); + update(); +} + +void MainVisual::add ( Buffer *b, unsigned long w, int c, int p ) +{ + if (!m_timer->isActive () || !m_vis) + return; + long len = b->nbytes, cnt; + short *l = 0, *r = 0; + + len /= c; + len /= ( p / 8 ); + if ( len > 512 ) + len = 512; + cnt = len; + + if ( c == 2 ) + { + l = new short[len]; + r = new short[len]; + + if ( p == 8 ) + stereo16_from_stereopcm8 ( l, r, b->data, cnt ); + else if ( p == 16 ) + stereo16_from_stereopcm16 ( l, r, ( short * ) b->data, cnt ); + } + else if ( c == 1 ) + { + l = new short[len]; + + if ( p == 8 ) + mono16_from_monopcm8 ( l, b->data, cnt ); + else if ( p == 16 ) + mono16_from_monopcm16 ( l, ( short * ) b->data, cnt ); + } + else + len = 0; + + m_nodes.append ( new VisualNode ( l, r, len, w ) ); +} + +void MainVisual::timeout() +{ + VisualNode *node = 0; + + if ( /*playing &&*/ output()) + { + //output()->mutex()->lock (); + //long olat = output()->latency(); + //long owrt = output()->written(); + //output()->mutex()->unlock(); + + //long synctime = owrt < olat ? 0 : owrt - olat; + + mutex()->lock (); + VisualNode *prev = 0; + while ((!m_nodes.isEmpty())) + { + node = m_nodes.first(); + /*if ( node->offset > synctime ) + break;*/ + + if ( prev ) + delete prev; + m_nodes.removeFirst(); + + prev = node; + + } + mutex()->unlock(); + node = prev; + } + + if (m_vis) + m_vis->process ( node ); + delete node; + + if ( m_vis ) + { + if (m_draw) + drawBackGround(); + m_draw = FALSE; + m_pixmap = m_bg; + QPainter p(&m_pixmap); + m_vis->draw (&p); + } + else + m_pixmap.fill("Red"); + update(); +} + +void MainVisual::paintEvent ( QPaintEvent * ) +{ + QPainter painter ( this ); + painter.drawPixmap ( 0,0,m_pixmap ); +} + +void MainVisual::hideEvent ( QHideEvent *) +{ + m_timer->stop(); +} + +void MainVisual::showEvent ( QShowEvent *) +{ + if (m_vis) + m_timer->start(); +} + +void MainVisual::mousePressEvent (QMouseEvent *e) +{ + if (e->button() == Qt::RightButton) + m_menu->exec(e->globalPos()); + else + { + if (!m_vis) + setVisual(new mainvisual::Analyzer); + else if (m_vis->name() == "Analyzer") + setVisual(new mainvisual::Scope); + else if (m_vis->name() == "Scope") + setVisual(0); + + QString str = "Off"; + if (m_vis) + str = m_vis->name(); + foreach(QAction *act, m_visModeGroup->actions ()) + if (str == act->data().toString()) + { + act->setChecked(TRUE); + break; + } + } +} + +void MainVisual::drawBackGround() +{ + m_bg = QPixmap (75,20); + QPainter painter(&m_bg); + for (int x = 0; x < 75; x += 2) + { + painter.setPen(m_skin->getVisColor(0)); + painter.drawLine(x + 1, 0, x + 1, 20); + for (int y = 0; y < 20; y +=2) + { + painter.setPen(m_skin->getVisColor(0)); + painter.drawPoint(x,y); + painter.setPen(m_skin->getVisColor(1)); + painter.drawPoint(x,y + 1); + } + } +} + +void MainVisual::updateSettings() +{ + drawBackGround(); + m_pixmap = m_bg; + update(); + QAction *act = m_fpsGroup->checkedAction (); + if (act) + m_timer->setInterval (1000/act->data().toInt()); + else + m_timer->setInterval (40); + + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + act = m_peaksFalloffGroup->checkedAction (); + if (act) + settings.setValue("Visualization/peaks_falloff", act->data().toInt()); + else + settings.setValue("Visualization/peaks_falloff", 3); + + act = m_analyzerFalloffGroup->checkedAction (); + if (act) + settings.setValue("Visualization/analyzer_falloff", act->data().toInt()); + else + settings.setValue("Visualization/analyzer_falloff", 3); + + settings.setValue("Visualization/show_peaks", m_peaksAction->isChecked()); + + act = m_analyzerModeGroup->checkedAction(); + if (act) + settings.setValue("Visualization/analyzer_mode", act->data().toInt()); + else + settings.setValue("Visualization/analyzer_mode", 0); + + act = m_analyzerTypeGroup->checkedAction(); + if (act) + settings.setValue("Visualization/analyzer_type", act->data().toInt()); + else + settings.setValue("Visualization/analyzer_type", 1); + + act = m_visModeGroup->checkedAction (); + QString visName; + if (act) + visName = act->data().toString(); + else + visName == "Off"; + + if (visName == "Analyzer") + setVisual(new mainvisual::Analyzer); + else if (visName == "Scope") + setVisual(new mainvisual::Scope); + else + setVisual(0); + +} + +void MainVisual::createMenu() +{ + m_menu = new QMenu (this); + connect(m_menu, SIGNAL(triggered (QAction *)),SLOT(updateSettings())); + QMenu *visMode = m_menu->addMenu(tr("Visualization Mode")); + m_visModeGroup = new QActionGroup(this); + m_visModeGroup->setExclusive(TRUE); + m_visModeGroup->addAction(tr("Analyzer"))->setData("Analyzer"); + m_visModeGroup->addAction(tr("Scope"))->setData("Scope"); + m_visModeGroup->addAction(tr("Off"))->setData("Off"); + foreach(QAction *act, m_visModeGroup->actions ()) + { + act->setCheckable(TRUE); + visMode->addAction(act); + } + + QMenu *analyzerMode = m_menu->addMenu(tr("Analyzer Mode")); + m_analyzerModeGroup = new QActionGroup(this); + m_analyzerTypeGroup = new QActionGroup(this); + m_analyzerModeGroup->addAction(tr("Normal"))->setData(0); + m_analyzerModeGroup->addAction(tr("Fire"))->setData(1); + m_analyzerModeGroup->addAction(tr("Vertical Lines"))->setData(2); + m_analyzerTypeGroup->addAction(tr("Lines"))->setData(0); + m_analyzerTypeGroup->addAction(tr("Bars"))->setData(1); + foreach(QAction *act, m_analyzerModeGroup->actions ()) + { + act->setCheckable(TRUE); + analyzerMode->addAction(act); + } + analyzerMode->addSeparator (); + foreach(QAction *act, m_analyzerTypeGroup->actions ()) + { + act->setCheckable(TRUE); + analyzerMode->addAction(act); + } + analyzerMode->addSeparator (); + m_peaksAction = analyzerMode->addAction(tr("Peaks")); + m_peaksAction->setCheckable(TRUE); + + + QMenu *refreshRate = m_menu->addMenu(tr("Refresh Rate")); + m_fpsGroup = new QActionGroup(this); + m_fpsGroup->setExclusive(TRUE); + m_fpsGroup->addAction(tr("50 fps"))->setData(50); + m_fpsGroup->addAction(tr("25 fps"))->setData(25); + m_fpsGroup->addAction(tr("10 fps"))->setData(10); + m_fpsGroup->addAction(tr("5 fps"))->setData(5); + foreach(QAction *act, m_fpsGroup->actions ()) + { + act->setCheckable(TRUE); + refreshRate->addAction(act); + } + + QMenu *analyzerFalloff = m_menu->addMenu(tr("Analyzer Falloff")); + m_analyzerFalloffGroup = new QActionGroup(this); + m_analyzerFalloffGroup->setExclusive(TRUE); + m_analyzerFalloffGroup->addAction(tr("Slowest"))->setData(1); + m_analyzerFalloffGroup->addAction(tr("Slow"))->setData(2); + m_analyzerFalloffGroup->addAction(tr("Medium"))->setData(3); + m_analyzerFalloffGroup->addAction(tr("Fast"))->setData(4); + m_analyzerFalloffGroup->addAction(tr("Fastest"))->setData(5); + foreach(QAction *act, m_analyzerFalloffGroup->actions ()) + { + act->setCheckable(TRUE); + analyzerFalloff->addAction(act); + } + + QMenu *peaksFalloff = m_menu->addMenu(tr("Peaks Falloff")); + m_peaksFalloffGroup = new QActionGroup(this); + m_peaksFalloffGroup->setExclusive(TRUE); + m_peaksFalloffGroup->addAction(tr("Slowest"))->setData(1); + m_peaksFalloffGroup->addAction(tr("Slow"))->setData(2); + m_peaksFalloffGroup->addAction(tr("Medium"))->setData(3); + m_peaksFalloffGroup->addAction(tr("Fast"))->setData(4); + m_peaksFalloffGroup->addAction(tr("Fastest"))->setData(5); + foreach(QAction *act, m_peaksFalloffGroup->actions ()) + { + act->setCheckable(TRUE); + peaksFalloff->addAction(act); + } + update(); +} + + +void MainVisual::readSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + + QString name = settings.value("Visualization/type","Analyzer").toString(); + m_visModeGroup->actions ()[0]->setChecked(TRUE); + foreach(QAction *act, m_visModeGroup->actions ()) + if (name == act->data().toString()) + act->setChecked(TRUE); + + m_peaksAction->setChecked( + settings.value("Visualization/show_peaks", TRUE).toBool()); + + int fps = settings.value("Visualization/rate", 25).toInt(); + m_fpsGroup->actions ()[1]->setChecked(TRUE); + foreach(QAction *act, m_fpsGroup->actions ()) + if (fps == act->data().toInt()) + act->setChecked(TRUE); + + int mode = settings.value("Visualization/analyzer_mode", 0).toInt(); + m_analyzerModeGroup->actions ()[0]->setChecked(TRUE); + foreach(QAction *act, m_analyzerModeGroup->actions ()) + if (mode == act->data().toInt()) + act->setChecked(TRUE); + + int type = settings.value("Visualization/analyzer_type", 1).toInt(); + m_analyzerTypeGroup->actions ()[1]->setChecked(TRUE); + foreach(QAction *act, m_analyzerTypeGroup->actions ()) + if (type == act->data().toInt()) + act->setChecked(TRUE); + + int speed = settings.value("Visualization/peaks_falloff", 3).toInt(); + m_peaksFalloffGroup->actions ()[2]->setChecked(TRUE); + foreach(QAction *act, m_peaksFalloffGroup->actions ()) + if (speed == act->data().toInt()) + act->setChecked(TRUE); + + speed = settings.value("Visualization/analyzer_falloff", 3).toInt(); + m_analyzerFalloffGroup->actions ()[2]->setChecked(TRUE); + foreach(QAction *act, m_analyzerFalloffGroup->actions ()) + if (speed == act->data().toInt()) + act->setChecked(TRUE); + + updateSettings(); +} + +using namespace mainvisual; + +Analyzer::Analyzer() + : m_analyzerBarWidth ( 4 ), m_fps ( 20 ) +{ + m_size = QSize(75,20); + clear(); + m_skin = Skin::getPointer(); + + double peaks_speed[] = { 0.05, 0.1, 0.2, 0.4, 0.8 }; + double analyzer_speed[] = { 1.2, 1.8, 2.2, 2.8, 2.4 }; + + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + m_peaks_falloff = + peaks_speed[settings.value("Visualization/peaks_falloff", 3).toInt()-1]; + m_analyzer_falloff = + analyzer_speed[settings.value("Visualization/analyzer_falloff", 3).toInt()-1]; + m_show_peaks = settings.value("Visualization/show_peaks", TRUE).toBool(); + + m_lines = settings.value("Visualization/analyzer_type", 1).toInt() == 0; + m_mode = settings.value("Visualization/analyzer_mode", 0).toInt(); +} + +Analyzer::~Analyzer() +{} + +void Analyzer::clear() +{ + for ( int i = 0; i< 75; ++i ) + { + m_intern_vis_data[i] = 0; + m_peaks[i] = 0; + } +} + +bool Analyzer::process ( VisualNode *node ) +{ + static fft_state *state = 0; + if ( !state ) + state = fft_init(); + short dest[256]; + + const int xscale_long[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 61, 66, 71, 76, 81, 87, 93, 100, 107, + 114, 122, 131, 140, 150, 161, 172, 184, 255 + }; + + const int xscale_short[] = + { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 11, 15, 20, 27, + 36, 47, 62, 82, 107, 141, 184, 255 + }; + + if ( node ) + { + //i = node->length; + calc_freq ( dest, node->left ); + } + else + return FALSE; + const double y_scale = 3.60673760222; /* 20.0 / log(256) */ + int max = m_lines ? 75 : 19, y, j; + + for ( int i = 0; i < max; i++ ) + { + if (m_lines) + for ( j = xscale_long[i], y = 0; j < xscale_long[i + 1]; j++ ) + { + if ( dest[j] > y ) + y = dest[j]; + } + else + for ( j = xscale_short[i], y = 0; j < xscale_short[i + 1]; j++ ) + { + if ( dest[j] > y ) + y = dest[j]; + } + y >>= 7; + int magnitude = 0; + if ( y != 0 ) + { + magnitude = int(log (y) * y_scale); + if ( magnitude > 15 ) + magnitude = 15; + if ( magnitude < 0 ) + magnitude = 0; + } + + m_intern_vis_data[i] -= m_analyzer_falloff; + m_intern_vis_data[i] = magnitude > m_intern_vis_data[i] + ? magnitude : m_intern_vis_data[i]; + if (m_show_peaks) + { + m_peaks[i] -= m_peaks_falloff; + m_peaks[i] = magnitude > m_peaks[i] + ? magnitude : m_peaks[i]; + } + } + return TRUE; +} + +void Analyzer::draw ( QPainter *p) +{ + if (m_lines) + for ( int j = 0; j < 75; ++j ) + { + for ( int i = 0; i <= m_intern_vis_data[j]; ++i ) + { + if (m_mode == 0) + p->setPen (m_skin->getVisColor (18-i)); + else if (m_mode == 1) + p->setPen (m_skin->getVisColor (3+(int(m_intern_vis_data[j])-i))); + else + p->setPen (m_skin->getVisColor (18-int(m_intern_vis_data[j]))); + p->drawPoint (j, m_size.height()-i); + } + p->setPen (m_skin->getVisColor (23)); + if (m_show_peaks) + p->drawPoint (j, m_size.height()-int(m_peaks[j])); + } + else + for (int j = 0; j < 19; ++j) + { + for (int i = 0; i <= m_intern_vis_data[j]; ++i) + { + if (m_mode == 0) + p->setPen (m_skin->getVisColor (18-i)); + else if (m_mode == 1) + p->setPen (m_skin->getVisColor (3+(int(m_intern_vis_data[j])-i))); + else + p->setPen (m_skin->getVisColor (18-int(m_intern_vis_data[j]))); + p->drawLine (j*4,m_size.height()-i, (j+1)*4-2,m_size.height()-i); + } + p->setPen (m_skin->getVisColor (23)); + if (m_show_peaks) + p->drawLine (j*4,m_size.height()-int(m_peaks[j]), + (j+1) *4-2,m_size.height()-int(m_peaks[j])); + } +} + +Scope::Scope() +{ + clear(); + m_skin = Skin::getPointer(); +} + +void Scope::clear() +{ + for (int i = 0; i< 75; ++i) + m_intern_vis_data[i] = 7; +} + +Scope::~Scope() +{} + +bool Scope::process(VisualNode *node) +{ + if (!node) + return FALSE; + + int step = (node->length << 8)/74; + int pos = 0; + + for (int i = 0; i < 75; ++i) + { + pos += step; + m_intern_vis_data[i] = (node->left[pos >> 8] >> 12); + + if (m_intern_vis_data[i] > 5) + m_intern_vis_data[i] = 5; + else if (m_intern_vis_data[i] < -5) + m_intern_vis_data[i] = -5; + } + return TRUE; +} + +void Scope::draw(QPainter *p) +{ + for ( int i = 0; i<73; ++i ) + { + int h1 = 10 - m_intern_vis_data[i]; + int h2 = 10 - m_intern_vis_data[i+1]; + if (h1 > h2) + qSwap(h1, h2); + p->setPen (m_skin->getVisColor(19 + (10 - h2)/2 )); + p->drawLine(i, h1, i, h2); + } + for ( int i = 0; i< 75; ++i ) + m_intern_vis_data[i] = 0; +} diff --git a/src/ui/mainvisual.h b/src/ui/mainvisual.h new file mode 100644 index 000000000..5c5b76256 --- /dev/null +++ b/src/ui/mainvisual.h @@ -0,0 +1,172 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef MAINVISUAL_H +#define MAINVISUAL_H + +#include +#include +#include +#include + +#include "logscale.h" + +class QSettings; +class QTimer; +class QMenu; +class QActionGroup; + +class Buffer; + + +class VisualNode +{ +public: + VisualNode(short *l, short *r, unsigned long n, unsigned long o) + : left(l), right(r), length(n), offset(o) + { + // left and right are allocated and then passed to this class + // the code that allocated left and right should give up all ownership + } + + ~VisualNode() + { + delete [] left; + delete [] right; + } + + short *left, *right; + long length, offset; +}; + +class VisualBase +{ +public: + virtual ~VisualBase() + {}; + virtual void clear() = 0; + virtual bool process(VisualNode *node) = 0; + virtual void draw(QPainter *) = 0; + virtual const QString name() = 0; +}; + +class Skin; + +class MainVisual : public Visual +{ + Q_OBJECT + +public: + MainVisual( QWidget *parent = 0); + virtual ~MainVisual(); + + static MainVisual *getPointer(); + + void setVisual( VisualBase *newvis ); + + void add(Buffer *, unsigned long, int, int); + void clear(); + void paintEvent(QPaintEvent *); + +protected: + virtual void hideEvent (QHideEvent *); + virtual void showEvent (QShowEvent *); + virtual void mousePressEvent (QMouseEvent *); + +public slots: + void timeout(); + +private slots: + void updateSettings(); + +private: + void drawBackGround(); + void createMenu(); + void readSettings(); + static MainVisual *pointer; + VisualBase *m_vis; + QPixmap m_pixmap; + QPixmap m_bg; + QList m_nodes; + QTimer *m_timer; + bool m_playing; + bool m_draw; + Skin *m_skin; + //menu and actions + QMenu *m_menu; + //action groups + QActionGroup *m_visModeGroup; + QActionGroup *m_fpsGroup; + QActionGroup *m_peaksFalloffGroup; + QActionGroup *m_analyzerFalloffGroup; + QActionGroup *m_analyzerModeGroup; + QActionGroup *m_analyzerTypeGroup; + QAction *m_peaksAction; +}; + +namespace mainvisual +{ +class Analyzer : public VisualBase +{ +public: + Analyzer(); + virtual ~Analyzer(); + + void clear(); + bool process(VisualNode *node); + void draw(QPainter *p); + const QString name() + { + return "Analyzer"; + }; + +private: + QSize m_size; + int m_analyzerBarWidth, m_fps; + double m_intern_vis_data[75]; + double m_peaks[75]; + double m_peaks_falloff; + double m_analyzer_falloff; + bool m_show_peaks; + bool m_lines; + int m_mode; + Skin *m_skin; +}; + +class Scope : public VisualBase +{ +public: + Scope(); + virtual ~Scope(); + + void clear(); + bool process(VisualNode *node); + void draw(QPainter *p); + const QString name() + { + return "Scope"; + }; + +private: + int m_intern_vis_data[75]; + Skin *m_skin; +}; +} + +#endif diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp new file mode 100644 index 000000000..d81dbce3b --- /dev/null +++ b/src/ui/mainwindow.cpp @@ -0,0 +1,848 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "textscroller.h" +#include "mainwindow.h" +#include "constants.h" +#include "fileloader.h" +#include "skin.h" +#include "playlist.h" +#include "playlistmodel.h" +#include "configdialog.h" +#include "dock.h" +#include "eqwidget.h" +#include "mainvisual.h" +#include "playlistformat.h" +#include "jumptotrackdialog.h" +#include "aboutdialog.h" +#include +#include "filedialog.h" +#include "listwidget.h" +#include "visualmenu.h" +#include "commandlineoption.h" + +#define KEY_OFFSET 10 + +MainWindow::MainWindow(const QStringList& args,CommandLineOptionManager* option_manager, QWidget *parent) + : QMainWindow(parent) +{ + m_vis = 0; + seeking = FALSE; + m_update = FALSE; + m_paused = FALSE; + m_elapsed = 0; + m_option_manager = option_manager; + + setWindowIcon( QIcon(":/qmmp.xpm") ); + + m_skin = new Skin(this); + Dock *dock = new Dock(this); + dock->setMainWidget(this); + + setWindowFlags(Qt::FramelessWindowHint); + setFixedSize (275,116); + + display = new MainDisplay(this); + setCentralWidget(display); + display->show(); + display->setFocus (); + + m_playlistName = tr("Default"); + + m_playlist = new PlayList(this); + + connect (m_playlist,SIGNAL(next()),SLOT(next())); + connect (m_playlist,SIGNAL(prev()),SLOT(previous())); + connect (m_playlist,SIGNAL(play()),SLOT(play())); + connect (m_playlist,SIGNAL(pause()),SLOT(pause())); + connect (m_playlist,SIGNAL(stop()),SLOT(stop())); + connect (m_playlist,SIGNAL(eject()),SLOT(addFile())); + + connect (m_playlist,SIGNAL(newPlaylist()),SLOT(newPlaylist())); + connect (m_playlist,SIGNAL(loadPlaylist()),SLOT(loadPlaylist())); + connect (m_playlist,SIGNAL(savePlaylist()),SLOT(savePlaylist())); + + m_playListModel = new PlayListModel(this); + + connect(display,SIGNAL(shuffleToggled(bool)),m_playListModel,SLOT(prepareForShufflePlaying(bool))); + connect(display,SIGNAL(repeatableToggled(bool)),m_playListModel,SLOT(prepareForRepeatablePlaying(bool))); + + dock->addWidget(m_playlist); + + m_equalizer = new EqWidget(this); + dock->addWidget(m_equalizer); + connect(m_equalizer, SIGNAL(valueChanged()), SLOT(updateEQ())); + + m_playlist->setModel(m_playListModel); + + m_jumpDialog = new JumpToTrackDialog(this); + m_jumpDialog->setModel(m_playListModel); + connect(m_jumpDialog,SIGNAL(playRequest()),this,SLOT(play())); + m_jumpDialog->hide(); + + createActions(); + + m_core = new SoundCore(this); + m_titlebar = new TitleBar(this); + m_titlebar->move(0,0); + m_titlebar->show(); + m_titlebar->setActive(TRUE); + + readSettings(); + dock->updateDock(); + + display->setEQ(m_equalizer); + display->setPL(m_playlist); + + m_vis = MainVisual::getPointer(); + + m_core->addVisualization(m_vis); + m_core->showVisualization(this); + + connect(m_core, SIGNAL(outputStateChanged(const OutputState&)), + SLOT(showOutputState(const OutputState&))); + connect(m_core, SIGNAL(decoderStateChanged(const DecoderState&)), + SLOT(showDecoderState(const DecoderState&))); + connect(m_core, SIGNAL(titleChanged(const QString&)), + SLOT(changeTitle(const QString&))); + + connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); + updateEQ(); + updateSkin(); + + FileDialog::registerBuiltinFactories(); + FileDialog::registerExternalFactories(); + + m_generalHandler = new GeneralHandler(this); + connect(m_generalHandler, SIGNAL(playCalled()), SLOT(play())); + connect(m_generalHandler, SIGNAL(nextCalled()), SLOT(next())); + connect(m_generalHandler, SIGNAL(previousCalled()), SLOT(previous())); + connect(m_generalHandler, SIGNAL(stopCalled()), SLOT(stop())); + connect(m_generalHandler, SIGNAL(pauseCalled()), SLOT(pause())); + connect(m_generalHandler, SIGNAL(toggleVisibilityCalled()), SLOT(toggleVisibility())); + connect(m_generalHandler, SIGNAL(exitCalled()), SLOT(close())); + + m_playListModel->readSettings(); + char buf[PATH_MAX + 1]; + QString cwd = QString::fromLocal8Bit(getcwd(buf,PATH_MAX)); + processCommandArgs(args,cwd); +} + + +MainWindow::~MainWindow() +{ + stop(); +} + +void MainWindow::play() +{ + m_playListModel->doCurrentVisibleRequest(); + + if (m_core->isPaused()) + { + pause(); + return; + } + stop(); + if (m_playListModel->count() == 0) + return; + + m_equalizer->loadPreset(m_playListModel->currentItem()->fileName()); + m_playListModel->currentItem()->updateTags(); + m_playlist->listWidget()->updateList(); + QString s = m_playListModel->currentItem()->path(); + if (s.isEmpty()) + return; + if (m_core->play(s)) + { + display->setTime(0); + display->setMaxTime(m_core->length()); + } + else + { + //find out the reason why the playback failed + switch ((int) m_core->error()) + { + case SoundCore::OutputError: + { + stop(); + return; //unrecovable error in output, so abort playing + } + case SoundCore::DecoderError: + { + //error in decoder, so we should try to play next song + qApp->processEvents(); + if (!m_playListModel->isEmptyQueue()) + { + m_playListModel->setCurrentToQueued(); + } + else if (!m_playListModel->next()) + { + stop(); + display->hideTimeDisplay(); + return; + } + m_playlist->update(); + play(); + break; + } + } + } +} + +void MainWindow::replay() +{ + stop(); + play(); +} + +void MainWindow::seek(int pos) +{ + if (!seeking) + m_core->seek(pos); +} + + +void MainWindow::forward() +{ + seek(m_elapsed + KEY_OFFSET); +} + +void MainWindow::backward() +{ + seek(qMax(0,m_elapsed - KEY_OFFSET)); +} + +void MainWindow::setVolume(int volume, int balance) +{ + m_core->setVolume(volume-qMax(balance,0)*volume/100, + volume+qMin(balance,0)*volume/100); +} + +void MainWindow::pause(void) +{ + m_core->pause(); +} + +void MainWindow::stop() +{ + display->setTime(0); + m_core->stop(); +} +void MainWindow::next() +{ + if (!m_playListModel->isEmptyQueue()) + { + m_playListModel->setCurrentToQueued(); + } + else if (!m_playListModel->next()) + { + stop(); + display->hideTimeDisplay(); + return; + } + m_playlist->update(); + if (m_core->isInitialized()) + { + stop(); + m_elapsed = 0; + play(); + } + else + display->hideTimeDisplay(); +} +void MainWindow::previous() +{ + if (!m_playListModel->previous()) + { + display->hideTimeDisplay(); + return; + } + + m_playlist->update(); + if (m_core->isInitialized()) + { + stop(); + play(); + } + else + display->hideTimeDisplay(); +} + +void MainWindow::updateEQ() +{ + int b[10]; + for (int i=0; i<10; ++i) + b[i] = m_equalizer->gain(i); + m_core->setEQ(b, m_equalizer->preamp()); + m_core->setEQEnabled(m_equalizer->isEQEnabled()); +} + +void MainWindow::showOutputState(const OutputState &st) + +{ + if (seeking) + return; + + display->setInfo(st); + m_playlist->setInfo(st, m_core->length(), m_playListModel->totalLength()); + m_titlebar->setInfo(st); + m_equalizer->setInfo(st); + switch ((int) st.type()) + { + case OutputState::Playing: + { + m_generalHandler->setState(General::Playing); + if (m_playListModel->currentItem()) + { + SongInfo info; + FileTag *tag = m_playListModel->currentItem()->tag(); + if (tag && !tag->isEmpty()) + { + info.setValue(SongInfo::TITLE, tag->title()); + info.setValue(SongInfo::ARTIST, tag->artist()); + info.setValue(SongInfo::ALBUM, tag->album()); + info.setValue(SongInfo::COMMENT, tag->comment()); + info.setValue(SongInfo::GENRE, tag->genre()); + info.setValue(SongInfo::YEAR, tag->year()); + info.setValue(SongInfo::TRACK, tag->track()); + info.setValue(SongInfo::LENGTH, tag->length()); + } + else + info.setValue(SongInfo::TITLE, m_playlist->currentItem()->title()); + info.setValue(SongInfo::STREAM, + m_playlist->currentItem()->path().startsWith("http://")); + m_generalHandler->setSongInfo(info); + } + break; + } + case OutputState::Paused: + { + m_generalHandler->setState(General::Paused); + break; + } + case OutputState::Stopped: + { + m_generalHandler->setState(General::Stopped); + break; + } + case OutputState::Info: + { + m_elapsed = st.elapsedSeconds(); + } + } + +} +void MainWindow::showDecoderState(const DecoderState &st) +{ + switch ((int) st.type()) + { + case DecoderState::Finished: + { + next(); + break; + } + case DecoderState::Info: + { + qDebug("file info:"); + qDebug("ARTIST = %s", qPrintable(st.tag()->artist())); + qDebug("TITLE = %s", qPrintable(st.tag()->title())); + qDebug("ALBUM = %s", qPrintable(st.tag()->album())); + qDebug("COMMENT = %s", qPrintable(st.tag()->comment())); + qDebug("GENRE = %s", qPrintable(st.tag()->genre())); + qDebug("YEAR = %d", st.tag()->year()); + qDebug("TRACK = %d", st.tag()->track()); + qDebug("LENGTH = %d", st.tag()->length()); + if (m_playlist->currentItem()) + { + if (!st.tag()->isEmpty()) + { + SongInfo info; + info.setValue(SongInfo::TITLE, st.tag()->title()); + info.setValue(SongInfo::ARTIST, st.tag()->artist()); + info.setValue(SongInfo::ALBUM, st.tag()->album()); + info.setValue(SongInfo::COMMENT, st.tag()->comment()); + info.setValue(SongInfo::GENRE, st.tag()->genre()); + info.setValue(SongInfo::YEAR, st.tag()->year()); + info.setValue(SongInfo::TRACK, st.tag()->track()); + info.setValue(SongInfo::LENGTH, st.tag()->length()); + info.setValue(SongInfo::STREAM, + m_playlist->currentItem()->path().startsWith("http://")); + m_generalHandler->setSongInfo(info); + } + m_playlist->currentItem()->updateTags(st.tag()); + m_playlist->listWidget()->updateList(); + } + break; + } + } +} + +void MainWindow::changeTitle(const QString &title) +{ + if (m_playlist->currentItem()) + m_playlist->currentItem()->changeTitle(title); + m_playlist->listWidget()->updateList(); + SongInfo info; + info.setValue(SongInfo::TITLE, title); + info.setValue(SongInfo::STREAM, TRUE); + m_generalHandler->setSongInfo(info); +} + +void MainWindow::closeEvent ( QCloseEvent *) +{ + writeSettings(); + m_playlist->close(); + m_equalizer->close(); + QApplication::quit (); +} + +void MainWindow::addDir() +{ + /* + QString s = QFileDialog::getExistingDirectory( + this, + tr("Choose a directory"), + m_lastDir, + QFileDialog::DontResolveSymlinks | QFileDialog::ShowDirsOnly); + + if (s.isEmpty()) + return; + m_playListModel->addDirectory(s); + m_lastDir = s+"../"; + */ + if (FileDialog::isModal()) + { + qWarning("void MainWindow::addDir()"); + QString s = FileDialog::getExistingDirectory(this,tr("Choose a directory"),m_lastDir); + + if (s.isEmpty()) + return; + m_playListModel->addDirectory(s); + m_lastDir = s+"../"; + } + else + FileDialog::popup(m_playListModel,m_lastDir,FileDialog::AddDirs,Decoder::nameFilters()); +} + +void MainWindow::addFile() +{ + /* + QStringList files = QFileDialog::getOpenFileNames( + this, + tr("Select one or more files to open"), + m_lastDir, + Decoder::filter()); + if (files.isEmpty ()) + return; + + // foreach(QString s, files) + // m_playListModel->load(new MediaFile(s)); + + m_playListModel->addFiles(files); + m_lastDir = files.at(0); + */ + + + if (FileDialog::isModal()) + { + QStringList files = FileDialog::getOpenFileNames( + this, + tr("Select one or more files to open"), + m_lastDir, + Decoder::filter()); + if (files.isEmpty ()) + return; + /* + foreach(QString s, files) + m_playListModel->load(new MediaFile(s)); + */ + m_playListModel->addFiles(files); + m_lastDir = files.at(0); + } + else + FileDialog::popup(m_playListModel,m_lastDir,FileDialog::AddFiles,Decoder::nameFilters()); + +} + +void MainWindow::clear() +{ + m_playListModel->clear(); +} + +void MainWindow::startSeek() +{ + seeking = TRUE; +} + +void MainWindow::endSeek() +{ + seeking = FALSE; +} + +void MainWindow::changeEvent (QEvent * event) +{ + if (event->type() == QEvent::ActivationChange) + { + m_titlebar->setActive(isActiveWindow()); + } +} + +void MainWindow::readSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + if (!m_update) + { + settings.beginGroup("MainWindow"); + //geometry + move(settings.value("pos", QPoint(100, 100)).toPoint()); + //last directory + m_lastDir = settings.value("last_dir","/").toString(); + settings.endGroup(); + show(); + //visibility + m_playlist->setVisible(settings.value("Playlist/visible",TRUE).toBool()); + m_equalizer->setVisible(settings.value("Equalizer/visible",TRUE).toBool()); + bool val = settings.value("Playlist/repeatable",FALSE).toBool(); + + // Repeat/Shuffle + m_playListModel->prepareForRepeatablePlaying(val); + display->setIsRepeatable(val); + val = settings.value("Playlist/shuffle",FALSE).toBool(); + display->setIsShuffle(val); + m_playListModel->prepareForShufflePlaying(val); + + // Playlist name + m_playlistName = settings.value("Playlist/playlist_name","Default").toString(); + + m_update = TRUE; + } +} + +void MainWindow::writeSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("MainWindow"); + //geometry + settings.setValue("pos", this->pos()); + //last directory + settings.setValue("last_dir",m_lastDir); + settings.endGroup(); + + // Repeat/Shuffle + settings.beginGroup("Playlist"); + settings.setValue("repeatable",display->isRepeatable()); + settings.setValue("shuffle",display->isShuffle()); + + // Playlist name + settings.setValue("playlist_name",m_playlistName); + settings.endGroup(); +} + +void MainWindow::showSettings() +{ + m_confDialog = new ConfigDialog(this); + if (m_confDialog->exec() == QDialog::Accepted) + { + readSettings(); + m_playlist->readSettings(); + TextScroller::getPointer()->readSettings(); + m_core->updateConfig(); + m_generalHandler->updateConfig(); + m_visMenu->updateActions(); + } + delete m_confDialog; +} + +void MainWindow::toggleVisibility() +{ + if (isHidden()) + { + show(); + m_playlist->setVisible(display->isPlaylistVisible()); + m_equalizer->setVisible(display->isEqualizerVisible()); + if (isMinimized()) + { + if (isMaximized()) + showMaximized(); + else + showNormal(); + } + raise(); + activateWindow(); + } + else + { + hide(); + if (m_playlist->isVisible()) + m_playlist->hide(); + if (m_equalizer->isVisible()) + m_equalizer->hide(); + } +} + +void MainWindow::createActions() +{ + m_mainMenu = new QMenu(this); + m_mainMenu->addAction(tr("&Play"),this, SLOT(play()), tr("X")); + m_mainMenu->addAction(tr("&Pause"),this, SLOT(pause()), tr("C")); + m_mainMenu->addAction(tr("&Stop"),this, SLOT(stop()), tr("V")); + m_mainMenu->addAction(tr("&Previous"),this, SLOT(previous()), tr("Z")); + m_mainMenu->addAction(tr("&Next"),this, SLOT(next()), tr("B")); + m_mainMenu->addAction(tr("P&lay/Pause"),this, SLOT(playPause()), tr("Space")); + m_mainMenu->addAction(tr("&Queue"),m_playListModel, SLOT(addToQueue()), tr("Q")); + m_mainMenu->addSeparator(); + m_mainMenu->addAction(tr("&Jump To File"),this, SLOT(jumpToFile()), tr("J")); + m_mainMenu->addSeparator(); + m_visMenu = new VisualMenu(this); + m_mainMenu->addMenu(m_visMenu); + + m_mainMenu->addSeparator(); + m_mainMenu->addAction(tr("&Settings"),this, SLOT(showSettings()), tr("Ctrl+P")); + m_mainMenu->addSeparator(); + m_mainMenu->addAction(tr("&About"),this, SLOT(about())); + Dock::getPointer()->addActions(m_mainMenu->actions()); + m_mainMenu->addSeparator(); + m_mainMenu->addAction(tr("&Exit"),this, SLOT(close ()), tr("Ctrl+Q")); + + QAction* forward = new QAction(this); + forward->setShortcut(QKeySequence(Qt::Key_Right)); + connect(forward,SIGNAL(triggered(bool)),this,SLOT(forward())); + QAction* backward = new QAction(this); + backward->setShortcut(QKeySequence(Qt::Key_Left)); + connect(backward,SIGNAL(triggered(bool)),this,SLOT(backward())); + + Dock::getPointer()->addActions( QList() << forward << backward ); + Dock::getPointer()->addActions(m_mainMenu->actions()); +} + + +void MainWindow::about() +{ + AboutDialog dlg(this); + dlg.exec(); +} + +QMenu* MainWindow::menu() +{ + return m_mainMenu; +} + +void MainWindow::updateSkin() +{ + clearMask(); + m_equalizer->clearMask(); + /*qt bug workarround */ + setMask(QRegion(0,0,275,116)); + m_equalizer->setMask(QRegion(0,0,275,116)); + update(); + m_equalizer->update(); + + QRegion region = m_skin->getMWRegion(); + if (!region.isEmpty()) + setMask(region); + + region = m_skin->getPLRegion(); + if (!region.isEmpty()) + m_equalizer->setMask(region); +} + +void MainWindow::newPlaylist() +{ + m_playListModel->clear(); + m_playlistName = tr("Default"); +} + +void MainWindow::loadPlaylist() +{ + QStringList l; + QList p_list = m_playListModel->registeredPlaylistFormats(); + if (!p_list.isEmpty()) + { + foreach(PlaylistFormat* fmt,p_list) + l << fmt->getExtensions(); + + QString mask = tr("Playlist Files")+" (" + l.join(" *.").prepend("*.") + ")"; + if (FileDialog::isModal()) + { + //qWarning("Modal"); + QString f_name = FileDialog::getOpenFileName(this,tr("Open Playlist"),m_lastDir,mask); + if (!f_name.isEmpty()) + { + m_playListModel->loadPlaylist(f_name); + m_playlistName = QFileInfo(f_name).baseName(); + } + m_lastDir = QFileInfo(f_name).absoluteDir().path(); + } + else //FileDialog::popup(m_playListModel,m_lastDir,FileDialog::AddFiles,Decoder::nameFilters()); + // TODO: implement playlist loading with nonmodal dialogs + // For now we'll use default dialog + { + //qWarning("Modal"); + QString f_name = FileDialog::getOpenFileName(this,tr("Open Playlist"),m_lastDir,mask,0,true); + if (!f_name.isEmpty()) + { + m_playListModel->loadPlaylist(f_name); + m_playlistName = QFileInfo(f_name).baseName(); + } + m_lastDir = QFileInfo(f_name).absoluteDir().path(); + } + } + else + { + //qWarning("Non Modal"); + qWarning("Error: There is no registered playlist parsers"); + } +} + +void MainWindow::savePlaylist() +{ + QStringList l; + QList p_list = m_playListModel->registeredPlaylistFormats(); + if (!p_list.isEmpty()) + { + foreach(PlaylistFormat* fmt,p_list) + l << fmt->getExtensions(); + + QString mask = tr("Playlist Files")+" (" + l.join(" *.").prepend("*.") + ")"; + if (FileDialog::isModal()) + { + QString f_name = FileDialog::getSaveFileName(this, tr("Save Playlist"),m_lastDir + "/" + + m_playlistName + "." + l[0],mask); + + if (!f_name.isEmpty()) + { + m_playListModel->savePlaylist(f_name); + m_playlistName = QFileInfo(f_name).baseName(); + } + m_lastDir = QFileInfo(f_name).absoluteDir().path(); + } + else // TODO: implement saving playlists with nonmodal dialogs + // For now we'll use default dialog + { + QString f_name = FileDialog::getSaveFileName(this, tr("Save Playlist"),m_lastDir + "/" + + m_playlistName + "." + l[0],mask,0,true); + + if (!f_name.isEmpty()) + { + m_playListModel->savePlaylist(f_name); + m_playlistName = QFileInfo(f_name).baseName(); + } + m_lastDir = QFileInfo(f_name).absoluteDir().path(); + } + } + else + qWarning("Error: There is no registered playlist parsers"); +} + +void MainWindow::setFileList(const QStringList & l) +{ + if (!m_playListModel->setFileList(l)) + addFile(); +} + +void MainWindow::playPause() +{ + if (m_core->isInitialized()) + pause(); + else + play(); +} + +bool MainWindow::processCommandArgs(const QStringList &slist,const QString& cwd) +{ + if (slist.count() > 0) + { + QString str = slist[0]; + if (str.startsWith("--")) // is it a command? + { + if (m_option_manager->hasOption(str)) + { + m_option_manager->executeCommand(str,this); + } + else + return false; + } + else// maybe it is a list of files or dirs + { + QStringList full_path_list; + foreach(QString s,slist) + { + qWarning(qPrintable(cwd + "/" + s)); + if (s.left(1) == "/") //is it absolute path? + full_path_list << s; + else + full_path_list << cwd + "/" + s; + } + setFileList(full_path_list); + } + } + return true; +} + +void MainWindow::jumpToFile() +{ + if (m_jumpDialog->isHidden()) + { + m_jumpDialog->show(); + m_jumpDialog->refresh(); + } +} + +void MainWindow::handleCloseRequest() +{ + //if (m_hide_on_titlebar_close && m_tray->isVisible()) + /*toggleVisibility(); + else*/ + QApplication::closeAllWindows(); +} + +void MainWindow::addUrl( ) +{ + AddUrlDialog::popup(this,m_playListModel); +} + +SoundCore * MainWindow::soundCore() const +{ + return m_core; +} + +MainDisplay * MainWindow::mainDisplay() const +{ + return display; +} + +void MainWindow::keyPressEvent(QKeyEvent *ke) +{ + QKeyEvent event = QKeyEvent(ke->type(), ke->key(), + ke->modifiers(), ke->text(),ke->isAutoRepeat(), ke->count()); + QApplication::sendEvent(m_playlist,&event); +} diff --git a/src/ui/mainwindow.h b/src/ui/mainwindow.h new file mode 100644 index 000000000..25b2b3b75 --- /dev/null +++ b/src/ui/mainwindow.h @@ -0,0 +1,141 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + + +#include "output.h" +#include "decoder.h" +#include "display.h" +#include "mediafile.h" +#include "decoderfactory.h" +#include "titlebar.h" + +/** + @author Ilya Kotov +*/ +class PlayList; +class PlayListModel; +class ConfigDialog; +class EqWidget; +class MainVisual; +class Skin; +class SoundCore; +class JumpToTrackDialog; +class VisualMenu; +class GeneralHandler; + +class QMenu; +class QKeyEvent; +class CommandLineOptionManager; + + +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + MainWindow(const QStringList& args,CommandLineOptionManager*, QWidget *parent); + + ~MainWindow(); + + PlayList *getPLPointer(){return m_playlist;} + + void seek(int); + QMenu* menu(); + void setVolume(int volume, int balance); + SoundCore* soundCore()const; + MainDisplay* mainDisplay()const; + bool processCommandArgs(const QStringList &list,const QString& cwd); +public slots: + void previous(); + void play(); + void pause(); + void playPause(); + void stop(); + void next(); + void replay(); + void jumpToFile(); + void toggleVisibility(); + + void addDir(); + void addFile(); + void addUrl(); + + void newPlaylist(); + void loadPlaylist(); + void savePlaylist(); + + void setFileList(const QStringList&); + +protected: + virtual void closeEvent ( QCloseEvent *); + virtual void changeEvent ( QEvent * event ); + virtual void keyPressEvent ( QKeyEvent* ); + +private slots: + void showOutputState(const OutputState&); + void showDecoderState(const DecoderState&); + void changeTitle(const QString&); + void clear(); + void startSeek(); + void endSeek(); + void showSettings(); + void updateEQ(); + void updateSkin(); + void forward(); + void backward(); + //void trayActivated(QSystemTrayIcon::ActivationReason); + void about(); + void handleCloseRequest(); + +private: + void readSettings(); + void writeSettings(); + void createActions(); + bool seeking; + SoundCore *m_core; + QMenu *m_mainMenu; + MainDisplay *display; + PlayList *m_playlist; + PlayListModel *m_playListModel; + TitleBar *m_titlebar; + ConfigDialog *m_confDialog; + int m_preamp; + EqWidget *m_equalizer; + MainVisual *m_vis; + QString m_lastDir; + bool m_update; + bool m_showMessage; + int m_messageDelay; + bool m_paused; + bool m_showToolTip; + Skin *m_skin; + QString m_playlistName; + JumpToTrackDialog* m_jumpDialog; + bool m_hide_on_titlebar_close; + int m_elapsed; + VisualMenu *m_visMenu; + CommandLineOptionManager* m_option_manager; + GeneralHandler *m_generalHandler; +}; + +#endif diff --git a/src/ui/mediafile.cpp b/src/ui/mediafile.cpp new file mode 100644 index 000000000..6ffb5514f --- /dev/null +++ b/src/ui/mediafile.cpp @@ -0,0 +1,169 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +#include + +#include "mediafile.h" + +MediaFile::MediaFile(const QString& path) : m_flag(FREE) +{ + m_selected = FALSE; + m_current = FALSE; + m_path = path; + m_tag = 0; + + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + m_use_meta = settings.value ("PlayList/load_metadata", TRUE).toBool(); + //format + m_format = settings.value("PlayList/title_format", "%p - %t").toString(); + if (m_use_meta && !path.startsWith("http://")) + { + m_tag = Decoder::createTag(path); + readMetadata(); + } + else + m_title = m_path.startsWith("http://") ? m_path: m_path.section('/',-1); +} + + +MediaFile::~MediaFile() +{ + if (m_tag) + delete m_tag; +} + +const QString MediaFile::path()const +{ + return m_path; +} +const QString MediaFile::fileName() const +{ + return m_path.section('/',-1); +} + +const QString MediaFile::title() const +{ + return m_title; +} + +int MediaFile::length() const +{ + if (m_tag) + return m_tag->length(); + else + return 0; +} + +void MediaFile::setSelected(bool yes) +{ + m_selected = yes; +} + +bool MediaFile::isSelected() const +{ + return m_selected; +} + +uint MediaFile::year() const +{ + return m_year; +} + +bool MediaFile::isCurrent() +{ + return m_current; +} + +void MediaFile::setCurrent(bool cur) +{ + m_current = cur; +} + +void MediaFile::updateTags(const FileTag *tag) +{ + if (m_tag) + { + delete m_tag; + m_tag = 0; + } + if (!tag->isEmpty()) + m_tag = new FileTag(*tag); + readMetadata(); +} + +void MediaFile::updateTags() +{ + if (m_path.startsWith("http://")) + return; + if (m_tag) + { + delete m_tag; + m_tag = 0; + } + m_tag = Decoder::createTag(m_path); + readMetadata(); +} + +void MediaFile::readMetadata() +{ + if (m_use_meta && m_tag && !m_tag->isEmpty()) + { + m_year = m_tag->year(); + m_title = m_format; + m_title.replace("%p",m_tag->artist()); + m_title.replace("%a",m_tag->album()); + m_title.replace("%t",m_tag->title()); + m_title.replace("%n",QString("%1").arg(m_tag->track())); + m_title.replace("%g",m_tag->genre ()); + m_title.replace("%f",m_path.section('/',-1)); + m_title.replace("%F",m_path); + //m_title.replace("%d",); + m_title.replace("%y",QString("%1").arg(m_tag->year ())); + //m_title.replace("%c",); + } + else + m_title = m_path.startsWith("http://") ? m_path: m_path.section('/',-1); +} + +void MediaFile::changeTitle(const QString &newtitle) +{ + m_title = newtitle; +} + +void MediaFile::setFlag(FLAGS f) +{ + m_flag = f; +} + + +MediaFile::FLAGS MediaFile::flag() const +{ + return m_flag; +} + +FileTag *MediaFile::tag() +{ + if(m_tag && m_tag->isEmpty()) + return 0; + return m_tag; +} + diff --git a/src/ui/mediafile.h b/src/ui/mediafile.h new file mode 100644 index 000000000..1652bf92d --- /dev/null +++ b/src/ui/mediafile.h @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef MEDIAFILE_H +#define MEDIAFILE_H + +#include + +class FileTag; +/** + @author Ilya Kotov +*/ + + +class MediaFile +{ +public: + /*! + * Current state of media file. + * FREE - instance is free and may be deleted + * EDITING - instance is currently busy in some kind of operation(tags editing etc.) + * and can't be deleted at the moment. Set flag SCHEDULED_FOR_DELETION for it + * instead of delete operator call. + */ + enum FLAGS{FREE = 0,EDITING,SCHEDULED_FOR_DELETION}; + + MediaFile() : m_flag(FREE) + {}; + MediaFile(const QString&); + + ~MediaFile(); + + const QString path()const; + const QString title()const; + const QString fileName()const; + uint year()const; + int length()const; + void setSelected(bool); + bool isSelected()const; + bool isCurrent(); + void setCurrent(bool); + void updateTags(const FileTag*); + void updateTags(); + void changeTitle(const QString&); + FLAGS flag()const; + void setFlag(FLAGS); + FileTag *tag(); + +private: + void readMetadata(); + QString m_path; + QString m_title; + uint m_year; + FileTag *m_tag; + bool m_selected; + bool m_current; + bool m_use_meta; + QString m_format; + FLAGS m_flag; + +}; + +#endif diff --git a/src/ui/monostereo.cpp b/src/ui/monostereo.cpp new file mode 100644 index 000000000..659fec7be --- /dev/null +++ b/src/ui/monostereo.cpp @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include + +#include "skin.h" +#include "monostereo.h" + +MonoStereo::MonoStereo ( QWidget *parent ) + : PixmapWidget ( parent ) +{ + m_skin = Skin::getPointer(); + m_pixmap = QPixmap ( 54,12 ); + setChannels ( 0 ); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); +} + + +MonoStereo::~MonoStereo() +{} + +void MonoStereo::setChannels ( int c ) +{ + m_channels = c; + QPainter paint ( &m_pixmap ); + switch ( ( int ) c ) + { + case 0: + { + paint.drawPixmap ( 0,0,m_skin->getMSPart ( Skin::MONO_I ) ); + paint.drawPixmap ( 27,0,m_skin->getMSPart ( Skin::STEREO_I ) ); + break; + } + case 1: + { + paint.drawPixmap ( 0,0,m_skin->getMSPart ( Skin::MONO_A ) ); + paint.drawPixmap ( 27,0,m_skin->getMSPart ( Skin::STEREO_I ) ); + break; + } + } + if ( c > 1 ) + { + paint.drawPixmap ( 0,0,m_skin->getMSPart ( Skin::MONO_I ) ); + paint.drawPixmap ( 27,0,m_skin->getMSPart ( Skin::STEREO_A ) ); + } + setPixmap ( m_pixmap ); +} + +void MonoStereo::updateSkin() +{ + setChannels ( m_channels ); +} diff --git a/src/ui/monostereo.h b/src/ui/monostereo.h new file mode 100644 index 000000000..be1419c5c --- /dev/null +++ b/src/ui/monostereo.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef MONOSTEREO_H +#define MONOSTEREO_H + +#include + +/** + @author Ilya Kotov +*/ +class Skin; + +class MonoStereo : public PixmapWidget +{ +Q_OBJECT +public: + MonoStereo(QWidget *parent = 0); + + ~MonoStereo(); + + void setChannels(int); + +private slots: + void updateSkin(); + +private: + Skin *m_skin; + QPixmap m_pixmap; + int m_channels; + +}; + +#endif diff --git a/src/ui/mp3player.cpp b/src/ui/mp3player.cpp new file mode 100644 index 000000000..cf6b27535 --- /dev/null +++ b/src/ui/mp3player.cpp @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include + +#include "mainwindow.h" +#include "playlist.h" +#include "qmmpstarter.h" + +int main(int argc, char *argv[]) +{ + QApplication a (argc, argv ); + QTranslator translator; + QString locale = QLocale::system().name(); + translator.load(QString(":/qmmp_") + locale); + a.installTranslator(&translator); + + QMMPStarter starter(argc,argv); + Q_UNUSED(starter) + + return a.exec(); +} diff --git a/src/ui/number.cpp b/src/ui/number.cpp new file mode 100644 index 000000000..9f127965e --- /dev/null +++ b/src/ui/number.cpp @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "number.h" +#include "skin.h" + +Number::Number(QWidget *parent) + : PixmapWidget(parent) +{ + m_skin = Skin::getPointer(); + //TODO default value?? + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); +} + + +Number::~Number() +{ +} + +void Number::setValue(int n) +{ + setPixmap(m_skin->getNumber(n)); + m_value = n; +} + +void Number::updateSkin(void) +{ + setValue(m_value); +} diff --git a/src/ui/number.h b/src/ui/number.h new file mode 100644 index 000000000..1c89f71d4 --- /dev/null +++ b/src/ui/number.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef NUMBER_H +#define NUMBER_H + +#include "pixmapwidget.h" + +/** + @author Ilya Kotov +*/ +class Skin; + +class Number : public PixmapWidget +{ +Q_OBJECT +public: + Number(QWidget *parent = 0); + + ~Number(); + + void setValue(int); + +private slots: + void updateSkin(void); + +private: + Skin *m_skin; + int m_value; + +}; + +#endif diff --git a/src/ui/pixmapwidget.cpp b/src/ui/pixmapwidget.cpp new file mode 100644 index 000000000..a0f4ff7fd --- /dev/null +++ b/src/ui/pixmapwidget.cpp @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "pixmapwidget.h" + +PixmapWidget::PixmapWidget(QWidget *parent) + : QWidget(parent) +{} + + +PixmapWidget::~PixmapWidget() +{} + +void PixmapWidget::setPixmap(const QPixmap pixmap) +{ + m_pixmap = pixmap; + resize(m_pixmap.size()); + update(); +} + +void PixmapWidget::paintEvent ( QPaintEvent *) +{ + QPainter paint(this); + paint.drawPixmap(0,0, m_pixmap); +} + diff --git a/src/ui/pixmapwidget.h b/src/ui/pixmapwidget.h new file mode 100644 index 000000000..24d34260e --- /dev/null +++ b/src/ui/pixmapwidget.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef PIXMAPWIDGET_H +#define PIXMAPWIDGET_H + +#include + +/** + @author Ilya Kotov +*/ +class QPixmap; + +class PixmapWidget : public QWidget +{ +Q_OBJECT +public: + PixmapWidget(QWidget *parent = 0); + + ~PixmapWidget(); + + virtual void setPixmap(const QPixmap); + +protected: + void paintEvent ( QPaintEvent * event ); + +private: + QPixmap m_pixmap; + + + +}; + +#endif diff --git a/src/ui/playlist.cpp b/src/ui/playlist.cpp new file mode 100644 index 000000000..282463ef0 --- /dev/null +++ b/src/ui/playlist.cpp @@ -0,0 +1,471 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include "dock.h" +#include "fileloader.h" +#include "playlist.h" +#include "skin.h" +#include "listwidget.h" +#include "button.h" +#include "mediafile.h" +#include "playlistmodel.h" +#include "playlisttitlebar.h" +#include "playlistslider.h" +#include "pixmapwidget.h" +#include "symboldisplay.h" +#include "playlistcontrol.h" +#include "keyboardmanager.h" +#include + +PlayList::PlayList ( QWidget *parent ) + : QWidget ( parent ) +{ + setWindowFlags ( Qt::Dialog | Qt::FramelessWindowHint ); + + m_update = FALSE; + m_resize = FALSE; + m_anchor_row = -1; + + createMenus(); + + + resize ( 275,116 ); + setMinimumSize ( 275,116 ); + setBaseSize ( 275,116 ); + m_listWidget = new ListWidget ( this ); + m_listWidget->show(); + m_listWidget->setGeometry ( 12,20,243,58 ); + + m_plslider = new PlayListSlider ( this ); + m_plslider->show(); + + setSizeIncrement ( 25,29 ); + m_skin = Skin::getPointer(); + + m_buttonAdd = new Button ( this,Skin::PL_BT_ADD,Skin::PL_BT_ADD ); + m_buttonAdd->move ( 11,86 ); + m_buttonSub = new Button ( this,Skin::PL_BT_SUB,Skin::PL_BT_SUB ); + m_buttonSub->move ( 40,86 ); + m_selectButton = new Button ( this,Skin::PL_BT_SEL,Skin::PL_BT_SEL ); + m_selectButton->move ( 70,86 ); + m_sortButton= new Button ( this,Skin::PL_BT_SORT,Skin::PL_BT_SORT ); + m_sortButton->move ( 99,86 ); + m_playlistButton = new Button ( this,Skin::PL_BT_LST,Skin::PL_BT_LST ); + + m_pl_control = new PlaylistControl ( this ); + m_pl_control->move ( 0,0 ); + m_pl_control->show(); + + m_length_totalLength = new SymbolDisplay ( this,14 ); + m_length_totalLength->setAlignment ( Qt::AlignLeft ); + m_length_totalLength -> show(); + + m_current_time = new SymbolDisplay ( this,6 ); + m_current_time->show(); + + m_keyboardManager = new KeyboardManager ( this ); + + connect ( m_listWidget, SIGNAL ( selectionChanged() ), parent, SLOT ( replay() ) ); + + connect ( m_plslider, SIGNAL ( sliderMoved ( int ) ), m_listWidget, SLOT ( scroll ( int ) ) ); + connect ( m_listWidget, SIGNAL ( positionChanged ( int, int ) ), m_plslider, + SLOT ( setPos ( int, int ) ) ); + connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT ( update() ) ); + connect ( m_buttonAdd, SIGNAL ( clicked() ), SLOT ( showAddMenu() ) ); + connect ( m_buttonSub, SIGNAL ( clicked() ), SLOT ( showSubMenu() ) ); + connect ( m_selectButton, SIGNAL ( clicked() ), SLOT ( showSelectMenu() ) ); + connect ( m_sortButton, SIGNAL ( clicked() ), SLOT ( showSortMenu() ) ); + connect ( m_playlistButton, SIGNAL ( clicked() ), SLOT ( showPlaylistMenu() ) ); + + connect ( m_pl_control, SIGNAL ( nextClicked() ), SIGNAL ( next() ) ); + connect ( m_pl_control, SIGNAL ( previousClicked() ), SIGNAL ( prev() ) ); + connect ( m_pl_control, SIGNAL ( playClicked() ), SIGNAL ( play() ) ); + connect ( m_pl_control, SIGNAL ( pauseClicked() ), SIGNAL ( pause() ) ); + connect ( m_pl_control, SIGNAL ( stopClicked() ), SIGNAL ( stop() ) ); + connect ( m_pl_control, SIGNAL ( ejectClicked() ), SIGNAL ( eject() ) ); + m_titleBar = new PlayListTitleBar ( this ); + m_titleBar->move ( 0,0 ); + readSettings(); +} + + +PlayList::~PlayList() +{} + +void PlayList::createMenus() +{ + m_addMenu = new QMenu ( this ); + m_subMenu = new QMenu ( this ); + m_selectMenu = new QMenu ( this ); + m_sortMenu = new QMenu ( this ); + m_playlistMenu = new QMenu ( this ); +} + +void PlayList::createActions() +{ //add menu + QAction *addFileAct = new QAction ( tr ( "&Add File" ),this ); + addFileAct->setShortcut ( tr ( "F" ) ); + m_addMenu->addAction ( addFileAct ); + connect ( addFileAct, SIGNAL ( triggered() ), parent(), SLOT ( addFile () ) ); + m_actions << addFileAct; + + QAction *addDirAct = new QAction ( tr ( "&Add Directory" ),this ); + addDirAct->setShortcut ( tr ( "D" ) ); + m_addMenu->addAction ( addDirAct ); + connect ( addDirAct, SIGNAL ( triggered() ), parent(), SLOT ( addDir () ) ); + m_actions << addDirAct; + + QAction *addUrlAct = new QAction ( tr ( "&Add Url" ),this ); + addUrlAct->setShortcut ( tr ( "U" ) ); + m_addMenu->addAction ( addUrlAct ); + connect ( addUrlAct, SIGNAL ( triggered() ), parent(), SLOT ( addUrl () ) ); + m_actions << addUrlAct; + + //remove menu + QAction *remSelAct = new QAction ( tr ( "&Remove Selected" ),this ); + remSelAct->setShortcut ( tr ( "Del" ) ); + m_subMenu->addAction ( remSelAct ); + connect ( remSelAct, SIGNAL ( triggered() ), + m_playListModel, SLOT ( removeSelected () ) ); + this->addAction ( remSelAct ); + + QAction *remAllAct = new QAction ( tr ( "&Remove All" ),this ); + //remAllAct->setShortcut(tr("D")); FIXME: add correct shortcat + m_subMenu->addAction ( remAllAct ); + connect ( remAllAct, SIGNAL ( triggered() ), m_playListModel, SLOT ( clear () ) ); + m_actions << remAllAct; + + QAction *remUnselAct = new QAction ( tr ( "&Remove Unselected" ),this ); + m_subMenu->addAction ( remUnselAct ); + connect ( remUnselAct, SIGNAL ( triggered() ), + m_playListModel, SLOT ( removeUnselected () ) ); + + //listwidget menu + QAction *detailsAct = new QAction ( tr ( "&View Track Details" ),this ); + detailsAct->setShortcut ( tr ( "Alt+I" ) ); + m_listWidget->menu()->addAction ( detailsAct ); + connect ( detailsAct, SIGNAL ( triggered() ), m_playListModel, SLOT ( showDetails () ) ); + + // sort menu + m_sortMenu->addAction ( detailsAct ); + m_sortMenu->addSeparator(); + + QMenu* sort_mode_menu = new QMenu ( tr ( "Sort List" ),m_sortMenu ); + + QSignalMapper* signalMapper = new QSignalMapper ( this ); + QAction* titleAct = sort_mode_menu->addAction ( tr ( "By Title" ) ); + connect ( titleAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); + signalMapper->setMapping ( titleAct, PlayListModel::TITLE ); + + QAction* nameAct = sort_mode_menu->addAction ( tr ( "By Filename" ) ); + connect ( nameAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); + signalMapper->setMapping ( nameAct, PlayListModel::FILENAME ); + + QAction* pathnameAct = sort_mode_menu->addAction ( tr ( "By Path + Filename" ) ); + connect ( pathnameAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); + signalMapper->setMapping ( pathnameAct, PlayListModel::PATH_AND_FILENAME ); + + QAction* dateAct = sort_mode_menu->addAction ( tr ( "By Date" ) ); + connect ( dateAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); + signalMapper->setMapping ( dateAct, PlayListModel::DATE ); + + connect ( signalMapper, SIGNAL ( mapped ( int ) ), + m_playListModel, SLOT ( sort ( int ) ) ); + + m_sortMenu->addMenu ( sort_mode_menu ); + + sort_mode_menu = new QMenu ( tr ( "Sort Selection" ),m_sortMenu ); + signalMapper = new QSignalMapper ( this ); + titleAct = sort_mode_menu->addAction ( tr ( "By Title" ) ); + connect ( titleAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); + signalMapper->setMapping ( titleAct, PlayListModel::TITLE ); + + nameAct = sort_mode_menu->addAction ( tr ( "By Filename" ) ); + connect ( nameAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); + signalMapper->setMapping ( nameAct, PlayListModel::FILENAME ); + + pathnameAct = sort_mode_menu->addAction ( tr ( "By Path + Filename" ) ); + connect ( pathnameAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); + signalMapper->setMapping ( pathnameAct, PlayListModel::PATH_AND_FILENAME ); + + dateAct = sort_mode_menu->addAction ( tr ( "By Date" ) ); + connect ( dateAct, SIGNAL ( triggered ( bool ) ), signalMapper, SLOT ( map() ) ); + signalMapper->setMapping ( dateAct, PlayListModel::DATE ); + + connect ( signalMapper, SIGNAL ( mapped ( int ) ), + m_playListModel, SLOT ( sortSelection ( int ) ) ); + + m_sortMenu->addMenu ( sort_mode_menu ); + + m_sortMenu->addSeparator(); + m_sortMenu->addAction ( tr ( "Randomize List" ),m_playListModel,SLOT ( randomizeList() ) ); + m_sortMenu->addAction ( tr ( "Reverse List" ),m_playListModel,SLOT ( reverseList() ) ); + + m_listWidget->menu()->addSeparator(); + m_listWidget->menu()->addActions ( m_subMenu->actions() ); + m_actions << detailsAct; + + //select menu + QAction *invSelAct = new QAction ( tr ( "Invert Selection" ),this ); + m_selectMenu->addAction ( invSelAct ); + connect ( invSelAct, SIGNAL ( triggered() ), + m_playListModel, SLOT ( invertSelection () ) ); + + m_selectMenu->addSeparator(); + + QAction *selNoneAct = new QAction ( tr ( "&Select None" ),this ); + //selNoneAct->setShortcut(tr("Ctrl+Shift+A")); + m_selectMenu->addAction ( selNoneAct ); + connect ( selNoneAct, SIGNAL ( triggered() ), + m_playListModel, SLOT ( clearSelection () ) ); + this->addAction ( selNoneAct ); + + QAction *selAllAct = new QAction ( tr ( "&Select All" ),this ); + selAllAct->setShortcut ( tr ( "Ctrl+A" ) ); + m_selectMenu->addAction ( selAllAct ); + connect ( selAllAct, SIGNAL ( triggered() ), + m_playListModel, SLOT ( selectAll () ) ); + this->addAction ( selAllAct ); + +// Playlist Menu + QAction *newListAct = new QAction ( tr ( "&New List" ),this ); + newListAct->setShortcut ( tr ( "Shift+N" ) ); + m_actions << newListAct; + m_playlistMenu->addAction ( newListAct ); + connect ( newListAct, SIGNAL ( triggered() ), this, SIGNAL ( newPlaylist() ) ); + m_playlistMenu->addSeparator(); + + QAction *loadListAct = new QAction ( tr ( "&Load List" ),this ); + loadListAct->setShortcut ( tr ( "O" ) ); + m_playlistMenu->addAction ( loadListAct ); + connect ( loadListAct, SIGNAL ( triggered() ), this, SIGNAL ( loadPlaylist() ) ); + + QAction *saveListAct = new QAction ( tr ( "&Save List" ),this ); + saveListAct->setShortcut ( tr ( "Shift+S" ) ); + m_playlistMenu->addAction ( saveListAct ); + connect ( saveListAct, SIGNAL ( triggered() ), this, SIGNAL ( savePlaylist() ) ); + this->addActions ( m_playlistMenu->actions() ); + + Dock::getPointer()->addActions ( m_actions ); +} + +void PlayList::closeEvent ( QCloseEvent* ) +{ + writeSettings(); +} + +void PlayList::paintEvent ( QPaintEvent * ) +{ + int m_sx = ( width()-275 ) /25; + int m_sy = ( height()-116 ) /29; + drawPixmap ( m_sx, m_sy ); +} + +void PlayList::drawPixmap ( int sx, int sy ) +{ + QPainter paint; + paint.begin ( this ); + paint.drawPixmap ( 0,20,m_skin->getPlPart ( Skin::PL_LFILL ) ); + for ( int i = 1; igetPlPart ( Skin::PL_LFILL ) ); + } + paint.drawPixmap ( 0,78+29*sy,m_skin->getPlPart ( Skin::PL_LSBAR ) ); + for ( int i = 0; igetPlPart ( Skin::PL_SFILL1 ) ); + } + + paint.drawPixmap ( 125+sx*25,78+sy*29,m_skin->getPlPart ( Skin::PL_RSBAR ) ); + paint.end(); + +} + +void PlayList::resizeEvent ( QResizeEvent *e ) +{ + int sx = ( e->size().width()-275 ) /25; + int sy = ( e->size().height()-116 ) /29; + if (sx < 0 || sy < 0) + return; + + m_titleBar->resize ( 275+25*sx,20 ); + m_plslider->resize ( 20,58+sy*29 ); + + m_listWidget->resize ( 243+25*sx,58+29*sy ); + + m_buttonAdd->move ( 11,86+29*sy ); + m_buttonSub->move ( 40,86+29*sy ); + m_selectButton->move ( 70,86+29*sy ); + m_sortButton->move ( 99,86+29*sy ); + + m_pl_control->move ( 128+sx*25,100+29*sy ); + m_playlistButton->move ( 228+sx*25,86+29*sy ); + + m_length_totalLength -> move ( 131+sx*25,88+29*sy ); + m_current_time->move ( 190+sx*25,101+29*sy ); + + m_plslider->move ( 255+sx*25,20 ); +} +void PlayList::mousePressEvent ( QMouseEvent *e ) +{ + m_pos = e->pos (); + if ( ( m_pos.x() > width()-25 ) && ( m_pos.y() > height()-25 ) ) + { + m_resize = TRUE; + setCursor ( Qt::SizeFDiagCursor ); + } + else + m_resize = FALSE; +} +void PlayList::mouseMoveEvent ( QMouseEvent *e ) +{ + if ( m_resize ) + { + resize ( e->x() +25, e->y() +25 ); + //usleep(32000); + } +} +void PlayList::mouseReleaseEvent ( QMouseEvent * ) +{ + setCursor ( Qt::ArrowCursor ); + /*if (m_resize) + m_listWidget->updateList();*/ + m_resize = FALSE; + Dock::getPointer()->updateDock(); +} +void PlayList::setModel ( PlayListModel *model ) +{ + m_playListModel = model; + m_listWidget->setModel (model); + m_keyboardManager->setModel (model); + m_titleBar->setModel (model); + createActions(); +} + +void PlayList::changeEvent ( QEvent * event ) +{ + if ( event->type() == QEvent::ActivationChange ) + { + m_titleBar->setActive ( isActiveWindow() ); + } +} + +void PlayList::readSettings() +{ + if ( m_update ) + { + m_listWidget->readSettings(); + m_titleBar->readSettings(); + } + else + { + QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup ( "PlayList" ); + //position + move ( settings.value ("pos", QPoint ( 100, 332 ) ).toPoint()); + settings.endGroup(); + m_update = TRUE; + } + +} + +void PlayList::writeSettings() +{ + QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); + settings.beginGroup ( "PlayList" ); + //position + settings.setValue ( "pos", this->pos() ); + settings.endGroup(); +} + +void PlayList::showAddMenu() +{ + m_addMenu->exec ( m_buttonAdd->mapToGlobal ( QPoint ( 0,0 ) ) ); +} + +void PlayList::showSubMenu() +{ + m_subMenu->exec ( m_buttonSub->mapToGlobal ( QPoint ( 0,0 ) ) ); +} + +void PlayList::showSelectMenu() +{ + m_selectMenu->exec ( m_selectButton->mapToGlobal ( QPoint ( 0,0 ) ) ); +} + +void PlayList::showSortMenu() +{ + m_sortMenu->exec ( m_sortButton->mapToGlobal ( QPoint ( 0,0 ) ) ); +} + + + +QString PlayList::formatTime ( int sec ) +{ + int minutes = sec / 60; + int seconds = sec % 60; + + QString str_minutes = QString::number ( minutes ); + QString str_seconds = QString::number ( seconds ); + + if ( minutes < 10 ) str_minutes.prepend ( "0" ); + if ( seconds < 10 ) str_seconds.prepend ( "0" ); + + return str_minutes + ":" + str_seconds; +} + +void PlayList::setInfo (const OutputState &st,int length_current, int length_total) +{ + if ( st.type() == OutputState::Info ) + { + m_current_time->display ( formatTime ( st.elapsedSeconds() ) ); + m_current_time->update(); + + QString str_length = formatTime ( length_current ) + "/" + formatTime ( length_total ); + m_length_totalLength->display ( str_length ); + m_length_totalLength->update(); + } +} + +MediaFile *PlayList::currentItem() +{ + if ( m_playListModel ) + return m_playListModel->currentItem(); + else + return 0; +} + +void PlayList::showPlaylistMenu() +{ + m_playlistMenu->exec ( m_playlistButton->mapToGlobal ( QPoint ( 0,0 ) ) ); +} + +void PlayList::keyPressEvent ( QKeyEvent *ke ) +{ + if ( m_keyboardManager->handleKeyPress ( ke ) ) + update(); +} diff --git a/src/ui/playlist.h b/src/ui/playlist.h new file mode 100644 index 000000000..4e8bdc1f8 --- /dev/null +++ b/src/ui/playlist.h @@ -0,0 +1,124 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef PLAYLIST_H +#define PLAYLIST_H + +#include + +class KeyboardManager; + +/** + @author Ilya Kotov +*/ + +class QMenu; + +class Skin; +class ListWidget; +class MediaFile; +class Button; +class PlayListModel; +class PlayListTitleBar; +class PlayListSlider; +class MainWindow; +class SymbolDisplay; +class OutputState; +class PixmapWidget; +class PlaylistControl; + +class PlayList : public QWidget +{ + Q_OBJECT + public: + PlayList ( QWidget *parent = 0 ); + + ~PlayList(); + void load ( MediaFile * ); + void setModel ( PlayListModel * ); + void readSettings(); + void setInfo ( const OutputState &,int,int ); + MediaFile *currentItem(); + ListWidget* listWidget() const{return m_listWidget;} + + signals: + void play(); + void next(); + void prev(); + void pause(); + void stop(); + void eject(); + void loadPlaylist(); + void savePlaylist(); + void newPlaylist(); + void closed(); + + private slots: + void showAddMenu(); + void showSubMenu(); + void showSelectMenu(); + void showSortMenu(); + void showPlaylistMenu(); + + + private: + QString formatTime ( int sec ); + void drawPixmap ( int, int ); + void writeSettings(); + void createMenus(); + void createActions(); + QMenu *m_addMenu; + QMenu *m_subMenu; + QMenu *m_selectMenu; + QMenu *m_sortMenu; + QMenu *m_playlistMenu; + Button *m_buttonAdd; + Button *m_buttonSub; + Button *m_selectButton; + Button *m_sortButton; + Button* m_playlistButton; + + PlaylistControl* m_pl_control; + SymbolDisplay* m_length_totalLength; + SymbolDisplay* m_current_time; + + Skin *m_skin; + ListWidget *m_listWidget; + PlayListModel *m_playListModel; + PlayListTitleBar *m_titleBar; + PlayListSlider *m_plslider; + QList m_actions; + QPoint m_pos; + bool m_resize; + bool m_update; + int m_anchor_row; + KeyboardManager* m_keyboardManager; + + protected: + virtual void paintEvent ( QPaintEvent * ); + virtual void resizeEvent ( QResizeEvent * ); + virtual void mouseMoveEvent ( QMouseEvent * ); + virtual void mousePressEvent ( QMouseEvent * ); + virtual void mouseReleaseEvent ( QMouseEvent * ); + virtual void changeEvent ( QEvent* ); + virtual void closeEvent ( QCloseEvent* ); + virtual void keyPressEvent ( QKeyEvent* ); +}; + +#endif diff --git a/src/ui/playlistcontrol.cpp b/src/ui/playlistcontrol.cpp new file mode 100644 index 000000000..8f111fe4e --- /dev/null +++ b/src/ui/playlistcontrol.cpp @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include "playlistcontrol.h" +#include "skin.h" + +PlaylistControl::PlaylistControl(QWidget* parent) : PixmapWidget(parent) +{ + m_skin = Skin::getPointer(); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(update())); +} + +void PlaylistControl::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.drawPixmap(0,0,m_skin->getPlPart(Skin::PL_CONTROL)); +} + +void PlaylistControl::mouseReleaseEvent(QMouseEvent *me) +{ + QPoint pt = me->pos(); + if(QRect(4,1,7,7).contains(pt)) + emit previousClicked(); + else if(QRect(12,1,7,7).contains(pt)) + emit playClicked(); + else if(QRect(21,1,7,7).contains(pt)) + emit pauseClicked(); + else if(QRect(31,1,7,7).contains(pt)) + emit stopClicked(); + else if(QRect(40,1,7,7).contains(pt)) + emit nextClicked(); + else if(QRect(49,1,7,7).contains(pt)) + emit ejectClicked(); +} diff --git a/src/ui/playlistcontrol.h b/src/ui/playlistcontrol.h new file mode 100644 index 000000000..26c3871d4 --- /dev/null +++ b/src/ui/playlistcontrol.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + + /** + @author Vladimir Kuznetsov + */ + +#ifndef _PALYLISTCONTROL_H +#define _PALYLISTCONTROL_H + +#include "pixmapwidget.h" + +class PaintEvent; +class Skin; +class QMouseEvent; + +class PlaylistControl : public PixmapWidget +{ +Q_OBJECT +public: + PlaylistControl(QWidget* parent = 0); + void paintEvent(QPaintEvent*); + void mouseReleaseEvent(QMouseEvent*); +signals: + void previousClicked(); + void nextClicked(); + void pauseClicked(); + void playClicked(); + void stopClicked(); + void ejectClicked(); +protected: + Skin* m_skin; +}; + +#endif diff --git a/src/ui/playlistformat.cpp b/src/ui/playlistformat.cpp new file mode 100644 index 000000000..d9ce45b77 --- /dev/null +++ b/src/ui/playlistformat.cpp @@ -0,0 +1,287 @@ +/*************************************************************************** +* Copyright (C) 2006 by Ilya Kotov * +* forkotov02@hotmail.ru * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#ifndef XSPF_PLUGIN + #include + #include + #include + #include "version.h" +#endif + +#include "playlistformat.h" + +#include "mediafile.h" + +bool PLSPlaylistFormat::hasFormat(const QString & f) +{ + foreach(QString s,m_supported_formats) + if(f == s) + return true; + + return false; +} + +QStringList PLSPlaylistFormat::getExtensions() const +{ + return m_supported_formats; +} + +PLSPlaylistFormat::PLSPlaylistFormat() +{ + m_supported_formats << "pls"; +} + +QString PLSPlaylistFormat::name() const +{ + return "PLSPlaylistFormat"; +} + + +QStringList PLSPlaylistFormat::decode(const QString & contents) +{ + QStringList out; + QStringList splitted = contents.split("\n"); + if(!splitted.isEmpty()) + { + if(splitted.takeAt(0).toLower().contains("[playlist]")) + { + foreach(QString str, splitted) + { + if(str.startsWith("File")) + { + QString unverified = str.remove(0,str.indexOf(QChar('=')) + 1); + if(QFileInfo(unverified).exists()) + out << QFileInfo(unverified).absoluteFilePath(); + else + qWarning("File %s does not exist",unverified.toLocal8Bit().data()); + } + } + return out; + } + } + else + qWarning("Error parsing PLS format"); + + return QStringList(); +} + +QString PLSPlaylistFormat::encode(const QList< MediaFile * > & contents) +{ + QStringList out; + out << QString("[playlist]"); + int counter = 1; + foreach(MediaFile* f,contents) + { + QString begin = "File" + QString::number(counter) + "="; + out.append(begin + f->path()); + begin = "Title" + QString::number(counter) + "="; + out.append(begin + f->title()); + begin = "Length" + QString::number(counter) + "="; + out.append(begin + QString::number(f->length())); + counter ++; + } + out << "NumberOfEntries=" + QString::number(contents.count()); + return out.join("\n"); +} + + + + +bool M3UPlaylistFormat::hasFormat(const QString & f) +{ + foreach(QString s,m_supported_formats) + if(f == s) + return true; + + return false; +} + +QStringList M3UPlaylistFormat::getExtensions() const +{ + return m_supported_formats; +} + +M3UPlaylistFormat::M3UPlaylistFormat() +{ + m_supported_formats << "m3u"; +} + +QStringList M3UPlaylistFormat::decode(const QString & contents) +{ + QStringList out; + QStringList splitted = contents.split("\n"); + if(!splitted.isEmpty()) + { + if(splitted.takeAt(0).contains("#EXTM3U")) + { + foreach(QString str, splitted) + { + if(str.startsWith("#EXTINF:")) + ;//TODO: Let's skip it for now... + else if(QFileInfo(str).exists()) + out << QFileInfo(str).absoluteFilePath(); + else + qWarning("File %s does not exist",str.toLocal8Bit().data()); + } + return out; + } + } + else + qWarning("Error parsing M3U format"); + + return QStringList(); +} + +QString M3UPlaylistFormat::encode(const QList< MediaFile * > & contents) +{ + QStringList out; + out << QString("#EXTM3U"); + foreach(MediaFile* f,contents) + { + QString info = "#EXTINF:" + QString::number(f->length()) + "," + f->title(); + out.append(info); + out.append(f->path()); + } + return out.join("\n"); +} + +QString M3UPlaylistFormat::name() const +{ + return "M3UPlaylistFormat"; +} + + +// Needs more work - it's better use libSpiff there and put it as plugin. + +QStringList XSPFPlaylistFormat::decode(const QString & contents) +{ + QStringList out; + QDomDocument doc; + QString errorMsg; + int errorCol; + int errorRow; + bool ok = doc.setContent(contents, &errorMsg, &errorRow, &errorCol); + + if(!ok) + qDebug("Parse Error: %s\tRow:%d\tCol%d", + qPrintable(errorMsg), errorRow, errorCol ); + + QDomElement rootElement = doc.firstChildElement("playlist"); + if(rootElement.isNull()) + qWarning("Error parsing XSPF: can't find 'playlist' element"); + + QDomElement tracklistElement = rootElement.firstChildElement("trackList"); + if(tracklistElement.isNull()) + qWarning("Error parsing XSPF: can't find 'trackList' element"); + + QDomElement child = tracklistElement.firstChildElement("track"); + + while (!child.isNull()) + { + QString str = QUrl(child.firstChildElement("location").text()).toString(QUrl::RemoveScheme); + out << str; + child = child.nextSiblingElement(); + } + + return out; +} + +// Needs more work - it's better use libSpiff there and put it as plugin. + +QString XSPFPlaylistFormat::encode(const QList< MediaFile * > & files) +{ + QDomDocument doc; + QDomElement root = doc.createElement("playlist"); + root.setAttribute("version",QString("1")); + root.setAttribute("xmlns",QString("http://xspf.org/ns/0")); + + QDomElement creator = doc.createElement("creator"); + QDomText text = doc.createTextNode("qmmp-" + QString(QMMP_STR_VERSION)); + creator.appendChild(text); + root.appendChild(creator); + + QDomElement tracklist = doc.createElement("trackList"); + + int counter = 1; + foreach(MediaFile* f,files) + { + QDomElement track = doc.createElement("track"); + + QDomElement ch = doc.createElement("location"); + QDomText text = doc.createTextNode(/*QString("file://") + */QFileInfo(f->path()).absoluteFilePath()); + ch.appendChild(text); + track.appendChild(ch); + + ch = doc.createElement("title"); + text = doc.createTextNode(f->title()); + ch.appendChild(text); + track.appendChild(ch); + + ch = doc.createElement("trackNum"); + text = doc.createTextNode(QString::number(counter)); + ch.appendChild(text); + track.appendChild(ch); + + ch = doc.createElement("year"); + text = doc.createTextNode(QString::number(f->year())); + ch.appendChild(text); + track.appendChild(ch); + + tracklist.appendChild(track); + counter ++; + } + + root.appendChild(tracklist); + doc.appendChild( root ); + QString xml_header("\n"); + return doc.toString().prepend(xml_header); +} + +XSPFPlaylistFormat::XSPFPlaylistFormat() +{ + m_supported_formats << "xspf"; +} + +bool XSPFPlaylistFormat::hasFormat(const QString & f) +{ + foreach(QString s,m_supported_formats) + if(f == s) + return true; + + return false; +} + +QStringList XSPFPlaylistFormat::getExtensions() const +{ + return m_supported_formats; +} + + +QString XSPFPlaylistFormat::name() const +{ + return "XSPFPlaylistFormat"; +} + + + + + diff --git a/src/ui/playlistformat.h b/src/ui/playlistformat.h new file mode 100644 index 000000000..a87018d63 --- /dev/null +++ b/src/ui/playlistformat.h @@ -0,0 +1,116 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef _PALYLISTFORMAT_H +#define _PALYLISTFORMAT_H +#include + + +class MediaFile; +/*! + * Abstract interface for playlist formats. + * + * @author Vladimir Kuznetsov + */ +class PlaylistFormat +{ +public: + virtual ~PlaylistFormat(){;} + /*! + * Takes raw contents of playlist file, should return string list of + * ready file pathes to fill the playlist. + */ + virtual QStringList decode(const QString& contents) = 0; + + /*! + * Takes the list of MediaFile objects, should return string of + * encoded playlist file + */ + virtual QString encode(const QList& contents) = 0; + + /*! + * Returns list of file extensions that current format supports + */ + virtual QStringList getExtensions()const = 0; + + /*! + * Verifies is the \b ext file extension supported by current playlist format. + */ + virtual bool hasFormat(const QString& ext) = 0; + + /// Unique name of playlist format. + virtual QString name()const = 0; +}; + +Q_DECLARE_INTERFACE(PlaylistFormat,"PlaylistFormatInterface/1.0"); + +/*! + * Class for PLS playlist format parsing + */ +class PLSPlaylistFormat : public PlaylistFormat +{ +public: + PLSPlaylistFormat(); + virtual QStringList getExtensions()const; + virtual bool hasFormat(const QString&); + virtual QStringList decode(const QString& contents); + virtual QString encode(const QList& contents); + virtual QString name()const; +protected: + QStringList m_supported_formats; + +}; + + + +/*! + * Class for M3U playlist format parsing + */ +class M3UPlaylistFormat : public PlaylistFormat +{ + public: + M3UPlaylistFormat(); + virtual QStringList getExtensions()const; + virtual bool hasFormat(const QString&); + virtual QStringList decode(const QString& contents); + virtual QString encode(const QList& contents); + virtual QString name()const; +protected: + QStringList m_supported_formats; +}; + + +/*! + * Class for XSPF playlist format parsing + */ +class XSPFPlaylistFormat : public PlaylistFormat +{ + public: + XSPFPlaylistFormat(); + virtual QStringList getExtensions()const; + virtual bool hasFormat(const QString&); + virtual QStringList decode(const QString& contents); + virtual QString encode(const QList& contents); + virtual QString name()const; + protected: + QStringList m_supported_formats; +}; + +#endif diff --git a/src/ui/playlistmodel.cpp b/src/ui/playlistmodel.cpp new file mode 100644 index 000000000..196608438 --- /dev/null +++ b/src/ui/playlistmodel.cpp @@ -0,0 +1,899 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "fileloader.h" +#include "playlistmodel.h" +#include "mediafile.h" +#include "playlistformat.h" +#include "playstate.h" + +#include + +#define INVALID_ROW -1 + +TagUpdater::TagUpdater(QObject* o,MediaFile* f):m_observable(o),m_file(f) +{ + m_file->setFlag(MediaFile::EDITING); + connect (m_observable, SIGNAL(destroyed (QObject * )),SLOT(updateTag())); + connect (m_observable, SIGNAL(destroyed (QObject * )),SLOT(deleteLater())); +} + +void TagUpdater::updateTag() +{ + if(m_file->flag() == MediaFile::SCHEDULED_FOR_DELETION) + { + delete m_file; + m_file = NULL; + } + else + { + m_file->updateTags(); + m_file->setFlag(MediaFile::FREE); + } +} + + +PlayListModel::PlayListModel ( QObject *parent ) + : QObject ( parent ) , m_selection() +{ + qsrand(time(0)); + m_total_length = 0; + m_current = 0; + m_block_update_signals = false; + is_repeatable_list = false; + m_play_state = new NormalPlayState(this); + //readSettings(); + + registerPlaylistFormat( new PLSPlaylistFormat); + registerPlaylistFormat( new M3UPlaylistFormat); +#ifndef XSPF_PLUGIN + registerPlaylistFormat( new XSPFPlaylistFormat); +#endif + loadExternalPlaylistFormats(); +} + +PlayListModel::~PlayListModel() +{ + writeSettings(); + clear(); + delete m_play_state; + qDeleteAll(m_registered_pl_formats); + + foreach(GuardedFileLoader l,m_running_loaders) + { + if (!l.isNull()) + { + l->finish(); + l->wait(); + } + } +} + +void PlayListModel::load ( MediaFile *file ) +{ + if (m_files.isEmpty()) + m_currentItem = file; + + m_total_length += file->length(); + m_files << file; + + //if (!m_block_update_signals) + emit listChanged(); +} + +int PlayListModel::count() +{ + return m_files.size(); +} + +MediaFile* PlayListModel::currentItem() +{ + if ( m_files.isEmpty() ) + return 0; + else + return m_files.at ( qMin(m_files.size() - 1, m_current)); +} + +int PlayListModel::currentRow() +{ + return m_current; +} + +bool PlayListModel::setCurrent ( int c ) +{ + if ( c > count()-1 || c < 0) + return FALSE; + m_current = c; + m_currentItem = m_files.at(c); + emit currentChanged(); + emit listChanged(); + return TRUE; +} + + +bool PlayListModel::next() +{ + if (isFileLoaderRunning()) + m_play_state->prepare(); + + return m_play_state->next(); +} + +bool PlayListModel::previous() +{ + if (isFileLoaderRunning()) + m_play_state->prepare(); + + return m_play_state->previous();//) +} + +void PlayListModel::clear() +{ + foreach(GuardedFileLoader l,m_running_loaders) + { + if (!l.isNull()) + { + l->finish(); + l->wait(); + } + } + + m_running_loaders.clear(); + + m_current = 0; + while ( !m_files.isEmpty() ) + { + MediaFile* mf = m_files.takeFirst(); + + if(mf->flag() == MediaFile::FREE) + { + delete mf; + } + else if(mf->flag() == MediaFile::EDITING) + { + mf->setFlag(MediaFile::SCHEDULED_FOR_DELETION); + } + } + + m_total_length = 0; + m_play_state->resetState(); + emit listChanged(); +} + +void PlayListModel::clearSelection() +{ + for ( int i = 0; isetSelected ( FALSE ); + emit listChanged(); +} + +QList PlayListModel::getTitles ( int b,int l ) +{ + QList m_titles; + for ( int i = b; ( i < b + l ) && ( i < m_files.size() ); ++i ) + m_titles << m_files.at ( i )->title(); + return m_titles; +} + +QList PlayListModel::getTimes ( int b,int l ) +{ + QList m_times; + for ( int i = b; ( i < b + l ) && ( i < m_files.size() ); ++i ) + m_times << QString ( "%1" ).arg ( m_files.at ( i )->length() /60 ) +":" + +QString ( "%1" ).arg ( m_files.at ( i )->length() %60/10 ) + + QString ( "%1" ).arg ( m_files.at ( i )->length() %60%10 ); + return m_times; +} + +bool PlayListModel::isSelected ( int row ) +{ + if (m_files.count() > row && row >= 0) + return m_files.at ( row )->isSelected(); + + return false; +} + +void PlayListModel::setSelected ( int row, bool yes ) +{ + if (m_files.count() > row && row >= 0) + m_files.at ( row )->setSelected ( yes ); +} + +void PlayListModel::removeSelected() +{ + removeSelection(false); +} + +void PlayListModel::removeUnselected() +{ + removeSelection(true); +} + +void PlayListModel::removeSelection(bool inverted) +{ + int i = 0; + + int select_after_delete = -1; + + while ( !m_files.isEmpty() && iisSelected() ^ inverted ) + { + MediaFile* f = m_files.takeAt ( i ); + m_total_length -= f->length(); + if (m_total_length < 0) + m_total_length = 0; + + if(f->flag() == MediaFile::FREE) + { + delete f; + f = NULL; + } + else if(f->flag() == MediaFile::EDITING) + f->setFlag(MediaFile::SCHEDULED_FOR_DELETION); + + select_after_delete = i; + + if ( m_current >= i && m_current!=0 ) + m_current--; + } + else + i++; + } + + if (!m_files.isEmpty()) + m_currentItem = m_files.at(m_current); + + if (select_after_delete >= m_files.count()) + select_after_delete = m_files.count() - 1; + + setSelected(select_after_delete,true); + + m_play_state->prepare(); + + emit listChanged(); +} + +void PlayListModel::invertSelection() +{ + for ( int i = 0; isetSelected ( !m_files.at ( i )->isSelected() ); + emit listChanged(); +} + +void PlayListModel::selectAll() +{ + for ( int i = 0; isetSelected ( TRUE ); + emit listChanged(); +} + +void PlayListModel::showDetails() +{ + for ( int i = 0; iisSelected() ) + { + DecoderFactory *fact = Decoder::findByPath ( m_files.at ( i )->path() ); + if ( fact ) + { + QObject* o = fact->showDetails ( 0, m_files.at ( i )->path() ); + if(o) + { + TagUpdater *updater = new TagUpdater(o,m_files.at(i)); + m_editing_files.append(m_files.at(i)); + connect (updater, SIGNAL(destroyed (QObject * )),SIGNAL(listChanged())); + } + } + + return; + } + } + +} + + +void PlayListModel::readSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + m_current = settings.value("Playlist/current",0).toInt(); + + QFile file ( QDir::homePath() +"/.qmmp/playlist.txt" ); + file.open ( QIODevice::ReadOnly ); + + QStringList files; + QByteArray line; + m_files.clear(); + + while (!file.atEnd ()) + { + line = file.readLine(); + files << QString::fromUtf8 ( line ).trimmed (); + } + + file.close (); + + if(m_current > files.count() - 1) + m_current = 0; + + int preload = (files.count() < 100) ? files.count() : 100; + + for (int i = 0;i < preload;i++) + { + load(new MediaFile(files.takeAt(0))); + } + + if (files.isEmpty()) + { + doCurrentVisibleRequest (); + return; + } + + FileLoader* f_loader = createFileLoader(); + connect(f_loader, SIGNAL(finished ()), SLOT(doCurrentVisibleRequest ())); + + f_loader->setFilesToLoad(files); + //f_loader->start(QThread::IdlePriority); + QTimer::singleShot(1000,f_loader,SLOT(start())); + //m_play_state->prepare(); +} + +void PlayListModel::writeSettings() +{ + QFile file ( QDir::homePath() +"/.qmmp/playlist.txt" ); + file.open ( QIODevice::WriteOnly ); + foreach ( MediaFile* m, m_files ) + file.write ( m->path().toUtf8 () +"\n" ); + file.close (); + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.setValue("Playlist/current", m_current); +} + +void PlayListModel::addFile(const QString& path) +{ + if (path.isEmpty ()) + return; + if (path.startsWith("http://")) + load(new MediaFile(path)); + else if (Decoder::supports(path)) + load(new MediaFile(path)); + + m_play_state->prepare(); +} + +FileLoader * PlayListModel::createFileLoader() +{ + FileLoader* f_loader = new FileLoader(this); +// f_loader->setStackSize(20 * 1024 * 1024); + m_running_loaders << f_loader; + connect(f_loader,SIGNAL(newMediaFile(MediaFile*)),this,SLOT(load(MediaFile*)),Qt::QueuedConnection); + connect(f_loader,SIGNAL(finished()),this,SLOT(preparePlayState())); + connect(f_loader,SIGNAL(finished()),f_loader,SLOT(deleteLater())); + return f_loader; +} + +void PlayListModel::addFiles(const QStringList &files) +{ + FileLoader* f_loader = createFileLoader(); + f_loader->setFilesToLoad(files); + f_loader->start(QThread::IdlePriority); +} + +void PlayListModel::addDirectory(const QString& s) +{ + FileLoader* f_loader = createFileLoader(); + f_loader->setDirectoryToLoad(s); + f_loader->start(QThread::IdlePriority); +} + +void PlayListModel::addFileList(const QStringList &l) +{ +// qWarning("void// PlayListModel::addFileList(const QStringList &l)"); + foreach(QString str,l) + { + QFileInfo f_info(str); + if (f_info.exists()) + { + if (f_info.isDir()) + addDirectory(str); + else + addFile(str); + } + // Do processing the rest of events to avoid GUI freezing + QApplication::processEvents(QEventLoop::AllEvents,10); + } +} + +bool PlayListModel::setFileList(const QStringList & l) +{ + bool model_cleared = FALSE; + foreach(QString str,l) + { + QFileInfo f_info(str); + if (f_info.exists()) + { + if (!model_cleared) + { + clear(); + model_cleared = TRUE; + } + if (f_info.isDir()) + addDirectory(str); + else + addFile(str); + } + // Do processing the rest of events to avoid GUI freezing + QApplication::processEvents(QEventLoop::AllEvents,10); + } + + return model_cleared; +} + +int PlayListModel::firstSelectedUpper(int row) +{ + for (int i = row - 1;i >= 0;i--) + { + if (isSelected(i)) + return i; + } + return -1; +} + +int PlayListModel::firstSelectedLower(int row) +{ + for (int i = row + 1;i < count() ;i++) + { + if (isSelected(i)) + return i; + } + return -1; +} + +void PlayListModel::moveItems( int from, int to ) +{ + // Get rid of useless work + if (from == to) + return; + + QList selected_rows = getSelectedRows(); + + if (! (bottommostInSelection(from) == INVALID_ROW || + from == INVALID_ROW || + topmostInSelection(from) == INVALID_ROW) + ) + { + if (from > to) + foreach(int i, selected_rows) + if (i + to - from < 0) + break; + else + m_files.move(i,i + to - from); + else + for (int i = selected_rows.count() - 1; i >= 0; i--) + if (selected_rows[i] + to -from >= m_files.count()) + break; + else + m_files.move(selected_rows[i],selected_rows[i] + to - from); + + m_current = m_files.indexOf(m_currentItem); + + emit listChanged(); + } +} + + + +int PlayListModel::topmostInSelection( int row) +{ + if ( row == 0) + return 0; + + for (int i = row - 1;i >= 0;i--) + { + if (isSelected(i)) + continue; + else + return i + 1; + } + return 0; +} + +int PlayListModel::bottommostInSelection( int row ) +{ + if (row >= m_files.count() - 1) + return row; + + for (int i = row + 1;i < count() ;i++) + { + if (isSelected(i)) + continue; + else + return i - 1; + } + return count() - 1; +} + +const SimpleSelection& PlayListModel::getSelection(int row ) +{ + m_selection.m_top = topmostInSelection( row ); + m_selection.m_anchor = row; + m_selection.m_bottom = bottommostInSelection( row ); + m_selection.m_selected_rows = getSelectedRows(); + return m_selection; +} + +QList PlayListModel::getSelectedRows() const +{ + QListselected_rows; + for (int i = 0;iisSelected()) + { + selected_rows.append(i); + } + } + return selected_rows; +} + +QList< MediaFile * > PlayListModel::getSelectedItems() const +{ + QListselected_items; + for (int i = 0;iisSelected()) + { + selected_items.append(m_files[i]); + } + } + return selected_items; +} + +void PlayListModel::addToQueue() +{ + QList selected_items = getSelectedItems(); + foreach(MediaFile* file,selected_items) + {/* + if (isQueued(file)) + m_queued_songs.removeAt(m_queued_songs.indexOf(file)); + else + m_queued_songs.append(file); + */ + setQueued(file); + } + emit listChanged(); +} + +void PlayListModel::setQueued(MediaFile* file) +{ + if (isQueued(file)) + m_queued_songs.removeAt(m_queued_songs.indexOf(file)); + else + m_queued_songs.append(file); + + emit listChanged(); +} + +bool PlayListModel::isQueued(MediaFile* f) const +{ + return m_queued_songs.contains(f); +} + +void PlayListModel::setCurrentToQueued() +{ + setCurrent(row(m_queued_songs.at(0))); + m_queued_songs.pop_front(); +} + +bool PlayListModel::isEmptyQueue() const +{ + return m_queued_songs.isEmpty(); +} + +void PlayListModel::randomizeList() +{ + for (int i = 0;i < m_files.size();i++) + m_files.swap(qrand()%m_files.size(),qrand()%m_files.size()); + + m_current = m_files.indexOf(m_currentItem); + emit listChanged(); +} + +void PlayListModel::reverseList() +{ + for (int i = 0;i < m_files.size()/2;i++) + m_files.swap(i,m_files.size() - i - 1); + + m_current = m_files.indexOf(m_currentItem); + emit listChanged(); +} + +////===============THE BEGINNING OF SORT IMPLEMENTATION =======================//// + +// First we'll implement bundle of static compare procedures +// to sort items in different ways +static bool _titleLessComparator(MediaFile* s1,MediaFile* s2) +{ + return s1->title() < s2->title(); +} + +static bool _titleGreaterComparator(MediaFile* s1,MediaFile* s2) +{ + return s1->title() > s2->title(); +} + +static bool _pathAndFilenameLessComparator(MediaFile* s1,MediaFile* s2) +{ + return s1->path() < s2->path(); +} + +static bool _pathAndFilenameGreaterComparator(MediaFile* s1,MediaFile* s2) +{ + return s1->path() > s2->path(); +} + +static bool _filenameLessComparator(MediaFile* s1,MediaFile* s2) +{ + QFileInfo i_s1(s1->path()); + QFileInfo i_s2(s2->path()); + return i_s1.baseName() < i_s2.baseName(); +} + +static bool _filenameGreaterComparator(MediaFile* s1,MediaFile* s2) +{ + QFileInfo i_s1(s1->path()); + QFileInfo i_s2(s2->path()); + return i_s1.baseName() > i_s2.baseName(); +} + +static bool _dateLessComparator(MediaFile* s1,MediaFile* s2) +{ + return s1->year() < s2->year(); +} + +static bool _dateGreaterComparator(MediaFile* s1,MediaFile* s2) +{ + return s1->year() > s2->year(); +} + +// This is main sort method +void PlayListModel::doSort(int sort_mode,QList& list_to_sort) +{ + QList::iterator begin; + QList::iterator end; + + begin = list_to_sort.begin(); + end = list_to_sort.end(); + + bool (*compareLessFunc)(MediaFile*,MediaFile*) = 0; + bool (*compareGreaterFunc)(MediaFile*,MediaFile*) = 0; + + switch (sort_mode) + { + case TITLE: + compareLessFunc = _titleLessComparator; + compareGreaterFunc = _titleGreaterComparator; + break; + case FILENAME: + compareLessFunc = _filenameLessComparator; + compareGreaterFunc = _filenameGreaterComparator; + break; + case PATH_AND_FILENAME: + compareLessFunc = _pathAndFilenameLessComparator; + compareGreaterFunc = _pathAndFilenameGreaterComparator; + break; + case DATE: + compareLessFunc = _dateLessComparator; + compareGreaterFunc = _dateGreaterComparator; + break; + //qWarning("TODO Sort by Date: %s\t%d",__FILE__,__LINE__); + default: + compareLessFunc = _titleLessComparator; + compareGreaterFunc = _titleGreaterComparator; + } + + static bool sorted_asc = false; + if (!sorted_asc) + { + qSort(begin,end,compareLessFunc); + sorted_asc = true; + } + else + { + qSort(begin,end,compareGreaterFunc); + sorted_asc = false; + } + + m_current = m_files.indexOf(m_currentItem); +} + +void PlayListModel::sortSelection(int mode) +{ + QListselected_items = getSelectedItems(); + QListselected_rows = getSelectedRows(); + + doSort(mode,selected_items); + + for (int i = 0;i < selected_rows.count();i++) + m_files.replace(selected_rows[i],selected_items[i]); + + m_current = m_files.indexOf(m_currentItem); + emit listChanged(); +} + +void PlayListModel::sort(int mode) +{ + doSort(mode,m_files); + emit listChanged(); +} + +////=============== THE END OF SORT IMPLEMENTATION =======================//// + +void PlayListModel::prepareForShufflePlaying(bool val) +{ + if (m_play_state) + delete m_play_state; + + if (val) + m_play_state = new ShufflePlayState(this); + else + m_play_state = new NormalPlayState(this); + +} + +void PlayListModel::prepareForRepeatablePlaying(bool val) +{ + is_repeatable_list = val; +} + +void PlayListModel::doCurrentVisibleRequest() +{ + emit currentChanged(); + emit listChanged(); +} + +void PlayListModel::setUpdatesEnabled(bool yes) +{ + if (yes) + { + m_block_update_signals = false; + emit listChanged(); + } + else + { + m_block_update_signals = true; + } +} + +void PlayListModel::loadPlaylist(const QString & f_name) +{ + + foreach(PlaylistFormat* prs,m_registered_pl_formats.values()) + { + if (prs->hasFormat(QFileInfo(f_name).completeSuffix().toLower())) + { + QFile file(f_name); + if (file.open(QIODevice::ReadOnly)) + { + clear(); + addFiles(prs->decode(QTextStream(&file).readAll())); + file.close(); + } + else + qWarning("Error opening %s",f_name.toLocal8Bit().data()); + } + } +} + +void PlayListModel::savePlaylist(const QString & f_name) +{ + foreach(PlaylistFormat* prs,m_registered_pl_formats.values()) + { + if (prs->hasFormat(QFileInfo(f_name).completeSuffix().toLower())) + { + QFile file(f_name); + if (file.open(QIODevice::WriteOnly)) + { + QTextStream ts(&file); + ts << prs->encode(m_files); + file.close(); + } + else + qWarning("Error opening %s",f_name.toLocal8Bit().data()); + } + } +} + + +void PlayListModel::loadExternalPlaylistFormats() +{ + QDir pluginsDir (QDir::homePath()+"/.qmmp/plugins/PlaylistFormats"); + //pluginsDir.cdUp(); + //pluginsDir.cd("plugins/PlaylistFormats"); + foreach (QString fileName, pluginsDir.entryList(QDir::Files)) + { + QPluginLoader loader(pluginsDir.absoluteFilePath(fileName)); + QObject *plugin = loader.instance(); + if (loader.isLoaded()) + qDebug("PlaylistFormat: plugin loaded - %s", qPrintable(fileName)); + + PlaylistFormat *fmt = 0; + if (plugin) + fmt = qobject_cast(plugin); + + if (fmt) + if (!registerPlaylistFormat(fmt)) + qDebug("Warning: Plugin with name %s is already registered...", + qPrintable(fmt->name())); + } +} + +bool PlayListModel::registerPlaylistFormat(PlaylistFormat* p) +{ + QString name = p->name(); + if (!m_registered_pl_formats.contains(name)) + { + m_registered_pl_formats.insert(name,p); + return true; + } + return false; +} + +bool PlayListModel::isFileLoaderRunning() const +{ + foreach(FileLoader* l,m_running_loaders) + if (l && l->isRunning()) + return TRUE; + + return FALSE; +} + +void PlayListModel::preparePlayState() +{ + m_play_state->prepare(); +} + + + + + + + + + + + + + + diff --git a/src/ui/playlistmodel.h b/src/ui/playlistmodel.h new file mode 100644 index 000000000..b3ac19c04 --- /dev/null +++ b/src/ui/playlistmodel.h @@ -0,0 +1,377 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef PLAYLISTMODEL_H +#define PLAYLISTMODEL_H + +#include +#include +#include +#include +#include +#include + +//#include "fileloader.h" +class FileLoader; + +/** + @author Ilya Kotov +*/ + +class MediaFile; +class PlayState; +class PlaylistFormat; +class PlayListModel; + +struct SimpleSelection +{ + SimpleSelection() + { + ; + } + inline bool isValid()const + { + return (m_bottom != -1) && (m_anchor != -1) && (m_top != -1); + } + inline void dump()const + { + qWarning("top: %d\tbotom: %d\tanchor: %d",m_top,m_bottom,m_anchor); + } + inline int count()const + { + return m_bottom - m_top + 1; + } + int m_bottom; + int m_top; + int m_anchor; + QListm_selected_rows; +}; + +/*! + * Helper class used for tags update after details dialog closing. + * @author Vladimir Kuznetsov + */ +class TagUpdater : public QObject +{ + Q_OBJECT + QObject* m_observable; + MediaFile* m_file; +public: + TagUpdater(QObject* o,MediaFile* f); +protected slots: + void updateTag(); +}; + + +class PlayListModel : public QObject +{ + Q_OBJECT +public: + PlayListModel(QObject *parent = 0); + + ~PlayListModel(); + + int count(); + MediaFile* currentItem(); + int row(MediaFile* f)const + { + return m_files.indexOf(f); + } + MediaFile* item(int row)const + { + return m_files.at(row); + } + int currentRow(); + bool setCurrent (int); + bool isSelected(int); + void setSelected(int, bool); + + bool next(); + bool previous(); + + QList getTitles(int,int); + QList getTimes(int,int); + + void moveItems(int from,int to); + + /*! + * Returns \b true if \b f file is in play queue, else return \b false + */ + bool isQueued(MediaFile* f) const; + + bool isRepeatableList()const + { + return is_repeatable_list; + } + + /*! + * Sets current song to the file that is nex in queue, if queue is empty - does nothing + */ + void setCurrentToQueued(); + + /*! + * Returns \b true if play queue is empty,otherwise - \b false. + */ + bool isEmptyQueue()const; + + /*! + * Returns index of \b f file in queue.e + */ + int queuedIndex(MediaFile* f)const + { + return m_queued_songs.indexOf(f); + } + + /*! + * Returns current selection(playlist can contain a lot of selections, + * this method returns selection which \b row belongs to) + */ + const SimpleSelection& getSelection(int row); + + /*! + * Returns vector with selected rows indexes. + */ + QList getSelectedRows()const; + /*! + * Returns vector of \b MediaFile pointers that are selected. + */ + QList getSelectedItems()const; + + QList items()const + { + return m_files; + } + + /*! + * Returns number of first item that selected upper the \b row item. + */ + int firstSelectedUpper(int row); + + /*! + * Returns number of first item that selected lower the \b row item. + */ + int firstSelectedLower(int row); + + /*! + * Returns total lenght in seconds of all songs. + */ + int totalLength()const + { + return m_total_length; + } + + /*! + * Registers playlist format parser. + */ + bool registerPlaylistFormat(PlaylistFormat* p); + + /*! + * Checks and loads external playlist format plugins + */ + void loadExternalPlaylistFormats(); + + /*! + * Returns vector of reistered format parsers. + */ + const QList registeredPlaylistFormats()const + { + return m_registered_pl_formats.values(); + } + + const QStringList registeredPlaylistFormatNames()const + { + return m_registered_pl_formats.keys(); + } + + /*! + * Loads playlist with \b f_name name. + */ + void loadPlaylist(const QString& f_name); + + /*! + * Saves current songs to the playlist with \b f_name name. + */ + void savePlaylist(const QString& f_name); + + /*! + * Enum of available sort modes + */ + enum SortMode + { + TITLE,FILENAME,PATH_AND_FILENAME,DATE + }; + +signals: + void listChanged(); + void currentChanged(); + +public slots: + void load(MediaFile *); + void clear(); + void clearSelection(); + void removeSelected(); + void removeUnselected(); + void invertSelection(); + void selectAll(); + void showDetails(); + void doCurrentVisibleRequest(); + + void addFile(const QString&); + + /*! + * Adds the list \b l of files to the model. + */ + void addFiles(const QStringList& l); + + /*! + * Adds \b dir to the model. + */ + void addDirectory(const QString& dir); + + /*! + * Loads list of files (regular files or directories), + * returns \b TRUE if at least one file has been successfully loaded, + * otherwise \b FALSE + */ + bool setFileList(const QStringList&); + + void addFileList(const QStringList &l); + + void randomizeList(); + void reverseList(); + + /*! + * Prepares model for shuffle playing. \b yes parameter is true - model iterates in shuffle mode. + */ + void prepareForShufflePlaying(bool yes); + + /*! + * Prepares model for shuffle playing. \b yes parameter is true - model iterates in repeat mode. + */ + void prepareForRepeatablePlaying(bool); + + /*! + * Sorts selected items in \b mode sort mode. + */ + void sortSelection(int mode); + + /*! + * Sorts items in \b mode sort mode. + */ + void sort(int mode); + + /*! + * Adds selected items to play queue. + */ + void addToQueue(); + + /*! + * Sets \b f media file to queue. + */ + void setQueued(MediaFile* f); + + void preparePlayState(); + +private: + + /*! + * This internal method performs sorting of \b list_to_sort list of items. + */ + void doSort(int mode,QList& list_to_sort); + /*! + * Returns topmost row in current selection + */ + int topmostInSelection(int); + + /*! + * Returns bottommost row in current selection + */ + int bottommostInSelection(int); + + /*! + * Creates and initializes file loader object. + */ + FileLoader* createFileLoader(); + + + /*! + * Is someone of file loaders is running? + */ + bool isFileLoaderRunning()const; + + /*! + * Removes items from model. If \b inverted is \b false - + * selected items will be removed, else - unselected. + */ + void removeSelection(bool inverted = false); + +private: + + QList m_files; + QList m_editing_files; + MediaFile* m_currentItem; + + int m_current; + void readSettings(); + void writeSettings(); + + void setUpdatesEnabled(bool); + + bool updatesEnabled()const + { + return !m_block_update_signals; + } + + /*! + * This flyweight object represents current selection. + */ + SimpleSelection m_selection; + + /*! + * Songs in play queue. + */ + QListm_queued_songs; + + QMap m_registered_pl_formats; + + /*! + * Is playlist repeatable? + */ + bool is_repeatable_list; + + /// Current playing state (Normal or Shuffle) + PlayState* m_play_state; + + bool m_block_update_signals; + + int m_total_length; + + typedef QPointer GuardedFileLoader; + + /*! Vector of currently running file loaders. + * All loaders are automatically sheduled for deletion + * when finished. + */ + QVector m_running_loaders; + + friend class MainWindow; +}; + + +#endif diff --git a/src/ui/playlistslider.cpp b/src/ui/playlistslider.cpp new file mode 100644 index 000000000..098b3bcee --- /dev/null +++ b/src/ui/playlistslider.cpp @@ -0,0 +1,135 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "skin.h" +#include "playlistslider.h" +#include "pixmapwidget.h" + +PlayListSlider::PlayListSlider(QWidget *parent) + : QWidget(parent) +{ + m_skin = Skin::getPointer(); + + m_moving = FALSE; + m_pressed = FALSE; + m_min = 0; + m_max = 0; + m_value = 0; + pos = 0; + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); +} + + +PlayListSlider::~PlayListSlider() +{} + +void PlayListSlider::paintEvent(QPaintEvent *) +{ + int sy = (height()-58)/29; + int p=int(ceil(double(m_value-m_min)*(height()-18)/(m_max-m_min))); + QPainter paint(this); + paint.drawPixmap(0,0,m_skin->getPlPart(Skin::PL_RFILL)); + paint.drawPixmap(0,29,m_skin->getPlPart(Skin::PL_RFILL)); + + for (int i = 0; igetPlPart(Skin::PL_RFILL)); + } + if (m_pressed) + paint.drawPixmap(5,p,m_skin->getButton(Skin::PL_BT_SCROLL_P)); + else + paint.drawPixmap(5,p,m_skin->getButton(Skin::PL_BT_SCROLL_N)); + m_pos = p; +} + +void PlayListSlider::mousePressEvent(QMouseEvent *e) +{ + + m_moving = TRUE; + press_pos = e->y(); + if (m_posy() && e->y()y()-m_pos; + } + else + { + m_value = convert(qMax(qMin(height()-18,e->y()-9),0)); + press_pos = 9; + if (m_value!=m_old) + { + emit sliderMoved(m_value); + m_old = m_value; + //qDebug ("%d",m_value); + } + } + m_pressed = TRUE; + update(); +} + +void PlayListSlider::mouseReleaseEvent(QMouseEvent*) +{ + m_moving = FALSE; + m_pressed = FALSE; + update(); +} + +void PlayListSlider::mouseMoveEvent(QMouseEvent* e) +{ + if (m_moving) + { + int po = e->y(); + po = po - press_pos; + + if (0<=po && po<=height()-18) + { + m_value = convert(po); + update(); + if (m_value!=m_old) + { + + m_old = m_value; + emit sliderMoved(m_value); + } + } + } +} + +void PlayListSlider::setPos(int p, int max) +{ + m_max = max; + m_value = p; + if(m_moving) + return; + update(); +} + +void PlayListSlider::updateSkin() +{ + update(); +} + +int PlayListSlider::convert(int p) +{ + return int(floor(double(m_max-m_min)*(p)/(height()-18)+m_min)); +} + diff --git a/src/ui/playlistslider.h b/src/ui/playlistslider.h new file mode 100644 index 000000000..a8eb45c66 --- /dev/null +++ b/src/ui/playlistslider.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef PLAYLISTSLIDER_H +#define PLAYLISTSLIDER_H + +#include + +class Skin; +class PixmapWidget; +/** + @author Ilya Kotov +*/ +class PlayListSlider : public QWidget +{ +Q_OBJECT +public: + PlayListSlider(QWidget *parent = 0); + + ~PlayListSlider(); + +public slots: + void setPos(int pos, int max); + +signals: + void sliderMoved (int); + +private slots: + void updateSkin(); + +private: + Skin *m_skin; + PixmapWidget *m_scroll; + int m_old; + bool m_moving, m_pressed; + int press_pos; + int m_min, m_max, m_value, pos, m_pos; + int convert(int); // value = convert(position); + +protected: + void paintEvent(QPaintEvent*); + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); +}; + +#endif diff --git a/src/ui/playlisttitlebar.cpp b/src/ui/playlisttitlebar.cpp new file mode 100644 index 000000000..a583065ca --- /dev/null +++ b/src/ui/playlisttitlebar.cpp @@ -0,0 +1,284 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include + +#include "dock.h" +#include "button.h" +#include "playlistmodel.h" +#include "playlisttitlebar.h" +#include "skin.h" + +PlayListTitleBar::PlayListTitleBar(QWidget *parent) + : PixmapWidget(parent) +{ + m_active = FALSE; + m_resize = FALSE; + m_shade2 = 0; + m_model = 0; + m_shaded = FALSE; + m_align = FALSE; + m_skin = Skin::getPointer(); + setSizeIncrement(25,1); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); + m_pl = qobject_cast(parent); + m_mw = qobject_cast(m_pl->parent()); + + m_close = new Button(this,Skin::PL_BT_CLOSE_N, Skin::PL_BT_CLOSE_P); + connect (m_close, SIGNAL(clicked()), m_pl, SIGNAL(closed())); + m_close->move(264,3); + m_shade = new Button(this, Skin::PL_BT_SHADE1_N, Skin::PL_BT_SHADE1_P); + connect(m_shade, SIGNAL(clicked()), SLOT(shade())); + m_shade->move(255,3); + resize(275,20); + setMinimumWidth(275); + readSettings(); + QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); + m_pl->resize (settings.value ("PlayList/size", QSize (275, 116)).toSize()); + if (settings.value ("PlayList/shaded", FALSE).toBool()) + shade(); + resize(m_pl->width(),height()); + m_align = TRUE; +} + + +PlayListTitleBar::~PlayListTitleBar() +{ + QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); + settings.setValue ("PlayList/size", QSize (m_pl->width(), m_shaded ? m_height:m_pl->height())); + settings.setValue ("PlayList/shaded", m_shaded); +} + +void PlayListTitleBar::drawPixmap(int sx) +{ + m_close->move(264+sx*25,3); + m_shade->move(255+sx*25,3); + if (m_shade2) + m_shade2->move(255+sx*25,3); + QPixmap pixmap(275+sx*25,20); + pixmap.fill("black"); + QPainter paint; + paint.begin(&pixmap); + if (m_shaded) + { + paint.drawPixmap(0,0,m_skin->getPlPart(Skin::PL_TITLEBAR_SHADED2)); + for (int i = 1; igetPlPart(Skin::PL_TFILL_SHADED)); + } + } + + if (m_active) + { + if (m_shaded) + { + m_shade2->show(); + paint.drawPixmap(225+sx*25,0,m_skin->getPlPart(Skin::PL_TITLEBAR_SHADED1_A)); + } + else + { + paint.drawPixmap(0,0,m_skin->getPlPart(Skin::PL_CORNER_UL_A)); + for (int i = 1; igetPlPart(Skin::PL_TFILL1_A)); + } + paint.drawPixmap(100-12+12*sx,0,m_skin->getPlPart(Skin::PL_TITLEBAR_A)); + paint.drawPixmap(250+sx*25,0,m_skin->getPlPart(Skin::PL_CORNER_UR_A)); + m_close->show(); + m_shade->show(); + } + } + else + { + if (m_shaded) + { + m_shade2->hide(); + paint.drawPixmap(275-50+sx*25,0,m_skin->getPlPart(Skin::PL_TITLEBAR_SHADED1_I)); + } + else + { + paint.drawPixmap(0,0,m_skin->getPlPart(Skin::PL_CORNER_UL_I)); + for (int i = 1; igetPlPart(Skin::PL_TFILL1_I)); + } + paint.drawPixmap(100-12+12*sx,0,m_skin->getPlPart(Skin::PL_TITLEBAR_I)); + paint.drawPixmap(250+sx*25,0,m_skin->getPlPart(Skin::PL_CORNER_UR_I)); + m_close->hide(); + m_shade->hide(); + } + } + if (m_shaded) + { + //draw text background + for (int i = 0; i < 47 + sx*5; ++i) + { + paint.drawPixmap(8+i*5,2,m_skin->getLetter(' ')); + paint.drawPixmap(8+i*5,6,m_skin->getLetter(' ')); + } + //draw text + paint.setFont(m_font); + paint.setPen(QString(m_skin->getPLValue("normal"))); + paint.drawText(9, 11, m_truncatedText); + } + paint.end(); + setPixmap(pixmap); +} + +void PlayListTitleBar::resizeEvent(QResizeEvent *e) +{ + truncate(); + drawPixmap((e->size().width()-275)/25); +} + +void PlayListTitleBar::mousePressEvent(QMouseEvent* event) +{ + switch ((int) event->button ()) + { + case Qt::LeftButton: + { + pos = event->pos(); + + if (m_shaded && (width() - 30) < pos.x() && pos.x() < (width() - 22)) + { + m_resize = TRUE; + m_pl->setCursor (Qt::SizeHorCursor); + } + + + break; + } + case Qt::RightButton: + { + m_mw->menu()->exec(event->globalPos()); + } + } +} + +void PlayListTitleBar::mouseReleaseEvent(QMouseEvent*) +{ + Dock::getPointer()->updateDock(); + m_resize = FALSE; + m_pl->setCursor (Qt::ArrowCursor); +} + +void PlayListTitleBar::mouseMoveEvent(QMouseEvent* event) +{ + QPoint npos = (event->globalPos()-pos); + QPoint oldpos = npos; + if (m_shaded && m_resize) + { + m_pl->resize((event->x() + 25), m_pl->height()); + resize((event->x() + 25), height()); + } + else + Dock::getPointer()->move(m_pl, npos); +} + +void PlayListTitleBar::setActive(bool a) +{ + m_active = a; + drawPixmap((width()-275)/25); +} + + +void PlayListTitleBar::setModel(PlayListModel *model) +{ + m_model = model; + connect (m_model, SIGNAL(listChanged()), SLOT(showCurrent())); +} + +void PlayListTitleBar::readSettings() +{ + QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); + QString fontname = settings.value("PlayList/Font","").toString(); + if (fontname.isEmpty ()) + fontname = QFont("Helvetica [Cronyx]", 8).toString(); + m_font.fromString(fontname); + m_font.setPointSize(8); +} + +void PlayListTitleBar::updateSkin() +{ + drawPixmap((width()-275)/25); +} + +void PlayListTitleBar::shade() +{ + m_shaded = !m_shaded; + + if (m_shaded) + { + m_height = m_pl->height(); + m_pl->setFixedHeight(14); + m_shade->hide(); + m_shade2 = new Button(this, Skin::PL_BT_SHADE2_N, Skin::PL_BT_SHADE2_P); + m_shade2->move(254,3); + connect(m_shade2, SIGNAL(clicked()), SLOT(shade())); + m_shade2->show(); + } + else + { + m_pl->setMinimumSize (275,116); + m_pl->setMaximumSize (10000,10000); + m_pl->resize(width(),m_height); + delete m_shade2; + m_shade2 = 0; + m_shade->show(); + } + showCurrent(); + update(); + if (m_align) + Dock::getPointer()->align(m_pl, m_shaded? -m_height+14: m_height-14); +} + +void PlayListTitleBar::showCurrent() +{ + if (m_model) + { + MediaFile* info = m_model->currentItem(); + if (info) + { + m_text = QString("%1. ").arg(m_model->currentRow()+1); + m_text.append(info->title()); + m_text.append(QString(" (%1:%2)").arg(info->length()/60).arg(info->length()%60)); + } + else + m_text.clear(); + } + truncate(); + drawPixmap((width()-275)/25); +} + +void PlayListTitleBar::truncate() +{ + m_truncatedText = m_text; + QFontMetrics metrics(m_font); + bool truncate = FALSE; + while (metrics.width(m_truncatedText) > (this->width() - 35)) + { + truncate = TRUE; + m_truncatedText = m_truncatedText.left(m_truncatedText.length()-1); + } + if (truncate) + m_truncatedText = m_truncatedText.left(m_truncatedText.length()-3).trimmed()+"..."; +} diff --git a/src/ui/playlisttitlebar.h b/src/ui/playlisttitlebar.h new file mode 100644 index 000000000..f50018371 --- /dev/null +++ b/src/ui/playlisttitlebar.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef PLAYLISTTITLEBAR_H +#define PLAYLISTTITLEBAR_H + +#include "playlist.h" +#include "pixmapwidget.h" +#include "mainwindow.h" + +/** + @author Ilya Kotov +*/ +class Skin; +class MainWindow; +class Button; +class PlayListModel; + +class PlayListTitleBar : public PixmapWidget +{ +Q_OBJECT +public: + PlayListTitleBar(QWidget *parent = 0); + + ~PlayListTitleBar(); + + void setActive(bool); + void setModel(PlayListModel *model); + void readSettings(); + +private slots: + void updateSkin(); + void shade(); + void showCurrent(); + +private: + void drawPixmap(int); + void truncate(); + Skin *m_skin; + QPoint pos; + bool m_active; + PlayList* m_pl; + MainWindow* m_mw; + Button* m_close; + Button* m_shade; + Button* m_shade2; + bool m_shaded; + bool m_align, m_resize; + int m_height; + PlayListModel* m_model; + QString m_text; + QString m_truncatedText; + QFont m_font; + +protected: + void resizeEvent(QResizeEvent*); + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); +}; + +#endif diff --git a/src/ui/playstate.cpp b/src/ui/playstate.cpp new file mode 100644 index 000000000..373619574 --- /dev/null +++ b/src/ui/playstate.cpp @@ -0,0 +1,138 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +ShufflePlayState::ShufflePlayState(PlayListModel * model) : PlayState(model) +{ + prepare(); +} + +bool ShufflePlayState::next() +{ + int itm_count = m_model->items().count(); + + if (itm_count > 0) + { + if (m_shuffled_current >= m_shuffled_indexes.count() -1 ) + { + if (!m_model->isRepeatableList()) + return FALSE; + else + prepare(); + } + + if (m_shuffled_current < m_shuffled_indexes.count() - 1)m_shuffled_current++; + + return m_model->setCurrent(m_shuffled_indexes.at(m_shuffled_current)); + } + return FALSE; +} + +bool ShufflePlayState::previous() +{ + int itm_count = m_model->items().count(); + + if (itm_count > 0) + { + if (m_shuffled_current <= 0) + { + if (!m_model->isRepeatableList()) + return FALSE; + else + { + prepare(); + m_shuffled_current = m_shuffled_indexes.count() - 1; + } + } + + if (itm_count > 1) m_shuffled_current --; + + m_model->setCurrent(m_shuffled_indexes.at(m_shuffled_current)); + return TRUE; + } + return FALSE; +} + +void ShufflePlayState::prepare() +{ + resetState(); + for (int i = 0;i < m_model->items().count();i++) + { + if (i != m_model->currentRow()) + m_shuffled_indexes << i; + } + + for (int i = 0;i < m_shuffled_indexes.count();i++) + m_shuffled_indexes.swap(qrand()%m_shuffled_indexes.size(),qrand()%m_shuffled_indexes.size()); + + m_shuffled_indexes.prepend(m_model->currentRow()); +} + +void ShufflePlayState::resetState() +{ + m_shuffled_indexes.clear(); + m_shuffled_current = 0; +} + + + + + +NormalPlayState::NormalPlayState(PlayListModel * model) : PlayState(model) +{} + + +bool NormalPlayState::next() +{ + int itm_count = m_model->items().count(); + + if (itm_count > 0) + { + if ( m_model->currentRow() == itm_count - 1) + { + if (m_model->isRepeatableList()) + return m_model->setCurrent(0); + else + return FALSE; + } + return m_model->setCurrent(m_model->currentRow() + 1); + } + else + return FALSE; +} + +bool NormalPlayState::previous() +{ + int itm_count = m_model->items().count(); + + if (itm_count > 0) + { + if ( m_model->currentRow() < 1 && !m_model->isRepeatableList()) + return FALSE; + else if (m_model->setCurrent(m_model->currentRow() - 1)) + return TRUE; + else if (m_model->isRepeatableList()) + return m_model->setCurrent(m_model->items().count() - 1); + } + + return FALSE; +} + diff --git a/src/ui/playstate.h b/src/ui/playstate.h new file mode 100644 index 000000000..e4af7fa6f --- /dev/null +++ b/src/ui/playstate.h @@ -0,0 +1,109 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef _PLAYSTATE_H +#define _PLAYSTATE_H + +/** + @author Vladimir Kuznetsov + */ + +#include + +/*! + * Abstract class that represents data model playing states + */ +class PlayState +{ +public: + /*! Makes single step forward through songs list. + * If the step has done returns \b true, otherwise \b false + */ + virtual bool next() = 0; + + /*! Makes single step back through songs list. + * If the step has done returns \b true, otherwise \b false + */ + virtual bool previous() = 0; + + /*! + * Service method, resets state to it's defaults. + */ + virtual void resetState() + { + ; + }; + + /*! + * Service method, can be used for state initializing. + */ + virtual void prepare() + { + ; + } + virtual ~PlayState() + { + ; + } + PlayState(PlayListModel* model) : m_model(model) + { + ; + } +protected: + + /// Data model + PlayListModel* m_model; +}; + +/*! + * Represents normal playing state. + * @author Vladimir Kuznetsov + */ +class NormalPlayState : public PlayState +{ +public: + virtual bool next(); + virtual bool previous(); + NormalPlayState(PlayListModel* model); +}; + +/*! + * Represents shuffle playing state. + * @author Vladimir Kuznetsov + */ +class ShufflePlayState : public PlayState +{ +public: + virtual bool next(); + virtual bool previous(); + virtual void prepare(); + ShufflePlayState(PlayListModel* model); + virtual void resetState(); +private: + + /// Current shuffled index. + int m_shuffled_current; + + /// List of indexes used for shuffled playing. + QList m_shuffled_indexes; +}; + + +#endif diff --git a/src/ui/playstatus.cpp b/src/ui/playstatus.cpp new file mode 100644 index 000000000..913199c4f --- /dev/null +++ b/src/ui/playstatus.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "skin.h" +#include "playstatus.h" + +PlayStatus::PlayStatus ( QWidget *parent ) + : PixmapWidget ( parent ) +{ + m_skin = Skin::getPointer(); + setStatus ( STOP ); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); +} + + +PlayStatus::~PlayStatus() +{} + +void PlayStatus::setStatus ( Type st ) +{ + m_status = st; + switch ( ( uint ) st ) + { + case PLAY: + { + setPixmap ( m_skin->getItem ( Skin::PLAY )); + break; + } + case STOP: + { + setPixmap ( m_skin->getItem ( Skin::STOP )); + break; + } + case PAUSE: + { + setPixmap ( m_skin->getItem ( Skin::PAUSE )); + break; + } + } +} + +void PlayStatus::updateSkin() +{ + setStatus ( m_status ); +} + + diff --git a/src/ui/playstatus.h b/src/ui/playstatus.h new file mode 100644 index 000000000..b050de1ca --- /dev/null +++ b/src/ui/playstatus.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef PLAYSTATUS_H +#define PLAYSTATUS_H + +#include + +/** + @author Ilya Kotov +*/ +class Skin; + +class PlayStatus : public PixmapWidget +{ +Q_OBJECT +public: + PlayStatus(QWidget *parent = 0); + + ~PlayStatus(); + + enum Type + { + PLAY, + STOP, + PAUSE, + }; + +void setStatus(Type); + +private slots: + void updateSkin(); + +private: + Skin *m_skin; + Type m_status; +}; + +#endif diff --git a/src/ui/pluginitem.cpp b/src/ui/pluginitem.cpp new file mode 100644 index 000000000..2ccd8e41d --- /dev/null +++ b/src/ui/pluginitem.cpp @@ -0,0 +1,182 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pluginitem.h" + +/*Input*/ +InputPluginItem::InputPluginItem(QObject *parent, DecoderFactory *fact, + const QString &filePath) + : QObject(parent) +{ + m_fileName = filePath.section('/',-1); + m_factory = fact; +} + +InputPluginItem::~InputPluginItem() +{} + +bool InputPluginItem::isSelected() +{ + QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); + QStringList blacklist = settings.value("Decoder/disabled_plugins").toStringList(); + return !blacklist.contains(m_fileName); +} + +DecoderFactory* InputPluginItem::factory() +{ + return m_factory; +} + +void InputPluginItem::setSelected(bool select) +{ + QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); + QStringList blacklist = settings.value("Decoder/disabled_plugins").toStringList(); + if (select) + blacklist.removeAll (m_fileName); + else + blacklist.append (m_fileName); + settings.setValue("Decoder/disabled_plugins", blacklist); +} + +/*Output*/ +OutputPluginItem::OutputPluginItem(QObject *parent, OutputFactory *fact, + const QString &filePath): QObject(parent) +{ + m_fileName = filePath.section('/',-1); + m_factory = fact; +} + + +OutputPluginItem::~OutputPluginItem() +{} + +void OutputPluginItem::select() +{ + QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); + settings.setValue("Output/plugin_file", m_fileName); +} + +bool OutputPluginItem::isSelected() +{ + QSettings settings (QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat); + return m_fileName == settings.value("Output/plugin_file","libalsa.so").toString(); +} + +OutputFactory *OutputPluginItem::factory() +{ + return m_factory; +} + +/*Visual*/ +VisualPluginItem::VisualPluginItem(QObject *parent, VisualFactory *fact, + const QString &filePath): QObject(parent) +{ + m_fileName = filePath.section('/',-1); + m_factory = fact; +} + + +VisualPluginItem::~VisualPluginItem() +{} + +void VisualPluginItem::select(bool on) +{ + if(on) + SoundCore::instance()->addVisual(m_factory, 0); + else + SoundCore::instance()->removeVisual(m_factory); +} + +bool VisualPluginItem::isSelected() +{ + return Visual::isEnabled(m_factory); +} + +VisualFactory *VisualPluginItem::factory() +{ + return m_factory; +} + +/*Effect*/ +EffectPluginItem::EffectPluginItem(QObject *parent, EffectFactory *fact, + const QString &filePath): QObject(parent) +{ + m_fileName = filePath.section('/',-1); + m_factory = fact; +} + + +EffectPluginItem::~EffectPluginItem() +{} + +void EffectPluginItem::select(bool on) +{ + Effect::setEnabled(m_factory, on); +} + +bool EffectPluginItem::isSelected() +{ + return Effect::isEnabled(m_factory); +} + +EffectFactory *EffectPluginItem::factory() +{ + return m_factory; +} + +/*General*/ +GeneralPluginItem::GeneralPluginItem(QObject *parent, GeneralFactory *fact, + const QString &filePath): QObject(parent) +{ + m_fileName = filePath.section('/',-1); + m_factory = fact; +} + + +GeneralPluginItem::~GeneralPluginItem() +{} + +void GeneralPluginItem::select(bool on) +{ + General::setEnabled(m_factory, on); +} + +bool GeneralPluginItem::isSelected() +{ + return General::isEnabled(m_factory); +} + +GeneralFactory *GeneralPluginItem::factory() +{ + return m_factory; +} + diff --git a/src/ui/pluginitem.h b/src/ui/pluginitem.h new file mode 100644 index 000000000..8b3dc3b73 --- /dev/null +++ b/src/ui/pluginitem.h @@ -0,0 +1,132 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef PLUGINITEM_H +#define PLUGINITEM_H + +#include + +/** + @author Ilya Kotov +*/ + +class DecoderFactory; +class OutputFactory; +class VisualFactory; +class EffectFactory; +class GeneralFactory; + +class InputPluginItem : public QObject +{ + Q_OBJECT +public: + InputPluginItem(QObject *parent, DecoderFactory *fact, const QString &filePath); + + ~InputPluginItem(); + + bool isSelected(); + DecoderFactory * factory(); + +public slots: + void setSelected(bool); + +private: + QString m_fileName; + DecoderFactory *m_factory; + +}; + +class OutputPluginItem : public QObject +{ + Q_OBJECT +public: + OutputPluginItem(QObject *parent, OutputFactory *fact, const QString &filePath); + + ~OutputPluginItem(); + + bool isSelected(); + OutputFactory * factory(); + +public slots: + void select(); + +private: + QString m_fileName; + OutputFactory *m_factory; + +}; + +class VisualPluginItem : public QObject +{ + Q_OBJECT +public: + VisualPluginItem(QObject *parent, VisualFactory *fact, const QString &filePath); + + ~VisualPluginItem(); + + bool isSelected(); + VisualFactory * factory(); + +public slots: + void select(bool); + +private: + QString m_fileName; + VisualFactory *m_factory; +}; + +class EffectPluginItem : public QObject +{ + Q_OBJECT +public: + EffectPluginItem(QObject *parent, EffectFactory *fact, const QString &filePath); + + ~EffectPluginItem(); + + bool isSelected(); + EffectFactory * factory(); + +public slots: + void select(bool); + +private: + QString m_fileName; + EffectFactory *m_factory; +}; + +class GeneralPluginItem : public QObject +{ + Q_OBJECT +public: + GeneralPluginItem(QObject *parent, GeneralFactory *fact, const QString &filePath); + + ~GeneralPluginItem(); + + bool isSelected(); + GeneralFactory * factory(); + +public slots: + void select(bool); + +private: + QString m_fileName; + GeneralFactory *m_factory; +}; + +#endif diff --git a/src/ui/positionbar.cpp b/src/ui/positionbar.cpp new file mode 100644 index 000000000..5431fd4f3 --- /dev/null +++ b/src/ui/positionbar.cpp @@ -0,0 +1,137 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include "skin.h" +#include "button.h" +#include "mainwindow.h" + +#include "positionbar.h" + + +PositionBar::PositionBar(QWidget *parent) + : PixmapWidget(parent) +{ + m_skin = Skin::getPointer(); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); + setPixmap(m_skin->getPosBar()); + mw = qobject_cast(window()); + m_moving = FALSE; + m_min = 0; + m_max = 50; + m_old = m_value = 0; + draw(FALSE); +} + + +PositionBar::~PositionBar() +{} + +void PositionBar::mousePressEvent(QMouseEvent *e) +{ + + m_moving = TRUE; + press_pos = e->x(); + if(m_posx() && e->x()x()-m_pos; + } + else + { + m_value = convert(qMax(qMin(width()-30,e->x()-15),0)); + press_pos = 15; + if (m_value!=m_old) + { + emit sliderMoved(m_value); + + } + } + draw(); +} + +void PositionBar::mouseMoveEvent (QMouseEvent *e) +{ + if(m_moving) + { + int po = e->x(); + po = po - press_pos; + + if(0<=po && po<=width()-30) + { + m_value = convert(po); + draw(); + emit sliderMoved(m_value); + } + } +} + +void PositionBar::mouseReleaseEvent(QMouseEvent*) +{ + m_moving = FALSE; + draw(FALSE); + if (m_value!=m_old) + { + m_old = m_value; + mw->seek(m_value); + } + +} + +void PositionBar::setValue(int v) +{ + if (m_moving || m_max == 0) + return; + m_value = v; + draw(FALSE); +} + +void PositionBar::setMax(int max) +{ + m_max = max; + draw(FALSE); +} + +void PositionBar::updateSkin() +{ + draw(FALSE); + //setPixmap(m_skin->getPosBar()); + //setButtonPixmap(Skin::BT_POSBAR_N); +} + +void PositionBar::draw(bool pressed) +{ + int p=int(ceil(double(m_value-m_min)*(width()-30)/(m_max-m_min))); + m_pixmap = m_skin->getPosBar(); + QPainter paint(&m_pixmap); + if(pressed) + paint.drawPixmap(p,0,m_skin->getButton(Skin::BT_POSBAR_P)); + else + paint.drawPixmap(p,0,m_skin->getButton(Skin::BT_POSBAR_N)); + setPixmap(m_pixmap); + m_pos = p; +} + +int PositionBar::convert(int p) +{ + return int(ceil(double(m_max-m_min)*(p)/(width()-30)+m_min)); +} diff --git a/src/ui/positionbar.h b/src/ui/positionbar.h new file mode 100644 index 000000000..ea03ef14a --- /dev/null +++ b/src/ui/positionbar.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef POSITIONBAR_H +#define POSITIONBAR_H + +#include "pixmapwidget.h" + +/** + @author Ilya Kotov +*/ + +class QMouseEvent; + +class MainWindow; +class Skin; + + +class PositionBar : public PixmapWidget +{ + Q_OBJECT +public: + PositionBar(QWidget *parent = 0); + + ~PositionBar(); + +public slots: + void setValue(int); + int value()const{return m_value;} + void setMax(int); + +signals: + void sliderMoved (int); + +private slots: + void updateSkin(); + +private: + Skin *m_skin; + bool m_moving; + int press_pos; + int m_max, m_min, m_pos, m_value, m_old; + QPixmap m_pixmap; + MainWindow *mw; + int convert(int); // value = convert(position); + void draw(bool pressed = TRUE); + +protected: + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + + +}; + +#endif diff --git a/src/ui/preseteditor.cpp b/src/ui/preseteditor.cpp new file mode 100644 index 000000000..1b55a229d --- /dev/null +++ b/src/ui/preseteditor.cpp @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "eqpreset.h" + +#include "preseteditor.h" + +PresetEditor::PresetEditor(QWidget *parent) + : QDialog(parent) +{ + ui.setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + connect(ui.loadButton,SIGNAL(clicked()),SLOT(loadPreset())); + connect(ui.deleteButton,SIGNAL(clicked()),SLOT(deletePreset())); +} + + +PresetEditor::~PresetEditor() +{ + while (ui.presetListWidget->count () !=0) + ui.presetListWidget->takeItem (0); + + while (ui.autoPresetListWidget->count () !=0) + ui.autoPresetListWidget->takeItem (0); +} + +void PresetEditor::addPresets(const QList &presets) +{ + foreach(QListWidgetItem *item, presets) + { + ui.presetListWidget->addItem(item); + } +} + +void PresetEditor::addAutoPresets(const QList &presets) +{ + foreach(QListWidgetItem *item, presets) + { + ui.autoPresetListWidget->addItem(item); + } +} + +void PresetEditor::loadPreset() +{ + EQPreset* preset = 0; + if (ui.tabWidget->currentIndex () == 0) + preset = (EQPreset *) ui.presetListWidget->currentItem (); + if (ui.tabWidget->currentIndex () == 1) + preset = (EQPreset *) ui.autoPresetListWidget->currentItem (); + if (preset) + emit presetLoaded(preset); +} + +void PresetEditor::deletePreset() +{ + EQPreset* preset = 0; + if (ui.tabWidget->currentIndex () == 0) + preset = (EQPreset *) ui.presetListWidget->currentItem (); + if (ui.tabWidget->currentIndex () == 1) + preset = (EQPreset *) ui.autoPresetListWidget->currentItem (); + if (preset) + emit presetDeleted(preset); +} diff --git a/src/ui/preseteditor.h b/src/ui/preseteditor.h new file mode 100644 index 000000000..35302b185 --- /dev/null +++ b/src/ui/preseteditor.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef PRESETEDITOR_H +#define PRESETEDITOR_H + +#include + +#include "ui_preseteditor.h" + +/** + @author Ilya Kotov +*/ + +class EQPreset; + +class PresetEditor : public QDialog +{ +Q_OBJECT +public: + PresetEditor(QWidget *parent = 0); + + ~PresetEditor(); + + void addPresets(const QList&); + void addAutoPresets(const QList&); + +signals: + void presetLoaded(EQPreset*); + void presetDeleted(EQPreset*); + +private slots: + void loadPreset(); + void deletePreset(); + +private: + Ui::PresetEditor ui; + +}; + +#endif diff --git a/src/ui/qmmpstarter.cpp b/src/ui/qmmpstarter.cpp new file mode 100644 index 000000000..b04916983 --- /dev/null +++ b/src/ui/qmmpstarter.cpp @@ -0,0 +1,154 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "unixdomainsocket.h" +#include + +#include "mainwindow.h" +#include "version.h" +#include "qmmpstarter.h" +#include "commandlineoption.h" + +#define MAXCOMMANDSIZE 1024 + +QMMPStarter::QMMPStarter(int argc,char ** argv,QObject* parent) : QObject(parent),mw(NULL) +{ + m_option_manager = new CommandLineOptionManager(); + QStringList tmp; + for(int i = 1;i < argc;i++) + tmp << QString::fromLocal8Bit(argv[i]); + + argString = tmp.join("\n"); + + if(argString == "--help") + { + printUsage(); + exit(0); + } + else if(argString == "--version") + { + printVersion(); + exit(0); + } + + if(argString.startsWith("--") && // command? + !m_option_manager->hasOption(argString) + ) + { + qFatal("QMMP: Unknown command..."); + exit(1); + } + + m_sock = new UnixDomainSocket(this); + if(m_sock->bind(UDS_PATH)) + { + startMainWindow(); + } + else if(!m_sock->alive(UDS_PATH)){ + // Socket is present but not connectable - application was terminated previously??? + unlink(UDS_PATH); + if(m_sock->bind(UDS_PATH)) + { + startMainWindow(); + } + else + { + qDebug("Fatal socket error, exiting"); + exit(1); + } + } + else // socket is alive, qmmp application is already running. passing command to it! + writeCommand(); +} + +QMMPStarter::~ QMMPStarter() +{ + if(mw) delete mw; +} + +void QMMPStarter::startMainWindow() +{ + connect(m_sock, SIGNAL(readyRead()),this, SLOT(readCommand())); + QStringList arg_l = argString.split("\n", QString::SkipEmptyParts); + mw = new MainWindow(arg_l,m_option_manager,0); +} + +void QMMPStarter::writeCommand() +{ + if(!argString.isEmpty()) + { + char buf[PATH_MAX + 1]; + QString workingDir = QString(getcwd(buf,PATH_MAX)) + "\n"; + + QByteArray barray; + barray.append(workingDir); + barray.append(argString); + m_sock->writeDatagram ( barray.data(),UDS_PATH); + } + else + { + printUsage(); + } + + exit(0); +} + +void QMMPStarter::readCommand() +{ + QByteArray inputArray; + inputArray.resize(MAXCOMMANDSIZE); + bzero(inputArray.data(),inputArray.size()); + m_sock->readDatagram(inputArray.data(), inputArray.size()); + QStringList slist = QString(inputArray).split("\n",QString::SkipEmptyParts); + QString cwd = slist.takeAt(0); + if(mw) + { + mw->processCommandArgs(slist,cwd); + } + +} + +void QMMPStarter::printUsage() +{ + qWarning( + "Usage: qmmp [options] [files] \n" + "Options:\n" + "--------\n" + ); + for(int i = 0; i< m_option_manager->count();i++) + { + qWarning(qPrintable((*m_option_manager)[i]->helpString())); + } + qWarning( + "--help Display this text and exit.\n" + "--version Print version number and exit.\n\n" + "Ideas, patches, bugreports send to forkotov02@hotmail.ru\n" + ); +} + +void QMMPStarter::printVersion() +{ + qWarning("QMMP version: %s",QMMP_STR_VERSION); +} + + + diff --git a/src/ui/qmmpstarter.h b/src/ui/qmmpstarter.h new file mode 100644 index 000000000..010c5385f --- /dev/null +++ b/src/ui/qmmpstarter.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ + +#ifndef _QMMPSTARTER_H +#define _QMMPSTARTER_H + +#include +#include +#include + +class UnixDomainSocket; +class MainWindow; +class CommandLineOptionManager; + +/*! + * QMMPStarter represents wrapper object that is responsible + * for proper QMMP initialization(only one instance of running + * MainWindow) and passing command line args to application. + * @author Vladimir Kuznetsov + */ +class QMMPStarter : public QObject +{ +Q_OBJECT +public: + QMMPStarter(int argc,char ** argv,QObject* parent = 0); + ~QMMPStarter(); +protected slots: + + /*! + * Passes command args to the running application + */ + void writeCommand(); + + void readCommand(); +private: + /*! + * Prints usage + */ + void printUsage(); + + /*! + * Prints version of program + */ + void printVersion(); + + void startMainWindow(); +private: + MainWindow* mw; + UnixDomainSocket* m_sock; + QString argString; + CommandLineOptionManager* m_option_manager; +}; + +#endif + + diff --git a/src/ui/shadedbar.cpp b/src/ui/shadedbar.cpp new file mode 100644 index 000000000..63b2017c0 --- /dev/null +++ b/src/ui/shadedbar.cpp @@ -0,0 +1,139 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include + +#include "skin.h" + +#include "shadedbar.h" + +ShadedBar::ShadedBar(QWidget *parent, uint slider1, uint slider2, uint slider3) + : QWidget(parent) +{ + m_slider1 = slider1; + m_slider2 = slider2; + m_slider3 = slider3; + setFixedSize(97,7); + //setAutoFillBackground (TRUE); + m_skin = Skin::getPointer(); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); + m_moving = FALSE; + m_min = 0; + m_max = 100; + m_old = m_value = 0; + draw(); +} + + +ShadedBar::~ShadedBar() +{ +} + +void ShadedBar::mousePressEvent(QMouseEvent *e) +{ + + m_moving = TRUE; + press_pos = e->x(); + if(m_posx() && e->x()x()-m_pos; + } + else + { + m_value = convert(qMax(qMin(width()-3,e->x()-1),0)); + press_pos = 1; + if (m_value!=m_old) + { + emit sliderMoved(m_value); + } + } + draw(); +} + +void ShadedBar::mouseMoveEvent (QMouseEvent *e) +{ + if(m_moving) + { + int po = e->x(); + po = po - press_pos; + + if(0<=po && po<=width()-3) + { + m_value = convert(po); + draw(); + emit sliderMoved(m_value); + qDebug("%d", m_value); + } + } +} + +void ShadedBar::mouseReleaseEvent(QMouseEvent*) +{ + m_moving = FALSE; + draw(); + m_old = m_value; +} + +void ShadedBar::setValue(int v) +{ + if (m_moving || m_max == 0) + return; + m_value = v; + draw(); +} + +void ShadedBar::setRange(int min, int max) +{ + m_max = max; + m_min = min; + draw(); +} + +void ShadedBar::updateSkin() +{ + draw(); +} + +void ShadedBar::draw() +{ + if (m_value <= m_min + (m_max - m_min)/3) + m_pixmap = m_skin->getEqPart(m_slider1); + else if(m_min + (m_max - m_min)/3 < m_value && m_value <= m_min + 2*(m_max - m_min)/3) + m_pixmap = m_skin->getEqPart(m_slider2); + else + m_pixmap = m_skin->getEqPart(m_slider3); + m_pos = int(ceil(double(m_value-m_min)*(width()-3)/(m_max-m_min))); + update(); +} + +int ShadedBar::convert(int p) +{ + return int(ceil(double(m_max-m_min)*(p)/(width()-3)+m_min)); +} + +void ShadedBar::paintEvent(QPaintEvent*) +{ + QPainter paint(this); + paint.drawPixmap(m_pos,0,m_pixmap); +} + diff --git a/src/ui/shadedbar.h b/src/ui/shadedbar.h new file mode 100644 index 000000000..4ea8c871f --- /dev/null +++ b/src/ui/shadedbar.h @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SHADEDBAR_H +#define SHADEDBAR_H + +#include + +class QMouseEvent; +class QPaintEvent; + +class Skin; + + +/** + @author Ilya Kotov +*/ +class ShadedBar : public QWidget +{ + Q_OBJECT +public: + ShadedBar(QWidget *parent = 0, uint slider1 = 0, uint slider2 = 0, uint slider3 = 0); + + ~ShadedBar(); + int value() + { + return m_value; + }; + int isPressed() + { + return m_moving; + } + void setRange(int min, int max); + +public slots: + void setValue(int); + +signals: + void sliderMoved (int); + +private slots: + void updateSkin(); + +private: + Skin *m_skin; + bool m_moving; + int press_pos; + int m_max, m_min, m_pos, m_value, m_old, m_x; + QPixmap m_pixmap; + int convert(int); // value = convert(position); + void draw(); + uint m_slider1, m_slider2, m_slider3; + +protected: + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + void paintEvent(QPaintEvent*); +}; + +#endif diff --git a/src/ui/shadedvisual.cpp b/src/ui/shadedvisual.cpp new file mode 100644 index 000000000..2dea3d419 --- /dev/null +++ b/src/ui/shadedvisual.cpp @@ -0,0 +1,205 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include "skin.h" +#include "mainvisual.h" +#include "inlines.h" + + +#include "shadedvisual.h" + +ShadedVisual::ShadedVisual(QWidget *parent) + : Visual(parent) +{ + setFixedSize(38,5); + m_pixmap = QPixmap (38,5); + m_skin = Skin::getPointer(); + m_timer = new QTimer(this); + connect(m_timer, SIGNAL (timeout()), this, SLOT (timeout())); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); + m_timer->setInterval(50); + m_timer->start(); + clear(); +} + + +ShadedVisual::~ShadedVisual() +{} + +void ShadedVisual::add(Buffer *b, unsigned long w, int c, int p) +{ + if (!m_timer->isActive ()) + return; + long len = b->nbytes, cnt; + short *l = 0, *r = 0; + + len /= c; + len /= ( p / 8 ); + if ( len > 512 ) + len = 512; + cnt = len; + + if ( c == 2 ) + { + l = new short[len]; + r = new short[len]; + + if ( p == 8 ) + stereo16_from_stereopcm8 ( l, r, b->data, cnt ); + else if ( p == 16 ) + stereo16_from_stereopcm16 ( l, r, ( short * ) b->data, cnt ); + } + else if ( c == 1 ) + { + l = new short[len]; + + if ( p == 8 ) + mono16_from_monopcm8 ( l, b->data, cnt ); + else if ( p == 16 ) + mono16_from_monopcm16 ( l, ( short * ) b->data, cnt ); + } + else + len = 0; + + if (len) + m_nodes.append (new VisualNode (l, r, len, w)); +} + +void ShadedVisual::clear() +{ + while (!m_nodes.isEmpty()) + m_nodes.removeFirst(); + m_l = 0; + m_r = 0; + m_pixmap.fill(m_skin->getVisColor(0)); + update(); +}; + +void ShadedVisual::timeout() +{ + VisualNode *node = 0; + m_pixmap.fill(m_skin->getVisColor(0)); + + if ( /*playing &&*/ output()) + { + //output()->mutex()->lock (); + //long olat = output()->latency(); + //long owrt = output()->written(); + //output()->mutex()->unlock(); + + //long synctime = owrt < olat ? 0 : owrt - olat; + + mutex()->lock (); + VisualNode *prev = 0; + while ((!m_nodes.isEmpty())) + { + node = m_nodes.takeFirst(); + /*if ( node->offset > synctime ) + break;*/ + + if (prev) + delete prev; + prev = node; + } + mutex()->unlock(); + node = prev; + } + + if (!node) + return; + process (node); + delete node; + QPainter p(&m_pixmap); + draw (&p); + update(); +} + +void ShadedVisual::process (VisualNode *node) +{ + if (!node) + return; + + int step = (node->length << 8)/74; + int pos = 0; + int l = 0; + int r = 0; + int j_l = 0, j_r = 0; + + for (int i = 0; i < 75; ++i) + { + pos += step; + + if (node->left) + { + j_l = abs((node->left[pos >> 8] >> 12)); + + if (j_l > 15) + j_l = 15; + l = qMax(l, j_l); + } + if (node->right) + { + j_r = abs((node->right[pos >> 8] >> 12)); + if (j_r > 15) + j_r = 15; + r = qMax(r, j_r); + } + } + m_l -= 0.5; + m_l = m_l > l ? m_l : l; + m_r -= 0.5; + m_r = m_r > r ? m_r : r; +} + +void ShadedVisual::draw (QPainter *p) +{ + for (int i = 0; i < m_l; ++i) + { + p->fillRect (i*3, 0, 3, 2, QBrush(m_skin->getVisColor (17-i))); + } + for (int i = 0; i < m_r; ++i) + { + p->fillRect (i*3, 3, 3, 2, QBrush(m_skin->getVisColor (17-i))); + } +} + +void ShadedVisual::paintEvent (QPaintEvent *) +{ + QPainter painter (this); + painter.drawPixmap (0,0,m_pixmap); +} + +void ShadedVisual::hideEvent (QHideEvent *) +{ + m_timer->stop(); +} + +void ShadedVisual::showEvent (QShowEvent *) +{ + m_timer->start(); +} + +void ShadedVisual::updateSkin() +{ + clear(); +} + diff --git a/src/ui/shadedvisual.h b/src/ui/shadedvisual.h new file mode 100644 index 000000000..e46331ecb --- /dev/null +++ b/src/ui/shadedvisual.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SHADEDVISUAL_H +#define SHADEDVISUAL_H + + +#include +#include +#include + +class QTimer; +class QPixmap; + +class Skin; +class VisualNode; + +/** + @author Ilya Kotov +*/ +class ShadedVisual : public Visual +{ + Q_OBJECT +public: + ShadedVisual(QWidget *parent = 0); + + ~ShadedVisual(); + + void add(Buffer *, unsigned long, int, int); + void clear(); + + void paintEvent (QPaintEvent *); + void hideEvent (QHideEvent *); + void showEvent (QShowEvent *); + +public slots: + void timeout(); + +private slots: + void updateSkin(); + +private: + void process (VisualNode *node); + void draw (QPainter *); + Skin *m_skin; + QTimer *m_timer; + QPixmap m_pixmap; + QList m_nodes; + double m_l, m_r; + +}; + +#endif diff --git a/src/ui/skin.cpp b/src/ui/skin.cpp new file mode 100644 index 000000000..b7f787ad4 --- /dev/null +++ b/src/ui/skin.cpp @@ -0,0 +1,771 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "skin.h" + +Skin *Skin::pointer = 0; + +Skin *Skin::getPointer() +{ + if ( !pointer ) + pointer = new Skin(); + return pointer; +} + +QPixmap Skin::getPixmap ( const QString& name, QDir dir ) +{ + dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); + QFileInfoList f = dir.entryInfoList(); + for ( int j = 0; j < f.size(); ++j ) + { + QFileInfo fileInfo = f.at ( j ); + QString fn = fileInfo.fileName().toLower(); + if ( fn.section ( ".",0,0 ) == name ) + { + return QPixmap ( fileInfo.filePath() ); + } + } + return QPixmap(); +} + +Skin::Skin ( QObject *parent ) + : QObject ( parent ) +{ + pointer = this; + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + QString path = settings.value("skin_path","").toString(); + if (path.isEmpty() || !QDir(path).exists ()) + path = ":/default"; + setSkin (QDir::cleanPath(path)); + /* skin directory */ + QDir skinDir(QDir::homePath()+"/.qmmp"); + skinDir.mkdir ("skins"); +} + + +Skin::~Skin() +{} + +void Skin::setSkin ( const QString& path ) +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.setValue("skin_path",path); + + qDebug ( path.toAscii() ); //TODO don't clear lists + m_skin_dir = QDir ( path ); + + m_pledit_txt.clear(); + loadPLEdit(); + loadMain(); + buttons.clear(); + loadButtons(); + loadShufRep(); + titlebar.clear(); + loadTitleBar(); + loadPosBar(); + m_numbers.clear(); + loadNumbers(); + m_pl_parts.clear(); + loadPlayList(); + m_eq_parts.clear(); + loadEq_ex(); + m_eq_bar.clear(); + m_eq_spline.clear(); + loadEqMain(); + m_vis_colors.clear(); + loadVisColor(); + loadLetters(); + loadMonoSter(); + loadVolume(); + loadBalance(); + loadRegion(); + loadColors(); + + emit skinChanged(); +} + +void Skin::loadMain() +{ + QPixmap *pixmap = getPixmap ("main"); + if (!pixmap) + pixmap = getDummyPixmap("main"); + + m_main = pixmap->copy ( 0,0,275,116 ); + delete pixmap; +} + +void Skin::loadButtons() +{ + + QPixmap *pixmap = getPixmap ("cbuttons"); + + if (!pixmap) + pixmap = getDummyPixmap("cbuttons"); + + buttons[BT_PREVIOUS_N] = pixmap->copy ( 0, 0,23,18 ); + buttons[BT_PREVIOUS_P] = pixmap->copy ( 0,18,23,18 ); + + buttons[BT_PLAY_N] = pixmap->copy ( 23, 0,23,18 ); + buttons[BT_PLAY_P] = pixmap->copy ( 23,18,23,18 ); + + buttons[BT_PAUSE_N] = pixmap->copy ( 46, 0,23,18 ); + buttons[BT_PAUSE_P] = pixmap->copy ( 46,18,23,18 ); + + buttons[BT_STOP_N] = pixmap->copy ( 69, 0,23,18 ); + buttons[BT_STOP_P] = pixmap->copy ( 69,18,23,18 ); + + buttons[BT_NEXT_N] = pixmap->copy ( 92, 0,22,18 ); + buttons[BT_NEXT_P] = pixmap->copy ( 92,18,22,18 ); + + buttons[BT_EJECT_N] = pixmap->copy ( 114, 0,22,16 ); + buttons[BT_EJECT_P] = pixmap->copy ( 114,16,22,16 ); + delete pixmap; + +} + +void Skin::loadTitleBar() +{ + + QPixmap *pixmap = getPixmap ("titlebar"); + + if (!pixmap) + pixmap = getDummyPixmap("titlebar"); + + buttons[BT_MENU_N] = pixmap->copy ( 0,0,9,9 ); + buttons[BT_MENU_P] = pixmap->copy ( 0,9,9,9 ); + buttons[BT_MINIMIZE_N] = pixmap->copy ( 9,0,9,9 ); + buttons[BT_MINIMIZE_P] = pixmap->copy ( 9,9,9,9 ); + buttons[BT_CLOSE_N] = pixmap->copy ( 18,0,9,9 ); + buttons[BT_CLOSE_P] = pixmap->copy ( 18,9,9,9 ); + buttons[BT_SHADE1_N] = pixmap->copy ( 0,18,9,9 ); + buttons[BT_SHADE1_P] = pixmap->copy ( 9,18,9,9 ); + buttons[BT_SHADE2_N] = pixmap->copy ( 0,27,9,9 ); + buttons[BT_SHADE2_P] = pixmap->copy ( 9,27,9,9 ); + titlebar[TITLEBAR_A] = pixmap->copy ( 27, 0,275,14 ); + titlebar[TITLEBAR_I] = pixmap->copy ( 27,15,275,14 ); + titlebar[TITLEBAR_SHADED_A] = pixmap->copy ( 27,29,275,14 ); + titlebar[TITLEBAR_SHADED_I] = pixmap->copy ( 27,42,275,14 ); + delete pixmap; + +} + +void Skin::loadPosBar() +{ + + QPixmap *pixmap = getPixmap ("posbar"); + + if (!pixmap) + pixmap = getDummyPixmap("posbar"); + + if (pixmap->width() > 249) + { + buttons[BT_POSBAR_N] = pixmap->copy ( 248,0,29, pixmap->height()); + buttons[BT_POSBAR_P] = pixmap->copy ( 278,0,29, pixmap->height()); + } + else + { + QPixmap dummy(29, pixmap->height()); + dummy.fill(Qt::transparent); + buttons[BT_POSBAR_N] = dummy; + buttons[BT_POSBAR_P] = dummy; + } + posbar = pixmap->copy ( 0,0,248,pixmap->height() ); + delete pixmap; + +} + +void Skin::loadNumbers() +{ + QPixmap *pixmap = getPixmap ( "numbers" ); + if ( !pixmap ) + { + pixmap = getPixmap ( "nums_ex" ); + } + for ( uint i = 0; i < 10; i++ ) + { + m_numbers << pixmap->copy ( i*9, 0, 9, 13 ); + } + if (pixmap->width() > 107) + { + m_numbers << pixmap->copy(99, 0, 9,13 ); + } + else + { // We didn't find "-" symbol. So we have to extract it from "2". + // Winamp uses this method too. + QPixmap pix = pixmap->copy(90,0,9,13); + QPixmap minus = pixmap->copy(18,6,9,1); + QPainter paint(&pix); + paint.drawPixmap(0,6, minus); + m_numbers << pix; + } + delete pixmap; +} + +void Skin::loadPlayList() +{ + + QPixmap *pixmap = getPixmap ("pledit"); + + if (!pixmap) + pixmap = getDummyPixmap("pledit"); + + m_pl_parts[PL_CORNER_UL_A] = pixmap->copy ( 0,0,25,20 ); + m_pl_parts[PL_CORNER_UL_I] = pixmap->copy ( 0,21,25,20 ); + + m_pl_parts[PL_CORNER_UR_A] = pixmap->copy ( 153,0,25,20 ); + m_pl_parts[PL_CORNER_UR_I] = pixmap->copy ( 153,21,25,20 ); + + m_pl_parts[PL_TITLEBAR_A] = pixmap->copy ( 26,0,100,20 ); + m_pl_parts[PL_TITLEBAR_I] = pixmap->copy ( 26,21,100,20 ); + + m_pl_parts[PL_TFILL1_A] = pixmap->copy ( 127,0,25,20 ); + m_pl_parts[PL_TFILL1_I] = pixmap->copy ( 127,21,25,20 ); + + //m_pl_parts[PL_TFILL2_A] = pixmap->copy();//FIXME: ����� + //m_pl_parts[PL_TFILL2_I] = pixmap->copy(); + + m_pl_parts[PL_LFILL] = pixmap->copy ( 0,42,12,29 ); + m_pl_parts[PL_RFILL] = pixmap->copy ( 31,42,20,29 ); //??? + + m_pl_parts[PL_LSBAR] = pixmap->copy ( 0,72,125,38 ); + m_pl_parts[PL_RSBAR] = pixmap->copy ( 126,72,150,38 ); + m_pl_parts[PL_SFILL1] = pixmap->copy ( 179,0,25,38 ); + m_pl_parts[PL_SFILL2] = pixmap->copy ( 250,21,75,38 ); + m_pl_parts[PL_TITLEBAR_SHADED1_A] = pixmap->copy ( 99,42,50,14 ); + m_pl_parts[PL_TITLEBAR_SHADED1_I] = pixmap->copy ( 99,57,50,14 ); + m_pl_parts[PL_TITLEBAR_SHADED2] = pixmap->copy ( 72,42,25,14 ); + m_pl_parts[PL_TFILL_SHADED] = pixmap->copy ( 72,57,25,14 ); + + m_pl_parts[PL_CONTROL] = pixmap->copy(129,94,60,8); + + buttons[PL_BT_ADD] = pixmap->copy ( 11,80,25,18 ); + buttons[PL_BT_SUB] = pixmap->copy ( 40,80,25,18 ); + buttons[PL_BT_SEL] = pixmap->copy ( 70,80,25,18 ); + buttons[PL_BT_SORT] = pixmap->copy ( 99,80,25,18 ); + buttons[PL_BT_LST] = pixmap->copy(229, 80, 25, 18); + buttons[PL_BT_SCROLL_N] = pixmap->copy ( 52,53,8,18 ); + buttons[PL_BT_SCROLL_P] = pixmap->copy ( 61,53,8,18 ); + + buttons[PL_BT_CLOSE_N] = pixmap->copy (167,3,9,9); + buttons[PL_BT_CLOSE_P] = pixmap->copy (52,42,9,9); + buttons[PL_BT_SHADE1_N] = pixmap->copy (158,3,9,9); + buttons[PL_BT_SHADE1_P] = pixmap->copy (62,42,9,9); + buttons[PL_BT_SHADE2_N] = pixmap->copy (129,45,9,9); + buttons[PL_BT_SHADE2_P] = pixmap->copy (150,42,9,9); + +} + +QPixmap *Skin::getPixmap ( const QString& name ) +{ + m_skin_dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); + QFileInfoList f = m_skin_dir.entryInfoList(); + for ( int j = 0; j < f.size(); ++j ) + { + QFileInfo fileInfo = f.at ( j ); + QString fn = fileInfo.fileName().toLower(); + if ( fn.section ( ".",0,0 ) == name ) + { + return new QPixmap ( fileInfo.filePath() ); + } + } + return 0; +} + +void Skin::loadPLEdit() +{ + m_skin_dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); + QString path; + QFileInfoList list = m_skin_dir.entryInfoList(); + for ( int i = 0; i < list.size(); ++i ) + { + QFileInfo fileInfo = list.at ( i ); + if ( fileInfo.fileName().toLower() == "pledit.txt" ) + { + path = fileInfo.filePath (); + break; + } + } + + if ( path.isNull () ) + { + qDebug ( "Skin: Cannot find pledit.txt" ); + return; + } + + + QFile file ( path ); + + if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) ) + return; + + while ( !file.atEnd () ) + { + QByteArray line = file.readLine (); + QList l = line.split ( '=' ); + if ( l.count () == 2 ) + { + m_pledit_txt[l[0].toLower () ] = l[1].trimmed(); + } + else if ( line.length() == 0 ) + { + break; + } + } + +} + +void Skin::loadEqMain() +{ + QPixmap *pixmap = getPixmap ("eqmain"); + + if (!pixmap) + pixmap = getDummyPixmap("eqmain"); + + m_eq_parts[ EQ_MAIN ] = pixmap->copy ( 0,0,275,116 ); + m_eq_parts[ EQ_TITLEBAR_A ] = pixmap->copy ( 0,134,275,14 ); + m_eq_parts[ EQ_TITLEBAR_I ] = pixmap->copy ( 0,149,275,14 ); + m_eq_parts[ EQ_GRAPH ] = pixmap->copy ( 0,294,113,19 ); + for ( int i = 0; i < 14; ++i ) + { + m_eq_bar << pixmap->copy ( 13 + i*15,164,14,63 ); + } + for ( int i = 0; i < 14; ++i ) + { + m_eq_bar << pixmap->copy ( 13 + i*15,229,14,63 ); + } + buttons[ EQ_BT_BAR_N ] = pixmap->copy ( 0,164,11,11 ); + buttons[ EQ_BT_BAR_P ] = pixmap->copy ( 0,164+12,11,11 ); + + buttons[ EQ_BT_ON_N ] = pixmap->copy ( 69,119,28,12 ); + buttons[ EQ_BT_ON_P ] = pixmap->copy ( 128,119,28,12 ); + buttons[ EQ_BT_OFF_N ] = pixmap->copy ( 10, 119,28,12 ); + buttons[ EQ_BT_OFF_P ] = pixmap->copy ( 187,119,28,12 ); + + buttons[ EQ_BT_PRESETS_N ] = pixmap->copy ( 224,164,44,12 ); + buttons[ EQ_BT_PRESETS_P ] = pixmap->copy ( 224,176,44,12 ); + + buttons[ EQ_BT_AUTO_1_N ] = pixmap->copy ( 94,119,33,12 ); + buttons[ EQ_BT_AUTO_1_P ] = pixmap->copy ( 153,119,33,12 ); + buttons[ EQ_BT_AUTO_0_N ] = pixmap->copy ( 35, 119,33,12 ); + buttons[ EQ_BT_AUTO_0_P ] = pixmap->copy ( 212,119,33,12 ); + + buttons[ EQ_BT_CLOSE_N ] = pixmap->copy ( 0,116,9,9 ); + buttons[ EQ_BT_CLOSE_P ] = pixmap->copy ( 0,125,9,9 ); + buttons[ EQ_BT_SHADE1_N ] = pixmap->copy ( 254,137,9,9 ); + + for ( int i = 0; i < 19; ++i ) + { + m_eq_spline << pixmap->copy ( 115, 294+i, 1, 1 ); + } + delete pixmap; + +} + +void Skin::loadEq_ex() +{ + QPixmap *pixmap = getPixmap ("eq_ex"); + + if (!pixmap) + pixmap = getDummyPixmap("eq_ex"); + + buttons[ EQ_BT_SHADE1_P ] = pixmap->copy (1,38,9,9); + buttons[ EQ_BT_SHADE2_N ] = pixmap->copy (254,3,9,9); + buttons[ EQ_BT_SHADE2_P ] = pixmap->copy (1,47,9,9); + m_eq_parts[ EQ_TITLEBAR_SHADED_A ] = pixmap->copy(0,0,275,14); + m_eq_parts[ EQ_TITLEBAR_SHADED_I ] = pixmap->copy(0,15,275,14); + m_eq_parts[ EQ_VOLUME1 ] = pixmap->copy(1,30,3,8); + m_eq_parts[ EQ_VOLUME2 ] = pixmap->copy(4,30,3,8); + m_eq_parts[ EQ_VOLUME3 ] = pixmap->copy(7,30,3,8); + m_eq_parts[ EQ_BALANCE1 ] = pixmap->copy(11,30,3,8); + m_eq_parts[ EQ_BALANCE2 ] = pixmap->copy(14,30,3,8); + m_eq_parts[ EQ_BALANCE3 ] = pixmap->copy(17,30,3,8); + + delete pixmap; +} + +void Skin::loadVisColor() +{ + //QList colors; + m_skin_dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); + QString path; + QFileInfoList list = m_skin_dir.entryInfoList(); + for ( int i = 0; i < list.size(); ++i ) + { + QFileInfo fileInfo = list.at ( i ); + if ( fileInfo.fileName().toLower() == "viscolor.txt" ) + { + path = fileInfo.filePath (); + break; + } + } + + if ( path.isNull () ) + { + qDebug ( "Skin: Cannot find viscolor.txt" ); + return; + } + + + QFile file ( path ); + + if ( !file.open ( QIODevice::ReadOnly | QIODevice::Text ) ) + return; + + int j = 0; + while ( !file.atEnd () && j<24 ) + { + j++; + QByteArray line = file.readLine (); + QString tmp = QString::fromAscii ( line ); + tmp = tmp.trimmed (); + int i = tmp.indexOf ( "//" ); + if ( i>0 ) + tmp.truncate ( tmp.indexOf ( "//" ) ); + QStringList list = tmp.split ( "," ); + if ( list.count () >= 3 ) + { + //colors + int r = list.at ( 0 ).toInt(); + int g = list.at ( 1 ).toInt(); + int b = list.at ( 2 ).toInt(); + m_vis_colors << QColor ( r,g,b ); + } + else if ( line.length() == 0 ) + { + break; + } + } + if (m_vis_colors.size() < 24) + { + qWarning ( "Skin: cannot parse viscolor.txt" ); + while (m_vis_colors.size() < 24) + m_vis_colors << QColor (0,0,0); + } +} + +void Skin::loadShufRep() +{ + QPixmap *pixmap = getPixmap ("shufrep"); + + if (!pixmap) + pixmap = getDummyPixmap("shufrep"); + + buttons[ BT_EQ_ON_N ] = pixmap->copy ( 0,73,23,12 ); + buttons[ BT_EQ_ON_P ] = pixmap->copy ( 46,73,23,12 ); + buttons[ BT_EQ_OFF_N ] = pixmap->copy ( 0,61,23,12 ); + buttons[ BT_EQ_OFF_P ] = pixmap->copy ( 46,61,23,12 ); + + buttons[ BT_PL_ON_N ] = pixmap->copy ( 23,73,23,12 ); + buttons[ BT_PL_ON_P ] = pixmap->copy ( 69,73,23,12 ); + buttons[ BT_PL_OFF_N ] = pixmap->copy ( 23,61,23,12 ); + buttons[ BT_PL_OFF_P ] = pixmap->copy ( 69,61,23,12 ); + + //buttons[ BT_PL_CLOSE_N ] = pixmap->copy (); + //buttons[ BT_PL_CLOSE_P ] = pixmap->copy (); + + buttons[REPEAT_ON_N] = pixmap->copy ( 0,30, 28, 15 ); + buttons[REPEAT_ON_P] = pixmap->copy ( 0,45, 28, 15 ); + + buttons[REPEAT_OFF_N] = pixmap->copy ( 0, 0,28,15 ); + buttons[REPEAT_OFF_P] = pixmap->copy ( 0,15,28,15 ); + + buttons[SHUFFLE_ON_N] = pixmap->copy ( 28,30,46,15 ); + buttons[SHUFFLE_ON_P] = pixmap->copy ( 28,45,46,15 ); + + buttons[SHUFFLE_OFF_N] = pixmap->copy ( 28, 0,46,15 ); + buttons[SHUFFLE_OFF_P] = pixmap->copy ( 28,15,46,15 ); + + delete pixmap; + +} + +void Skin::loadLetters( void ) +{ + QPixmap *img = getPixmap("text"); + + if (!img) + img = getDummyPixmap("text"); + + QList > ( letters ); + for ( int i = 0; i < 3; i++ ) + { + QList ( l ); + for ( int j = 0; j < 31; j++ ) + { + l.append ( img->copy ( j*5, i*6, 5, 6 ) ); + } + letters.append ( l ); + } + + delete img; + + + /* alphabet */ + for ( uint i = 97; i < 123; i++ ) + { + m_letters.insert(i, letters[0][i-97]); + } + + /* digits */ + for ( uint i = 0; i <= 9; i++ ) + { + m_letters.insert ( i+48, letters[1][i] ); + } + + /* special characters */ + m_letters.insert('"', letters[0][27]); + m_letters.insert('@', letters[0][28]); + m_letters.insert(':', letters[1][12]); + m_letters.insert('(', letters[1][13]); + m_letters.insert(')', letters[1][14]); + m_letters.insert('-', letters[1][15]); + m_letters.insert('\'', letters[1][16]); + m_letters.insert('`', letters[1][16]); + m_letters.insert('!', letters[1][17]); + m_letters.insert('_', letters[1][18]); + m_letters.insert('+', letters[1][19]); + m_letters.insert('\\', letters[1][20]); + m_letters.insert('/', letters[1][21]); + m_letters.insert('[', letters[1][22]); + m_letters.insert(']', letters[1][23]); + m_letters.insert('^', letters[1][24]); + m_letters.insert('&', letters[1][25]); + m_letters.insert('%', letters[1][26]); + m_letters.insert('.', letters[1][27]); + m_letters.insert(',', letters[1][27]); + m_letters.insert('=', letters[1][28]); + m_letters.insert('$', letters[1][29]); + m_letters.insert('#', letters[1][30]); + + m_letters.insert(229, letters[2][0]); + m_letters.insert(246, letters[2][1]); + m_letters.insert(228, letters[2][2]); + m_letters.insert('?', letters[2][3]); + m_letters.insert('*', letters[2][4]); + m_letters.insert(' ', letters[2][5]); + + /* text background */ + //m_items->insert (TEXTBG, letters[2][6]); +} + +void Skin::loadMonoSter() +{ + QPixmap *pixmap = getPixmap("monoster"); + + if (!pixmap) + pixmap = getDummyPixmap("monoster"); + + m_ms_parts.clear(); + m_ms_parts[ MONO_A ] = pixmap->copy ( 29,0,27,12 ); + m_ms_parts[ MONO_I ] = pixmap->copy ( 29,12,27,12 ); + m_ms_parts[ STEREO_A ] = pixmap->copy ( 0,0,27,12 ); + m_ms_parts[ STEREO_I ] = pixmap->copy ( 0,12,27,12 ); + + delete pixmap; + + m_parts.clear(); + QPainter paint; + pixmap = getPixmap("playpaus"); + + if (!pixmap) + pixmap = getDummyPixmap("playpaus"); + + QPixmap part(11, 9); + paint.begin(&part); + paint.drawPixmap (0, 0, 3, 9, *pixmap, 36, 0, 3, 9); + paint.drawPixmap (3, 0, 8, 9, *pixmap, 1, 0, 8, 9); + paint.end(); + m_parts [PLAY] = part.copy(); + + part = QPixmap(11, 9); + paint.begin(&part); + paint.drawPixmap (0, 0, 2, 9, *pixmap, 27, 0, 2, 9); + paint.drawPixmap (2, 0, 9, 9, *pixmap, 9, 0, 9, 9); + paint.end(); + m_parts [PAUSE] = part.copy(); + + part = QPixmap(11, 9); + paint.begin(&part); + paint.drawPixmap (0, 0, 2, 9, *pixmap, 27, 0, 2, 9); + paint.drawPixmap (2, 0, 9, 9, *pixmap, 18, 0, 9, 9); + paint.end(); + m_parts [STOP] = part.copy(); + + delete pixmap; +} + +void Skin::loadVolume() +{ + QPixmap *pixmap = getPixmap("volume"); + + if (!pixmap) + pixmap = getDummyPixmap("volume"); + + m_volume.clear(); + for (int i = 0; i < 28; ++i) + m_volume.append(pixmap->copy ( 0,i*15,66,13 )); + if (pixmap->height() > 425) + { + buttons [BT_VOL_N] = pixmap->copy (15,422,14, pixmap->height() - 422); + buttons [BT_VOL_P] = pixmap->copy (0, 422,14, pixmap->height() - 422); + } + else + { + buttons [BT_VOL_N] = QPixmap(); + buttons [BT_VOL_P] = QPixmap(); + } + delete pixmap; +} + +void Skin::loadBalance() +{ + QPixmap *pixmap = getPixmap ( "balance" ); + if (!pixmap) + pixmap = getPixmap ( "volume" ); + + if (!pixmap) + pixmap = getDummyPixmap("balance"); + + m_balance.clear(); + for (int i = 0; i < 28; ++i) + m_balance.append(pixmap->copy ( 9,i*15,38,13 )); + if (pixmap->height() > 427) + { + buttons [BT_BAL_N] = pixmap->copy (15, 422,14,pixmap->height()-422); + buttons [BT_BAL_P] = pixmap->copy (0,422,14,pixmap->height()-422); + } + else + { + buttons [BT_BAL_N] = QPixmap(); + buttons [BT_BAL_P] = QPixmap(); + } + delete pixmap; +} + +void Skin::loadRegion() +{ + m_mwRegion = QRegion(); + m_plRegion = QRegion(); + m_skin_dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); + QString path; + QFileInfoList list = m_skin_dir.entryInfoList(); + for ( int i = 0; i < list.size(); ++i ) + { + QFileInfo fileInfo = list.at ( i ); + if ( fileInfo.fileName().toLower() == "region.txt" ) + { + path = fileInfo.filePath (); + break; + } + } + + if ( path.isNull () ) + { + qDebug ( "Skin: cannot find region.txt. Transparenty disabled" ); + return; + } + m_mwRegion = createRegion(path, "Normal"); + m_plRegion = createRegion(path, "Equalizer"); +} + +QRegion Skin::createRegion(const QString &path, const QString &key) +{ + QRegion region; + QSettings settings(path, QSettings::IniFormat); + QStringList numPoints = settings.value(key+"/NumPoints").toStringList(); + QStringList value = settings.value(key+"/PointList").toStringList(); + QStringList numbers; + foreach(QString str, value) + numbers << str.split(" ", QString::SkipEmptyParts); + + QList regions; + + QList::iterator n; + n = numbers.begin(); + for (int i = 0; i < numPoints.size(); ++i) + { + QList lp; + for (int j = 0; j < numPoints.at(i).toInt()*2; j++) + { + lp << n->toInt(); + n ++; + } + QVector points; + + for (int l = 0; l < lp.size(); l+=2) + { + points << QPoint(lp.at(l), lp.at(l+1)); + } + region = region.united(QRegion(QPolygon(points))); + } + return region; +} + +QPixmap * Skin::getDummyPixmap(const QString& name) +{ + QDir dir (":/default"); + dir.setFilter ( QDir::Files | QDir::Hidden | QDir::NoSymLinks ); + QFileInfoList f = dir.entryInfoList(); + for ( int j = 0; j < f.size(); ++j ) + { + QFileInfo fileInfo = f.at ( j ); + QString fn = fileInfo.fileName().toLower(); + if ( fn.section ( ".",0,0 ) == name ) + { + return new QPixmap ( fileInfo.filePath() ); + } + } + qFatal("Skin:: default skin corrupted"); + return 0; +} + +void Skin::loadColors() +{ + //extract color from image + QPixmap pix = m_letters['*']; + QImage img = pix.toImage(); + img = img.convertToFormat(QImage::Format_Indexed8); + + QPixmap pix2 = m_letters[' ']; + QImage img2 = pix2.toImage(); + img2 = img2.convertToFormat(QImage::Format_Indexed8); + QVector c1 = img.colorTable (); + QVector c2 = img2.colorTable (); + //qDebug("%d -- %d", img.numColors (), img2.numColors ()); + QColor color; + color.setNamedColor(getPLValue("normal")); + + for (int i = 0; i < c1.size(); ++i) + { + if (c2.indexOf(c1[i]) == -1) + { + if(img.numColors () == img2.numColors () + 1) + color = QColor(c1[i]); + break; + } + } + m_scroller_color = color; +} diff --git a/src/ui/skin.h b/src/ui/skin.h new file mode 100644 index 000000000..d981c4613 --- /dev/null +++ b/src/ui/skin.h @@ -0,0 +1,340 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SKIN_H +#define SKIN_H + +#include +#include +#include +#include +#include + +/* + @author Ilya Kotov +*/ + + +class Skin : public QObject +{ + Q_OBJECT +public: + Skin(QObject *parent = 0); + + ~Skin(); + + static Skin *getPointer(); + static QPixmap getPixmap(const QString&, QDir); + void setSkin(const QString& path); + const QPixmap getMain() const + { + return m_main; + }; + const QPixmap getButton(uint bt) const + { + return buttons[bt]; + }; + const QPixmap getTitleBar(uint tb) const + { + return titlebar[tb]; + }; + const QPixmap getPosBar() const + { + return posbar; + }; + const QPixmap getNumber(uint n) const + { + return m_numbers[n]; + }; + /*! + * Returns count of numbers in number list. + * We need this to check if we have "-" in pixmaps. + * if no we should draw it manually. + */ + const uint getNumCount(void) const + { + return m_numbers.count(); + } + const QPixmap getPlPart(uint p) const + { + return m_pl_parts[p]; + }; + const QPixmap getEqPart(uint p) const + { + return m_eq_parts[p]; + }; + const QPixmap getEqSlider(uint n) const + { + return m_eq_bar[n]; + }; + const QPixmap getEqSpline(uint n) const + { + return m_eq_spline[n]; + }; + const QPixmap getMSPart(uint n) const + { + return m_ms_parts[n]; + }; + const QPixmap getLetter(const QChar& ch) + { + return m_letters[ch]; + }; + const QPixmap getItem(uint n) const + { + return m_parts[n]; + }; + const QPixmap getVolumeBar(int n) const + { + return m_volume[n]; + }; + const QPixmap getBalanceBar(int n) const + { + return m_balance[n]; + }; + const QByteArray getPLValue (QByteArray c) const + { + return m_pledit_txt[c]; + }; + const QColor getVisColor(int n) const + { + return m_vis_colors[n]; + }; + const QRegion getMWRegion() const + { + return m_mwRegion; + }; + const QRegion getPLRegion() const + { + return m_plRegion; + }; + const QColor scrollerTextColor() const + { + return m_scroller_color; + }; + + enum Buttons + { + BT_PREVIOUS_N = 0, + BT_PREVIOUS_P, + BT_PLAY_N, + BT_PLAY_P, + BT_PAUSE_N, + BT_PAUSE_P, + BT_STOP_N, + BT_STOP_P, + BT_NEXT_N, + BT_NEXT_P, + BT_EJECT_N, + BT_EJECT_P, + /*titlebar.* */ + BT_MENU_N, + BT_MENU_P, + BT_MINIMIZE_N, + BT_MINIMIZE_P, + BT_CLOSE_N, + BT_CLOSE_P, + BT_SHADE1_N, + BT_SHADE1_P, + BT_SHADE2_N, + BT_SHADE2_P, + BT_CLOSE_SHADED_N, + BT_CLOSE_SHADED_P, + + /* posbar.* */ + BT_POSBAR_N, + BT_POSBAR_P, + /* pledit.* */ + PL_BT_ADD, + PL_BT_SUB, + PL_BT_SEL, + PL_BT_SORT, + PL_BT_LST, + PL_BT_SCROLL_N, + PL_BT_SCROLL_P, + PL_BT_CLOSE_N, + PL_BT_CLOSE_P, + PL_BT_SHADE1_N, + PL_BT_SHADE1_P, + PL_BT_SHADE2_N, + PL_BT_SHADE2_P, + + /* eqmain.* */ + EQ_BT_BAR_N, + EQ_BT_BAR_P, + EQ_BT_ON_N, + EQ_BT_ON_P, + EQ_BT_OFF_N, + EQ_BT_OFF_P, + EQ_BT_PRESETS_N, + EQ_BT_PRESETS_P, + EQ_BT_AUTO_1_N, + EQ_BT_AUTO_1_P, + EQ_BT_AUTO_0_N, + EQ_BT_AUTO_0_P, + EQ_BT_CLOSE_N, + EQ_BT_CLOSE_P, + EQ_BT_SHADE1_N, + + /* eq_ex.* */ + EQ_BT_SHADE1_P, + EQ_BT_SHADE2_N, + EQ_BT_SHADE2_P, + + /* shufrep.* */ + BT_EQ_ON_N, + BT_EQ_ON_P, + BT_EQ_OFF_N, + BT_EQ_OFF_P, + BT_PL_ON_N, + BT_PL_ON_P, + BT_PL_OFF_N, + BT_PL_OFF_P, + BT_PL_CLOSE_N, + BT_PL_CLOSE_P, + REPEAT_ON_N, + REPEAT_ON_P, + REPEAT_OFF_N, + REPEAT_OFF_P, + SHUFFLE_ON_N, + SHUFFLE_ON_P, + SHUFFLE_OFF_N, + SHUFFLE_OFF_P, + /* volume.* */ + BT_VOL_N, + BT_VOL_P, + /* balance.* */ + BT_BAL_N, + BT_BAL_P, + }; + enum TitleBar + { + TITLEBAR_A = 0, + TITLEBAR_I, + TITLEBAR_SHADED_A, + TITLEBAR_SHADED_I, + }; + enum PlayList + { + PL_CORNER_UL_A = 0, + PL_CORNER_UL_I, + PL_CORNER_UR_A, + PL_CORNER_UR_I, + PL_TITLEBAR_A, + PL_TITLEBAR_I, + PL_TFILL1_A, + PL_TFILL1_I, + PL_TFILL2_A, + PL_TFILL2_I, + PL_LFILL, + PL_RFILL, + PL_LSBAR, + PL_RSBAR, + PL_SFILL1, + PL_SFILL2, + PL_CONTROL, + PL_TITLEBAR_SHADED1_A, + PL_TITLEBAR_SHADED1_I, + PL_TITLEBAR_SHADED2, + PL_TFILL_SHADED, + }; + enum Equalizer + { + EQ_MAIN = 0, + EQ_TITLEBAR_A, + EQ_TITLEBAR_I, + EQ_GRAPH, + EQ_TITLEBAR_SHADED_A, + EQ_TITLEBAR_SHADED_I, + EQ_VOLUME1, + EQ_VOLUME2, + EQ_VOLUME3, + EQ_BALANCE1, + EQ_BALANCE2, + EQ_BALANCE3, + }; + enum MonoSter + { + MONO_A = 0, + MONO_I, + STEREO_A, + STEREO_I, + }; + enum OtherParts + { + PLAY = 0, + PAUSE, + STOP, + }; +signals: + void skinChanged(); + +private: + QPixmap *getPixmap(const QString&); + + /*! + * As far as there is no standard in skin making we cannot be sure + * that all needful images we can find in skin :( This will cause + * segfaults and asserts. So to prevent this we need such method + * to load pixmap from default skin. + */ + QPixmap *getDummyPixmap(const QString&); + static Skin *pointer; + QDir m_skin_dir; + QMap buttons; + QMap titlebar; + QMap m_pl_parts; + QMap m_eq_parts; + QMap m_ms_parts; + QMap m_parts; + QMap m_letters; + QMap m_pledit_txt; + QColor m_scroller_color; + QPixmap m_main; + QPixmap posbar; + QList m_numbers; + QList m_eq_bar; + QList m_eq_spline; + QList m_volume; + QList m_balance; + QList m_vis_colors; + QRegion m_mwRegion; + QRegion m_plRegion; + + void loadMain(); + void loadButtons(); + void loadTitleBar(); + void loadPosBar(); + void loadNumbers(); + void loadPlayList(); + void loadPLEdit(); + void loadEqMain(); + void loadEq_ex(); + void loadVisColor(); + void loadShufRep(); + void loadLetters(); + void loadMonoSter(); + void loadVolume(); + void loadBalance(); + void loadRegion(); + void loadColors(); + QRegion createRegion(const QString &path, const QString &key); + +}; + +#endif diff --git a/src/ui/skinreader.cpp b/src/ui/skinreader.cpp new file mode 100644 index 000000000..c29246d8d --- /dev/null +++ b/src/ui/skinreader.cpp @@ -0,0 +1,148 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#include "skinreader.h" + +SkinReader::SkinReader(QObject *parent) + : QObject(parent) +{ + m_process = new QProcess(this); + //create cache dir + QDir dir(QDir::homePath() +"/.qmmp/"); + dir.mkdir("cache"); + dir.cd("cache"); + dir.mkdir("skins"); +} + + +SkinReader::~SkinReader() +{} + +void SkinReader::updateCache() +{ + QDir dir(QDir::homePath() +"/.qmmp/skins"); + dir.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks); + QFileInfoList f = dir.entryInfoList(); + dir.setPath(qApp->applicationDirPath()+"/../share/qmmp/skins"); + dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); + f << dir.entryInfoList(); + //clear removed skins from cache + QDir cache_dir(QDir::homePath() +"/.qmmp/cache/skins"); + cache_dir.setFilter(QDir::Dirs | QDir::Hidden | QDir::NoDotAndDotDot); + QFileInfoList d = cache_dir.entryInfoList(); + + foreach(QFileInfo dirInfo, d) + { + bool del = TRUE; + foreach(QFileInfo fileInfo, f) + { + if (fileInfo.baseName () == dirInfo.fileName ()) + { + del = FALSE; + break; + } + } + if (del) + { + qDebug("SkinReader: deleting %s from cache", + qPrintable(dirInfo.fileName ())); + + cache_dir.cd(dirInfo.fileName ()); + cache_dir.setFilter(QDir::Files | QDir::Hidden); + QFileInfoList removeList = cache_dir.entryInfoList(); + foreach(QFileInfo to_remove, removeList) + cache_dir.remove(to_remove.fileName ()); + cache_dir.cdUp(); + cache_dir.rmdir(dirInfo.fileName ()); + } + } + //add new skins to cache + foreach(QFileInfo fileInfo, f) + { + bool create = TRUE; + foreach(QFileInfo dirInfo, d) + { + if (fileInfo.baseName () == dirInfo.fileName ()) + { + create = FALSE; + break; + } + } + if (create) + { + qDebug("SkinReader: adding %s to cache", + qPrintable(fileInfo.fileName ())); + cache_dir.mkdir(fileInfo.baseName ()); + QString name = fileInfo.fileName ().toLower(); + + if (name.endsWith(".tgz") || name.endsWith(".tar.gz")) + untar(fileInfo.filePath (), cache_dir.absolutePath ()+"/"+ + fileInfo.baseName ()); + if (name.endsWith(".zip") || name.endsWith(".wsz")) + unzip(fileInfo.filePath (), cache_dir.absolutePath ()+"/"+ + fileInfo.baseName ()); + } + } +} + +void SkinReader::untar(const QString &from, const QString &to) +{ + QByteArray array; + QStringList args; + //list archive + args << "tf" <start("tar", args); + m_process->waitForFinished(); + array = m_process->readAllStandardOutput (); + QString str = QString(array); + QStringList outputList = str.split("\n",QString::SkipEmptyParts); + foreach(QString str, outputList) + { + str = str.trimmed(); + args.clear(); + args << "xvfk" << from << "-O" << str; + m_process->start("tar", args); + m_process->waitForFinished(); + array = m_process->readAllStandardOutput (); + QString name = str.right(str.size() - str.indexOf("/",Qt::CaseInsensitive) - 1).trimmed().toLower(); + + QFile file(to+"/"+name); + file.open(QIODevice::WriteOnly); + file.write(array); + file.close(); + } +} + +void SkinReader::unzip(const QString &from, const QString &to) +{ + QStringList args; + args << "-j" << "-o" << "-d" << to << from; + m_process->start("unzip", args); + m_process->waitForFinished(); +} + diff --git a/src/ui/skinreader.h b/src/ui/skinreader.h new file mode 100644 index 000000000..321a5fbbf --- /dev/null +++ b/src/ui/skinreader.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SKINREADER_H +#define SKINREADER_H + +#include + +/** + @author Ilya Kotov +*/ +class QProcess; + +class SkinReader : public QObject +{ + Q_OBJECT +public: + SkinReader(QObject *parent = 0); + + ~SkinReader(); + + void updateCache(); + +private: + QProcess *m_process; + void untar(const QString &from, const QString &to); + void unzip(const QString &from, const QString &to); +}; + +#endif diff --git a/src/ui/stuff.qrc b/src/ui/stuff.qrc new file mode 100644 index 000000000..e9c99d558 --- /dev/null +++ b/src/ui/stuff.qrc @@ -0,0 +1,28 @@ + + + + ../../COPYING + html/about_en.html + html/about_ru.html + html/authors_en.txt + html/thanks_en.txt + html/authors_ru.txt + html/thanks_ru.txt + default/balance.png + default/eqmain.png + default/numbers.png + default/pledit.txt + default/text.png + default/volume.png + default/cbuttons.png + default/main.png + default/playpaus.png + default/posbar.png + default/titlebar.png + default/eq_ex.png + default/monoster.png + default/pledit.png + default/shufrep.png + default/viscolor.txt + + diff --git a/src/ui/symboldisplay.cpp b/src/ui/symboldisplay.cpp new file mode 100644 index 000000000..b3942a6bb --- /dev/null +++ b/src/ui/symboldisplay.cpp @@ -0,0 +1,91 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include + +#include "skin.h" + +#include "symboldisplay.h" + +SymbolDisplay::SymbolDisplay ( QWidget *parent, int digits ) + : PixmapWidget ( parent ), m_digits ( digits ), m_text(), m_max(0) +{ + m_alignment = Qt::AlignRight; + m_skin = Skin::getPointer(); + connect ( m_skin, SIGNAL ( skinChanged() ), this, SLOT (draw())); + draw(); + for (int i=0; igetLetter ( ' ' ); + int w = bg.size().width(); + int h = bg.size().height(); + QPixmap tmp ( m_digits*w,h ); + QPainter paint ( &tmp ); + int j; + for ( int i = 0; i < m_digits; ++i ) + { + if (m_alignment == Qt::AlignRight) // TODO: add align Center + { + j = str.size() -1 - i; + if ( j >= 0 ) + paint.drawPixmap ( ( m_digits-1-i ) *w,0,m_skin->getLetter ( str.at ( j ) ) ); + else + paint.drawPixmap ( ( m_digits-1-i ) *w,0,m_skin->getLetter ( ' ' ) ); + } + else + { + if (i < str.size()) + paint.drawPixmap ( i * w,0,m_skin->getLetter ( str.at ( i ) ) ); + else + paint.drawPixmap ( i * w,0,m_skin->getLetter ( ' ' ) ); + ; + } + } + setPixmap(tmp); +} + +void SymbolDisplay::display(int val) +{ + if (val < m_max) + display(QString::number(val)); + else + display(QString("%1h").arg(val/100)); +} + diff --git a/src/ui/symboldisplay.h b/src/ui/symboldisplay.h new file mode 100644 index 000000000..065579b7a --- /dev/null +++ b/src/ui/symboldisplay.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef SYMBOLDISPLAY_H +#define SYMBOLDISPLAY_H + +#include + +#include "pixmapwidget.h" + +/** + @author Vladimir Kuznetsov + */ + +class Skin; + +class SymbolDisplay : public PixmapWidget +{ + Q_OBJECT +public: + SymbolDisplay(QWidget *parent = 0, int digits = 3); + + ~SymbolDisplay(); + void display(const QString&); + void display(int); + void setAlignment(Qt::Alignment a) + { + m_alignment = a; + } + Qt::Alignment alignment()const + { + return m_alignment; + } + +private slots: + void draw(); + +private: + Skin* m_skin; + QPixmap m_pixmap; + int m_digits; + QString m_text; + Qt::Alignment m_alignment; + int m_max; + +}; + +#endif diff --git a/src/ui/textscroller.cpp b/src/ui/textscroller.cpp new file mode 100644 index 000000000..35e4ed4eb --- /dev/null +++ b/src/ui/textscroller.cpp @@ -0,0 +1,116 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "skin.h" +#include "textscroller.h" +#include "version.h" + +TextScroller *TextScroller::pointer = 0; + +TextScroller *TextScroller::getPointer() +{ + return pointer; +} + + +TextScroller::TextScroller ( QWidget *parent ) + : PixmapWidget ( parent ) +{ + pointer = this; + m_skin = Skin::getPointer(); + m_pixmap = QPixmap ( 154,15 ); + x = 0; + m_text = "Qt-based Multimedia Player (Qmmp " + QString(QMMP_STR_VERSION) + ")"; + m_update = FALSE; + readSettings(); + m_timer = new QTimer ( this ); + connect ( m_timer, SIGNAL ( timeout() ),SLOT ( addOffset() ) ); + m_timer->setInterval(50); + m_timer->start(); + updateSkin(); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); +} + + +TextScroller::~TextScroller() +{} + +void TextScroller::addOffset() +{ + m_pixmap.fill ( Qt::transparent ); + QPainter paint ( &m_pixmap ); + x--; + paint.setPen(m_color); + paint.setFont(m_font); + paint.drawText ( 154+x,12, m_text ); + paint.drawText ( 154+x+m_metrics->width ( m_text ) + 15,12, m_text ); + if ( 154 + x < - m_metrics->width ( m_text ) - 15 +1) + { + x=-154; + } + setPixmap ( m_pixmap ); +} + +void TextScroller::setText(const QString& text) +{ + if (m_text != text) + { + m_text = text; + x = -50; + } +} + +void TextScroller::updateSkin() +{ + m_color.setNamedColor(m_skin->getPLValue("normal")); +} + +void TextScroller::readSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + QString fontname = settings.value("MainWindow/Font","").toString(); + if (fontname.isEmpty ()) + fontname = QFont("Helvetica [Cronyx]", 9).toString(); + m_font.fromString(fontname); + + if (m_update) + { + delete m_metrics; + m_metrics = new QFontMetrics(m_font); + } + else + { + m_update = TRUE; + m_metrics = new QFontMetrics(m_font); + } +} + +void TextScroller::hideEvent ( QHideEvent *) +{ + m_timer->stop(); +} + +void TextScroller::showEvent ( QShowEvent *) +{ + m_timer->start(); +} diff --git a/src/ui/textscroller.h b/src/ui/textscroller.h new file mode 100644 index 000000000..7346ce29a --- /dev/null +++ b/src/ui/textscroller.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef TEXTSCROLLER_H +#define TEXTSCROLLER_H + +#include + +/** + @author Ilya Kotov +*/ + +class QTimer; + +class Skin; + +class TextScroller : public PixmapWidget +{ +Q_OBJECT +public: + TextScroller(QWidget *parent = 0); + + ~TextScroller(); + + static TextScroller *getPointer(); + void setText(const QString&); + void readSettings(); + +private slots: + void addOffset(); + void updateSkin(); + +protected: + void hideEvent ( QHideEvent *); + void showEvent ( QShowEvent *); + +private: + bool m_update; + static TextScroller *pointer; + QPixmap m_pixmap; + int x; + QFont m_font; + QFontMetrics *m_metrics; + QString m_text; + Skin *m_skin; + QColor m_color; + QTimer *m_timer; +}; + +#endif diff --git a/src/ui/timeindicator.cpp b/src/ui/timeindicator.cpp new file mode 100644 index 000000000..9b81ba040 --- /dev/null +++ b/src/ui/timeindicator.cpp @@ -0,0 +1,127 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include +#include +#include + +#include "skin.h" +#include "timeindicator.h" + +TimeIndicator::TimeIndicator ( QWidget *parent ) + : PixmapWidget ( parent ) +{ + m_skin = Skin::getPointer(); + m_pixmap = QPixmap ( 65,13 ); + m_elapsed = true; + m_time = m_songDuration = 0; + readSettings(); + m_needToShowTime = false; + updateSkin(); + reset(); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); +} + +void TimeIndicator::setTime ( int t ) +{ + m_time = t; + m_pixmap.fill ( Qt::transparent ); + QPainter paint ( &m_pixmap ); + + if (!m_elapsed) + { + t = m_songDuration - t; + paint.drawPixmap(QPoint(2,0),m_skin->getNumber( 10 )); + } + if(t < 0) + t = 0; + + paint.drawPixmap(QPoint(13,0),m_skin->getNumber( t/600%10 )); + paint.drawPixmap(QPoint(26,0),m_skin->getNumber( t/60%10 )); + paint.drawPixmap(QPoint(43,0),m_skin->getNumber( t%60/10 )); + paint.drawPixmap(QPoint(56,0),m_skin->getNumber( t%60%10 )); + + setPixmap ( m_pixmap ); + +} + +void TimeIndicator::reset() +{ + m_pixmap.fill ( Qt::transparent ); + QPainter paint ( &m_pixmap ); + setPixmap ( m_pixmap ); +} + +void TimeIndicator::mousePressEvent(QMouseEvent* e ) +{ + if (m_needToShowTime && e->button() & Qt::LeftButton) + { + m_elapsed = m_elapsed ? false : true; + setTime(m_time); + } + PixmapWidget::mousePressEvent(e); +} + +void TimeIndicator::setSongDuration(int d) +{ + m_songDuration = d; +} + +TimeIndicator::~TimeIndicator() +{ + writeSettings(); +} + + +void TimeIndicator::updateSkin() +{ + if (m_needToShowTime) + setTime(m_time); +} + +void TimeIndicator::readSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("Display"); + m_elapsed = settings.value("Elapsed",true).toBool(); + settings.endGroup(); +} + + +void TimeIndicator::writeSettings() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("Display"); + settings.setValue("Elapsed",m_elapsed); + settings.endGroup(); +} + + +void TimeIndicator::setNeedToShowTime(bool need) +{ + m_needToShowTime = need; + if (!need) reset(); +} + +void TimeIndicator::mouseMoveEvent(QMouseEvent *) +{} + +void TimeIndicator::mouseReleaseEvent(QMouseEvent *) +{} + diff --git a/src/ui/timeindicator.h b/src/ui/timeindicator.h new file mode 100644 index 000000000..19981a4b3 --- /dev/null +++ b/src/ui/timeindicator.h @@ -0,0 +1,63 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef TIMEINDICATOR_H +#define TIMEINDICATOR_H + +#include + +class QMouseEvent; + +class Skin; + + +/** Class TimeIndicator + * @author Vladimir Kuznetsov + * + * Represents time indicator in the main display. Can show elapsed + * and rest time of song (mouse press on indicator changes mode) + */ +class TimeIndicator : public PixmapWidget +{ + Q_OBJECT +public: + TimeIndicator(QWidget *parent = 0); + ~TimeIndicator(); + void setTime ( int t ); + void setSongDuration(int); + void setNeedToShowTime(bool); +protected: + virtual void mousePressEvent(QMouseEvent*); + virtual void mouseMoveEvent(QMouseEvent*); + virtual void mouseReleaseEvent(QMouseEvent*); + void writeSettings(); + void readSettings(); + void reset(); +private slots: + void updateSkin(); +private: + QPixmap m_pixmap; + Skin *m_skin; + int m_time; + int m_songDuration; + bool m_elapsed; + bool m_needToShowTime; +}; + +#endif diff --git a/src/ui/titlebar.cpp b/src/ui/titlebar.cpp new file mode 100644 index 000000000..bdbd86b2e --- /dev/null +++ b/src/ui/titlebar.cpp @@ -0,0 +1,226 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include "symboldisplay.h" +#include "skin.h" +#include "button.h" +#include "dock.h" +#include "titlebarcontrol.h" +#include "shadedvisual.h" +#include "titlebar.h" + +TitleBar::TitleBar(QWidget *parent) + : PixmapWidget(parent) +{ + m_align = FALSE; + m_skin = Skin::getPointer(); + setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_A)); + m_mw = qobject_cast(parent); + m_shaded = FALSE; + m_currentTime = 0; + //buttons + m_menu = new Button(this,Skin::BT_MENU_N,Skin::BT_MENU_P); + connect(m_menu,SIGNAL(clicked()),this,SLOT(showMainMenu())); + m_menu->move(6,3); + m_minimize = new Button(this,Skin::BT_MINIMIZE_N,Skin::BT_MINIMIZE_P); + m_minimize->move(244,3); + connect(m_minimize, SIGNAL(clicked()), m_mw, SLOT(showMinimized())); + m_shade = new Button(this,Skin::BT_SHADE1_N,Skin::BT_SHADE1_P); + m_shade->move(254,3); + connect(m_shade, SIGNAL(clicked()), SLOT(shade())); + m_close = new Button(this,Skin::BT_CLOSE_N,Skin::BT_CLOSE_P); + m_close->move(264,3); + connect(m_close, SIGNAL(clicked()), m_mw, SLOT(handleCloseRequest())); + setActive(FALSE); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); + + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + if (settings.value("Display/shaded", FALSE).toBool()) + shade(); + m_align = TRUE; +} + + +TitleBar::~TitleBar() +{ + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.setValue("Display/shaded", m_shaded); +} + +void TitleBar::mousePressEvent(QMouseEvent* event) +{ + switch ((int) event->button ()) + { + case Qt::LeftButton: + { + m_pos = event->pos(); + Dock::getPointer()->calculateDistances(); + break; + } + case Qt::RightButton: + { + m_mw->menu()->exec(event->globalPos()); + } + } +} + +void TitleBar::mouseReleaseEvent(QMouseEvent*) +{ + Dock::getPointer()->updateDock(); +} +void TitleBar::mouseMoveEvent(QMouseEvent* event) +{ + QPoint npos = (event->globalPos()-m_pos); + Dock::getPointer()->move(m_mw, npos); +} + +void TitleBar::setActive(bool a) +{ + if (a) + { + if (m_shaded) + { + setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_SHADED_A)); + m_shade2->show(); + } + else + { + setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_A)); + m_shade->show(); + } + m_menu->show(); + m_minimize->show(); + m_close->show(); + } + else + { + if (m_shaded) + { + setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_SHADED_I)); + m_shade2->hide(); + } + else + { + setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_I)); + m_shade->hide(); + } + m_menu->hide(); + m_minimize->hide(); + m_close->hide(); + } +} + +void TitleBar::updateSkin() +{ + setActive(FALSE); +} + +void TitleBar::showMainMenu() +{ + m_mw->menu()->exec(m_menu->mapToGlobal(m_menu->pos())); +} + +void TitleBar::shade() +{ + m_shaded = !m_shaded; + + if (m_shaded) + { + m_mw->setFixedSize(275,14); + setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_SHADED_A)); + m_shade->hide(); + m_shade2 = new Button(this,Skin::BT_SHADE2_N, Skin::BT_SHADE2_P); + m_shade2->move(254,3); + connect(m_shade2, SIGNAL(clicked()), SLOT(shade())); + m_shade2->show(); + m_currentTime = new SymbolDisplay(this, 6); + m_currentTime->move(127,4); + m_currentTime->show(); + m_currentTime->display("--:--"); + m_control = new TitleBarControl(this); + m_control->move(168,2); + m_control->show(); + connect (m_control, SIGNAL (nextClicked()), parent(), SLOT (next())); + connect (m_control, SIGNAL (previousClicked()), parent(), SLOT (previous())); + connect (m_control, SIGNAL (playClicked()), parent(), SLOT (play())); + connect (m_control, SIGNAL (pauseClicked()), parent(), SLOT (pause())); + connect (m_control, SIGNAL (stopClicked()), parent(), SLOT (stop())); + connect (m_control, SIGNAL (ejectClicked()), parent(), SLOT (addFile())); + m_visual = new ShadedVisual(this); + SoundCore::instance()->addVisualization(m_visual); + m_visual->show(); + m_visual->move(79,5); + } + else + { + m_mw->setFixedSize(275,116); + setPixmap(m_skin->getTitleBar(Skin::TITLEBAR_A)); + delete m_shade2; + delete m_currentTime; + delete m_control; + SoundCore::instance()->removeVisual(m_visual); + delete m_visual; + m_shade2 = 0; + m_currentTime = 0; + m_shade->show(); + } + if(m_align) + Dock::getPointer()->align(m_mw, m_shaded? -102: 102); +} + +QString TitleBar::formatTime ( int sec ) +{ + int minutes = sec / 60; + int seconds = sec % 60; + + QString str_minutes = QString::number ( minutes ); + QString str_seconds = QString::number ( seconds ); + + if ( minutes < 10 ) str_minutes.prepend ( "0" ); + if ( seconds < 10 ) str_seconds.prepend ( "0" ); + + return str_minutes + ":" + str_seconds; +} + +void TitleBar::setInfo(const OutputState &st) +{ + if (!m_currentTime) + return; + switch ( ( int ) st.type() ) + { + case OutputState::Info: + { + m_currentTime->display(formatTime(st.elapsedSeconds())); + break; + } + case OutputState::Stopped: + { + m_currentTime->display("--:--"); + break; + } + } +} diff --git a/src/ui/titlebar.h b/src/ui/titlebar.h new file mode 100644 index 000000000..4428a188c --- /dev/null +++ b/src/ui/titlebar.h @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef TITLEBAR_H +#define TITLEBAR_H + +#include +#include + +#include "pixmapwidget.h" +#include "playlist.h" +#include "mainwindow.h" + +/** + @author Ilya Kotov +*/ +class MainWindow; +class QMouseEvent; + +class Skin; +class Button; +class SymbolDisplay; +class TitleBarControl; +class ShadedVisual; + +class TitleBar : public PixmapWidget +{ +Q_OBJECT +public: + TitleBar(QWidget *parent = 0); + + ~TitleBar(); + + void setActive(bool); + void setInfo(const OutputState &st); + +private slots: + void updateSkin(); + void showMainMenu(); + void shade(); + +private: + Skin *m_skin; + QPoint m_pos; + MainWindow *m_mw; + Button *m_menu; + Button *m_minimize; + Button *m_shade; + Button *m_shade2; + Button *m_close; + SymbolDisplay *m_currentTime; + QString formatTime (int); + bool m_shaded; + bool m_align; + TitleBarControl *m_control; + ShadedVisual *m_visual; + +protected: + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); +}; + + + +#endif diff --git a/src/ui/titlebarcontrol.cpp b/src/ui/titlebarcontrol.cpp new file mode 100644 index 000000000..8238c287a --- /dev/null +++ b/src/ui/titlebarcontrol.cpp @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include "titlebarcontrol.h" + +TitleBarControl::TitleBarControl(QWidget *parent) + : QWidget(parent) +{ + //setAutoFillBackground(TRUE); + setFixedSize(57,10); +} + + +TitleBarControl::~TitleBarControl() +{ +} + +void TitleBarControl::mousePressEvent (QMouseEvent *) +{} + +void TitleBarControl::mouseReleaseEvent (QMouseEvent * event) +{ + QPoint pt = event->pos(); + if(QRect(0,0,8,10).contains(pt)) + emit previousClicked(); + else if(QRect(8,0,11,10).contains(pt)) + emit playClicked(); + else if(QRect(19,0,10,10).contains(pt)) + emit pauseClicked(); + else if(QRect(29,0,8,10).contains(pt)) + emit stopClicked(); + else if(QRect(37,0,10,10).contains(pt)) + emit nextClicked(); + else if(QRect(47,0,10,10).contains(pt)) + emit ejectClicked(); +} + +void TitleBarControl::mouseMoveEvent(QMouseEvent*) +{} diff --git a/src/ui/titlebarcontrol.h b/src/ui/titlebarcontrol.h new file mode 100644 index 000000000..c368b2186 --- /dev/null +++ b/src/ui/titlebarcontrol.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef TITLEBARCONTROL_H +#define TITLEBARCONTROL_H + +#include + +class QMouseEvent; + +/** + @author Ilya Kotov +*/ +class TitleBarControl : public QWidget +{ +Q_OBJECT +public: + TitleBarControl(QWidget *parent = 0); + ~TitleBarControl(); + +signals: + void previousClicked(); + void nextClicked(); + void pauseClicked(); + void playClicked(); + void stopClicked(); + void ejectClicked(); + +protected: + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + + + +}; + +#endif diff --git a/src/ui/togglebutton.cpp b/src/ui/togglebutton.cpp new file mode 100644 index 000000000..86b809ef2 --- /dev/null +++ b/src/ui/togglebutton.cpp @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "skin.h" +#include "togglebutton.h" + + +ToggleButton::ToggleButton ( QWidget *parent,uint on_n,uint on_p,uint off_n,uint off_p ) + : PixmapWidget ( parent ) +{ + m_on_n = on_n; + m_on_p = on_p; + m_off_n = off_n; + m_off_p = off_p; + m_on = FALSE; + skin = Skin::getPointer(); + setON ( FALSE ); + connect ( skin, SIGNAL ( skinChanged() ), this, SLOT ( updateSkin() ) ); +} + + +ToggleButton::~ToggleButton() +{} + +bool ToggleButton::isChecked() +{ + return m_on; +} + +void ToggleButton::updateSkin() +{ + //setPixmap ( skin->getButton ( name_normal ) ); + setON ( m_on ); +} + +void ToggleButton::click() +{ + m_on = !m_on; + setON (m_on); + emit clicked(m_on); +} + +void ToggleButton::setON ( bool on ) +{ + m_on = on; + if ( on ) + setPixmap ( skin->getButton ( m_on_n ) ); + else + setPixmap ( skin->getButton ( m_off_n ) ); +} +void ToggleButton::mousePressEvent ( QMouseEvent* ) +{ + if ( m_on ) + setPixmap ( skin->getButton ( m_off_p ) ); + else + setPixmap ( skin->getButton ( m_on_p ) ); +} + +void ToggleButton::mouseReleaseEvent ( QMouseEvent* ) +{ + m_on = !m_on; + setON ( m_on ); + emit clicked( m_on ); +} diff --git a/src/ui/togglebutton.h b/src/ui/togglebutton.h new file mode 100644 index 000000000..a15d7476f --- /dev/null +++ b/src/ui/togglebutton.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef TOGGLEBUTTON_H +#define TOGGLEBUTTON_H + +#include + +/** + @author Ilya Kotov +*/ +class Skin; + +class ToggleButton : public PixmapWidget +{ +Q_OBJECT +public: + ToggleButton( QWidget *parent, uint on_n, uint on_p, uint off_n, uint off_p ); + + ~ToggleButton(); + + bool isChecked(); + void setON(bool); + +signals: + void clicked(bool); + +public slots: + void click(); + +private slots: + void updateSkin(); + +private: + Skin *skin; + uint m_on_n, m_on_p, m_off_n, m_off_p; + bool m_on; + +protected: + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); +}; + + +#endif diff --git a/src/ui/translations/qmmp_cs.ts b/src/ui/translations/qmmp_cs.ts new file mode 100644 index 000000000..faba9c1b9 --- /dev/null +++ b/src/ui/translations/qmmp_cs.ts @@ -0,0 +1,716 @@ + + + + + AboutDialog + + + :/html/about_en.html + :/html/about_cs.html + + + + :/html/authors_en.txt + :/html/authors_cs.txt + + + + :/html/thanks_en.txt + :/html/thanks_cs.txt + + + + About Qmmp + O Qmmp + + + + About + O aplikaci + + + + Authors + Autoři + + + + Thanks To + Poděkování + + + + License Agreement + Licence + + + + AddUrlDialog + + + Enter URL to add + Přidat URL + + + + ConfigDialog + + + Enabled + Povoleno + + + + Description + Popis + + + + Filename + Soubor + + + + Artist + Umělec + + + + Album + Album + + + + Title + Název + + + + Tracknumber + Číslo stopy + + + + Genre + Žánr + + + + Filepath + Soubor + + + + Date + Datum + + + + Year + Rok + + + + Comment + Komentář + + + + Qmmp Settings + Nastavení Qmmp + + + + Appearance + Vzhled + + + + Playlist + Seznam skladeb + + + + Plugins + Moduly + + + + Advanced + Pokročilé + + + + Skins + Témata + + + + Fonts + Písma + + + + Player: + Přehrávač: + + + + Playlist: + Seznam skladeb: + + + + ??? + ??? + + + + ... + ... + + + + Metadata + Metadata + + + + Load metadata from files + Číst ze souborů metadata + + + + Song Display + Zobrazení skladby + + + + Title format: + Formát titulku: + + + + Preferences + Nastavení + + + + Information + Informace + + + + Input + Vstup + + + + Output + Výstup + + + + Tray Icon + Ikona v doku + + + + Show tooltip + Zobrazovat tooltip + + + + Show message + Zobrazovat zprávy + + + + Message delay, ms: + Doba zobrazení zpráv, v ms: + + + + Show tray icon + Zobrazovat ikonu v doku + + + + Action On Close + Při zavření okna + + + + Hide to tray + Schovat do doku + + + + Quit + Ukončit + + + + Close + Zavřít + + + + Connectivity + Síť + + + + File Dialog + Souborový dialog + + + + Proxy + Proxy + + + + Enable proxy usage + Povolit používání proxy + + + + Proxy host name: + Adresa proxy: + + + + Proxy port: + Port proxy: + + + + Use authentication with proxy + Použít autorizaci pro proxy + + + + Proxy user name: + Uživatelské jméno: + + + + Proxy password: + Heslo: + + + + Decoder + + + All Supported Bitstreams ( + Všechny podporované formáty ( + + + + EqWidget + + + preset + předvolba + + + + &Load/Delete + &Načíst/Odstranit + + + + &Save Preset + &Uložit předvolbu + + + + &Save Auto-load Preset + Uložit &automatickou předvolbu + + + + &Import + &Importovat + + + + &Clear + &Vynulovat + + + + Saving Preset + Uložení předvolby + + + + Preset name: + Název předvolby: + + + + preset # + předvolba # + + + + Import Preset + Importovat předvolbu + + + + JumpToTrackDialog + + + Unqueue + Vyřadit + + + + Queue + Zařadit + + + + Jump To Track + Přeskočit na skladbu + + + + Filter + Filtr + + + + Refresh + Načíst znovu + + + + Jump To + Přeskočit na + + + + Close + Zavřít + + + + MainWindow + + + Default + Seznam + + + + Now Playing + Nyní se přehrává + + + + Choose a directory + Výběr adresáře + + + + Select one or more files to open + Vyberte jeden či více souborů k otevření + + + + &Play + Pře&hrát + + + + X + X + + + + &Pause + Pau&za + + + + C + C + + + + &Stop + &Stop + + + + V + V + + + + &Previous + &Předchozí + + + + Z + Z + + + + &Next + &Další + + + + B + B + + + + &Queue + &Fronta + + + + Q + Q + + + + &Jump To File + Přeskočit na soubo&r + + + + J + J + + + + &Settings + &Nastavení + + + + Ctrl+P + Ctrl+P + + + + &About + O &aplikaci + + + + &Exit + U&končit + + + + Ctrl+Q + Ctrl+Q + + + + Playlist Files + Seznamy skladeb + + + + Open Playlist + Načíst seznam skladeb + + + + Save Playlist + Uložit seznam skladeb + + + + PlayList + + + &Add File + Přidat &soubor + + + + F + F + + + + &Add Directory + Přidat &adresář + + + + D + D + + + + &Remove Selected + &Odstranit vybrané + + + + Del + Del + + + + &Remove All + Odstranit &vše + + + + &Remove Unselected + Odstranit &nevybrané + + + + &View Track Details + Zobrazit &informace o skladbě + + + + Alt+I + Alt+I + + + + Sort List + Seřadit seznam + + + + By Title + Podle názvu skladby + + + + By Filename + Podle názvu souboru + + + + By Path + Filename + Podle cesty a názvu souboru + + + + By Date + Podle data + + + + Sort Selection + Seřadit výběr + + + + Randomize List + Zamíchat seznam + + + + Reverse List + Obrátit pořadí seznamu + + + + Invert Selection + Invertovat výběr + + + + &Select None + &Zrušit výběr + + + + &Select All + &Vybrat vše + + + + Ctrl+A + Ctrl+A + + + + &New List + &Nový seznam + + + + Shift+N + Shift+N + + + + &Load List + Načíst &seznam + + + + O + O + + + + &Save List + &Uložit seznam + + + + Shift+S + Shift+S + + + + &Add Url + Přidat &URL + + + + U + U + + + + PresetEditor + + + Preset Editor + Editor předvoleb + + + + Load + Načíst + + + + Delete + Odstranit + + + + Preset + Předvolba + + + + Auto-preset + Automatická předvolba + + + diff --git a/src/ui/translations/qmmp_locales.qrc b/src/ui/translations/qmmp_locales.qrc new file mode 100644 index 000000000..64ac204fa --- /dev/null +++ b/src/ui/translations/qmmp_locales.qrc @@ -0,0 +1,8 @@ + + + + qmmp_ru.qm + qmmp_tr.qm + qmmp_zh_CN.qm + + diff --git a/src/ui/translations/qmmp_ru.qm b/src/ui/translations/qmmp_ru.qm new file mode 100644 index 000000000..38c82d0e8 Binary files /dev/null and b/src/ui/translations/qmmp_ru.qm differ diff --git a/src/ui/translations/qmmp_ru.ts b/src/ui/translations/qmmp_ru.ts new file mode 100644 index 000000000..32fdd757d --- /dev/null +++ b/src/ui/translations/qmmp_ru.ts @@ -0,0 +1,645 @@ + + + + + AboutDialog + + + About Qmmp + О Qmmp + + + + About + О программе + + + + License Agreement + Лицензия + + + + :/html/about_en.html + :/html/about_ru.html + + + + :/html/authors_en.txt + :/html/authors_ru.txt + + + + :/html/thanks_en.txt + :/html/thanks_ru.txt + + + + Authors + Авторы + + + + Thanks To + Благодарности + + + + ConfigDialog + + + Enabled + Включён + + + + Description + Описание + + + + Filename + Имя файла + + + + Artist + Исполнитель + + + + Album + Альбом + + + + Title + Название + + + + Tracknumber + Номер трека + + + + Genre + Жанр + + + + Filepath + Путь к файлу + + + + Date + Дата + + + + Year + Год + + + + Comment + Комментарий + + + + Qmmp Settings + Настройки Qmmp + + + + Skins + Обложки + + + + Fonts + Шрифты + + + + Player: + Плеер: + + + + Playlist: + Список: + + + + ??? + ??? + + + + ... + ... + + + + Metadata + Метаданные + + + + Load metadata from files + Считывать метаданные из файлов + + + + Song Display + Список песен + + + + Title format: + Формат названия: + + + + Input + Ввод + + + + Output + Вывод + + + + Preferences + Настройки + + + + Information + Информация + + + + Tray Icon + Системный значок + + + + Show tooltip + Всплывающая подсказка + + + + Show message + Показывать сообщение + + + + Message delay, ms: + Задержка сообщения, мс: + + + + Show tray icon + Показывать системный значок + + + + Appearance + Внешний вид + + + + Playlist + Список + + + + Plugins + Модули + + + + Advanced + Дополнительно + + + + Close + Закрыть + + + + Action On Close + Реакция на закрытие + + + + Hide to tray + Свернуть в системный лоток + + + + Quit + Выход + + + + EqWidget + + + preset + предустановка + + + + &Load/Delete + &Загрузить/Удалить + + + + &Save Preset + &Сохранить предустановку + + + + &Save Auto-load Preset + &Сохранить авто-предустановку + + + + &Clear + &Очистить + + + + Saving Preset + Сохранение предустановки + + + + Preset name: + Имя предустановки: + + + + preset # + предустановка # + + + + &Import + &Импортировать + + + + Import Preset + Импорт предустановки + + + + JumpToTrackDialog + + + Unqueue + Снять с очереди + + + + Queue + В очередь + + + + Jump To Track + Перейти к треку + + + + Filter + Фильтр + + + + Refresh + Обновить + + + + Jump To + Перейти к + + + + Close + Закрыть + + + + MainWindow + + + Default + + + + + Now Playing + Сейчас играет + + + + Choose a directory + Выберите директорию + + + + Select one or more files to open + Выберите один или несколько файлов + + + + &Play + &Воспроизвести + + + + X + + + + + &Pause + &Приостановить + + + + C + + + + + &Stop + &Стоп + + + + V + + + + + &Previous + &Назад + + + + Z + + + + + &Next + &Вперёд + + + + B + + + + + &Queue + &В очередь + + + + Q + + + + + &Jump To File + &Перейти к файлу + + + + J + + + + + &Settings + &Настройки + + + + Ctrl+P + + + + + &Exit + &Выход + + + + Ctrl+Q + + + + + Open Playlist + Открыть список + + + + Save Playlist + Сохранить список + + + + &About + &О программе + + + + Playlist Files + Файлы списков + + + + PlayList + + + F + + + + + D + + + + + Alt+I + + + + + Ctrl+A + + + + + O + + + + + &Add File + &Добавить файл + + + + &Add Directory + &Добавить директорию + + + + &Remove Selected + &Удалить выделенное + + + + &Remove All + &Удалить всё + + + + &Remove Unselected + &Удалить невыделенное + + + + &View Track Details + &Информация + + + + Sort List + Сортировать + + + + By Title + По названию + + + + By Filename + По имени файла + + + + By Path + Filename + По пути и файлу + + + + By Date + По дате + + + + Sort Selection + Сортировать выделенное + + + + Randomize List + Перемешать + + + + Reverse List + Перевернуть + + + + Invert Selection + Инвертировать выделение + + + + &Select None + &Снять выделение + + + + &Select All + &Выделить всё + + + + &New List + &Новый лист + + + + Shift+N + + + + + &Load List + &Загрузить лист + + + + &Save List + &Сохранить лист + + + + Shift+S + + + + + Del + + + + + PresetEditor + + + Preset Editor + Редактор предустановок + + + + Load + Загрузить + + + + Delete + Удалить + + + + Preset + Предустановка + + + + Auto-preset + Авто-предустановка + + + diff --git a/src/ui/translations/qmmp_tr.qm b/src/ui/translations/qmmp_tr.qm new file mode 100644 index 000000000..1180e41d5 Binary files /dev/null and b/src/ui/translations/qmmp_tr.qm differ diff --git a/src/ui/translations/qmmp_tr.ts b/src/ui/translations/qmmp_tr.ts new file mode 100644 index 000000000..73f8206d6 --- /dev/null +++ b/src/ui/translations/qmmp_tr.ts @@ -0,0 +1,644 @@ + + + + AboutDialog + + + About Qmmp + Qmmp Hakkında + + + + About + Hakkında + + + + License Agreement + Lisans Anlaşması + + + + :/html/about_en.html + :/html/about_en.html + + + + :/html/authors_en.txt + :/html/authors_en.txt + + + + :/html/thanks_en.txt + :/html/thanks_en.txt + + + + Authors + Yazarlar + + + + Thanks To + Teşekkürler + + + + ConfigDialog + + + Enabled + Etkinleştirildi + + + + Description + Açıklama + + + + Filename + Dosya adı + + + + Artist + Sanatçı + + + + Album + Albüm + + + + Title + Başlık + + + + Tracknumber + Parça Numarası + + + + Genre + Tarz + + + + Filepath + Dosya yolu + + + + Date + Tarih + + + + Year + Yıl + + + + Comment + Yorum + + + + Qmmp Settings + Qmmp Ayarları + + + + Skins + Kabuklar + + + + Fonts + Fontlar + + + + Player: + Oynatıcı: + + + + Playlist: + Çalma Listesi: + + + + ??? + ??? + + + + ... + ... + + + + Metadata + Veri bilgisi + + + + Load metadata from files + Veri bilgisini dosyadan yükle + + + + Song Display + Şarkı Göstergesi + + + + Title format: + Başlık formatı: + + + + Input + Giriş + + + + Output + Çıkış + + + + Preferences + Tercihler + + + + Information + Bilgi + + + + Tray Icon + Sistem Çekmecesi Simgesi + + + + Show tooltip + İpuçlarını göster + + + + Show message + Mesaj göster + + + + Message delay, ms: + Mesaj görüntü süresi, ms: + + + + Show tray icon + Sistem çekmecesi simgesini göster + + + + Appearance + Görünüm + + + + Playlist + Çalma Listesi + + + + Plugins + Eklentiler + + + + Advanced + Gelişmiş + + + + Close + Kapat + + + + Action On Close + + + + + Hide to tray + + + + + Quit + + + + + EqWidget + + + preset + tanımlanmış ayar + + + + &Load/Delete + &Yükle/Sil + + + + &Save Preset + Tanımlanmış &Ayarları Kaydet + + + + &Save Auto-load Preset + &Otomatik Tanımlanmış Ayarları Kaydet + + + + &Clear + &Temizle + + + + Saving Preset + Tanımlanmış Ayarla Kaydediliyor + + + + Preset name: + Tanımlanmış ayar adı: + + + + preset # + tanımlanmış ayar # + + + + &Import + &İçe Aktar + + + + Import Preset + Tanımlanmış Ayarları Al + + + + JumpToTrackDialog + + + Unqueue + Kuyrukta Değil + + + + Queue + Kuyruk + + + + Jump To Track + Parçaya Git + + + + Filter + Filtre + + + + Refresh + Yenile + + + + Jump To + Git + + + + Close + Kapat + + + + MainWindow + + + Default + Öntanımlı + + + + Now Playing + Şimdi Çalınıyor + + + + Choose a directory + Bir dizin seçin + + + + Select one or more files to open + Açmak için bir yada daha çok dosya seçin + + + + &Play + &Çal + + + + X + X + + + + &Pause + &Duraklat + + + + C + C + + + + &Stop + &Durdur + + + + V + V + + + + &Previous + &Önceki + + + + Z + Z + + + + &Next + &Sonraki + + + + B + B + + + + &Queue + &Kuyruğa ekle + + + + Q + Q + + + + &Jump To File + &Parçaya Git + + + + J + J + + + + &Settings + &Ayarlar + + + + Ctrl+P + Ctrl+P + + + + &Exit + &Çıkış + + + + Ctrl+Q + Ctrl+Q + + + + Open Playlist + Çalma Listesini Aç + + + + Save Playlist + Çalma Listesini Kaydet + + + + &About + &Hakkında + + + + Playlist Files + Çalma Listesi Dosyaları + + + + PlayList + + + F + F + + + + D + D + + + + Alt+I + Alt+I + + + + Ctrl+A + Ctrl+A + + + + O + O + + + + &Add File + &Dosya Ekle + + + + &Add Directory + &Dizin Ekle + + + + &Remove Selected + &Seçileni Kaldır + + + + &Remove All + &Hepsini Kaldır + + + + &Remove Unselected + &Seçilmemişleri Kaldır + + + + &View Track Details + &Parça Detaylarını Göster + + + + Sort List + Listeyi Sınıflandır + + + + By Title + Başlığa Göre + + + + By Filename + Dosya Adına Göre + + + + By Path + Filename + Dosya Yolu + Dosya Adına Göre + + + + By Date + Tarihe Göre + + + + Sort Selection + Seçilenleri Sınıflandır + + + + Randomize List + Rastgele Listele + + + + Reverse List + Listeyi Ters Çevir + + + + Invert Selection + Seçimi Tersine Çevir + + + + &Select None + &Hiçbirini Seçme + + + + &Select All + &Tümünü Seç + + + + &New List + &Yeni Liste + + + + Shift+N + Shift+N + + + + &Load List + &Liste Yükle + + + + &Save List + &Listeyi Kaydet + + + + Shift+S + Shift+S + + + + Del + + + + + PresetEditor + + + Preset Editor + Tanımlanmış Ayar Düzenleyici + + + + Load + Yükle + + + + Delete + Sil + + + + Preset + Tanımlanmış Ayar + + + + Auto-preset + Ayarları Otomatik Tanımla + + + diff --git a/src/ui/translations/qmmp_zh_CN.qm b/src/ui/translations/qmmp_zh_CN.qm new file mode 100644 index 000000000..2e3e3f2ea Binary files /dev/null and b/src/ui/translations/qmmp_zh_CN.qm differ diff --git a/src/ui/translations/qmmp_zh_CN.ts b/src/ui/translations/qmmp_zh_CN.ts new file mode 100644 index 000000000..3aeefd569 --- /dev/null +++ b/src/ui/translations/qmmp_zh_CN.ts @@ -0,0 +1,507 @@ + + + AboutDialog + + About Qmmp + 关于 Qmmp + + + About + 关于 + + + License Agreement + 许可协议 + + + :/html/about_en.html + :/html/about_zh_CN.html + + + :/html/authors_en.txt + :/html/authors_zh_CN.txt + + + :/html/thanks_en.txt + :/html/thanks_zh_CN.txt + + + Authors + 作者 + + + Thanks To + 感谢 + + + + ConfigDialog + + Enabled + 启用 + + + Description + 描述 + + + Filename + 文件名 + + + Artist + 艺术家 + + + Album + 专辑 + + + Title + 标题 + + + Tracknumber + 轨迹 + + + Genre + 流派 + + + Filepath + 文件路径 + + + Date + 日期 + + + Year + + + + Comment + 注释 + + + Qmmp Settings + Qmmp 设置 + + + Skins + 皮肤 + + + Fonts + 字体 + + + Player: + 播放器: + + + Playlist: + 播放列表: + + + ??? + ??? + + + ... + ... + + + Metadata + 元数据 + + + Load metadata from files + 从文件载入元数据 + + + Song Display + 显示歌曲 + + + Title format: + 标题格式: + + + Input + 输入 + + + Output + 输出 + + + Preferences + 参数设置 + + + Information + 信息 + + + Tray Icon + 托盘图标 + + + Show tooltip + 显示工具栏 + + + Show message + 显示通知 + + + Message delay, ms: + 消息延迟,毫秒: + + + Show tray icon + 显示托盘图标 + + + Appearance + 外观 + + + Playlist + 播放列表 + + + Plugins + 插件 + + + Advanced + 高级 + + + Close + 关闭 + + + + EqWidget + + preset + 预设 + + + &Load/Delete + 载入/删除(&L) + + + &Save Preset + 保存预设(&S) + + + &Save Auto-load Preset + 保存自动载入预设(&S) + + + &Clear + 清除(&C) + + + Saving Preset + 保存预设 + + + Preset name: + 预设名字: + + + preset # + 预设 # + + + &Import + 导入(&I) + + + Import Preset + 导入预设 + + + + JumpToTrackDialog + + Unqueue + 移出队列 + + + Queue + 加入队列 + + + Jump To Track + 跳跃至音轨 + + + Filter + 过滤 + + + Refresh + 刷新 + + + Jump To + 跳跃至 + + + Close + 关闭 + + + + MainWindow + + Default + 默认 + + + Now Playing + 正在播放 + + + Choose a directory + 选择一个目录 + + + Select one or more files to open + 选择打开一个或更多文件 + + + &Play + 播放(&P) + + + X + X + + + &Pause + 暂停(&P) + + + C + C + + + &Stop + 停止(&S) + + + V + V + + + &Previous + 上一个(&P) + + + Z + Z + + + &Next + 下一个(&N) + + + B + B + + + &Queue + 队列&Q) + + + Q + Q + + + &Jump To File + 跳跃至文件(&J) + + + J + J + + + &Settings + 设置(&S) + + + Ctrl+P + Ctrl+P + + + &Exit + 退出(&E) + + + Ctrl+Q + Q + + + Open Playlist + 打开播放列表 + + + Save Playlist + 保存播放列表 + + + &About + 关于(&A) + + + Playlist Files + 播放列表文件 + + + + PlayList + + F + F + + + D + D + + + Delete + 删除 + + + Alt+I + Alt+I + + + Ctrl+A + Ctrl+A + + + O + O + + + &Add File + 添加文件(&A) + + + &Add Directory + 添加文件夹(&A) + + + &Remove Selected + 移除所选(&R) + + + &Remove All + 移除全部(&R) + + + &Remove Unselected + 移除未选(&R) + + + &View Track Details + 查看音轨详细信息(&V) + + + Sort List + 列表排序 + + + By Title + 按标题 + + + By Filename + 按文件名 + + + By Path + Filename + 按路径+文件名 + + + By Date + 按日期 + + + Sort Selection + 选择排序 + + + Randomize List + 随机产生列表 + + + Reverse List + 逆序列表 + + + Invert Selection + 反选 + + + &Select None + 选择无(&S) + + + &Select All + 全选(&S) + + + &New List + 新建列表(&N) + + + Shift+N + Shift+N + + + &Load List + 载入列表(&L) + + + &Save List + 保存列表(&S) + + + Shift+S + Shift+S + + + + PresetEditor + + Preset Editor + 预设编辑器 + + + Load + 装入 + + + Delete + 删除 + + + Preset + 预设 + + + Auto-preset + 预设自动 + + + diff --git a/src/ui/ui.pro b/src/ui/ui.pro new file mode 100644 index 000000000..527c205f2 --- /dev/null +++ b/src/ui/ui.pro @@ -0,0 +1,149 @@ +# ???? ?????? ? KDevelop ?????????? qmake. +# ------------------------------------------- +# ?????????? ???????????? ???????? ???????? ???????: ./src +# ???? - ??????????: ../bin/mp3player + +include(../qmmp.pri) + +FORMS += ./forms/configdialog.ui \ + ./forms/preseteditor.ui \ + ./forms/jumptotrackdialog.ui \ + ./forms/aboutdialog.ui \ + ./forms/addurldialog.ui + +HEADERS += mainwindow.h \ + fileloader.h \ + button.h \ + display.h \ + skin.h \ + titlebar.h \ + positionbar.h \ + number.h \ + playlist.h \ + mediafile.h \ + listwidget.h \ + playlistmodel.h \ + pixmapwidget.h \ + playlisttitlebar.h \ + configdialog.h \ + playlistslider.h \ + dock.h \ + eqwidget.h \ + eqtitlebar.h \ + eqslider.h \ + togglebutton.h \ + eqgraph.h \ + mainvisual.h \ + inlines.h \ + fft.h \ + logscale.h \ + textscroller.h \ + monostereo.h \ + playstatus.h \ + pluginitem.h \ + volumebar.h \ + balancebar.h \ + playstate.h \ + symboldisplay.h \ + playlistformat.h \ + playlistcontrol.h \ + version.h \ + qmmpstarter.h \ + eqpreset.h \ + preseteditor.h \ + jumptotrackdialog.h \ + aboutdialog.h \ + timeindicator.h \ + keyboardmanager.h \ + filedialog.h \ + unixdomainsocket.h \ + commandlineoption.h \ + addurldialog.h \ + skinreader.h \ + visualmenu.h \ + titlebarcontrol.h \ + shadedvisual.h \ + shadedbar.h + +SOURCES += mainwindow.cpp \ + mp3player.cpp \ + fileloader.cpp \ + button.cpp \ + display.cpp \ + skin.cpp \ + titlebar.cpp \ + positionbar.cpp \ + number.cpp \ + playlist.cpp \ + mediafile.cpp \ + listwidget.cpp \ + playlistmodel.cpp \ + pixmapwidget.cpp \ + playlisttitlebar.cpp \ + configdialog.cpp \ + playlistslider.cpp \ + dock.cpp \ + eqwidget.cpp \ + eqtitlebar.cpp \ + eqslider.cpp \ + togglebutton.cpp \ + eqgraph.cpp \ + mainvisual.cpp \ + fft.c \ + logscale.cpp \ + textscroller.cpp \ + monostereo.cpp \ + playstatus.cpp \ + pluginitem.cpp \ + volumebar.cpp \ + balancebar.cpp \ + playstate.cpp \ + symboldisplay.cpp \ + playlistformat.cpp \ + playlistcontrol.cpp \ + qmmpstarter.cpp \ + eqpreset.cpp \ + preseteditor.cpp \ + jumptotrackdialog.cpp \ + aboutdialog.cpp \ + timeindicator.cpp \ + keyboardmanager.cpp \ + filedialog.cpp \ + unixdomainsocket.cpp \ + commandlineoption.cpp \ + addurldialog.cpp \ + skinreader.cpp \ + visualmenu.cpp \ + titlebarcontrol.cpp \ + shadedvisual.cpp \ + shadedbar.cpp + +#Some conf to redirect intermediate stuff in separate dirs +UI_DIR=./.build/ui/ +MOC_DIR=./.build/moc/ +OBJECTS_DIR=./.build/obj + + +QT += network xml +TARGET = ../../bin/qmmp +CONFIG += thread release \ +warn_on +QMAKE_LIBDIR += ../../lib qmmpui +LIBS += -Wl,-rpath,../lib +LIBS += -L../../lib -lqmmp -lqmmpui +INCLUDEPATH += ../qmmp ../ +RESOURCES = images/images.qrc \ + stuff.qrc +TEMPLATE = app +target.path = /bin +INSTALLS += target + + +#RESOURCES += translations/qmmp_locales.qrc + +#TRANSLATIONS = translations/qmmp_ru.ts \ +# translations/qmmp_tr.ts \ +# translations/qmmp_zh_CN.ts + + + diff --git a/src/ui/unixdomainsocket.cpp b/src/ui/unixdomainsocket.cpp new file mode 100644 index 000000000..5769676be --- /dev/null +++ b/src/ui/unixdomainsocket.cpp @@ -0,0 +1,67 @@ +#include +#include +#include +#include + +#include "unixdomainsocket.h" + + +UnixDomainSocket::UnixDomainSocket(QObject * parent ) : QUdpSocket(parent){ + _bound = false; + _s = socket(AF_UNIX, SOCK_DGRAM, 0); + this->setSocketDescriptor(_s); +} + +UnixDomainSocket::~UnixDomainSocket(){ + + if(_bound){ + ::unlink(_local.sun_path); + } +} + +bool UnixDomainSocket::bind(const QString& path){ + + int len; + bzero(&_local,sizeof(_local)); + _local.sun_family = AF_UNIX; + strcpy(_local.sun_path,path.toLocal8Bit().data()); + len = strlen(_local.sun_path) + sizeof(_local.sun_family); + bool res = !(::bind(_s, (struct sockaddr *)&_local, len)); + if(res) + _bound = true; + return res; +} + + +bool UnixDomainSocket::alive(const QString& path) +{ + socklen_t len; + struct sockaddr_un server; + bzero(&server,sizeof(server)); + server.sun_family = AF_UNIX; + strcpy(server.sun_path,path.toLocal8Bit().data()); + len = strlen(server.sun_path) + sizeof(server.sun_family); + + if (::connect(_s, (struct sockaddr *)&server, len) == -1) + { + perror("connect"); + return false; + } + return true; +} +// +void UnixDomainSocket::writeDatagram(const char* command,const QString& path) +{ + socklen_t len; + struct sockaddr_un server; + bzero(&server,sizeof(server)); + server.sun_family = AF_UNIX; + strcpy(server.sun_path,path.toLocal8Bit().data()); + + len = strlen(server.sun_path) + sizeof(server.sun_family); + + sendto(_s,command,strlen(command),0,(struct sockaddr*)&server,len); +} + + + diff --git a/src/ui/unixdomainsocket.h b/src/ui/unixdomainsocket.h new file mode 100644 index 000000000..37e5a364b --- /dev/null +++ b/src/ui/unixdomainsocket.h @@ -0,0 +1,46 @@ +#ifndef UNIXDOMAINSOCKET_H +#define UNIXDOMAINSOCKET_H + +#include +#include +#include +#include +#include + + +/*! + * UnixDomainSocket class is a wrapper around the unix domain sockets implementation. + * Used for QMMP interprocess communications. + * @author Vladimir Kuznetsov + */ +class UnixDomainSocket : public QUdpSocket +{ +Q_OBJECT +public: + UnixDomainSocket(QObject * parent = 0 ); + + /*! + * Try to bind socket to \b path. Returns \b true on success, otherwise \b false + */ + bool bind(const QString& file); + + /*! + * Checks if socket at \b path path is alive( i.e. connectable). + */ + bool alive(const QString& path); + ~UnixDomainSocket(); + +public slots: + /*! + * Sends the datagram \b command to the socket at \b path path. + */ + void writeDatagram(const char* command,const QString& path); +private: + unsigned int _s; + struct sockaddr_un _local; + bool _bound; +}; + + +#endif + diff --git a/src/ui/version.h b/src/ui/version.h new file mode 100644 index 000000000..61fbc902e --- /dev/null +++ b/src/ui/version.h @@ -0,0 +1,11 @@ +#ifndef _QMMP_VERSION_H +#define _QMMP_VERSION_H + +#define QMMP_VERSION 0.1.4 + +#define QMMP_STR_VERSION "0.1.4" + +#define LISTEN_PORT_BASE 33000 +#define UDS_PATH "/tmp/qmmp.sock" + +#endif diff --git a/src/ui/visualmenu.cpp b/src/ui/visualmenu.cpp new file mode 100644 index 000000000..2b0ad6797 --- /dev/null +++ b/src/ui/visualmenu.cpp @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include + +#include +#include + +#include "pluginitem.h" +#include "visualmenu.h" + +VisualMenu::VisualMenu(QWidget *parent) + : QMenu(tr("Visualization"), parent) +{ + VisualFactory *factory = 0; + foreach(factory, *Visual::visualFactories()) + { + QAction *act = this->addAction(factory->properties().name); + act->setCheckable (TRUE); + act->setChecked (Visual::isEnabled(factory)); + VisualPluginItem *vi = new VisualPluginItem(this,factory, ""); + connect(act, SIGNAL(toggled(bool)), vi, SLOT(select(bool))); + } +} + +VisualMenu::~VisualMenu() +{ +} + +void VisualMenu::updateActions() +{ + for(int i = 0; i < Visual::visualFactories()->size(); ++i) + { + actions()[i]->setChecked(Visual::isEnabled(Visual::visualFactories()->at(i))); + } +} diff --git a/src/ui/visualmenu.h b/src/ui/visualmenu.h new file mode 100644 index 000000000..9202a8a7d --- /dev/null +++ b/src/ui/visualmenu.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2007 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef VISUALMENU_H +#define VISUALMENU_H + +#include + +/** + @author Ilya Kotov +*/ +class VisualMenu : public QMenu +{ +Q_OBJECT +public: + VisualMenu(QWidget *parent = 0); + + ~VisualMenu(); + +void updateActions(); + +}; + +#endif diff --git a/src/ui/volumebar.cpp b/src/ui/volumebar.cpp new file mode 100644 index 000000000..15c7db867 --- /dev/null +++ b/src/ui/volumebar.cpp @@ -0,0 +1,130 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include + +#include "skin.h" +#include "button.h" +#include "mainwindow.h" + +#include "volumebar.h" + + +VolumeBar::VolumeBar(QWidget *parent) + : PixmapWidget(parent) +{ + m_skin = Skin::getPointer(); + connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); + setPixmap(m_skin->getVolumeBar(0)); + mw = qobject_cast(window()); + m_moving = FALSE; + m_min = 0; + m_max = 100; + m_old = m_value = 0; + draw(FALSE); +} + + +VolumeBar::~VolumeBar() +{} + +void VolumeBar::mousePressEvent(QMouseEvent *e) +{ + + m_moving = TRUE; + press_pos = e->x(); + if(m_posx() && e->x()x()-m_pos; + } + else + { + m_value = convert(qMax(qMin(width()-18,e->x()-6),0)); + press_pos = 6; + if (m_value!=m_old) + { + emit sliderMoved(m_value); + + } + } + draw(); +} + +void VolumeBar::mouseMoveEvent (QMouseEvent *e) +{ + if(m_moving) + { + int po = e->x(); + po = po - press_pos; + + if(0<=po && po<=width()-18) + { + m_value = convert(po); + draw(); + emit sliderMoved(m_value); + } + } +} + +void VolumeBar::mouseReleaseEvent(QMouseEvent*) +{ + m_moving = FALSE; + draw(FALSE); + m_old = m_value; +} + +void VolumeBar::setValue(int v) +{ + if (m_moving || m_max == 0) + return; + m_value = v; + draw(FALSE); +} + +void VolumeBar::setMax(int max) +{ + m_max = max; + draw(FALSE); +} + +void VolumeBar::updateSkin() +{ + draw(FALSE); +} + +void VolumeBar::draw(bool pressed) +{ + int p=int(ceil(double(m_value-m_min)*(width()-18)/(m_max-m_min))); + m_pixmap = m_skin->getVolumeBar(27*(m_value-m_min)/(m_max-m_min)); + QPainter paint(&m_pixmap); + if(pressed) + paint.drawPixmap(p,1,m_skin->getButton(Skin::BT_VOL_P)); + else + paint.drawPixmap(p,1,m_skin->getButton(Skin::BT_VOL_N)); + setPixmap(m_pixmap); + m_pos = p; +} + +int VolumeBar::convert(int p) +{ + return int(ceil(double(m_max-m_min)*(p)/(width()-18)+m_min)); +} diff --git a/src/ui/volumebar.h b/src/ui/volumebar.h new file mode 100644 index 000000000..51bc7ac46 --- /dev/null +++ b/src/ui/volumebar.h @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (C) 2006 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program is free software; 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. * + ***************************************************************************/ +#ifndef VOLUMEBAR_H +#define VOLUMEBAR_H + +#include + +/** + @author Ilya Kotov +*/ + +class Skin; +class MainWindow; + +class VolumeBar : public PixmapWidget +{ +Q_OBJECT +public: + VolumeBar(QWidget *parent = 0); + + ~VolumeBar(); + + int value() { return m_value; }; + int isPressed() {return m_moving; } + +public slots: + void setValue(int); + void setMax(int); + +signals: + void sliderMoved (int); + +private slots: + void updateSkin(); + +private: + Skin *m_skin; + bool m_moving; + int press_pos; + int m_max, m_min, m_pos, m_value, m_old; + QPixmap m_pixmap; + MainWindow *mw; + int convert(int); // value = convert(position); + void draw(bool pressed = TRUE); + +protected: + void mousePressEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + + +}; + +#endif diff --git a/src/unixdomainsocket.cpp b/src/unixdomainsocket.cpp deleted file mode 100644 index ecf8aa6f0..000000000 --- a/src/unixdomainsocket.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include -#include - -#include "unixdomainsocket.h" - - -UnixDomainSocket::UnixDomainSocket(QObject * parent ) : QUdpSocket(parent){ - _binded = false; - _s = socket(AF_UNIX, SOCK_DGRAM, 0); - this->setSocketDescriptor(_s); -} - -UnixDomainSocket::~UnixDomainSocket(){ - - if(_binded){ - ::unlink(_local.sun_path); - } -} - -bool UnixDomainSocket::bind(const QString& path){ - - int len; - bzero(&_local,sizeof(_local)); - _local.sun_family = AF_UNIX; - strcpy(_local.sun_path,path.toLocal8Bit().data()); - len = strlen(_local.sun_path) + sizeof(_local.sun_family); - bool res = !(::bind(_s, (struct sockaddr *)&_local, len)); - if(res) - _binded = true; - return res; -} - - -bool UnixDomainSocket::alive(const QString& path) -{ - socklen_t len; - struct sockaddr_un server; - bzero(&server,sizeof(server)); - server.sun_family = AF_UNIX; - strcpy(server.sun_path,path.toLocal8Bit().data()); - len = strlen(server.sun_path) + sizeof(server.sun_family); - - if (::connect(_s, (struct sockaddr *)&server, len) == -1) - { - perror("connect"); - return false; - } - return true; -} - -void UnixDomainSocket::writeDatagram(const char* command,const QString& path) -{ - socklen_t len; - struct sockaddr_un server; - bzero(&server,sizeof(server)); - server.sun_family = AF_UNIX; - strcpy(server.sun_path,path.toLocal8Bit().data()); - - len = strlen(server.sun_path) + sizeof(server.sun_family); - - sendto(_s,command,strlen(command),0,(struct sockaddr*)&server,len); -} - - - diff --git a/src/unixdomainsocket.h b/src/unixdomainsocket.h deleted file mode 100644 index 7538e685a..000000000 --- a/src/unixdomainsocket.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef UNIXDOMAINSOCKET_H -#define UNIXDOMAINSOCKET_H - -#include -#include -#include -#include -#include - - -/*! - * UnixDomainSocket class is a wrapper around the unix domain sockets implementation. - * Used for QMMP interprocess communications. - * @author Vladimir Kuznetsov - */ -class UnixDomainSocket : public QUdpSocket -{ -Q_OBJECT -public: - UnixDomainSocket(QObject * parent = 0 ); - - /*! - * Try to bind socket to \b path. Returns \b true on success, otherwise \b false - */ - bool bind(const QString& file); - - /*! - * Checks if socket at \b path path is alive( i.e. connectable). - */ - bool alive(const QString& path); - ~UnixDomainSocket(); - -public slots: - /*! - * Sends the datagram \b command to the socket at \b path path. - */ - void writeDatagram(const char* command,const QString& path); -private: - unsigned int _s; - struct sockaddr_un _local; - bool _binded; -}; - - -#endif - diff --git a/src/version.h b/src/version.h deleted file mode 100644 index 61fbc902e..000000000 --- a/src/version.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _QMMP_VERSION_H -#define _QMMP_VERSION_H - -#define QMMP_VERSION 0.1.4 - -#define QMMP_STR_VERSION "0.1.4" - -#define LISTEN_PORT_BASE 33000 -#define UDS_PATH "/tmp/qmmp.sock" - -#endif diff --git a/src/visualmenu.cpp b/src/visualmenu.cpp deleted file mode 100644 index 2b0ad6797..000000000 --- a/src/visualmenu.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -#include -#include - -#include "pluginitem.h" -#include "visualmenu.h" - -VisualMenu::VisualMenu(QWidget *parent) - : QMenu(tr("Visualization"), parent) -{ - VisualFactory *factory = 0; - foreach(factory, *Visual::visualFactories()) - { - QAction *act = this->addAction(factory->properties().name); - act->setCheckable (TRUE); - act->setChecked (Visual::isEnabled(factory)); - VisualPluginItem *vi = new VisualPluginItem(this,factory, ""); - connect(act, SIGNAL(toggled(bool)), vi, SLOT(select(bool))); - } -} - -VisualMenu::~VisualMenu() -{ -} - -void VisualMenu::updateActions() -{ - for(int i = 0; i < Visual::visualFactories()->size(); ++i) - { - actions()[i]->setChecked(Visual::isEnabled(Visual::visualFactories()->at(i))); - } -} diff --git a/src/visualmenu.h b/src/visualmenu.h deleted file mode 100644 index 9202a8a7d..000000000 --- a/src/visualmenu.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef VISUALMENU_H -#define VISUALMENU_H - -#include - -/** - @author Ilya Kotov -*/ -class VisualMenu : public QMenu -{ -Q_OBJECT -public: - VisualMenu(QWidget *parent = 0); - - ~VisualMenu(); - -void updateActions(); - -}; - -#endif diff --git a/src/volumebar.cpp b/src/volumebar.cpp deleted file mode 100644 index 15c7db867..000000000 --- a/src/volumebar.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include -#include -#include - -#include "skin.h" -#include "button.h" -#include "mainwindow.h" - -#include "volumebar.h" - - -VolumeBar::VolumeBar(QWidget *parent) - : PixmapWidget(parent) -{ - m_skin = Skin::getPointer(); - connect(m_skin, SIGNAL(skinChanged()), this, SLOT(updateSkin())); - setPixmap(m_skin->getVolumeBar(0)); - mw = qobject_cast(window()); - m_moving = FALSE; - m_min = 0; - m_max = 100; - m_old = m_value = 0; - draw(FALSE); -} - - -VolumeBar::~VolumeBar() -{} - -void VolumeBar::mousePressEvent(QMouseEvent *e) -{ - - m_moving = TRUE; - press_pos = e->x(); - if(m_posx() && e->x()x()-m_pos; - } - else - { - m_value = convert(qMax(qMin(width()-18,e->x()-6),0)); - press_pos = 6; - if (m_value!=m_old) - { - emit sliderMoved(m_value); - - } - } - draw(); -} - -void VolumeBar::mouseMoveEvent (QMouseEvent *e) -{ - if(m_moving) - { - int po = e->x(); - po = po - press_pos; - - if(0<=po && po<=width()-18) - { - m_value = convert(po); - draw(); - emit sliderMoved(m_value); - } - } -} - -void VolumeBar::mouseReleaseEvent(QMouseEvent*) -{ - m_moving = FALSE; - draw(FALSE); - m_old = m_value; -} - -void VolumeBar::setValue(int v) -{ - if (m_moving || m_max == 0) - return; - m_value = v; - draw(FALSE); -} - -void VolumeBar::setMax(int max) -{ - m_max = max; - draw(FALSE); -} - -void VolumeBar::updateSkin() -{ - draw(FALSE); -} - -void VolumeBar::draw(bool pressed) -{ - int p=int(ceil(double(m_value-m_min)*(width()-18)/(m_max-m_min))); - m_pixmap = m_skin->getVolumeBar(27*(m_value-m_min)/(m_max-m_min)); - QPainter paint(&m_pixmap); - if(pressed) - paint.drawPixmap(p,1,m_skin->getButton(Skin::BT_VOL_P)); - else - paint.drawPixmap(p,1,m_skin->getButton(Skin::BT_VOL_N)); - setPixmap(m_pixmap); - m_pos = p; -} - -int VolumeBar::convert(int p) -{ - return int(ceil(double(m_max-m_min)*(p)/(width()-18)+m_min)); -} diff --git a/src/volumebar.h b/src/volumebar.h deleted file mode 100644 index 51bc7ac46..000000000 --- a/src/volumebar.h +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Ilya Kotov * - * forkotov02@hotmail.ru * - * * - * This program is free software; 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. * - ***************************************************************************/ -#ifndef VOLUMEBAR_H -#define VOLUMEBAR_H - -#include - -/** - @author Ilya Kotov -*/ - -class Skin; -class MainWindow; - -class VolumeBar : public PixmapWidget -{ -Q_OBJECT -public: - VolumeBar(QWidget *parent = 0); - - ~VolumeBar(); - - int value() { return m_value; }; - int isPressed() {return m_moving; } - -public slots: - void setValue(int); - void setMax(int); - -signals: - void sliderMoved (int); - -private slots: - void updateSkin(); - -private: - Skin *m_skin; - bool m_moving; - int press_pos; - int m_max, m_min, m_pos, m_value, m_old; - QPixmap m_pixmap; - MainWindow *mw; - int convert(int); // value = convert(position); - void draw(bool pressed = TRUE); - -protected: - void mousePressEvent(QMouseEvent*); - void mouseReleaseEvent(QMouseEvent*); - void mouseMoveEvent(QMouseEvent*); - - -}; - -#endif -- cgit v1.2.3-13-gbd6f