From 864081102a5f252415f41950b3039a896b4ae9c5 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Mon, 8 Oct 2012 18:43:29 +0000 Subject: Awkwars's plugins - welcome to our trunk git-svn-id: http://svn.miranda-ng.org/main/trunk@1822 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Watrack/HlpDlg.pas | 83 ++ plugins/Watrack/docs/const.php | 157 +++ plugins/Watrack/docs/m_music.h | 386 +++++++ plugins/Watrack/docs/m_music.inc | 404 +++++++ plugins/Watrack/docs/sampledll.dpr | 139 +++ plugins/Watrack/docs/wat.php | 28 + plugins/Watrack/docs/watrack_history.txt | 519 +++++++++ plugins/Watrack/docs/watrack_readme.txt | 110 ++ plugins/Watrack/formats/fmt_aac.pas | 93 ++ plugins/Watrack/formats/fmt_ape.pas | 137 +++ plugins/Watrack/formats/fmt_avi.pas | 295 +++++ plugins/Watrack/formats/fmt_dummy.pas | 46 + plugins/Watrack/formats/fmt_flv.pas | 334 ++++++ plugins/Watrack/formats/fmt_m4a.pas | 378 ++++++ plugins/Watrack/formats/fmt_mkv.pas | 235 ++++ plugins/Watrack/formats/fmt_mp3.pas | 460 ++++++++ plugins/Watrack/formats/fmt_mpc.pas | 90 ++ plugins/Watrack/formats/fmt_ofr.pas | 74 ++ plugins/Watrack/formats/fmt_ogg.pas | 522 +++++++++ plugins/Watrack/formats/fmt_real.pas | 335 ++++++ plugins/Watrack/formats/fmt_tta.pas | 65 ++ plugins/Watrack/formats/fmt_wav.pas | 146 +++ plugins/Watrack/formats/fmt_wma.pas | 438 +++++++ plugins/Watrack/formats/tag_apev2.inc | 124 ++ plugins/Watrack/formats/tag_id3v1.inc | 175 +++ plugins/Watrack/formats/tag_id3v2.inc | 545 +++++++++ plugins/Watrack/formats/tags.pas | 21 + plugins/Watrack/global.pas | 86 ++ plugins/Watrack/i_cover.inc | 90 ++ plugins/Watrack/i_gui.inc | 114 ++ plugins/Watrack/i_opt_0.inc | 91 ++ plugins/Watrack/i_opt_1.inc | 256 ++++ plugins/Watrack/i_opt_dlg.inc | 57 + plugins/Watrack/i_options.inc | 171 +++ plugins/Watrack/i_timer.inc | 26 + plugins/Watrack/i_vars.inc | 37 + plugins/Watrack/icons/GO/GoAsm.Exe | Bin 0 -> 124416 bytes plugins/Watrack/icons/GO/GoLink.exe | Bin 0 -> 48640 bytes plugins/Watrack/icons/GO/GoRC.exe | Bin 0 -> 54784 bytes plugins/Watrack/icons/GO/icons.bat | 8 + plugins/Watrack/icons/GO/icons.rc | 58 + plugins/Watrack/icons/GO/waticons.h | 35 + plugins/Watrack/icons/GO/watrack_buttons.asm | 5 + plugins/Watrack/icons/MASM/icons.bat | 8 + plugins/Watrack/icons/MASM/icons.rc | 58 + plugins/Watrack/icons/MASM/iconspl.rc | 83 ++ plugins/Watrack/icons/MASM/poasm.exe | Bin 0 -> 653488 bytes plugins/Watrack/icons/MASM/polink.exe | Bin 0 -> 164528 bytes plugins/Watrack/icons/MASM/porc.dll | Bin 0 -> 146096 bytes plugins/Watrack/icons/MASM/porc.exe | Bin 0 -> 30208 bytes plugins/Watrack/icons/MASM/waticons.h | 35 + plugins/Watrack/icons/MASM/watrack.asm | 5 + plugins/Watrack/icons/TASM/RLINK32.DLL | Bin 0 -> 59904 bytes plugins/Watrack/icons/TASM/TASM32.EXE | Bin 0 -> 188416 bytes plugins/Watrack/icons/TASM/TLINK32.EXE | Bin 0 -> 208896 bytes plugins/Watrack/icons/TASM/brcc32.exe | Bin 0 -> 169008 bytes plugins/Watrack/icons/TASM/icons.bat | 9 + plugins/Watrack/icons/TASM/icons.rc | 58 + plugins/Watrack/icons/TASM/iconspl.rc | 61 + plugins/Watrack/icons/TASM/rw32core.dll | Bin 0 -> 812576 bytes plugins/Watrack/icons/TASM/waticons.h | 35 + plugins/Watrack/icons/TASM/watrack.asm | 8 + plugins/Watrack/icons/iconsets/players/1by1.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/AIMP.ico | Bin 0 -> 2550 bytes .../iconsets/players/Ashampoo Media Player.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/BeholdTV.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/Billy.ico | Bin 0 -> 2550 bytes .../icons/iconsets/players/Core Media Player.ico | Bin 0 -> 2550 bytes .../icons/iconsets/players/Crystal Player.ico | Bin 0 -> 2550 bytes .../icons/iconsets/players/Cyberlink PowerDVD.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/Evil Player.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/GOMPlayer.ico | Bin 0 -> 2550 bytes .../iconsets/players/Helium Music Manager.ico | Bin 0 -> 2550 bytes .../iconsets/players/J.River Media Center.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/JetAudio.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/KMPlayer.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/LastFM.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/MediaMonkey.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/MoreAmp.ico | Bin 0 -> 2862 bytes .../Watrack/icons/iconsets/players/MusikCube.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/QCDPlayer.ico | Bin 0 -> 2550 bytes .../icons/iconsets/players/Quicktime Player.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/RadLight.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/Real Player.ico | Bin 0 -> 2550 bytes .../icons/iconsets/players/Spider Player.ico | Bin 0 -> 2550 bytes .../icons/iconsets/players/Ultra player.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/VUPlayer.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/WMP 9.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/WinDVD.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/XMPlay.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/Zoom Player.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/alshow.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/alsong.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/apollo.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/audio.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/bsplayer.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/cms.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/flv.ico | Bin 0 -> 1406 bytes .../Watrack/icons/iconsets/players/foobar2000.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/itunes.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/la.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/mcone.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/mcx.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/mmatch.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/mpc.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/mplayer.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/pluton.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/saps.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/players/songbird.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/vlc.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/vp3.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/wany.ico | Bin 0 -> 1406 bytes plugins/Watrack/icons/iconsets/players/wifi.ico | Bin 0 -> 2550 bytes plugins/Watrack/icons/iconsets/players/winamp.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/disable.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/enable.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/true+256-solid/next.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/next_hovered.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/next_pressed.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/pause.ico | Bin 0 -> 2550 bytes .../iconsets/true+256-solid/pause_hovered.ico | Bin 0 -> 2550 bytes .../iconsets/true+256-solid/pause_pressed.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/true+256-solid/play.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/play_hovered.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/play_pressed.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/previous.ico | Bin 0 -> 2550 bytes .../iconsets/true+256-solid/previous_hovered.ico | Bin 0 -> 2550 bytes .../iconsets/true+256-solid/previous_pressed.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/slider.ico | Bin 0 -> 2550 bytes .../iconsets/true+256-solid/slider_hovered.ico | Bin 0 -> 2550 bytes .../iconsets/true+256-solid/slider_pressed.ico | Bin 0 -> 2550 bytes .../Watrack/icons/iconsets/true+256-solid/stop.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/stop_hovered.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/stop_pressed.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/volume_down.ico | Bin 0 -> 2550 bytes .../true+256-solid/volume_down_hovered.ico | Bin 0 -> 2550 bytes .../true+256-solid/volume_down_pressed.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true+256-solid/volume_up.ico | Bin 0 -> 2550 bytes .../iconsets/true+256-solid/volume_up_hovered.ico | Bin 0 -> 2550 bytes .../iconsets/true+256-solid/volume_up_pressed.ico | Bin 0 -> 2550 bytes .../icons/iconsets/true-solid-faith/next.ico | Bin 0 -> 1150 bytes .../iconsets/true-solid-faith/next_hovered.ico | Bin 0 -> 1150 bytes .../iconsets/true-solid-faith/next_pressed.ico | Bin 0 -> 1150 bytes .../icons/iconsets/true-solid-faith/pause.ico | Bin 0 -> 1150 bytes .../iconsets/true-solid-faith/pause_hovered.ico | Bin 0 -> 1150 bytes .../iconsets/true-solid-faith/pause_pressed.ico | Bin 0 -> 1150 bytes .../icons/iconsets/true-solid-faith/play.ico | Bin 0 -> 1150 bytes .../iconsets/true-solid-faith/play_hovered.ico | Bin 0 -> 1150 bytes .../iconsets/true-solid-faith/play_pressed.ico | Bin 0 -> 1150 bytes .../icons/iconsets/true-solid-faith/previous.ico | Bin 0 -> 1150 bytes .../iconsets/true-solid-faith/previous_hovered.ico | Bin 0 -> 1150 bytes .../iconsets/true-solid-faith/previous_pressed.ico | Bin 0 -> 1150 bytes .../icons/iconsets/true-solid-faith/slider.ico | Bin 0 -> 1150 bytes .../icons/iconsets/true-solid-faith/stop.ico | Bin 0 -> 1150 bytes .../iconsets/true-solid-faith/stop_hovered.ico | Bin 0 -> 1150 bytes .../iconsets/true-solid-faith/stop_pressed.ico | Bin 0 -> 1150 bytes .../icons/iconsets/true-solid-faith/ver.res | Bin 0 -> 744 bytes .../iconsets/true-solid-faith/volume_down.ico | Bin 0 -> 1150 bytes .../true-solid-faith/volume_down_hovered.ico | Bin 0 -> 1150 bytes .../true-solid-faith/volume_down_pressed.ico | Bin 0 -> 1150 bytes .../icons/iconsets/true-solid-faith/volume_up.ico | Bin 0 -> 1150 bytes .../true-solid-faith/volume_up_hovered.ico | Bin 0 -> 1150 bytes .../true-solid-faith/volume_up_pressed.ico | Bin 0 -> 1150 bytes plugins/Watrack/icons/make-buttons.bat | 4 + plugins/Watrack/icons/make-players.bat | 2 + plugins/Watrack/icons/make.bat | 16 + plugins/Watrack/icons/waticons.inc | 35 + plugins/Watrack/kolframe/frm.rc | 84 ++ plugins/Watrack/kolframe/frm.res | Bin 0 -> 3032 bytes plugins/Watrack/kolframe/frm_data.inc | 37 + plugins/Watrack/kolframe/frm_designer.inc | 164 +++ plugins/Watrack/kolframe/frm_dlg1.inc | 283 +++++ plugins/Watrack/kolframe/frm_dlg2.inc | 172 +++ plugins/Watrack/kolframe/frm_frame.inc | 497 ++++++++ plugins/Watrack/kolframe/frm_icogroup.inc | 115 ++ plugins/Watrack/kolframe/frm_rc.inc | 56 + plugins/Watrack/kolframe/frm_text.inc | 90 ++ plugins/Watrack/kolframe/frm_trackbar.inc | 229 ++++ plugins/Watrack/kolframe/frm_vars.inc | 80 ++ plugins/Watrack/kolframe/i_bitmap.inc | 290 +++++ plugins/Watrack/kolframe/kolframe.pas | 327 ++++++ plugins/Watrack/lastfm/i_const.inc | 17 + plugins/Watrack/lastfm/i_last_api.inc | 599 ++++++++++ plugins/Watrack/lastfm/i_last_dlg.inc | 120 ++ plugins/Watrack/lastfm/i_last_opt.inc | 44 + plugins/Watrack/lastfm/lastfm.ico | Bin 0 -> 2550 bytes plugins/Watrack/lastfm/lastfm.pas | 300 +++++ plugins/Watrack/lastfm/lastfm.rc | 38 + plugins/Watrack/lastfm/lastfm.res | Bin 0 -> 3720 bytes plugins/Watrack/lst_formats.inc | 16 + plugins/Watrack/lst_players.inc | 17 + plugins/Watrack/m_music.inc | 419 +++++++ plugins/Watrack/macros.pas | 93 ++ plugins/Watrack/make.bat | 26 + plugins/Watrack/myrtf.pas | 219 ++++ plugins/Watrack/myshows/i_const.inc | 14 + plugins/Watrack/myshows/i_cookies.inc | 91 ++ plugins/Watrack/myshows/i_myshows_api.inc | 247 ++++ plugins/Watrack/myshows/i_myshows_dlg.inc | 111 ++ plugins/Watrack/myshows/i_myshows_opt.inc | 47 + plugins/Watrack/myshows/myshows.ico | Bin 0 -> 1150 bytes plugins/Watrack/myshows/myshows.pas | 333 ++++++ plugins/Watrack/myshows/myshows.rc | 41 + plugins/Watrack/myshows/myshows.res | Bin 0 -> 1728 bytes plugins/Watrack/player.ini | 283 +++++ plugins/Watrack/players/mradio.ico | Bin 0 -> 1150 bytes plugins/Watrack/players/mradio.rc | 3 + plugins/Watrack/players/mradio.res | Bin 0 -> 1264 bytes plugins/Watrack/players/pl_1by1.pas | 84 ++ plugins/Watrack/players/pl_aimp.pas | 376 ++++++ plugins/Watrack/players/pl_apollo.pas | 263 +++++ plugins/Watrack/players/pl_behold.pas | 175 +++ plugins/Watrack/players/pl_bs.pas | 252 ++++ plugins/Watrack/players/pl_cowon.pas | 392 +++++++ plugins/Watrack/players/pl_foobar.pas | 534 +++++++++ plugins/Watrack/players/pl_itunes.pas | 392 +++++++ plugins/Watrack/players/pl_la.pas | 141 +++ plugins/Watrack/players/pl_lastfm.pas | 129 +++ plugins/Watrack/players/pl_mmonkey.pas | 181 +++ plugins/Watrack/players/pl_mpc.pas | 117 ++ plugins/Watrack/players/pl_mradio.pas | 345 ++++++ plugins/Watrack/players/pl_vlc.pas | 380 ++++++ plugins/Watrack/players/pl_winamp.pas | 170 +++ plugins/Watrack/players/pl_wmp.pas | 128 ++ plugins/Watrack/plugins/watrack_mpd/Makefile | 12 + .../Watrack/plugins/watrack_mpd/res/watrack_mpd.rc | 112 ++ .../plugins/watrack_mpd/src/commonheaders.h | 43 + .../Watrack/plugins/watrack_mpd/src/constants.h | 4 + plugins/Watrack/plugins/watrack_mpd/src/globals.h | 11 + plugins/Watrack/plugins/watrack_mpd/src/init.c | 112 ++ plugins/Watrack/plugins/watrack_mpd/src/m_music.h | 355 ++++++ plugins/Watrack/plugins/watrack_mpd/src/main.c | 433 +++++++ plugins/Watrack/plugins/watrack_mpd/src/main.h | 24 + plugins/Watrack/plugins/watrack_mpd/src/options.c | 91 ++ plugins/Watrack/plugins/watrack_mpd/src/resource.h | 32 + .../Watrack/plugins/watrack_mpd/src/utilities.c | 126 ++ .../Watrack/plugins/watrack_mpd/src/utilities.h | 6 + .../plugins/watrack_mpd/watrack_mpd.vcxproj | 299 +++++ .../watrack_mpd/watrack_mpd.vcxproj.filters | 56 + plugins/Watrack/popup/pop_dlg.inc | 179 +++ plugins/Watrack/popup/pop_opt.inc | 81 ++ plugins/Watrack/popup/pop_rc.inc | 34 + plugins/Watrack/popup/pop_vars.inc | 27 + plugins/Watrack/popup/popup.rc | 55 + plugins/Watrack/popup/popup.res | Bin 0 -> 3352 bytes plugins/Watrack/popup/popups.pas | 542 +++++++++ plugins/Watrack/popup/wat_info.ico | Bin 0 -> 1406 bytes plugins/Watrack/proto/i_proto_dlg.inc | 144 +++ plugins/Watrack/proto/i_proto_opt.inc | 35 + plugins/Watrack/proto/i_proto_rc.inc | 17 + plugins/Watrack/proto/proto.pas | 564 +++++++++ plugins/Watrack/proto/proto.rc | 36 + plugins/Watrack/proto/proto.res | Bin 0 -> 2624 bytes plugins/Watrack/proto/wat_context.ico | Bin 0 -> 1406 bytes plugins/Watrack/res/i_const.inc | 27 + plugins/Watrack/res/wat_disable.ico | Bin 0 -> 2550 bytes plugins/Watrack/res/wat_enable.ico | Bin 0 -> 2550 bytes plugins/Watrack/res/watrack.rc | 104 ++ plugins/Watrack/res/watrack.res | Bin 0 -> 8520 bytes plugins/Watrack/srv_format.pas | 394 +++++++ plugins/Watrack/srv_player.pas | 1220 ++++++++++++++++++++ plugins/Watrack/stat/default.tmpl | 89 ++ plugins/Watrack/stat/report.inc | 315 +++++ plugins/Watrack/stat/stat.rc | 50 + plugins/Watrack/stat/stat.res | Bin 0 -> 3320 bytes plugins/Watrack/stat/stat_data.inc | 16 + plugins/Watrack/stat/stat_dlg.inc | 223 ++++ plugins/Watrack/stat/stat_opt.inc | 62 + plugins/Watrack/stat/stat_rc.inc | 29 + plugins/Watrack/stat/stat_vars.inc | 21 + plugins/Watrack/stat/statlog.pas | 650 +++++++++++ plugins/Watrack/stat/wat_report.ico | Bin 0 -> 1406 bytes plugins/Watrack/status/i_hotkey.inc | 62 + plugins/Watrack/status/i_opt_11.inc | 459 ++++++++ plugins/Watrack/status/i_opt_12.inc | 108 ++ plugins/Watrack/status/i_opt_3.inc | 106 ++ plugins/Watrack/status/i_opt_status.inc | 49 + plugins/Watrack/status/i_opt_tmpl.inc | 244 ++++ plugins/Watrack/status/i_st_rc.inc | 45 + plugins/Watrack/status/i_st_vars.inc | 26 + plugins/Watrack/status/i_status.inc | 223 ++++ plugins/Watrack/status/status.pas | 142 +++ plugins/Watrack/status/status.rc | 88 ++ plugins/Watrack/status/status.res | Bin 0 -> 3092 bytes plugins/Watrack/status/tmpl.pas | 304 +++++ plugins/Watrack/templates/i_expkey.inc | 34 + plugins/Watrack/templates/i_macro.inc | 149 +++ plugins/Watrack/templates/i_opt_it.inc | 50 + plugins/Watrack/templates/i_text.inc | 135 +++ plugins/Watrack/templates/i_tmpl_dlg.inc | 117 ++ plugins/Watrack/templates/i_tmpl_rc.inc | 21 + plugins/Watrack/templates/i_variables.inc | 185 +++ plugins/Watrack/templates/templates.pas | 113 ++ plugins/Watrack/templates/templates.rc | 51 + plugins/Watrack/templates/templates.res | Bin 0 -> 1648 bytes plugins/Watrack/wat_api.pas | 183 +++ plugins/Watrack/waticons.inc | 35 + plugins/Watrack/waticons.pas | 202 ++++ plugins/Watrack/watrack.dpr | 675 +++++++++++ plugins/Watrack/winampapi.pas | 277 +++++ 300 files changed, 28064 insertions(+) create mode 100644 plugins/Watrack/HlpDlg.pas create mode 100644 plugins/Watrack/docs/const.php create mode 100644 plugins/Watrack/docs/m_music.h create mode 100644 plugins/Watrack/docs/m_music.inc create mode 100644 plugins/Watrack/docs/sampledll.dpr create mode 100644 plugins/Watrack/docs/wat.php create mode 100644 plugins/Watrack/docs/watrack_history.txt create mode 100644 plugins/Watrack/docs/watrack_readme.txt create mode 100644 plugins/Watrack/formats/fmt_aac.pas create mode 100644 plugins/Watrack/formats/fmt_ape.pas create mode 100644 plugins/Watrack/formats/fmt_avi.pas create mode 100644 plugins/Watrack/formats/fmt_dummy.pas create mode 100644 plugins/Watrack/formats/fmt_flv.pas create mode 100644 plugins/Watrack/formats/fmt_m4a.pas create mode 100644 plugins/Watrack/formats/fmt_mkv.pas create mode 100644 plugins/Watrack/formats/fmt_mp3.pas create mode 100644 plugins/Watrack/formats/fmt_mpc.pas create mode 100644 plugins/Watrack/formats/fmt_ofr.pas create mode 100644 plugins/Watrack/formats/fmt_ogg.pas create mode 100644 plugins/Watrack/formats/fmt_real.pas create mode 100644 plugins/Watrack/formats/fmt_tta.pas create mode 100644 plugins/Watrack/formats/fmt_wav.pas create mode 100644 plugins/Watrack/formats/fmt_wma.pas create mode 100644 plugins/Watrack/formats/tag_apev2.inc create mode 100644 plugins/Watrack/formats/tag_id3v1.inc create mode 100644 plugins/Watrack/formats/tag_id3v2.inc create mode 100644 plugins/Watrack/formats/tags.pas create mode 100644 plugins/Watrack/global.pas create mode 100644 plugins/Watrack/i_cover.inc create mode 100644 plugins/Watrack/i_gui.inc create mode 100644 plugins/Watrack/i_opt_0.inc create mode 100644 plugins/Watrack/i_opt_1.inc create mode 100644 plugins/Watrack/i_opt_dlg.inc create mode 100644 plugins/Watrack/i_options.inc create mode 100644 plugins/Watrack/i_timer.inc create mode 100644 plugins/Watrack/i_vars.inc create mode 100644 plugins/Watrack/icons/GO/GoAsm.Exe create mode 100644 plugins/Watrack/icons/GO/GoLink.exe create mode 100644 plugins/Watrack/icons/GO/GoRC.exe create mode 100644 plugins/Watrack/icons/GO/icons.bat create mode 100644 plugins/Watrack/icons/GO/icons.rc create mode 100644 plugins/Watrack/icons/GO/waticons.h create mode 100644 plugins/Watrack/icons/GO/watrack_buttons.asm create mode 100644 plugins/Watrack/icons/MASM/icons.bat create mode 100644 plugins/Watrack/icons/MASM/icons.rc create mode 100644 plugins/Watrack/icons/MASM/iconspl.rc create mode 100644 plugins/Watrack/icons/MASM/poasm.exe create mode 100644 plugins/Watrack/icons/MASM/polink.exe create mode 100644 plugins/Watrack/icons/MASM/porc.dll create mode 100644 plugins/Watrack/icons/MASM/porc.exe create mode 100644 plugins/Watrack/icons/MASM/waticons.h create mode 100644 plugins/Watrack/icons/MASM/watrack.asm create mode 100644 plugins/Watrack/icons/TASM/RLINK32.DLL create mode 100644 plugins/Watrack/icons/TASM/TASM32.EXE create mode 100644 plugins/Watrack/icons/TASM/TLINK32.EXE create mode 100644 plugins/Watrack/icons/TASM/brcc32.exe create mode 100644 plugins/Watrack/icons/TASM/icons.bat create mode 100644 plugins/Watrack/icons/TASM/icons.rc create mode 100644 plugins/Watrack/icons/TASM/iconspl.rc create mode 100644 plugins/Watrack/icons/TASM/rw32core.dll create mode 100644 plugins/Watrack/icons/TASM/waticons.h create mode 100644 plugins/Watrack/icons/TASM/watrack.asm create mode 100644 plugins/Watrack/icons/iconsets/players/1by1.ico create mode 100644 plugins/Watrack/icons/iconsets/players/AIMP.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Ashampoo Media Player.ico create mode 100644 plugins/Watrack/icons/iconsets/players/BeholdTV.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Billy.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Core Media Player.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Crystal Player.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Cyberlink PowerDVD.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Evil Player.ico create mode 100644 plugins/Watrack/icons/iconsets/players/GOMPlayer.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Helium Music Manager.ico create mode 100644 plugins/Watrack/icons/iconsets/players/J.River Media Center.ico create mode 100644 plugins/Watrack/icons/iconsets/players/JetAudio.ico create mode 100644 plugins/Watrack/icons/iconsets/players/KMPlayer.ico create mode 100644 plugins/Watrack/icons/iconsets/players/LastFM.ico create mode 100644 plugins/Watrack/icons/iconsets/players/MediaMonkey.ico create mode 100644 plugins/Watrack/icons/iconsets/players/MoreAmp.ico create mode 100644 plugins/Watrack/icons/iconsets/players/MusikCube.ico create mode 100644 plugins/Watrack/icons/iconsets/players/QCDPlayer.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Quicktime Player.ico create mode 100644 plugins/Watrack/icons/iconsets/players/RadLight.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Real Player.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Spider Player.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Ultra player.ico create mode 100644 plugins/Watrack/icons/iconsets/players/VUPlayer.ico create mode 100644 plugins/Watrack/icons/iconsets/players/WMP 9.ico create mode 100644 plugins/Watrack/icons/iconsets/players/WinDVD.ico create mode 100644 plugins/Watrack/icons/iconsets/players/XMPlay.ico create mode 100644 plugins/Watrack/icons/iconsets/players/Zoom Player.ico create mode 100644 plugins/Watrack/icons/iconsets/players/alshow.ico create mode 100644 plugins/Watrack/icons/iconsets/players/alsong.ico create mode 100644 plugins/Watrack/icons/iconsets/players/apollo.ico create mode 100644 plugins/Watrack/icons/iconsets/players/audio.ico create mode 100644 plugins/Watrack/icons/iconsets/players/bsplayer.ico create mode 100644 plugins/Watrack/icons/iconsets/players/cms.ico create mode 100644 plugins/Watrack/icons/iconsets/players/flv.ico create mode 100644 plugins/Watrack/icons/iconsets/players/foobar2000.ico create mode 100644 plugins/Watrack/icons/iconsets/players/itunes.ico create mode 100644 plugins/Watrack/icons/iconsets/players/la.ico create mode 100644 plugins/Watrack/icons/iconsets/players/mcone.ico create mode 100644 plugins/Watrack/icons/iconsets/players/mcx.ico create mode 100644 plugins/Watrack/icons/iconsets/players/mmatch.ico create mode 100644 plugins/Watrack/icons/iconsets/players/mpc.ico create mode 100644 plugins/Watrack/icons/iconsets/players/mplayer.ico create mode 100644 plugins/Watrack/icons/iconsets/players/pluton.ico create mode 100644 plugins/Watrack/icons/iconsets/players/saps.ico create mode 100644 plugins/Watrack/icons/iconsets/players/songbird.ico create mode 100644 plugins/Watrack/icons/iconsets/players/vlc.ico create mode 100644 plugins/Watrack/icons/iconsets/players/vp3.ico create mode 100644 plugins/Watrack/icons/iconsets/players/wany.ico create mode 100644 plugins/Watrack/icons/iconsets/players/wifi.ico create mode 100644 plugins/Watrack/icons/iconsets/players/winamp.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/disable.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/enable.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/next.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/next_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/next_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/pause.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/pause_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/pause_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/play.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/play_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/play_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/previous.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/previous_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/previous_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/slider.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/slider_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/slider_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/stop.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/stop_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/stop_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/volume_down.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/volume_down_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/volume_down_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/volume_up.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/volume_up_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true+256-solid/volume_up_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/next.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/next_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/next_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/pause.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/pause_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/pause_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/play.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/play_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/play_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/previous.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/previous_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/previous_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/slider.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/stop.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/stop_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/stop_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/ver.res create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/volume_down.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/volume_down_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/volume_down_pressed.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/volume_up.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/volume_up_hovered.ico create mode 100644 plugins/Watrack/icons/iconsets/true-solid-faith/volume_up_pressed.ico create mode 100644 plugins/Watrack/icons/make-buttons.bat create mode 100644 plugins/Watrack/icons/make-players.bat create mode 100644 plugins/Watrack/icons/make.bat create mode 100644 plugins/Watrack/icons/waticons.inc create mode 100644 plugins/Watrack/kolframe/frm.rc create mode 100644 plugins/Watrack/kolframe/frm.res create mode 100644 plugins/Watrack/kolframe/frm_data.inc create mode 100644 plugins/Watrack/kolframe/frm_designer.inc create mode 100644 plugins/Watrack/kolframe/frm_dlg1.inc create mode 100644 plugins/Watrack/kolframe/frm_dlg2.inc create mode 100644 plugins/Watrack/kolframe/frm_frame.inc create mode 100644 plugins/Watrack/kolframe/frm_icogroup.inc create mode 100644 plugins/Watrack/kolframe/frm_rc.inc create mode 100644 plugins/Watrack/kolframe/frm_text.inc create mode 100644 plugins/Watrack/kolframe/frm_trackbar.inc create mode 100644 plugins/Watrack/kolframe/frm_vars.inc create mode 100644 plugins/Watrack/kolframe/i_bitmap.inc create mode 100644 plugins/Watrack/kolframe/kolframe.pas create mode 100644 plugins/Watrack/lastfm/i_const.inc create mode 100644 plugins/Watrack/lastfm/i_last_api.inc create mode 100644 plugins/Watrack/lastfm/i_last_dlg.inc create mode 100644 plugins/Watrack/lastfm/i_last_opt.inc create mode 100644 plugins/Watrack/lastfm/lastfm.ico create mode 100644 plugins/Watrack/lastfm/lastfm.pas create mode 100644 plugins/Watrack/lastfm/lastfm.rc create mode 100644 plugins/Watrack/lastfm/lastfm.res create mode 100644 plugins/Watrack/lst_formats.inc create mode 100644 plugins/Watrack/lst_players.inc create mode 100644 plugins/Watrack/m_music.inc create mode 100644 plugins/Watrack/macros.pas create mode 100644 plugins/Watrack/make.bat create mode 100644 plugins/Watrack/myrtf.pas create mode 100644 plugins/Watrack/myshows/i_const.inc create mode 100644 plugins/Watrack/myshows/i_cookies.inc create mode 100644 plugins/Watrack/myshows/i_myshows_api.inc create mode 100644 plugins/Watrack/myshows/i_myshows_dlg.inc create mode 100644 plugins/Watrack/myshows/i_myshows_opt.inc create mode 100644 plugins/Watrack/myshows/myshows.ico create mode 100644 plugins/Watrack/myshows/myshows.pas create mode 100644 plugins/Watrack/myshows/myshows.rc create mode 100644 plugins/Watrack/myshows/myshows.res create mode 100644 plugins/Watrack/player.ini create mode 100644 plugins/Watrack/players/mradio.ico create mode 100644 plugins/Watrack/players/mradio.rc create mode 100644 plugins/Watrack/players/mradio.res create mode 100644 plugins/Watrack/players/pl_1by1.pas create mode 100644 plugins/Watrack/players/pl_aimp.pas create mode 100644 plugins/Watrack/players/pl_apollo.pas create mode 100644 plugins/Watrack/players/pl_behold.pas create mode 100644 plugins/Watrack/players/pl_bs.pas create mode 100644 plugins/Watrack/players/pl_cowon.pas create mode 100644 plugins/Watrack/players/pl_foobar.pas create mode 100644 plugins/Watrack/players/pl_itunes.pas create mode 100644 plugins/Watrack/players/pl_la.pas create mode 100644 plugins/Watrack/players/pl_lastfm.pas create mode 100644 plugins/Watrack/players/pl_mmonkey.pas create mode 100644 plugins/Watrack/players/pl_mpc.pas create mode 100644 plugins/Watrack/players/pl_mradio.pas create mode 100644 plugins/Watrack/players/pl_vlc.pas create mode 100644 plugins/Watrack/players/pl_winamp.pas create mode 100644 plugins/Watrack/players/pl_wmp.pas create mode 100644 plugins/Watrack/plugins/watrack_mpd/Makefile create mode 100644 plugins/Watrack/plugins/watrack_mpd/res/watrack_mpd.rc create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/commonheaders.h create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/constants.h create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/globals.h create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/init.c create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/m_music.h create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/main.c create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/main.h create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/options.c create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/resource.h create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/utilities.c create mode 100644 plugins/Watrack/plugins/watrack_mpd/src/utilities.h create mode 100644 plugins/Watrack/plugins/watrack_mpd/watrack_mpd.vcxproj create mode 100644 plugins/Watrack/plugins/watrack_mpd/watrack_mpd.vcxproj.filters create mode 100644 plugins/Watrack/popup/pop_dlg.inc create mode 100644 plugins/Watrack/popup/pop_opt.inc create mode 100644 plugins/Watrack/popup/pop_rc.inc create mode 100644 plugins/Watrack/popup/pop_vars.inc create mode 100644 plugins/Watrack/popup/popup.rc create mode 100644 plugins/Watrack/popup/popup.res create mode 100644 plugins/Watrack/popup/popups.pas create mode 100644 plugins/Watrack/popup/wat_info.ico create mode 100644 plugins/Watrack/proto/i_proto_dlg.inc create mode 100644 plugins/Watrack/proto/i_proto_opt.inc create mode 100644 plugins/Watrack/proto/i_proto_rc.inc create mode 100644 plugins/Watrack/proto/proto.pas create mode 100644 plugins/Watrack/proto/proto.rc create mode 100644 plugins/Watrack/proto/proto.res create mode 100644 plugins/Watrack/proto/wat_context.ico create mode 100644 plugins/Watrack/res/i_const.inc create mode 100644 plugins/Watrack/res/wat_disable.ico create mode 100644 plugins/Watrack/res/wat_enable.ico create mode 100644 plugins/Watrack/res/watrack.rc create mode 100644 plugins/Watrack/res/watrack.res create mode 100644 plugins/Watrack/srv_format.pas create mode 100644 plugins/Watrack/srv_player.pas create mode 100644 plugins/Watrack/stat/default.tmpl create mode 100644 plugins/Watrack/stat/report.inc create mode 100644 plugins/Watrack/stat/stat.rc create mode 100644 plugins/Watrack/stat/stat.res create mode 100644 plugins/Watrack/stat/stat_data.inc create mode 100644 plugins/Watrack/stat/stat_dlg.inc create mode 100644 plugins/Watrack/stat/stat_opt.inc create mode 100644 plugins/Watrack/stat/stat_rc.inc create mode 100644 plugins/Watrack/stat/stat_vars.inc create mode 100644 plugins/Watrack/stat/statlog.pas create mode 100644 plugins/Watrack/stat/wat_report.ico create mode 100644 plugins/Watrack/status/i_hotkey.inc create mode 100644 plugins/Watrack/status/i_opt_11.inc create mode 100644 plugins/Watrack/status/i_opt_12.inc create mode 100644 plugins/Watrack/status/i_opt_3.inc create mode 100644 plugins/Watrack/status/i_opt_status.inc create mode 100644 plugins/Watrack/status/i_opt_tmpl.inc create mode 100644 plugins/Watrack/status/i_st_rc.inc create mode 100644 plugins/Watrack/status/i_st_vars.inc create mode 100644 plugins/Watrack/status/i_status.inc create mode 100644 plugins/Watrack/status/status.pas create mode 100644 plugins/Watrack/status/status.rc create mode 100644 plugins/Watrack/status/status.res create mode 100644 plugins/Watrack/status/tmpl.pas create mode 100644 plugins/Watrack/templates/i_expkey.inc create mode 100644 plugins/Watrack/templates/i_macro.inc create mode 100644 plugins/Watrack/templates/i_opt_it.inc create mode 100644 plugins/Watrack/templates/i_text.inc create mode 100644 plugins/Watrack/templates/i_tmpl_dlg.inc create mode 100644 plugins/Watrack/templates/i_tmpl_rc.inc create mode 100644 plugins/Watrack/templates/i_variables.inc create mode 100644 plugins/Watrack/templates/templates.pas create mode 100644 plugins/Watrack/templates/templates.rc create mode 100644 plugins/Watrack/templates/templates.res create mode 100644 plugins/Watrack/wat_api.pas create mode 100644 plugins/Watrack/waticons.inc create mode 100644 plugins/Watrack/waticons.pas create mode 100644 plugins/Watrack/watrack.dpr create mode 100644 plugins/Watrack/winampapi.pas (limited to 'plugins/Watrack') diff --git a/plugins/Watrack/HlpDlg.pas b/plugins/Watrack/HlpDlg.pas new file mode 100644 index 0000000000..c420345bd4 --- /dev/null +++ b/plugins/Watrack/HlpDlg.pas @@ -0,0 +1,83 @@ +{help dialogs} +unit HlpDlg; + +interface + +uses windows; + +const + sFormatHelp:PWideChar = 'Text format codes'#13#10'{b}text{/b}'#9'bold'#13#10+ + '{i}text{/i}'#9'italic'#13#10'{u}text{/u}'#9'undeline'#13#10+ + '{cf##}text{/cf}'#9'text color'#13#10'{bg##}text{/bg}'#9+ + 'background color'#13#10'text - user text'#13#10+ + '## - color number (1-16)'#13#10'Color 0 is background color'#13#10+ + 'Color 17 is default text color'; + +function ShowColorHelpDlg(parent:HWND):integer; + +implementation + +uses messages,m_api; + +{$include res\i_const.inc} + +const + colors:array [0..15] of dword = ( + $00FFFFFF,$00000000,$007F0000,$00009300, + $000000FF,$0000007F,$009C009C,$00007FFC, + $0000FFFF,$0000FC00,$00939300,$00FFFF00, + $00FC0000,$00FF00FF,$007F7F7F,$00D2D2D2 + ); + +const + COLORDLG = 'COLOR'; + +function ColorHelpDlg(Dialog:HWnd;hMessage,wParam,lParam:DWord):integer; stdcall; +var + ps:tPaintStruct; + br:hBrush; + dc:hDC; + rc:tRect; + i,j:integer; +begin + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + end; + WM_COMMAND: + if (wParam shr 16)=BN_CLICKED then + case loword(wParam) of + IDOK, IDCANCEL: DestroyWindow(Dialog); + end; + WM_PAINT: begin + dc:=BeginPaint(Dialog,ps); + SetBkColor(dc,GetSysColor(COLOR_BTNFACE)); + for i:=0 to 1 do + begin + for j:=0 to 7 do + begin + with rc do + begin + left :=32+i*66; + top :=10+j*18; + right :=56+i*66; + bottom:=24+j*18; + end; + br:=CreateSolidBrush(colors[i*8+j]); + Rectangle(dc,rc.left-1,rc.top-1,rc.right+1,rc.bottom+1); + FillRect(dc,rc,br); + DeleteObject(br); + end; + end; + EndPaint(Dialog,ps); + end; + end; + result:=0; +end; + +function ShowColorHelpDlg(parent:HWND):integer; +begin + result:=CreateDialogW(hInstance,COLORDLG,parent,@ColorHelpDlg); +end; + +end. \ No newline at end of file diff --git a/plugins/Watrack/docs/const.php b/plugins/Watrack/docs/const.php new file mode 100644 index 0000000000..f34156280e --- /dev/null +++ b/plugins/Watrack/docs/const.php @@ -0,0 +1,157 @@ + diff --git a/plugins/Watrack/docs/m_music.h b/plugins/Watrack/docs/m_music.h new file mode 100644 index 0000000000..0246fabe34 --- /dev/null +++ b/plugins/Watrack/docs/m_music.h @@ -0,0 +1,386 @@ +#ifndef M_MUSIC +#define M_MUSIC + +#define MIID_WATRACK {0xfc6c81f4, 0x837e, 0x4430, {0x96, 0x01, 0xa0, 0xaa, 0x43, 0x17, 0x7a, 0xe3}} + +typedef struct tSongInfoA { + CHAR* artist; + CHAR* title; + CHAR* album; + CHAR* genre; + CHAR* comment; + CHAR* year; + CHAR* mfile; // media file + DWORD kbps; + DWORD khz; + DWORD channels; + DWORD track; + DWORD total; // music length + DWORD time; // elapsed time + CHAR* wndtext; // window title + CHAR* player; // player name + DWORD plyver; // player version + HANDLE icon; // player icon + DWORD fsize; // media file size + DWORD vbr; + int status; // WAT_MES_* const + HWND plwnd; // player window + // video part + DWORD codec; + DWORD width; + DWORD height; + DWORD fps; + __int64 date; + CHAR* txtver; + CHAR* lyric; + CHAR* cover; + DWORD volume; + CHAR* url; // player homepage +} SONGINFOA, *LPSONGINFOA; + +typedef struct tSongInfo { + WCHAR* artist; + WCHAR* title; + WCHAR* album; + WCHAR* genre; + WCHAR* comment; + WCHAR* year; + WCHAR* mfile; // media file + DWORD kbps; + DWORD khz; + DWORD channels; + DWORD track; + DWORD total; // music length + DWORD time; // elapsed time + WCHAR* wndtext; // window title + WCHAR* player; // player name + DWORD* plyver; // player version + HANDLE icon; // player icon + DWORD fsize; // media file size + DWORD vbr; + int status; // WAT_MES_* const + HWND plwnd; // player window + // video part + DWORD codec; + DWORD width; + DWORD height; + DWORD fps; + __int64 date; + WCHAR* txtver; + WCHAR* lyric; + WCHAR* cover; // cover path + DWORD volume; + WCHAR* url; // player homepage +} SONGINFO, *LPSONGINFO; + +#if defined(_UNICODE) + #define WAT_INF_TCHAR WAT_INF_UNICODE + #define SongInfoT tSongInfo +#else + #define WAT_INF_TCHAR WAT_INF_ANSI + #define SongInfoT tSongInfoA +#endif + + // result codes +#define WAT_RES_UNKNOWN -2 +#define WAT_RES_NOTFOUND -1 +#define WAT_RES_ERROR WAT_RES_NOTFOUND +#define WAT_RES_OK 0 +#define WAT_RES_ENABLED WAT_RES_OK +#define WAT_RES_DISABLED 1 + // internal +#define WAT_RES_NEWFILE 3 +#define WAT_RES_NEWPLAYER 4 + +// result for MS_WAT_GETMUSICINFO service +#define WAT_PLS_NORMAL WAT_RES_OK +#define WAT_PLS_NOMUSIC WAT_RES_DISABLED +#define WAT_PLS_NOTFOUND WAT_RES_NOTFOUND + +#define WAT_INF_UNICODE 0 +#define WAT_INF_ANSI 1 +#define WAT_INF_UTF8 2 +#define WAT_INF_CHANGES 0x100 + +/* + wParam : WAT_INF_* constant + lParam : pointer to LPSONGINGO (Unicode) or LPSONGINFOA (ANSI/UTF8) + Affects: Fill structure by currently played music info + returns: WAT_PLS_* constant + note: pointer will be point to global SONGINFO structure of plugin + warning: Non-Unicode data filled only by request + if lParam=0 only internal SongInfo structure will be filled + Example: + LPSONGINFO p; + PluginLink->CallService(MS_WAT_GETMUSICINFO,0,(DWORD)&p); +*/ +#define MS_WAT_GETMUSICINFO "WATrack/GetMusicInfo" + +/* + wParam:0 + lParam : pointer to pSongInfo (Unicode) + Affects: Fill structure by info from file named in SongInfo.mfile + returns: 0, if success + note: fields, which values can't be obtained, leaves old values. + you must free given strings by miranda mmi.free +*/ +#define MS_WAT_GETFILEINFO "WATrack/GetFileInfo" + +/* + wParam: encoding (WAT_INF_* consts, 0 = WAT_INF_UNICODE) + lParam: codepage (0 = ANSI) + Returns Global unicode SongInfo pointer or tranlated to Ansi/UTF8 structure +*/ +#define MS_WAT_RETURNGLOBAL "WATrack/GetMainStructure" + +//!! DON'T CHANGE THESE VALUES! +#define WAT_CTRL_FIRST 1 + +#define WAT_CTRL_PREV 1 +#define WAT_CTRL_PLAY 2 +#define WAT_CTRL_PAUSE 3 +#define WAT_CTRL_STOP 4 +#define WAT_CTRL_NEXT 5 +#define WAT_CTRL_VOLDN 6 +#define WAT_CTRL_VOLUP 7 +#define WAT_CTRL_SEEK 8 // lParam is new position (sec) + +#define WAT_CTRL_LAST 8 + +/* + wParam: button code (WAT_CTRL_* const) + lParam: 0, or value (see WAT_CTRL_* const comments) + Affects: emulate player button pressing + returns: 0 if unsuccesful +*/ +#define MS_WAT_PRESSBUTTON "WATrack/PressButton" + +/* + Get user's Music Info +*/ +#define MS_WAT_GETCONTACTINFO "WATrack/GetContactInfo" + +// ------------ Plugin/player status ------------ + +/* + wParam: 1 - switch off plugin + 0 - switch on plugin + -1 - switch plugin status + 2 - get plugin version + other - get plugin status + lParam: 0 + Affects: Switch plugin status to enabled or disabled + returns: old plugin status, 0, if was enabled +*/ +#define MS_WAT_PLUGINSTATUS "WATrack/PluginStatus" + +// ---------- events ------------ + +/*ME_WAT_MODULELOADED + wParam: 0, lParam: 0 +*/ +#define ME_WAT_MODULELOADED "WATrack/ModuleLoaded" + +#define WAT_EVENT_PLAYERSTATUS 1 //lParam: WAT_PLS_* const +#define WAT_EVENT_NEWTRACK 2 //lParam: LPSONGINFO +#define WAT_EVENT_PLUGINSTATUS 3 //lParam: 0-enabled; 1-dis.temporary; 2-dis.permanent +#define WAT_EVENT_NEWPLAYER 4 // +#define WAT_EVENT_NEWTEMPLATE 5 //lParam: TM_* constant + +/*ME_WAT_NEWSTATUS + Plugin or player status changed: + wParam: type of event (see above) + lParam: value +*/ +#define ME_WAT_NEWSTATUS "WATrack/NewStatus" + +// ---------- Popup module ------------ + +/* + wParam: not used + lParam: not used + Affects: Show popup or Info window with current music information + note: Only Info window will be showed if Popup plugin disabled +*/ +#define MS_WAT_SHOWMUSICINFO "WATrack/ShowMusicInfo" + +// --------- Statistic (report) module ------------- + +/* + wParam: pointer to log file name or NULL + lParam: pointer to report file name or NULL + Affects: Create report from log and run it (if option is set) + returns: 0 if unsuccesful + note: if wParam or lParam is a NULL then file names from options are used +*/ +#define MS_WAT_MAKEREPORT "WATrack/MakeReport" + +/* + wParam, lParam - not used + Affects: pack statistic file +*/ +#define MS_WAT_PACKLOG = "WATrack/PackLog" + +/* + wParam: not used + lParam: pointer to SongInfo +*/ +#define MS_WAT_ADDTOLOG = "WATrack/AddToLog" + +// ----------- Formats and players ----------- + +// media file status + +#define WAT_MES_STOPPED 0 +#define WAT_MES_PLAYING 1 +#define WAT_MES_PAUSED 2 +#define WAT_MES_UNKNOWN -1 + +#define WAT_ACT_REGISTER 1 +#define WAT_ACT_UNREGISTER 2 +#define WAT_ACT_DISABLE 3 +#define WAT_ACT_ENABLE 4 +#define WAT_ACT_GETSTATUS 5 // not found/enabled/disabled +#define WAT_ACT_SETACTIVE 6 +#define WAT_ACT_REPLACE 0x10000 // can be combined with WAT_REGISTERFORMAT + + // flags +#define WAT_OPT_DISABLED 0x00001 // format registered but disabled +#define WAT_OPT_ONLYONE 0x00002 // format can't be overwriten +#define WAT_OPT_PLAYERINFO 0x00004 // song info from player +#define WAT_OPT_WINAMPAPI 0x00008 // Winamp API support +#define WAT_OPT_CHECKTIME 0x00010 // check file time for changes +#define WAT_OPT_VIDEO 0x00020 // only for format registering used +#define WAT_OPT_LAST 0x00040 // (internal) +#define WAT_OPT_FIRST 0x00080 // (internal) +#define WAT_OPT_TEMPLATE 0x00100 // (internal) +#define WAT_OPT_IMPLANTANT 0x00200 // use process implantation +#define WAT_OPT_HASURL 0x00400 // (player registration) URL field present +#define WAT_OPT_CHANGES 0x00800 // obtain only chaged values + // (volume, status, window text, elapsed time) +#define WAT_OPT_APPCOMMAND 0x01000 // Special (multimedia) key support +#define WAT_OPT_CHECKALL 0x02000 // Check all players +#define WAT_OPT_KEEPOLD 0x04000 // Keep Old opened file +#define WAT_OPT_MULTITHREAD 0x08000 // Use multithread scan +#define WAT_OPT_SINGLEINST 0x10000 // Single player instance +#define WAT_OPT_PLAYERDATA 0x20000 // (internal) to obtain player data + + +typedef BOOL (__cdecl *LPREADFORMATPROC)(LPSONGINFO Info); + +typedef struct tMusicFormat { + LPREADFORMATPROC proc; + CHAR ext[8]; + UINT flags; +} MUSICFORMAT, *LPMUSICFORMAT; + +/* + wParam: action + lParam: pointer to MUSICFORMAT if wParam = WAT_ACT_REGISTER, + else - pointer to extension string (ANSI) + returns: see result codes +*/ +#define MS_WAT_FORMAT "WATrack/Format" + +/* + wParam - pointer to SONGINFO structure (plwind field must be initialized) + lParam - flags + Affects: trying to fill SongInfo using Winamp API +*/ +#define MS_WAT_WINAMPINFO "WATrack/WinampInfo" + +/* + wParam: window + lParam: LoWord - command; HiWord - value +*/ +#define MS_WAT_WINAMPCOMMAND "WATrack/WinampCommand" + +typedef int (__cdecl *LPINITPROC) (); +typedef int (__cdecl *LPDEINITPROC) (); +typedef int (__cdecl *LPSTATUSPROC) (HWND wnd); +typedef WCHAR (__cdecl *LPNAMEPROC) (HWND wnd, int flags); +typedef HWND (__cdecl *LPCHECKPROC) (HWND wnd,int flags); +typedef int (__cdecl *LPINFOPROC) (LPSONGINFO Info, int flags); +typedef int (__cdecl *LPCOMMANDPROC)(HWND wnd, int command, int value); + +typedef struct tPlayerCell { + CHAR* Desc; // Short player name + UINT flags; + HICON Icon; // can be 0. for registration only + LPINITPROC Init; // LPINITPROC; can be NULL. initialize any data + LPDEINITPROC DeInit; // LPDEINITPROC; can be NULL. finalize player processing + LPCHECKPROC Check; // check player + LPSTATUSPROC GetStatus; // tStatusProc; can be NULL. get player status + LPNAMEPROC GetName; // can be NULL. get media filename + LPINFOPROC GetInfo; // can be NULL. get info from player + LPCOMMANDPROC Command; // can be NULL. send command to player + CHAR* URL; // only if WAT_OPT_HASURL flag present + WCHAR* Notes; // any tips, notes etc for this player +} PLAYERCELL, *LPPLAYERCELL; + +/* + wParam: action + lParam: pointer to PLAYERCELL if wParam = WAT_ACT_REGISTER, + else - pointer to player description string (ANSI) + returns: player window handle or value>0 if found + note: If you use GetName or GetInfo field, please, do not return empty + filename even when mediafile is remote! +*/ +#define MS_WAT_PLAYER "WATrack/Player" + +// --------- Last FM --------- + +/* + Toggle LastFM scrobbling status + wParam,lParam=0 + Returns: previous state +*/ +#define MS_WAT_LASTFM "WATrack/LastFM" + +/* + Get Info based on currently played song + wParam: pLastFMInfo + lParam: int language (first 2 bytes - 2-letters language code) +*/ +typedef struct tLastFMInfo { + UINT request; // 0 - artist, 1 - album, 2 - track + WCHAR* artist; // artist + WCHAR* album; // album or similar artists for Artist info request + WCHAR* title; // track title + WCHAR* tags; // tags + WCHAR* info; // artist bio or wiki article + WCHAR* image; // photo/cover link + WCHAR* similar; + WCHAR* release; + UINT trknum; +}PLASTFMINFO, *LPLASTFMINFO; + +#define MS_WAT_LASTFMINFO "WATrack/LastFMInfo" + +// --------- Templates ---------- + +/* + wParam: 0 (standard Info) or pSongInfo + lParam: Unicode template + returns: New Unicode (replaced) string +*/ +#define MS_WAT_REPLACETEXT "WATrack/ReplaceText" + +/* + event types for History + Blob structure for EVENTTYPE_WAT_ANSWER: + Uniciode artist#0title#0album#0answer +*/ +#define EVENTTYPE_WAT_REQUEST 9601 +#define EVENTTYPE_WAT_ANSWER 9602 +#define EVENTTYPE_WAT_ERROR 9603 +#define EVENTTYPE_WAT_MESSAGE 9604 + +/* + wParam: 0 or parent window + lParam: 0 + note: Shows Macro help window with edit aliases ability +*/ +#define MS_WAT_MACROHELP "WATrack/MacroHelp" + +#endif diff --git a/plugins/Watrack/docs/m_music.inc b/plugins/Watrack/docs/m_music.inc new file mode 100644 index 0000000000..1850de52ba --- /dev/null +++ b/plugins/Watrack/docs/m_music.inc @@ -0,0 +1,404 @@ +{$IFNDEF M_MUSIC} +{$DEFINE M_MUSIC} + +// defined in interfaces.inc +//const MIID_WATRACK:MUUID='{FC6C81F4-837E-4430-9601-A0AA43177AE3}'; + +type + pSongInfoA = ^tSongInfoA; + tSongInfoA = packed record + artist :PAnsiChar; + title :PAnsiChar; + album :PAnsiChar; + genre :PAnsiChar; + comment :PAnsiChar; + year :PAnsiChar; + mfile :PAnsiChar; // media file + kbps :dword; + khz :dword; + channels :dword; + track :dword; + total :dword; // music length + time :dword; // elapsed time + wndtext :PAnsiChar; // window title + player :PAnsiChar; // player name + plyver :dword; // player version + icon :THANDLE; // player icon + fsize :dword; // media file size + vbr :dword; + status :integer; // WAT_MES_* const + plwnd :HWND; // player window + // video part + codec :dword; + width :dword; + height :dword; + fps :dword; + date :int64; + txtver :PAnsiChar; + lyric :PAnsiChar; + cover :PAnsiChar; + volume :dword; + url :PAnsiChar; // player homepage + winampwnd:HWND; + end; +type + pSongInfo=^tSongInfo; + tSongInfo = packed record + artist :pWideChar; + title :pWideChar; + album :pWideChar; + genre :pWideChar; + comment :pWideChar; + year :pWideChar; + mfile :pWideChar; // media file + kbps :dword; + khz :dword; + channels :dword; + track :dword; + total :dword; // music length + time :dword; // elapsed time + wndtext :pWideChar; // window title + player :pWideChar; // player name + plyver :dword; // player version + icon :THANDLE; // player icon + fsize :dword; // media file size + vbr :dword; + status :integer; // WAT_MES_* const + plwnd :HWND; // player window + // video part + codec :dword; + width :dword; + height :dword; + fps :dword; + date :int64; + txtver :pWideChar; + lyric :pWideChar; + cover :pWideChar; // cover path + volume :dword; + url :PWideChar; // player homepage + winampwnd:HWND; + end; + pSongInfoW = pSongInfo; + tSongInfoW = tSongInfo; + +const + // result codes + WAT_RES_UNKNOWN = -2; + WAT_RES_NOTFOUND = -1; + WAT_RES_ERROR = WAT_RES_NOTFOUND; + WAT_RES_OK = 0; + WAT_RES_ENABLED = WAT_RES_OK; + WAT_RES_DISABLED = 1; + // internal + WAT_RES_NEWFILE = 3; + WAT_RES_NEWPLAYER = 4; + +// result for MS_WAT_GETMUSICINFO service +const + WAT_PLS_NORMAL = WAT_RES_OK; + WAT_PLS_NOMUSIC = WAT_RES_DISABLED; + WAT_PLS_NOTFOUND = WAT_RES_NOTFOUND; + +const + WAT_INF_UNICODE = 0; + WAT_INF_ANSI = 1; + WAT_INF_UTF8 = 2; + WAT_INF_CHANGES = $100; + +const + MS_WAT_INSERT:PAnsiChar = 'WATrack/Insert'; + MS_WAT_EXPORT:PAnsiChar = 'WATrack/Export'; + +const +{ + wParam : WAT_INF_* constant + lParam : pointer to pSongInfo (Unicode) or pSongInfoA (ANSI/UTF8) + Affects: Fill structure by currently played music info + returns: WAT_PLS_* constant + note: pointer will be point to global SongInfo structure of plugin + warning: Non-Unicode data filled only by request + if lParam=0 only internal SongInfo structure will be filled + Example: + var p:pSongInfo; + PluginLink^.CallService(MS_WAT_GETMUSICINFO,0,dword(@p)); +} + MS_WAT_GETMUSICINFO:PAnsiChar = 'WATrack/GetMusicInfo'; +{ + wParam:0 + lParam : pointer to pSongInfo (Unicode) + Affects: Fill structure by info from file named in SongInfo.mfile + returns: 0, if success + note: fields, which values can't be obtained, leaves old values. + you must free given strings by miranda mmi.free +} + MS_WAT_GETFILEINFO:PAnsiChar = 'WATrack/GetFileInfo'; + +{ + wParam: encoding (WAT_INF_* consts, 0 = WAT_INF_UNICODE) + lParam: codepage (0 = ANSI) + Returns Global unicode SongInfo pointer or tranlated to Ansi/UTF8 structure +} + MS_WAT_RETURNGLOBAL:PAnsiChar = 'WATrack/GetMainStructure'; + +//!! DON'T CHANGE THESE VALUES! +const + WAT_CTRL_FIRST = 1; + + WAT_CTRL_PREV = 1; + WAT_CTRL_PLAY = 2; + WAT_CTRL_PAUSE = 3; + WAT_CTRL_STOP = 4; + WAT_CTRL_NEXT = 5; + WAT_CTRL_VOLDN = 6; + WAT_CTRL_VOLUP = 7; + WAT_CTRL_SEEK = 8; // lParam is new position (sec) + + WAT_CTRL_LAST = 8; + +{ + wParam: button code (WAT_CTRL_* const) + lParam: 0, or value (see WAT_CTRL_* const comments) + Affects: emulate player button pressing + returns: 0 if unsuccesful +} + MS_WAT_PRESSBUTTON:PAnsiChar = 'WATrack/PressButton'; + +{ + Get user's Music Info +} + MS_WAT_GETCONTACTINFO:PAnsiChar = 'WATrack/GetContactInfo'; + +// ------------ Plugin/player status ------------ + +{ + wParam: 1 - switch off plugin + 0 - switch on plugin + -1 - switch plugin status + 2 - get plugin version + other - get plugin status + lParam: 0 + Affects: Switch plugin status to enabled or disabled + returns: version, old plugin status, 0, if was enabled +} + MS_WAT_PLUGINSTATUS:PAnsiChar = 'WATrack/PluginStatus'; + + ME_WAT_MODULELOADED:PAnsiChar = 'WATrack/ModuleLoaded'; + +const + WAT_EVENT_PLAYERSTATUS = 1; // WAT_PLS_* const + WAT_EVENT_NEWTRACK = 2; // SongInfo ptr + WAT_EVENT_PLUGINSTATUS = 3; // 0-enabled; 1-dis.temporary; 2-dis.permanent + WAT_EVENT_NEWPLAYER = 4; // + WAT_EVENT_NEWTEMPLATE = 5; // TM_* constant + +{ + Plugin or player status changed: + wParam: type of event (see above) + lParam: value +} + ME_WAT_NEWSTATUS:PAnsiChar = 'WATrack/NewStatus'; + +// ---------- Popup module ------------ + +{ + wParam: not used + lParam: not used + Affects: Show popup or Info window with current music information + note: Only Info window will be showed if Popup plugin disabled +} + MS_WAT_SHOWMUSICINFO:PAnsiChar = 'WATrack/ShowMusicInfo'; + +// --------- Statistic (report) module ------------- + +{ + wParam: pointer to log file name or NIL + lParam: pointer to report file name or NIL + Affects: Create report from log and run it (if option is set) + returns: 0 if unsuccesful + note: if wParam or lParam is a NIL then file names from options are used +} + MS_WAT_MAKEREPORT :PAnsiChar = 'WATrack/MakeReport'; +// MS_WAT_MAKEREPORTW:PAnsiChar = 'WATrack/MakeReportW'; + +{ + wParam, lParam - not used + Affects: pack statistic file +} + MS_WAT_PACKLOG:PAnsiChar = 'WATrack/PackLog'; + +{ + wParam: not used + lParam: pointer to SongInfo +} + MS_WAT_ADDTOLOG:PAnsiChar = 'WATrack/AddToLog'; + +// ----------- Formats and players ----------- + +// media file status + +const + WAT_MES_STOPPED = 0; + WAT_MES_PLAYING = 1; + WAT_MES_PAUSED = 2; + WAT_MES_UNKNOWN = -1; + +const + WAT_ACT_REGISTER = 1; + WAT_ACT_UNREGISTER = 2; + WAT_ACT_DISABLE = 3; + WAT_ACT_ENABLE = 4; + WAT_ACT_GETSTATUS = 5; // not found/enabled/disabled + WAT_ACT_SETACTIVE = 6; + WAT_ACT_REPLACE = $10000; // can be combined with WAT_REGISTERFORMAT + +const + // flags + WAT_OPT_DISABLED = $00000001; // registered but disabled + WAT_OPT_ONLYONE = $00000002; // can't be overwriten + WAT_OPT_PLAYERINFO = $00000004; // song info from player + WAT_OPT_WINAMPAPI = $00000008; // Winamp API support + WAT_OPT_CHECKTIME = $00000010; // check file time for changes + WAT_OPT_VIDEO = $00000020; // only for format registering used + WAT_OPT_LAST = $00000040; // (internal-Winamp Clone) put to the end of queue + WAT_OPT_FIRST = $00000080; // (internal) + WAT_OPT_TEMPLATE = $00000100; // (internal) + WAT_OPT_IMPLANTANT = $00000200; // use process implantation + WAT_OPT_HASURL = $00000400; // (player registration) URL field present + WAT_OPT_CHANGES = $00000800; // obtain only chaged values + // (volume, status, window text, elapsed time) + WAT_OPT_APPCOMMAND = $00001000; // Special (multimedia) key support + WAT_OPT_CHECKALL = $00002000; // Check all players + WAT_OPT_KEEPOLD = $00004000; // Keep Old opened file + WAT_OPT_MULTITHREAD = $00008000; // Use multithread scan + WAT_OPT_SINGLEINST = $00010000; // Single player instance + WAT_OPT_PLAYERDATA = $00020000; // (internal) to obtain player data + +type + tReadFormatProc = function(var Info:tSongInfo):boolean; cdecl; + pMusicFormat = ^tMusicFormat; + tMusicFormat = packed record + proc :tReadFormatProc; + ext :array [0..7] of AnsiChar; + flags:cardinal; + end; + +const +{ + wParam: action + lParam: pointer to tMusicFormat if wParam = WAT_ACT_REGISTER, + else - pointer to extension string (ANSI) + returns: see result codes +} + MS_WAT_FORMAT:PAnsiChar = 'WATrack/Format'; + +{ + wParam: pointer to SongInfo structure (plwind field must be initialized) + lParam: flags + Affects: trying to fill SongInfo using Winamp API +} + MS_WAT_WINAMPINFO:PAnsiChar = 'WATrack/WinampInfo'; + +{ + wParam: window + lParam: LoWord - command; HiWord - value +} + MS_WAT_WINAMPCOMMAND:PAnsiChar = 'WATrack/WinampCommand'; + +type + tInitProc = function():integer;cdecl; + tDeInitProc = function():integer;cdecl; + tStatusProc = function(wnd:HWND):integer;cdecl; + tNameProc = function(wnd:HWND;flags:integer):pWideChar;cdecl; + tCheckProc = function(wnd:HWND;flags:integer):HWND;cdecl; + tInfoProc = function(var SongInfo:tSongInfo;flags:integer):integer;cdecl; + tCommandProc = function(wnd:HWND;command:integer;value:integer):integer;cdecl; + + pPlayerCell = ^tPlayerCell; + tPlayerCell = packed record + Desc :PAnsiChar; // Short player name + flags :cardinal; + Icon :HICON; // can be 0. for registration only + Init :pointer; // tInitProc; can be NIL. initialize any data + DeInit :pointer; // tDeInitProc; can be NIL. finalize player processing + Check :pointer; // tCheckProc; check player + GetStatus:pointer; // tStatusProc; can be NIL. get player status + GetName :pointer; // tNameProc; can be NIL. get media filename + GetInfo :pointer; // tInfoProc; can be NIL. get info from player + Command :pointer; // tCommandProc; can be NIL. send command to player + URL :PAnsiChar; // only if WAT_OPT_HASURL flag present + Notes :PWideChar; // any tips, notes etc for this player + end; + +const +{ + wParam: action + lParam: pointer to tPlayerCell if wParam = WAT_ACT_REGISTER, + else - pointer to player description string (ANSI) + returns: player window handle or value>0 if found + note: If you use GetName or GetInfo field, please, do not return empty + filename even when mediafile is remote! +} + MS_WAT_PLAYER:PAnsiChar = 'WATrack/Player'; + +// --------- Last FM --------- + +{ + Toggle LastFM scrobbling status + wParam,lParam=0 + Returns: previous state +} +const + MS_WAT_LASTFM:pAnsiChar = 'WATrack/LastFM'; + +{ + Get Info based on currently played song + wParam: pLastFMInfo + lParam: int language (first 2 bytes - 2-letters language code) +} +type + pLastFMInfo = ^tLastFMInfo; + tLastFMInfo = packed record + request:cardinal; // 0 - artist, 1 - album, 2 - track + artist :pWideChar; // artist + album :pWideChar; // album or similar artists for Artist info request + title :pWideChar; // track title + tags :pWideChar; // tags + info :pWideChar; // artist bio or wiki article + image :pAnsiChar; // photo/cover link + similar:pWideChar; + release:pWideChar; + trknum :cardinal; + end; +const + MS_WAT_LASTFMINFO:pAnsiChar = 'WATrack/LastFMInfo'; + +// --------- Templates ---------- + +const +{ + wParam: 0 (standard Info) or pSongInfo + lParam: Unicode template + returns: New Unicode (replaced) string +} + MS_WAT_REPLACETEXT:PAnsiChar = 'WATrack/ReplaceText'; + +{ + event types for History + Blob structure for EVENTTYPE_WAT_ANSWER: + Uniciode artist#0title#0album#0answer +} +const + EVENTTYPE_WAT_REQUEST = 9601; + EVENTTYPE_WAT_ANSWER = 9602; + EVENTTYPE_WAT_ERROR = 9603; + EVENTTYPE_WAT_MESSAGE = 9604; + +const +{ + wParam: 0 or parent window + lParam: 0 + note: Shows Macro help window with edit aliases ability +} + MS_WAT_MACROHELP:pAnsiChar = 'WATrack/MacroHelp'; + +{$ENDIF M_MUSIC} diff --git a/plugins/Watrack/docs/sampledll.dpr b/plugins/Watrack/docs/sampledll.dpr new file mode 100644 index 0000000000..908fe60597 --- /dev/null +++ b/plugins/Watrack/docs/sampledll.dpr @@ -0,0 +1,139 @@ +library testdll; + +uses m_api, Windows,common; + +{$include m_helpers.inc} +{$include m_music.inc} + +const + PluginInfo:TPLUGININFOEX=( + cbSize :sizeof(TPLUGININFOEX); + shortName :'Plugin Template'; + version :$00000001; + description:'The long description of your plugin, to go in the plugin options dialog'; + author :'J. Random Hacker'; + authorEmail:'noreply@sourceforge.net'; + copyright :'(c) 2003 J. Random Hacker'; + homepage :'http://miranda-icq.sourceforge.net/'; + flags :UNICODE_AWARE; + replacesDefaultModule:0; + uuid:'{00000000-0000-0000-0000-000000000000}' + ); +var + PluginInterfaces:array [0..1] of MUUID; + +var + hook:integer; + oldproc:tReadFormatProc; + +// -------- format -------- +Function mp3proc(var dst:tSongInfo):boolean;cdecl; +begin +{ + MP3 Handler here +} +//messagebox(0,'ok','',0); +// Example for old handler + if (int(@oldproc)<>WAT_RES_OK) and (int(@oldproc)<>WAT_RES_ERROR) then + result:=oldproc(dst) + else + result:=true; +end; + +// ---------- Player ---------- +var + plwnd:HWND; + +function Check(flags:integer):HWND;cdecl; +begin + result:=1; + plwnd:=12; +end; + +function GetFileName:pWideChar;cdecl; +begin + result:=nil; +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +begin + PluginLink^.CallService(MS_WAT_WINAMPINFO,integer(@SongInfo),flags); + SongInfo.plyver:=$1234; + result:=0; +end; + +function Command(command:integer;value:integer):integer;cdecl; +begin + result:=PluginLink^.CallService(MS_WAT_WINAMPCOMMAND,plwnd, + command+(value shl 16)); +end; + +function OnWATLoaded(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + tmp:tMusicFormat; + tmp1:tPlayerCell; +begin + PluginLink^.UnhookEvent(hook); + + FillChar(tmp,SizeOf(tMusicFormat),0); + lstrcpy(tmp.ext,'MP3'); + tmp.proc:=mp3proc; + oldproc:=tReadFormatProc(PluginLink^.CallService(MS_WAT_FORMAT, + WAT_ACT_REGISTER+WAT_ACT_REPLACE,dword(@tmp))); + + FillChar(tmp1,SizeOf(tPlayerCell),0); + tmp1.desc :='Sampler'; + tmp1.flags :=0;// WAT_OPT_WINAMPAPI + tmp1.Check :=@Check; + tmp1.GetInfo:=@GetInfo; + tmp1.Command:=@Command; + tmp1.GetName:=@GetFileName; + PluginLink^.CallService(MS_WAT_PLAYER,WAT_ACT_REGISTER+WAT_ACT_REPLACE,dword(@tmp1)); + result:=0; +end; + +function OnModuleLoaded(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + hook:=HookEvent(ME_WAT_MODULELOADED,@OnWATLoaded); + result:=0; +end; + +function MirandaPluginInfo(mirandaVersion:DWORD):PPLUGININFO; cdecl; +begin + result:=@PluginInfo; + PluginInfo.cbSize:=SizeOf(TPLUGININFO); +end; + +function MirandaPluginInfoEx(mirandaVersion:DWORD):PPLUGININFOEX; cdecl; +begin + result:=@PluginInfo; + PluginInfo.cbSize:=SizeOf(TPLUGININFOEX); +end; + +function Load(link: PPLUGINLINK): int; cdecl; +begin + PLUGINLINK := Pointer(link); + InitMMI; + Result:=0; + hook:=HookEvent(ME_SYSTEM_MODULESLOADED,@OnModuleLoaded); +end; + +function Unload: int; cdecl; +begin + Result:=0; +end; + +function MirandaPluginInterfaces:PMUUID; cdecl; +begin + PluginInterfaces[0]:=PluginInfo.uuid; + PluginInterfaces[1]:=MIID_LAST; + result:=@PluginInterfaces; +end; + +exports + Load, Unload, + MirandaPluginInfo + ,MirandaPluginInterfaces,MirandaPluginInfoEx; + +begin +end. diff --git a/plugins/Watrack/docs/wat.php b/plugins/Watrack/docs/wat.php new file mode 100644 index 0000000000..d15049dd72 --- /dev/null +++ b/plugins/Watrack/docs/wat.php @@ -0,0 +1,28 @@ + \ No newline at end of file diff --git a/plugins/Watrack/docs/watrack_history.txt b/plugins/Watrack/docs/watrack_history.txt new file mode 100644 index 0000000000..bea80d4e85 --- /dev/null +++ b/plugins/Watrack/docs/watrack_history.txt @@ -0,0 +1,519 @@ +0.0.6.12 (17 nov 2009) + Added Last.FM scrobbling support +0.0.6.11 (14 sep 2009) + Added watrack parts admin page + Fixed cover reading from OGG files + Fixed mRadio work when no avatar plugin presents + Fixed wrong LastFM recognition +0.0.6.10 (28 aug 2008) + Added basic LastFM support + Added hidden option 'xstatpause',ms (word type) to make pause between XStatus changing + Added option to emulate multimedia keys + Added avatar as cover for mRadio contacts support +0.0.6.9 (28 jan 2008) + Fixes for FLV format + Added option to assign 'music' and 'video' xstatuses + Changed Handle checking (to avoid Thread handle leak) + First tab setting notes shows on mouse hover (not click) +0.0.6.8 (29 oct 2007) + Added two options to alter filename search method + Fixed: mRadio track changing not catched +0.0.6.7 (26 aug 2007) + Added lyric support for APev2 tags, WMA + Added cover support for APev2 tags, WMA, OGG, SPX and fLaC + Optimized APEv2, OGG, fLaC and WMA reading code + Fixed ID3v2.4 tag reading code + Optimized mediafile handle checking +0.0.6.6 (9 aug 2007) + AIMP player support code changed + Fixed some memoryleaks +0.0.6.5 (20 jun 2007) + 'Use existing XStatus' options changes only message text, not title + Optimized FLV reading code + Fixed and optimized MPG reading code +0.0.6.4 (13 jun 2007) + Added AIMP control +0.0.6.3 (10 jun 2007) + Added: mRadio %version% macro support + Fixed: in rare case covers can be renamed and deleted + Fixed: %cover% value can be wrong if cover not present + Fixed: %volume% value for mRadio not obtaining +0.0.6.2 (9 jun 2007) + Small players code fixes + Commented some thread code (due to AIMP 1.77 changes) + Fixed version number + Added seek ability for local mediafiles +0.0.6.1 (7 jun 2007) + Added extended control for mRadio Mod + Added compatibility with AIMP 1.77 + Added service to obtain not only played file info + Fixed: frame not change cover picture obtained from mediafile tags +(01 jun 2007) + Added %nstatus% macro (like %status% but w/o translation) +(29 may 2007) + Very small fixes (for mRadio too) +(25 may 2007) + Added ability to show popups only by request, not new track +(20 may 2007) + Changed: added threads for popups and statistic + Changed: Music/player Info obtaining code + Fixed: QCD player recognizing and processing +(16 may 2007) + Added actions support for Popup Plus 2.1.0.5 +(15 may 2007) + Added %playerhome% (Player homepage url) macro +(11 may 2007) + Small fixes + Statistic code optimized for speed +(09 may 2007) + Added two buttons to check player/format list + AIMP player now processed separately + Changed code for played filename obtaining +0.0.6.0 (05 may 2007) + Many small codechanges and fixes + Music info request can be send by ASKWAT text sending (received as message) + Settings saved only in profile db now +0.0.5.0 (18 feb 2007) + Fixed: cover is showed only when backround picture name is not empty + Cover files deleted at exit now + Added volume field (see readme) to SongInfo structure. + Fixed: Cover from ID3v2 tag saved incorrectly + Fixed: Miranda crashed when shutdowned + Code cleaning and optimization +0.0.4.30 (24 dec.2006) + Changed internal code library + Fixed comment reading from ID3v2 tag +0.0.4.29 (29 nov 2006) + Small Fixes + Changes for external icon support for player.ini file + Fixed: ini file modified constantly if player not found +0.0.4.28 (16 nov 2006) + Other bugfixes + Fixed: Contact menu handler chain was broken +0.0.4.27 (15 nov 2006) + Small player handles fixes + Fixed: crash with WAV file samplesize<8 bit + Added options to choose Music info sharing ability + Added context menu music info request + Fixed bug with Frame redraw/resizing + Added external player definition +0.0.4.26 (7 nov 2006) + Added album sort mode to report + Fixed some report errors + Changes for old miranda versions (before 0.6) compatibility +0.0.4.25 (31 oct 2006) + INI file (not database) used by default + Winamp video width and height recognizing returned (for test) + Fixed: log file rewrited always + Fixed: Report creating from Options tab was wrong + Fixed: "Export default" button on options tab not work +0.0.4.24 (29 oct 2006) + Report code was rewritten to template support + Current settings saved when saving place changed (switch at last!) + Loading settings from profile database works now normally + Fixed: Player name case conversion was after WAT_EVENT_NEWTRACK sending + Width and Height recognition through Winamp API disables due to wrong return values +0.0.4.23 (15 oct 2006) + Save in INI/profile base file option returned + API changes + ID3v2 tag reading code was changed + Rewritten and reorganized internal structure + mBot script sample added +0.0.4.22 (17 sep 2006) + INI-file structure changes (frame, report and popup options is separated) + CyberLink PowerDVD recognizing added + ALSong player recognizing added + MediaInfo obtained at plugin start now (if refresh time is not 0) + First version of new Player API is finished + Underscore replaces by spaces only in text macros (not media filename) + Fixed: wrong action on "Use Frame" checkbox +0.0.4.21 (28 aug 2006) (test) + Miranda memory manager used now + Fixed: ID3v2 tags cannot process Unicode strings with reverse byte order + Media format API rewrited, new service added + Added event notifier for plugin loading + Added event notifier for plugin/player status changing +0.0.4.20 (20 aug 2006) + Only songs with known length are addings to log + Added frame text centering + Small bugfixes + Fixed: Mirada crashes while report creating changed from menu + Added mRadio plugin support (test) + Fixed: sometimes trackbar is hidden + Added SongBird player support +0.0.4.19 (11 aug 2006) + XStatus 'Watching pro7 on TV' works like 'Listening to music' XStatus but for video + Show/hide trakbar option is separated now + Sources changed for delphi7_up compatibility + Fixed: Sometimes plugin show hotkey registration error + Fixed: Timer stopped when Options page is open + Added some additional settings for frame text scrolling + Fixed: iTunes volume control does not work + Added menu item and toolbar button to disable plugin + Fixed error with unknown format tag in the frame template + Added WiFiRadio player support + Added option to hide frame when player not found +0.0.4.18 (14 jul 2006) + Added GOM player detection + {cf#nnnnnn} and {bg#nnnnnn} is define color with hex trucolor value 'nnnnnn' + Added frame text format support + Added pushed/hovered button status support if watrack_buttons.dll is used +0.0.4.17 (10 jul 2006) + Fixed: frame button not unpress when pressed button mouse moves out of frame + Added option to use or not gap between frame buttons + Option tabs changed back to theme ability + Added "skin" trackbar ability +0.0.4.16 (9 jul 2006) + Small interface changes + Volume buttons on the frame changed and can be hided now + '\t' combination (Tabulation) changed to '{tab}' tag format + Fixed avoid '\n' combination conflict in templates + Holding mouse button on volume control make continuous decremet/increment + Fixed some bugs + Added frame transparency +0.0.4.15 (5 jul 2006) + Added right align frame picture option + Fixed: text insertion hotkey do not always register + Service for player control is created + Added "Next track" to popup click options + If timer value greater than 499, time signify as milliseconds +0.0.4.14 (3 jul 2006) + Added bottom align frame picture option + Fixed: Miranda freezes on W2K when some radiobuttons clicked + Returned modified old code for Foobar recognize +0.0.4.13 (29 jun 2006) + Updater data changed for new hosting compatibility + Added support \t in templates (expanded when used) + Frame text now can be edited + Frame background can be picture (with effects: center, tile, stretch) + Options saves in profile directory as default (if old settings not found) + Foobar2000 recognizing code changed + Jabber chat recognized now + Fixed: 'Try to use OLE interface' option not changed + Added frame bitmap background support + Fixed: control icons in IcoLib not shows then watrack_icons.dll is not found + Volume control added + New Frame options added +0.0.4.12 (18 jun 2006) + Fixed (i hope) bug with info refresh while MediaMonkey finished + Added frame support with IcoLib support + Added control procedures for some players + Small speed optimization + Introduced option to enable/disable players OLE interface +0.0.4.11 (14 jun 2006) + Fixed FLV bug + Added MPEG file support (only MPEG audio stream) +0.0.4.10 test (11 jun 2006) + New macro %txtver% (text version number representation) was introduced + Small fixes + Imroved Foobar2000 support if foo_comserver2 plugin is present +0.0.4.9 (06 jun 2006) + Added partial support for MOV and 3GP file formats + Added support for ID3v2 tag v.2 + Added option to skip some plugin error messages (mainly for hotkeys) + INI file is not rewritten now if default player was not changed + Added QuickTime player support +0.0.4.8 (31 may 2006) + Added New options to insert text in text field of other apps + Code compiled with KOL (smaller size) +0.0.4.7 + Version numeration changed for more Updater compatibility. Last number is for betas. + Trying to use XP theming in TABs + Changed XStatus recovery code +0.0.4.6 (23 may 2006) + Variables and NewAwaySys works now with Unicode + Small interface changes + Added FLVPlayer support + Added option to check file date/time changes while playing + Added option to set XStatus regardless of ICQ status + Added option to replace underline with spaces + Fixed NAS service call + Added partial FLV format support + Fixed: some unicode named files can't be processed + Macro help removed from resource +0.0.4.5 (11 may 2006) + Changed Macro help window - with localisation support now + Added NewAwaySys (unicode) support for status text changings + Added MPlayer support + Fixed MusikCube player code + Fixed template formatting in IRC channel + Added partial MKV, WMV and ASF formats support + Changed RM reading code to video info compatibility + Added AVI file support (test version) + Added OGM file support + %fps%, %width%, %height% and %codec% macro added + OGG file info reading changes + Fixes for large files + Finally fixed bug with Popup templates + Options dialog changed again (Templates and Protocols tabs is merged) +0.0.4.4 (24 apr 2006) + Fixed: Template macro help not work + Changed WavPack reading code for v.4* compatibility + Fixed bug with INI file name processing + Status message now uses 'Status Text' template (was 'Status Title') + MediaMonkey player class now partially uses OLE interface + Music XStatus can be cleared when miranda starts without music + Watrack.ini used if private INI file is absent + Notes in first option tab is Unicode now + Changed work with statuses (normal and extended) + Changed plugin behaviour when Miranda started without played song + Default template texts changed + Fixed: unused strings was keeped in INI file. + Fixed: can crash when Variables plugin not exists + Fixed: protocols enabling-disabling not works properly + Fixed: Crashes when music played and templates changed + MediaMonkey recognized as separate player now, not Winamp clone + All settings now saved in INI-file + Template option dialog was totally rewrited +0.0.4.3 (26 mar 2006) + Added option to return Variables value in ANSI + Small save-related changes + Added 'AudioPlayer' support + Player icons moved to separate file (must be in icons or plugins directory) + Added player window handle to SongInfo structure + Added popup option to activate player window + Fixed: wrong 'Total logged music time' value + Added Core Media Player support +0.0.4.2 (03 mar 2006) + Fixed RM file reading + Fixed ID3v2 tag reading (UTF8 encoding) + Small option dialog interface changes + Localisation sample file included (russian) + psapi.dll included (needed when plugin can't get song filename) + Fixed WMA tag reading + Fixed LA player recognition (wrong player status was returned) + Old XStatus restored now if player not found + Changed: if XStatus title is empty, it is cleared now + Changed %music% command translation code +0.0.4.1 (26 feb 2006) + Deleted ICQ XStatus old API code + Added Creative Media Source support + Added 'version' resource + Status and popup templates are separated now + Added Media Commander Express player support + Added IcoLib support + Added VLC player support + Added Helium Music Manager support + Added Musicmatch Jukebox player support + Added %music% command with BB-code formatting in message dialog + Added option for player title formatting + Fixed error with filename in File info called from popup + Added support for J.River Media Center + Fixed situation when player is stopped + Fixed: 511 byte per string only saved in INI-file + Fixed player status for unknown filetypes + Small fix for MP4/M4A reading + Added partial M4A file format tag support + Added option to get unknown music format info from player + Changed WMA tag reading code to obtain number-type values + All resource language is Neutral now + Changed MusicCubeOne and SAPS players recognition + When 'no-music text' is empty and player stopped status message cleared + When 'Keep Status' is 'on' status text cleared + Song time can show more than 99 hours now + Changed recognizing song filename when Apollo is 'stopped' + Added Pluton player support + Fixed: Clearing 'Music' XStatus doesn't work with new ICQ API +0.0.4.0 (29 jan 2006) + Added option to disable log + Changed XStatus setting code to compatibles with new ICQ API + Fixed: Popup service function works only with TopToolBar + Vorbis comment tag names now case insensitive + Changed FLAC reading code. Now with Vorbis comments + Current music format saves and checks firstly + Fixed: 'Save settings in INI-file' option cleared if Options dialog opens + Nearby twin record in statistic file is ignored now + Relative report or statistic file path calculated now from Miranda directory + Corrected status changing when player stopped + Added %status% macro (works with not all players!!!) + Added option to save CSS file separately + Added automatic report file extension adding/changing + Added VBR/CBR text to File Info from pupup + Added %year% macro help (i just forgot) + Empty report file not created if log file is invalid + Added menu item and service function for report creating + Added support for SAPS player + Added support for Zoom player + Changed QCDPlayer code to support new QMPlayer +0.0.3.8 (19 jan 2006) + Fixed MP3 VBR reading bug + Added simple statistic (UTF8 enc.) (just for fun) + Added %vbr% macro and option for it + Added template when player not found + Changed Options interface + Changed Service function interface (please, see comments!) + Fixed wrong %total% value when 'Variables' plugin used + Added MusicCube One player support + OGG tags now translated as UTF8 + Fixed some ID3v2 tag reading issues and errors + Fixed track number recognize in APEv2 tag + Active Player places on first place (save in settings - AI! :) ) + Now MP3 files checked firstly + Changed Foobar2000 main window search procedure + Deep code changes (translating to Unicode strings and other) +0.0.3.7 (26 dec 2005) + Added file size text formatting + Corrected formatted text output + Fixed WMA reading code (again) + Fixed internal ANSI to Unicode transformation + Changed Options dialog +0.0.3.6 (21 dec 2005) + Added Unicode support + Fixed wrong WMA tag reading + Advances PopUp settings + Toolbar button for popup window added + Small code optimisation + Fixed chat or message window recognition + Partially avoiding WMP10 playlist bug + Added XMPlayer support + Added macros %size% (file size) and %type% (file ext.) +0.0.3.5 (05 dec 2005) + Now Status not processes and Popup not shows when player is stopped + Popup settings dialog created + Added BSPlayer support +0.0.3.4 (28 nov 2005) + Some changes for Service function (mainly description, see header) + Fixed (i hope): Miranda crushes sometimes by pressing hotkey + 'No-music text' can processed by Variables plugin + Now Status changing works in separated protocols + Fixed: Popup shows not always + Status template now multiline + Added player icon in Popup window +0.0.3.3 (24 nov 2005) + Changed Foobar2000 recognition for new versions + Remove elapsed time recongition within Foobar2000 (sorry!) + Now with player shutdown XStatus changes to 'none' and no sets anymore + Added simply PopUp support (Status Template value) + Added option to change XStatus only for existing Music xstatus + Added option to keep or not Music XStatus on player exit + Fixed: Miranda can crush while use Variables plugin +0.0.3.2 (19 nov 2005) + File renamed for avoiding Updater plugin crash + Fixed: format tag at the end of template not translated + Fixed variables help + Added support for ViPlay3 player + Data for 'Variables' plugin updated by timer + Added ability to switch off some players + Added ability to change processed status mode + Added ability to save settings in INI-file + Settings saved only from Options dialog, not on exit + Some code changes +0.0.3.0 (29 oct 2005) + Genre name table moved to resource + ICQ XStatus changes only for non-offline user mode + Fixed: 'new line' code inserted at the end +0.0.2.9 (27 oct 2005) + Fixed: Stupid bug - text not inserted into CHAT window + Temporary: text formatting used in ordinal message window too (only for testing) +0.0.2.8 (27 oct 2005) + Added support for RA/RM format (experimental) + Changed text formatting algorithm (test for Asian text, please!) + Created version archive on http://awkward.front.ru/archive/ + Try to use simple Updater plugin compatibility +0.0.2.7 (25 oct 2005) + Fixed: Status message not changed by timer + Added: experimental Chat window text formatting (see readme) +0.0.2.6 (23 oct 2005) + Fixed some bugs. + Other small changes. +0.0.2.5 (23 oct 2005) + Modified Option Dialog and added translation ability + Added partial support for AAC file format + Added support for MP4 with MP3-coding format + Added support for MusikCube player + Added alternative ID3v2 tag frames +0.0.2.4 (19 oct 2005) + Changed hotkey processing (not global hook now) + Changed some players recognition + Changed Music info interface (see include file) + Added support for 'Variables' plugin (not fully tested) + Added support for MediaMonkey Player + Added support for RealPlayer + Added support for MPC file format (only 'MPC' extension) + Added partial support for SPX file format (not tested) + Added partial support for OFR file format (not tested) + Now Status sets only if changed +0.0.2.2 (10 oct 2005) + (Not fully tested, save previous version!) + Now HotKey work only with own Miranda copy + New tag processing algorithm + Added WAV format support + Added experimental APE,TTA and FLAC formats support (not tested) + Added iTunes and PlayNow! players recognize + Some internal changes + Macro %samplerate% and %bitrate% (%khz% and %kbps% synonims) added + Fixed: unwanted XStatus changing to 'Music' +0.0.1.8 (05 oct 2005) + Fixed: Sometime Foobar2000 main window not recognized properly + Small speed optimisation + Added LightAlloy recognize + Empty "No-Music text" keep original Miranda status messages now + Fixed: in Apollo and OGG-file Bitrate was Bps, not KBps, + Samplerate was Hz, not KHz +0.0.1.7 (04 oct 2005) + Added automatic Music info refresh by timer + Added option to NOT insert music info into message window + Fixed: crash on some comments in ID3v2 +0.0.1.6 (03 oct 2005) + Changed Options dialog + Added simple Away-message support (only by Hotkey pressing) + Macro %year% now work +0.0.1.5 (02 oct 2005) + Support for Unicode value in ID3v2 + Add WMA tag support + Fixed: macro %genre% not translated + Fixed: Winamp window title processing +0.0.1.4 (29 sep 2005) + Added JetAudio support + Fixed: VBR MP3 length not propely calculated + Fixed music file name recognition + Added APEv2+ID3v1 at one time tag support +0.0.1.3 (28 sep 2005) + Now get music info from file on local network +0.0.1.2 (27 sep 2005) + Changed 'year' field type in music info + Added APEv2 tag support for MP3 + Remove Win98-code part + Other small changes +0.0.1.1 (25 sep 2005) + Test version. + win2KXP-only compatible. + Service function added. + MP3 IDv2 tag data read fixed + Some other bugs fixed (sorry, not all!). +0.0.1.0 (25 sep 2005) + Test version: new music file search algorithm (MP3 OGG WMA only) + Windows media player wrapper not needed now +0.0.0.9 (24 sep 2005) + correct MP3 file processing with padding at start + cutting template strings tail fixed again :( + add %percent% macro + Modified source code uploaded +0.0.0.8 (22 sep 2005) + cutting template strings tail (sometime) fixed + %wndtext% macro turn "on" again :) +0.0.0.7 (19 sep 2005) + MP3 tag support extended + OGG file info (not length, sorry!) added + music info readed at one time now (for Winamp-like API - at request too) + Apollo samplerate show changed + %comment% macro added +0.0.0.6 (18 sep 2005) + Macro %track% value changed + audio MPEG 2 & 2,5 and layer 1 & 2 file support added + Some code cleaning + Correct data view from MP3 Tag + Changed Artist-Title determination algorithm + Changed Winamp search algorithm +0.0.0.5 (14 sep 2005) + Work improved, more players added + Default macro processing added + Fix some bugs + FooBar without Winamp wrapper supported (not full) + MP3 tag v1 partial support added +0.0.0.3 (12 sep 2005) + New option interface + New engine for many player support + Macro support added +0.0.0.1 (07 sep 2005) + First release diff --git a/plugins/Watrack/docs/watrack_readme.txt b/plugins/Watrack/docs/watrack_readme.txt new file mode 100644 index 0000000000..ef2ec81e98 --- /dev/null +++ b/plugins/Watrack/docs/watrack_readme.txt @@ -0,0 +1,110 @@ +For what: + Insert Played music info in message window or Status text. ICQ extended + status supported. + +Requirements: + Windows 2K/XP (SP2 better) + Miranda 0.6.x + +Supported Players: + Winamp (http://www.winamp.com/) + Apollo (http://www.iki.fi/hy/apollo/) + 1by1 (http://www.mpesch3.de/) + Media Player Classic (http://gabest.org/) + Window Media Player (http://www.microsoft.com/windows/windowsmedia/players.aspx) + FooBar2000 (http://www.foobar2000.org/) + LightAlloy (http://www.softella.com/) + Cowon JetAudio (http://www.jetaudio.com/) + Quintessential Player (http://quinnware.com/) + iTunes (http://www.itunes.com/) + MediaMonkey (http://www.mediamonkey.com/) + Real Player (http://www.real.com/) + MusikCube (http://www.musikcube.com/) + BSPlayer (http://www.bsplayer.org/) + MusicCube One (http://www.rodi.dk/musiccubeone) + Zoom Player (http://www.inmatrix.com/) + Pluton (http://pluton.oss.ru/) + J. River Media Center (http://www.jrmediacenter.com/) + Musicmatch Jukebox (http://wwwp.musicmatch.com/) + VideoLAN media player (http://www.videolan.org/) + mRadio miranda plugin (http://miranda.kom.pl/dev/bankrut/) + ALSong&ALShow (http://www.altools.net/) + + and others. List of other players see in player.ini + +Supported Formats: + MP3, OGG, WMA, WAV, APE, TTA, AAC, FLA/FLAC, MPC, OFR/OFS, SPX, MP4, M4A, + ASF, WMV, AVI, MKV, OGM, RA/RM/RAM, FLV, MOV, 3GP, MPEG/MPG + +In Chat (and maybe message) window, you can use text formatting: +{b}text{/b} - 'bold' text +{i}text{/i} - 'italic' text +{u}text{/u} - 'undeline' text +{cf##}text{/cf} - text with color ## (0-15) +{bg##}text{/bg} - text with background color ## (0-15) +Sample:/me {b}listen{/b} {cf5}{i}%artist%{/i}{/cf} - {bg10}{u}"%title%"{/u}{/bg} + +Macros: + %album% - album + %artist% - artist + %bitrate% - bitrate + %channels% - number of channels + %codec% - video codec like 0x30355844 (DX50) + %comment% - comment from tag + %cover% - cover file name + %file% - media file name + %fps% - 100*FPS (Frames Per Second) for video files + %height% - video height in pixels + %genre% - genre + %kbps% - bitrate + %khz% - samplerate + %length% - total song length (sec) + %lyric% - lyric text + %mono% - "mono"/"stereo" + %nstatus%' - player status (stopped,playing,paused) - nontranslated + %percent% - %time% / %total% * 100% + %player% - player + %samplerate% - samplerate + %size% - media file size + %status%' - player status (stopped,playing,paused) + %time% - current song position (sec) + %title% - song title + %total% - total song length (sec) + %track% - track number + %txtver% - player version in text format + %type% - media file type (extension) + %vbr% - 'VBR' if VBR :) + %version% - player version + %width% - video width in pixels + %wndtext% - title from player window (usually "artist" - "title") + %year% - song year (from tag) + +Notes: + - Volume field has a original volume value in hiword and scaled to 0-15 range + in loword. Not all players supported. + - Frame background picture transparence is not implemented + - To obtain more information from foobar2000 player, you must download plugin + http://foosion.foobar2000.org/0.9/foo_comserver2-0.7-setup.exe + or use foo_winampspam plugin + - FileInfo (called from popup) not shows Video file properties + - FPS saves as FPS*100 + - Frame text output is Left-to-Right only now + +Known BUGs: + - if Frame text uses %time% macro, text can't scroll + - Foobar seeking with foo_winamp_spam may not work + - Miranda can freeze if Foobar OLE interface used + - Player can start again if OLE checks while it shutdown + - ICQLite and ICQ2003 users cannot see XStatus text changes + - in MP3 with VBR total song time sometime is not properly calculated + - default color of formated text is color of text at insert position + - some macros don't work with some players. Replaced by '' and 0 + - 1by1 player can show wrong elapsed time value + - some players version not properly displayed + - bad MP3 headers not properly handled + - plugin can show wrong song when Player scans directory for music files + +PS. To compile plugin you must use something like this: + dcc32 -$A+ -$H+ watrack.dpr + +All comments, errors & wishes please send to awkward@land.ru or panda75@bk.ru diff --git a/plugins/Watrack/formats/fmt_aac.pas b/plugins/Watrack/formats/fmt_aac.pas new file mode 100644 index 0000000000..db8e03b153 --- /dev/null +++ b/plugins/Watrack/formats/fmt_aac.pas @@ -0,0 +1,93 @@ +{AAC file process} +unit fmt_AAC; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadAAC(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,tags,srv_format; + +const + SampleRates:array [0..15] of dword = ( + 96000,88200,64000,48000,44100,32000,24000,22050, + 16000,12000,11025,8000,0,0,0,0); + +procedure ReadADIFheader(f:THANDLE;var Info:tSongInfo); +var + buf:array [0..29] of byte; + bs,sf_idx,skip:dword; +begin + BlockRead(f,buf,30); + if (buf[0] and $80)<>0 then + skip:=9 + else + skip:=0; + Info.kbps:=(((buf[0+skip] and $0F) shl 19)+(buf[1+skip] shl 11)+ + (buf[2+skip] shl 3)+{or}((buf[3+skip] and $E0){shr 5})) div 1000; + bs:=buf[0+skip] and $10; + if bs=0 then + sf_idx:=(buf[7+skip] and $78) shr 3 + else + sf_idx:=((buf[4+skip] and $07) shl 1)+((buf[5+skip] and $80) shr 7); + Info.khz:=SampleRates[sf_idx]; +end; + +procedure ReadADTSheader(var Info:tSongInfo;sign:dword); +type + l2b=record + b:array [0..3] of byte; + end; +var + sr_idx:integer; +begin + Info.channels:=((l2b(sign).b[2] and $01) shl 2)+ + ((l2b(sign).b[3] and $C0) shr 6); + sr_idx:=(l2b(sign).b[2] and $3C) shr 2; + Info.khz:=SampleRates[sr_idx] div 1000; +end; + +function ReadAAC(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + sign:dword; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + ReadID3v2(f,Info); + BlockRead(f,sign,4); + Info.khz:=44; + Info.kbps:=128; + Info.channels:=2; + if (lobyte(sign)=$FF) and ((hibyte(sign) and $F6)=$F0) then + ReadADTSheader(Info,sign) + else if sign=$46494441 then // 'ADIF' + ReadADIFheader(f,Info); + + ReadAPEv2(f,Info); + ReadID3v1(f,Info); + CloseHandle(f); + result:=true; +end; + +var + LocalFormatLink:twFormat; + +procedure InitLink; +begin + LocalFormatLink.Next:=FormatLink; + + LocalFormatLink.This.proc :=@ReadAAC; + LocalFormatLink.This.ext :='AAC'; + LocalFormatLink.This.flags:=0; + + FormatLink:=@LocalFormatLink; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_ape.pas b/plugins/Watrack/formats/fmt_ape.pas new file mode 100644 index 0000000000..fbabdac19c --- /dev/null +++ b/plugins/Watrack/formats/fmt_ape.pas @@ -0,0 +1,137 @@ +{APE file} +unit fmt_APE; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadAPE(var Info:tSongInfo):boolean; cdecl; + +implementation + +uses windows,common,io,tags,srv_format; + +const + defID = $2043414D; +type +(* Old Version ? + tMonkeyHeader = record + ID :dword; { Always "MAC " } + VersionID :word; { Version number * 1000 (3.91 = 3910) } + CompressionID :word; { Compression level code } + Flags :word; { Any format flags } + Channels :word; { Number of channels } + SampleRate :dword; { Sample rate (hz) } + HeaderBytes :dword; { Header length (without header ID) } + TerminatingBytes:dword; { Extended data } + Frames :dword; { Number of frames in the file } + FinalSamples :dword; { Number of samples in the final frame } + PeakLevel :dword; { Peak level (if stored) } + SeekElements :dword; { Number of seek elements (if stored) } + end; +*) + tMonkeyHeader = packed record + ID :dword; // should equal 'MAC ' + VersionID :dword; // version number * 1000 (3.81 = 3810) + nDescriptorBytes :dword; // descriptor bytes + nHeaderBytes :dword; // APEHeader bytes + nSeekTableBytes :dword; // bytes of the seek table + nHeaderDataBytes :dword; // header data bytes (from original file) + nFrameDataBytes :dword; // bytes of APE frame data + nFrameDataBytesHi:dword; // the high order number of APE frame data bytes + nTerminatingBytes:dword; // the terminating data of the file (w/o tag data) + cFileMD5:array [0..15] of byte; + end; +type + tAPEHeader = packed record + nCompressionLevel:word; // the compression level + nFormatFlags :word; // any format flags (for future use) + nBlocksPerFrame :dword; // the number of audio blocks in one frame + nFinalFrameBlocks:dword; // the number of audio blocks in the final frame + nTotalFrames :dword; // the total number of frames + nBitsPerSample :word; // the bits per sample (typically 16) + nChannels :word; // the number of channels (1 or 2) + nSampleRate :dword; // the sample rate (typically 44100) + end; + +const + MONKEY_COMPRESSION_FAST = 1000; // Fast (poor) + MONKEY_COMPRESSION_NORMAL = 2000; // Normal (good) + MONKEY_COMPRESSION_HIGH = 3000; // High (very good) + MONKEY_COMPRESSION_EXTRA_HIGH = 4000; // Extra high (best) +const + MONKEY_FLAG_8_BIT = 1; // Audio 8-bit + MONKEY_FLAG_CRC = 2; // New CRC32 error detection + MONKEY_FLAG_PEAK_LEVEL = 4; // Peak level stored + MONKEY_FLAG_24_BIT = 8; // Audio 24-bit + MONKEY_FLAG_SEEK_ELEMENTS = 16; // Number of seek elements stored + MONKEY_FLAG_WAV_NOT_STORED = 32; // WAV header not stored + +function ReadAPE(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + hdr:tMonkeyHeader; + hdr1:tAPEHeader; + blocks:dword; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + ReadID3v2(f,Info); + BlockRead(f,hdr ,SizeOf(tMonkeyHeader)); + BlockRead(f,hdr1,SizeOf(tAPEHeader)); //hdr.nHeaderBytes + if hdr1.nTotalFrames=0 then + blocks:=0 + else + blocks:=(hdr1.nTotalFrames-1)*hdr1.nBlocksPerFrame+hdr1.nFinalFrameBlocks; + Info.khz :=hdr1.nSampleRate div 1000; + if hdr1.nSampleRate<>0 then + Info.total :=blocks div hdr1.nSampleRate; + Info.channels:=hdr1.nChannels; +// Info.kbps:=Info.khz*deep*Info.channels/1152 +// Info.kbps:=(blocks*Info.channels*hdr1.nBitsPerSample) div (Info.total*8000); +// Info.kbps :=((hdr1.nBitsPerSample div 8)*hdr1.nSamplerate) div 1000; +(* Old version ? + if (hdr.ID<>DefID) or (hdr.SampleRate=0) or (hdr.Channels=0) then + exit; + if (hdr.VersionID>=3900) or + ((hdr.VersionID>=3800) and + (hdr.CompressionID=MONKEY_COMPRESSION_EXTRA_HIGH)) then + tmp:=73728 + else + tmp:=9216; + tmp:=(hdr.Frames-1)*tmp+hdr.FinalSamples; + Info.total :=tmp div hdr.SampleRate; + Info.khz :=hdr.SampleRate div 1000; + Info.channels:=hdr.Channels; + + Info.kbps:=tmp;//samples + if (hdr.Flags and MONKEY_FLAG_8_BIT)<>0 then tmp:=8 + else if (hdr.Flags and MONKEY_FLAG_24_BIT)<>0 then tmp:=24 + else tmp:=16; + Info.kbps:=((Info.kbps*tmp*hdr.Channels) div Info.Total) div 1000; +*) + ReadAPEv2(f,Info); + ReadID3v1(f,Info); + CloseHandle(f); + result:=true; +end; + +var + LocalFormatLink:twFormat; + +procedure InitLink; +begin + LocalFormatLink.Next:=FormatLink; + + LocalFormatLink.This.proc :=@ReadAPE; + LocalFormatLink.This.ext :='APE'; + LocalFormatLink.This.flags:=0; + + FormatLink:=@LocalFormatLink; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_avi.pas b/plugins/Watrack/formats/fmt_avi.pas new file mode 100644 index 0000000000..3646236cf7 --- /dev/null +++ b/plugins/Watrack/formats/fmt_avi.pas @@ -0,0 +1,295 @@ +{AVI file format} +unit fmt_AVI; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadAVI(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,srv_format; + +type + FOURCC = array [0..3] of AnsiChar; +type + tChunkHeader = packed record + case byte of + 0: (Lo,Hi:dword); {Common} + 1: (ID:FOURCC; {RIFF} + Length:dword); + end; + +const + sRIFF = $46464952; + sLIST = $5453494C; + savih = $68697661; { avi header } + sstrf = $66727473; { stream format } + sstrh = $68727473; { stream header } +const + smovi = $69766F6D; {movi list type} +const + svids = $73646976; {video} + sauds = $73647561; {audio} +const + sIART = $54524149; {director} + sICMT = $544D4349; {comment} + sICRD = $44524349; {creation date} + sIGNR = $524E4749; {genre} + sINAM = $4D414E49; {title} + sIPRT = $54525049; {part} + sIPRO = $4F525049; {produced by} + sISBJ = $4A425349; {subject description} + +type + tWaveFormatEx = packed record + wFormatTag :word; + nChannels :word; + nSamplesPerSec :dword; + nAvgBytesPerSec:dword; + nBlockAlign :word; + wBitsPerSample :word; + cbSize :word; + + Reserved1 :word; + wID :word; + fwFlags :word; + nBlockSize :word; + nFramesPerBlock:word; + nCodecDelay :word; {ms} + end; + +type + tMainAVIHeader = packed record {avih} + dwMicroSecPerFrame :dword; + dwMaxBytesPerSec :dword; + dwPaddingGranularity :dword; + dwFlags :dword; + dwTotalFrames :dword; { # frames in first movi list} + dwInitialFrames :dword; + dwStreams :dword; + dwSuggestedBufferSize:dword; + dwWidth :dword; + dwHeight :dword; + dwScale :dword; + dwRate :dword; + dwStart :dword; + dwLength :dword; + end; + +type + TAVIExtHeader = packed record {dmlh} + dwGrandFrames:dword; {total number of frames in the file} + dwFuture:array[0..60] of dword; + end; + +type + tAVIStreamHeader = packed record {strh} + fccType :FOURCC; {vids|auds} + fccHandler :FOURCC; + dwFlags :dword; + wPriority :word; + wLanguage :word; + dwInitialFrames :dword; + dwScale :dword; + dwRate :dword; + dwStart :dword; + dwLength :dword; + dwSuggestedBufferSize:dword; + dwQuality :dword; + dwSampleSize :dword; + rcFrame: packed record + left :word; + top :word; + right :word; + bottom:word; + end; + end; + +var + vora:dword; + +procedure Skip(f:THANDLE;bytes:dword); +var + i:dword; +begin + i:=FilePos(f); + if bytes=0 then + begin + if odd(i) then + Seek(f,i+1); + end + else + Seek(f,i+bytes+(bytes mod 2)); +end; + +procedure ProcessVideoFormat(f:THANDLE;Size:dword;var Info:tSongInfo); +var + bih:BitmapInfoHeader; +begin + BlockRead(f,bih,SizeOf(bih)); + Info.codec :=bih.biCompression; + Info.width :=bih.biWidth; + Info.height:=bih.biHeight; + Skip(f,Size-SizeOf(bih)); +end; + +procedure ProcessAudioFormat(f:THANDLE;Size:dword;var Info:tSongInfo); +{WAVEFORMATEX or PCMWAVEFORMAT} +var + AF:tWaveFormatEx; +begin + BlockRead(f,AF,SizeOf(AF)); + Info.channels:=AF.nChannels; + Info.khz :=AF.nSamplesPerSec div 1000; + Info.kbps :=(AF.nAvgBytesPerSec*8) div 1000; + Skip(f,Size-SizeOf(AF)); +end; + +function ProcessASH(f:THANDLE;var Info:tSongInfo):dword; +var + ASH:tAVIStreamHeader; +begin + BlockRead(f,ASH,SizeOf(ASH)); + with ASH do + begin + if dword(fccType)=svids then + begin + if ASH.dwScale<>0 then + Info.fps:=(ASH.dwRate*100) div ASH.dwScale; + if Info.fps<>0 then + Info.total:=(ASH.dwLength*100) div Info.fps; + ProcessASH:=1 + end + else if dword(fccType)=sauds then ProcessASH:=2 + else ProcessASH:=0; + end; +end; + +procedure ProcessMAH(f:THANDLE;var Info:tSongInfo); +var + MAH:tMainAVIHeader; +begin + BlockRead(f,MAH,SizeOf(MAH)); +// Info.width:=MAH.dwWidth; +// Info.height:=MAH.dwHeight; +// Info.fps:=100000000 div MAH.dwMicroSecPerFrame; +end; + +function ProcessChunk(f:THANDLE;var Info:tSongInfo):dword; +var + lTotal:dword; + Chunk:tChunkHeader; + cType:FOURCC; + ls:PAnsiChar; +begin + Skip(f,0); + if (BlockRead(f,Chunk,SizeOF(Chunk))=0) or (Chunk.Lo=0) then + begin + result:=FileSize(f); + Seek(f,FileSize(f)); + exit; + end; + result:=Chunk.Length+SizeOf(Chunk); + case Chunk.Lo of + sRIFF,sLIST: begin + BlockRead(f,cType,SizeOf(cType)); + if dword(cType)=smovi then + Skip(f,Chunk.Length-SizeOf(cType)) // result:=FileSize(f) + else + begin + lTotal:=SizeOf(FOURCC); + while lTotal0 do + begin + + len:=Reverse(pWord(ptr)^,2); inc(ptr,2); // key name length + key:=ptr; inc(ptr,len); // key name + + result:=ProcessValue(ptr,key,Info); + + if result=0 then break + else if result<0 then + begin + result:=1; + break; + end; + dec(i); + end; + end; + + // Object end marker, UI8[3]=0,0,9 + 9: begin + result:=-1; + inc(ptr,3); + end; + + 10: // array, 4 bytes - num of elements, elements + begin + i:=pdword(ptr)^; inc(ptr,4); + i:=Reverse(i,4); + while i>0 do + begin + result:=ProcessValue(ptr,nil,Info); + if result=0 then exit + else if result<0 then + begin + result:=1; + break; + end; + dec(i); + end; + end; + + // Date, Double + UI16 (UTC) + 11: begin + inc(ptr,8); + inc(ptr,2); + end; + + // LongString, 4 bytes = len, len - string + 12: begin + i:=pdword(ptr)^; inc(ptr,4); + i:=Reverse(i,4); + + inc(ptr,i); + end; + + end; +end; + +function ReadFLV(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + codec:transform; + FLVHdr:tFLVHeader; + StrmHdr:tFLVStream; + i,len:integer; + buf,pp,p,endbuf:PAnsiChar; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + + mGetMem(buf,BufSize); + endbuf:=buf+BlockRead(f,buf^,BufSize); + p:=buf; + CloseHandle(f); + move(p^,FLVHdr,SizeOf(tFLVHeader)); + if (FLVHdr.Signature[0]='F') and (FLVHdr.Signature[1]='L') and + (FLVHdr.Signature[2]='V') and (FLVHdr.Version=1) then + begin + inc(p,SizeOf(tFLVHeader)); + result:=true; + while (p0) do + begin + move(p^,StrmHdr,SizeOf(tFLVStream)); + inc(p,SizeOf(tFLVStream)); + len:=(StrmHdr.BodyLength[0] shl 16)+(StrmHdr.BodyLength[1] shl 8)+ + StrmHdr.BodyLength[2]; + pp:=p; + case StrmHdr.TagType of + + FLV_AUDIO: begin + Info.channels:=(ord(p^) and 1)+1; + // samplesize is (S_Byte and 2) shr 1 = 8 or 16 + case (ord(p^) and $C) shr 2 of + 0: Info.khz:=5; + 1: Info.khz:=11; + 2: Info.khz:=22; + 3: Info.khz:=44; + end; + FLVHdr.flags:=FLVHdr.flags and not 4; + end; + + FLV_VIDEO: begin + case ord(p^) and $0F of + 2: codec.txt:='H263'; + 3: codec.txt:='Scrn'; + 4,5: codec.txt:='VP6 '; + 6: codec.txt:='Src2'; + 7: codec.txt:='AVC '; + end; + Info.codec:=codec.num; + FLVHdr.flags:=FLVHdr.flags and not 1; + end; + + FLV_META: begin + if (StrmHdr.TagType and $40)=0 then // not encripted + begin + if pByte(p)^=2 then // string + begin + Inc(p); + i:=Reverse(pWord(p)^,2); inc(p,2); + if StrCmp(p,'onMetaData',i)=0 then // Metadata processing start + begin + inc(p,i); + ProcessValue(p,nil,Info); // metadata, no need key name, our info + // checking for video + if Info.codec<>0 then + FLVHdr.flags:=FLVHdr.flags and not 1; + // checking for audio + if (Info.khz<>0) and (Info.channels<>0) then + FLVHdr.flags:=FLVHdr.flags and not 4; + // break; // if metainfo is enough + end; + end; + end; + end; + + end; + p:=pp+len; + end; + end; + mFreeMem(buf); +end; + +var + LocalFormatLink:twFormat; + +procedure InitLink; +begin + LocalFormatLink.Next:=FormatLink; + + LocalFormatLink.This.proc :=@ReadFLV; + LocalFormatLink.This.ext :='FLV'; + LocalFormatLink.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLink; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_m4a.pas b/plugins/Watrack/formats/fmt_m4a.pas new file mode 100644 index 0000000000..1bfcf2309a --- /dev/null +++ b/plugins/Watrack/formats/fmt_m4a.pas @@ -0,0 +1,378 @@ +{M4A code template} +unit fmt_M4A; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadM4A(var Info:tSongInfo):boolean; cdecl; + +implementation + +uses windows,common,io,srv_format, +{$IFDEF KOL_MCK}KolZlibBzip{$ELSE}Zlib,zwrapper{$ENDIF}; + +type + mp4Atom = record + len:dword; + name:dword; + end; + +const + at_moov = $766F6F6D; + at_mvhd = $6468766D; + at_udta = $61746475; + at_meta = $6174656D; + at_ilst = $74736C69; + at_cmov = $766F6D63; + at_dcom = $6D6F6364; + at_cmvd = $64766D63; // 4 - unpacked size, data + at_trak = $6B617274; + at_tkhd = $64686B74; // not needed + at_mdia = $6169646D; + at_minf = $666E696D; + at_smhd = $64686D73; + at_vmhd = $64686D76; + at_stbl = $6C627473; + at_stsd = $64737473; + +const + atm_nam = $6D616EA9; // title + atm_ART = $545241A9; // artist + atm_wrt = $747277A9; // writer + atm_alb = $626C61A9; // album + atm_day = $796164A9; // date + atm_cmt = $746D63A9; // comment + atm_gen = $6E6567A9; // alt.genre + atm_gnre = $65726E67; // genre + atm_trkn = $6E6B7274; // track number +// atm_zlib = $62696C7A; + +type + pstsd = ^tstsd; + tstsd = packed record + version :byte; + flags :array [0..2] of byte; + NumEntries :dword; + SampleDescSize:dword; // $56 + DataFormat :dword; + reserved :array [0..5] of byte; + RefIndex :word; + Ver :word; + Revision :word; + Vendor :dword; + Temporal :dword; + Spacial :dword; + Width :word; + Height :word; + HRes :dword; //single; + VRes :dword; + DataSize :dword; + FrameCount :word; + CompNameLen :byte; + Compressor :array [0..18] of AnsiChar; + ColorDepth :word; + ColorTableID :word; + end; + pastsd = ^astsd; + astsd = packed record + Version :byte; + Flags :array [0..2] of byte; + NumEntires :dword; + DescSize :dword; + CodingName :array[0..3] of AnsiChar; + Reserved :array[0..5] of Byte; + RefIndex :Word; + Reserved_ :array[0..1] of dword; + ChannelCount:Word; + SampleSize :Word; + Pre_defined :Word; + Reserved___ :Word; + Samplerate :dword; + end; + pmvhd = ^mvhd; + mvhd = packed record + Version:byte; + flags:array [0..2] of byte; + Creation:dword; + Modification:dword; + TimeScale:dword; + Duration:dword; + end; + +procedure ReadAtom(f:THANDLE;var atom:mp4Atom); +begin + BlockRead(f,atom.len,4); + if atom.len>0 then + begin + BlockRead(f,atom.name,4); + atom.len:=BSwap(atom.len); + end + else + begin + atom.name:=0; + atom.len:=8; + end; +end; + +procedure GetAtom(var p:pbyte;var atom:mp4Atom); +begin + atom.len:=pdword(p)^; + inc(p,4); + if atom.len>0 then + begin + atom.name:=pdword(p)^; + inc(p,4); + atom.len:=BSwap(atom.len); + end + else + begin + atom.name:=0; + atom.len:=8; + end; +end; + +function SetTree(from:mp4Atom;var p:pbyte;path:PAnsiChar;var parent:pbyte):integer; +var + atom:mp4Atom; + len:cardinal; + saved:pbyte; +begin + saved:=p; + len:=0; + dec(from.len,SizeOf(from)); + parent:=p; + repeat + GetAtom(p,atom); + if atom.name=pdword(path)^ then + begin + inc(path,4); + if path^<>#0 then + begin + parent:=p; + inc(path); + len:=0; + from.len:=atom.len-SizeOf(atom); + end + else + begin + result:=atom.len; + exit; + end; + end + else + begin + inc(p,atom.len-SizeOf(atom)); + inc(len,atom.len); + end; + until len>=from.len; + result:=-1; + p:=saved; +end; + +function ReadInt(var p:pbyte):dword; +var + len:integer; +begin + len:=pdword(p)^; + inc(p,4); + len:=BSwap(len); + if len>0 then + inc(p,4); // 'data' + inc(p,4); // type? + inc(p,4); // encoding? + dec(len,8+8); + if len>4 then len:=4; + if len=2 then + begin + result:=p^*$100; + inc(p); + inc(result,p^); + inc(p); + end + else + begin + result:=BSwap(pdword(p)^); + inc(p,4); + end; +end; + +procedure ReadProp(var p:pbyte;var prop:pWideChar); +var + len:integer; + ltmp:PAnsiChar; + c:byte; +begin + len:=pdword(p)^; + inc(p,4); + len:=BSwap(len); + if len>0 then + inc(p,4); // 'data' + inc(p,4); // type? + inc(p,4); // encoding? + dec(len,8+8); + ltmp:=pointer(p); + inc(p,len); + c:=p^; + p^:=0; + UTF8ToWide(ltmp,prop); + p^:=c; +end; + +function ReadM4A(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + atom:mp4Atom; + cursize,parentsize:integer; + par,buf,p,pn,finish:pbyte; + size:integer; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + cursize:=0; + parentsize:=FileSize(f); + repeat + ReadAtom(f,atom); + if atom.name=at_moov then + begin + mGetMem(buf,atom.len); + BlockRead(f,buf^,atom.len); + p:=buf; + finish:=pByte(PAnsiChar(p)+atom.len-SizeOf(atom)); + repeat + GetAtom(p,atom); + pn:=PByte(PAnsiChar(p)+atom.len-SizeOf(atom)); + + if atom.name=at_cmov then + begin + size:=SetTree(atom,p,'cmvd',par); + if size>0 then + begin + ZDecompressBuf(PAnsiChar(p)+4,size-SizeOf(mp4Atom), + pointer(pn),size,BSwap(pdword(p)^)); + mFreeMem(buf); + buf:=pn; + p:=buf; + GetAtom(p,atom); //must be 'moov' + finish:=PByte(PAnsiChar(p)+atom.len-SizeOf(atom)); + continue; + end; + end; + + if atom.name=at_mvhd then + begin + if pmvhd(p)^.TimeScale<>0 then + Info.total:=BSwap(pmvhd(p)^.Duration) div BSwap(pmvhd(p)^.TimeScale); + end; + if atom.name=at_udta then + begin + size:=SetTree(atom,p,'meta.ilst',par); + if size>0 then + begin + cursize:=0; + repeat + GetAtom(p,atom); + if atom.name=atm_nam then ReadProp(p,Info.title) + else if atom.name=atm_ART then ReadProp(p,Info.artist) +// else if atom.name=atm_wrt then ReadProp(p,Info.title) + else if atom.name=atm_alb then ReadProp(p,Info.album) + else if atom.name=atm_day then ReadProp(p,Info.year) + else if atom.name=atm_cmt then ReadProp(p,Info.comment) +// else if atom.name=atm_gen then ReadProp(p,Info.genre) + else if atom.name=atm_gnre then Info.genre:=GenreName(ReadInt(p)-1) + else if atom.name=atm_trkn then Info.track:=ReadInt(p) + else + inc(p,atom.len-SizeOf(mp4Atom)); + inc(cursize,atom.len); + until cursize>=size; + end; + end; + // video properties + if atom.name=at_trak then + begin + if SetTree(atom,p,'mdia.minf.vmhd',par)>0 then + begin + p:=par; + if SetTree(atom,p,'stbl.stsd',par)>0 then + begin + Info.width :=swap(pstsd(p)^.Width); + Info.height:=swap(pstsd(p)^.Height); + Info.codec :=pstsd(p)^.DataFormat; + end; + end + // audio props + else if SetTree(atom,p,'mdia.minf.smhd',par)>0 then + begin + p:=par; + if SetTree(atom,p,'stbl.stsd',par)>0 then + begin + Info.khz:=(BSwap(pastsd(p)^.Samplerate) shr 16) div 1000; + Info.channels:=swap(pastsd(p)^.ChannelCount); + end; + p:=par; + if SetTree(atom,p,'stsz',par)>0 then + begin + if pdword(PAnsiChar(p)+4)^=0 then + Info.vbr:=1; + end; + end; + end; + p:=pn; + until PAnsiChar(p)>=PAnsiChar(finish); + mFreeMem(buf); + break; + end + else + Skip(f,atom.len-SizeOf(mp4Atom)); + inc(cursize,atom.len); + until cursize>=parentsize; + CloseHandle(f); +end; + +var + LocalFormatLinkM4A, + LocalFormatLinkMP4, + LocalFormatLinkMOV, + LocalFormatLink3GP:twFormat; + +procedure InitLink; +begin + LocalFormatLinkM4A.Next:=FormatLink; + + LocalFormatLinkM4A.This.proc :=@ReadM4A; + LocalFormatLinkM4A.This.ext :='M4A'; + LocalFormatLinkM4A.This.flags:=0; + + FormatLink:=@LocalFormatLinkM4A; + + LocalFormatLinkMP4.Next:=FormatLink; + + LocalFormatLinkMP4.This.proc :=@ReadM4A; + LocalFormatLinkMP4.This.ext :='MP4'; + LocalFormatLinkMP4.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLinkMP4; + + LocalFormatLinkMOV.Next:=FormatLink; + + LocalFormatLinkMOV.This.proc :=@ReadM4A; + LocalFormatLinkMOV.This.ext :='MOV'; + LocalFormatLinkMOV.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLinkMOV; + + LocalFormatLink3GP.Next:=FormatLink; + + LocalFormatLink3GP.This.proc :=@ReadM4A; + LocalFormatLink3GP.This.ext :='3GP'; + LocalFormatLink3GP.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLink3GP; + +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_mkv.pas b/plugins/Watrack/formats/fmt_mkv.pas new file mode 100644 index 0000000000..df01a82f59 --- /dev/null +++ b/plugins/Watrack/formats/fmt_mkv.pas @@ -0,0 +1,235 @@ +{MKV file process} +unit fmt_MKV; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadMKV(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,srv_format; + +const + idEBML = $A45DFA3; + idSegment = $8538067; + idInfo = $549A966; + idTimecodeScale = $AD7B1; + idDuration = $489; + idTracks = $654AE6B; + idTrackEntry = $2E; + idTrackType = $3; + idCodecPrivate = $23A2; + idName = $136E; + idVideo = $60; + idAudio = $61; + idPixelWidth = $30; + idPixelHeight = $3A; + idDefaultDuration = $3E383; + idSamplingFrequency = $35; + idChannels = $1F; + idCluster = $F43B675; + +function GetNumber(var ptr:pbyte):int64; +begin + if (ptr^ and $80)<>0 then + result:=ptr^ and $7F + else if (ptr^ and $40)<>0 then + begin + result:=(ptr^ and $3F) shl 8; inc(ptr); + result:=result+ptr^; + end + else if (ptr^ and $20)<>0 then + begin + result:=(ptr^ and $1F) shl 16; inc(ptr); + result:=result+(ptr^ shl 8); inc(ptr); + result:=result+ptr^; + end + else if (ptr^ and $10)<>0 then + begin + result:=(ptr^ and $0F) shl 24; inc(ptr); + result:=result+(ptr^ shl 16); inc(ptr); + result:=result+(ptr^ shl 8); inc(ptr); + result:=result+ptr^; + end + else if (ptr^ and $08)<>0 then + begin + result:=int64(ptr^ and $07) shl 32; inc(ptr); + result:=result+(ptr^ shl 24); inc(ptr); + result:=result+(ptr^ shl 16); inc(ptr); + result:=result+(ptr^ shl 8); inc(ptr); + result:=result+ptr^; + end + else if (ptr^ and $04)<>0 then + begin + result:=int64(ptr^ and $03) shl 40; inc(ptr); + result:=result+(int64(ptr^) shl 32); inc(ptr); + result:=result+(ptr^ shl 24); inc(ptr); + result:=result+(ptr^ shl 16); inc(ptr); + result:=result+(ptr^ shl 8); inc(ptr); + result:=result+ptr^; + end + else if (ptr^ and $02)<>0 then + begin + result:=int64(ptr^ and $01) shl 48; inc(ptr); + result:=result+(int64(ptr^) shl 40); inc(ptr); + result:=result+(int64(ptr^) shl 32); inc(ptr); + result:=result+(ptr^ shl 24); inc(ptr); + result:=result+(ptr^ shl 16); inc(ptr); + result:=result+(ptr^ shl 8); inc(ptr); + result:=result+ptr^; + end + else if (ptr^ and $01)<>0 then + begin + inc(ptr); + result:= (int64(ptr^) shl 48); inc(ptr); + result:=result+(int64(ptr^) shl 40); inc(ptr); + result:=result+(int64(ptr^) shl 32); inc(ptr); + result:=result+(ptr^ shl 24); inc(ptr); + result:=result+(ptr^ shl 16); inc(ptr); + result:=result+(ptr^ shl 8); inc(ptr); + result:=result+ptr^; + end + else + result:=0; + inc(ptr); +end; + +function GetInt(var ptr:pbyte;len:integer):int64; +var + i:integer; +begin + result:=0; + for i:=0 to len-1 do + begin + result:=(result shl 8)+ptr^; + inc(ptr); + end; +end; + +function GetFloat(var ptr:pbyte):single; +var + i:dword; + f:single absolute i; +begin + i:=( ptr^ shl 24); inc(ptr); + inc(i,ptr^ shl 16); inc(ptr); + inc(i,ptr^ shl 8); inc(ptr); + inc(i,ptr^); inc(ptr); + result:=f; +end; + +function ReadMKV(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + id,len:integer; + ptr:pByte; + buf:array [0..16383] of byte; + trktype,scale:integer; + ls:PAnsiChar; + tmp:integer; + lTotal:real; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + BlockRead(f,buf,SizeOf(buf)); + ptr:=@buf; + trktype:=0; + lTotal:=0; + scale:=1; + repeat + id :=GetNumber(ptr); + len:=GetNumber(ptr); + if id=idEBML then // just check + begin + result:=true; + inc(ptr,len); + end + else if id=idCluster then + break + else if id=idSegment then // do nothing + else if id=idInfo then // do nothing + else if id=idTracks then // do nothing + else if id=idTrackEntry then // do nothing + else if id=idVideo then // do nothing + else if id=idAudio then // do nothing + else if id=idTimecodeScale then + scale:=GetInt(ptr,len) + else if id=idDuration then + lTotal:=GetFloat(ptr) + else if id=idTrackType then + begin + tmp:=trktype; + trktype:=GetInt(ptr,len); // 1-video,2-audio + if (tmp=2) and (trktype=2) then + break; + end + else if (id=idCodecPrivate) and (trktype=1) then + begin + inc(ptr,16); + // 4 - ? (40=size included?) + // width,height + // 2 - ? + // 2 - bitperpixel? + Info.codec:=ptr^; inc(ptr); + Info.codec:=Info.codec+(ptr^ shl 8 ); inc(ptr); + Info.codec:=Info.codec+(ptr^ shl 16); inc(ptr); + Info.codec:=Info.codec+(ptr^ shl 24); + inc(ptr,len-19); + end + else if (id=idName) and (Info.title=NIL) then + begin + mGetMem(ls,len+1); + move(ptr^,ls^,len); + ls[len]:=#0; + AnsiToWide(ls,Info.title); + mFreeMem(ls); + inc(ptr,len); + end + else if id=idPixelWidth then + Info.width:=GetInt(ptr,len) + else if id=idPixelHeight then + Info.height:=GetInt(ptr,len) + else if id=idDefaultDuration then + begin + if trktype=1 then + begin + Info.fps:=(GetInt(ptr,len) div 1000); + if Info.fps<>0 then + Info.fps:=100000000 div Info.fps; + end + else + begin + GetInt(ptr,len); + end; + end + else if id=idSamplingFrequency then + Info.khz:=round(GetFloat(ptr)) div 1000 + else if id=idChannels then + Info.channels:=GetInt(ptr,len) + else + inc(ptr,len); + until pAnsiChar(ptr)>=(PAnsiChar(@buf)+SizeOf(buf)); + Info.total:=trunc(lTotal/(1000000000/scale)); + CloseHandle(f); +end; + +var + LocalFormatLink:twFormat; + +procedure InitLink; +begin + LocalFormatLink.Next:=FormatLink; + + LocalFormatLink.This.proc :=@ReadMKV; + LocalFormatLink.This.ext :='MKV'; + LocalFormatLink.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLink; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_mp3.pas b/plugins/Watrack/formats/fmt_mp3.pas new file mode 100644 index 0000000000..5d6c94745a --- /dev/null +++ b/plugins/Watrack/formats/fmt_mp3.pas @@ -0,0 +1,460 @@ +{MP3 file process} +unit fmt_MP3; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadMP3(var Info:tSongInfo):boolean; cdecl; +function ReadMPG(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,tags,srv_format; + +const + ScanSize = 16*1024; // block size to search header +type + tMP3FrameHdr = record + Version :integer; + Layer :cardinal; + Bitrate :cardinal; + Samplerate:cardinal; + Channel :cardinal; //Stereo, Joint, Dual, Mono + Length :cardinal; + CRC :boolean; + _Private :boolean; + Copyright :boolean; + Original :boolean; + isVBR :boolean; + end; + +// ........ ........ 111..... 11111111 syncword +// ........ ........ ...xx... ........ version (11=1, 10=2, 00=2.5) +// ........ ........ .....xx. ........ layer (01=III, 10=II, 11=I) +// ........ ........ .......x ........ crc (0=yes, 1=no) +// xx...... ........ ........ ........ mode (00=stereo, 10=joint, 01=dual, 11=mono) +// ..xx.... ........ ........ ........ mode ext (only for joint stereo) +// ....x... ........ ........ ........ copyright (0=no, 1=yes) +// .....x.. ........ ........ ........ original (0=orig, 1=copy) +// ......xx ........ ........ ........ emphasis (not 10) +// ........ xxxx.... ........ ........ bitrate (not 0000 nor 1111) +// ........ ....xx.. ........ ........ sampling rate (not 11) +// ........ ......x. ........ ........ padded (0=no, 1=yes) +// ........ .......x ........ ........ private bit + +const + btable:array [0..1,0..2,0..15] of word = ( + ( //MPEG 2 & 2.5 + (0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0), //Layer III + (0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0), //Layer II + (0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0) //Layer I + ),( //MPEG 1 + (0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,0), //Layer III + (0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384,0), //Layer II + (0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448,0) //Layer I + ) + ); + stable: array [0..3,0..2] of word = ( + (32000, 16000, 8000), //MPEG 2.5 + ( 0, 0, 0), //reserved + (22050, 24000, 16000), //MPEG 2 + (44100, 48000, 32000) //MPEG 1 + ); + +procedure TranslateFrameHdr(const block:array of byte;var MP3FrameHdr:tMP3FrameHdr); +begin + FillChar(MP3FrameHdr,SizeOf(MP3FrameHdr),0); + if block[0]=$FF then + begin + with MP3FrameHdr do + begin + Version :=(block[1] and $18) shr 3; + Layer :=(block[1] and $06) shr 1; + CRC :=not Odd(block[1]); + Bitrate :=btable[Version and 1][Layer-1][block[2] shr 4]; + Samplerate:=stable[Version][(block[2] and $0C) shr 2]; + _Private :=odd(block[2]); + Channel :=block[3] shr 6; + Copyright :=((block[3] and $08) shr 3)<>0; + Original :=((block[3] and $04) shr 2)<>0; + end; + end; +end; + +procedure CheckVBR(f:THANDLE; var hdr:tMP3FrameHdr); +var + pos,apos:cardinal; + sign:longint; + frames:longint; +begin + pos:=FilePos(f); + hdr.Length:=0; + if hdr.Version=3 then + begin + if hdr.Channel=3 then + apos:=17 + else + apos:=32; + end + else if hdr.Channel=3 then + apos:=9 + else + apos:=17; + Skip(f,apos); + BlockRead(f,sign,4); + hdr.isVBR:=sign=$676E6958; //Xing +//calculate length + if hdr.isVBR then + begin + if hdr.Samplerate<>0 then + begin +// Seek(f,pos+36); + BlockRead(f,sign,4); + if (sign and $01000000)<>0 then + begin + BlockRead(f,frames,4); + frames:=BSwap(frames); + hdr.Length:=Round((1152/hdr.Samplerate)*frames/(4-hdr.Version)); //! + end; + end; + end + else if hdr.Bitrate<>0 then + hdr.Length:=((8*(FileSize(f)-(pos-4))) div 1000) div hdr.Bitrate; +end; + +function SearchStart(f:THANDLE; var l:array of byte):Boolean; +var + CurPos:longint; + Buf:array [0..ScanSize] of byte; + i,j:integer; +begin + CurPos:=FilePos(f)-4; + Seek(f,CurPos); + j:=BlockRead(f,Buf,ScanSize); + i:=0; + while i$F0) then + begin + Seek(f,CurPos+i); + BlockRead(f,l,4); + result:=true; + Exit; + end; + inc(i); + end; + result:=false; +end; + +function ReadMP3(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + l:array [0..3] of byte; + hdr:tMP3FrameHdr; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + ReadID3v2(f,Info); + BlockRead(f,l,4); +// if l[0]<>$FF then + if not SearchStart(f,l) then + Exit; + TranslateFrameHdr(l,hdr); + CheckVBR(f,hdr); + Info.kbps :=hdr.Bitrate; + Info.khz :=hdr.Samplerate div 1000; + Info.total:=hdr.Length; + if hdr.Channel=3 then + Info.channels:=1 + else + Info.channels:=2; + Info.vbr:=ord(hdr.isVBR); + + ReadAPEv2(f,Info); + ReadID3v1(f,Info); + CloseHandle(f); + result:=true; +end; + +const + mpgAudio = 1; + mpgVideo = 2; + mpgVersion = 4; + +type + l2b=array [0..3] of byte; + +function ReadDWord(var p:pAnsiChar;endptr:pAnsiChar):integer; +begin + if (p+4)0; + if i=1 then + begin + result:=ReadByte(p,endptr) or $100; + exit; + end; + end; + until p>=endptr; + result:=0; +end; + +const + BufSize = 256*1024; + +function ReadMPG(var Info:tSongInfo):boolean; cdecl; +var + endptr,buf,p:PAnsiChar; + f:THANDLE; + BlockType:integer; + l:dword; + w:word; + b:byte; + flag:integer; + version,layer:integer; +// vbitrate:integer; +// FrmCnt:integer; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + flag:=mpgAudio+mpgVideo+mpgVersion; + + mGetMem(buf,BufSize); + endptr:=buf+BlockRead(f,buf^,BufSize); + CloseHandle(f); + p:=buf; +// FrmCnt:=0; + while (flag<>0) and (p0 then + begin + flag:=flag and not mpgVersion; + if (ReadByte(p,endptr) and $C0)=$40 then + Info.codec:=$3247504D // MPG2 + else + Info.codec:=$4745504D; // MPEG + end; + end; + $1B3: begin // Video + if (flag and mpgVideo)<>0 then + begin + l:=ReadDWord(p,endptr); + flag:=flag and not mpgVideo; + Info.width :=((l2b(l)[1] and $F0) shr 4)+(l2b(l)[0] shl 4); + Info.height:=((l2b(l)[1] and $0F) shl 8)+l2b(l)[2]; + case l2b(l)[3] and $F of + 1: Info.fps:=2397; + 2: Info.fps:=2400; + 3: Info.fps:=2500; + 4: Info.fps:=2997; + 5: Info.fps:=3000; + 6: Info.fps:=5000; + 7: Info.fps:=5994; + 8: Info.fps:=6000; + end; +// BlockRead(f,l,4); +// vbitrate:=(l2b(l)[0] shl 10)+(l2b(l)[1] shl 2)+(l2b(l)[2] shr 6); + end; + end; + 0,$1B7,$1B9: break; +{ + $1E0: begin + BlockRead(f,w,2); + w:=swap(w); + mGetMem(buf,w); + BlockRead(f,buf^,w); + p:=buf; + for l:=0 to w-4 do + begin + if pdword(p)^=$00010000 then + begin + inc(FrmCnt); + inc(p,4); + end + else + inc(p); + end; + mFreeMem(buf); + end; +} + $1C0: begin // audio + w:=swap(ReadWord(p,endptr)); + if flag and mpgAudio<>0 then + begin + flag:=flag and not mpgAudio; + b:=ReadByte(p,endptr); + dec(w); + if (b and $C0)=$80 then + begin + b:=ReadByte(p,endptr); + l:=ReadByte(p,endptr); + dec(w,2); + if (b and $80)<>0 then + begin + inc(p,5); + dec(w,5); + dec(l,5); + if (b and $40)<>0 then + begin + inc(p,5); + dec(w,5); + dec(l,5); + end; + end; + if l>0 then + begin + inc(p,l); + dec(w,l); + end; + end + else + begin + while (b and $80)<>0 do + begin + dec(w); + if w=0 then break; + b:=ReadByte(p,endptr); + end; + if (b and $40)<>0 then + begin + inc(p); + b:=ReadByte(p,endptr); + dec(w,2); + end; + if (b and $20)<>0 then + begin + inc(p,4); + dec(w,4); + if (b and $10)<>0 then + begin + inc(p,5); + dec(w,5); + end; + end; + end; + l:=ReadDWord(p,endptr); + version:=(l2b(l)[1] and $18) shr 3; + layer :=(l2b(l)[1] and $06) shr 1; + Info.kbps :=btable[version and 1][layer-1][l2b(l)[2] shr 4]; + Info.khz :=(stable[version][(l2b(l)[2] and $0C) shr 2]) div 1000; + Info.channels:=l2b(l)[3] shr 6; + if Info.channels=3 then + Info.channels:=1 + else + Info.channels:=2; +// if w>0 then inc(p,w); + end; +// else + inc(p,w); + end; +{ + $1B5: begin + BlockRead(f,l,4); + if (l2b(l)[0] and $F0)=$10 then + begin + vbitrate:=vbitrate+ + ((((l2b(l)[2] and $1F) shl 7)+(l2b(l)[3] shr 1)) shl 18); + end; + end; +} +{ + $1BD: begin + end; +} + $1C1..$1DF, // audio +//?? $1E0, + $1E1..$1EF, // video + $1BB{,$1BD},$1BE,$1BF: begin // system,private,padding,private + inc(p,swap(ReadWord(p,endptr))); + end; + end; + end; +// vbitrate:=(vbitrate*400) div 1000; +// Info.total:=(FrmCnt*100) div Info.fps; + mFreeMem(buf); + result:=true; +end; + +var + LocalFormatLinkMP3, + LocalFormatLinkMPG, + LocalFormatLinkMPEG:twFormat; + +procedure InitLink; +begin + LocalFormatLinkMP3.Next:=FormatLink; + + LocalFormatLinkMP3.This.proc :=@ReadMP3; + LocalFormatLinkMP3.This.ext :='MP3'; + LocalFormatLinkMP3.This.flags:=0; + + FormatLink:=@LocalFormatLinkMP3; + + LocalFormatLinkMPG.Next:=FormatLink; + + LocalFormatLinkMPG.This.proc :=@ReadMPG; + LocalFormatLinkMPG.This.ext :='MPG'; + LocalFormatLinkMPG.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLinkMPG; + + LocalFormatLinkMPEG.Next:=FormatLink; + + LocalFormatLinkMPEG.This.proc :=@ReadMPG; + LocalFormatLinkMPEG.This.ext :='MPEG'; + LocalFormatLinkMPEG.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLinkMPEG; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_mpc.pas b/plugins/Watrack/formats/fmt_mpc.pas new file mode 100644 index 0000000000..7d8671dde6 --- /dev/null +++ b/plugins/Watrack/formats/fmt_mpc.pas @@ -0,0 +1,90 @@ +{MPC file format} +unit fmt_MPC; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadMPC(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,tags,srv_format; + +const + DefID = $002B504D;// 'MP+' + +function ReadMPC(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + tmp:array [0..5] of dword; + samples,TotalFrames:dword; + lastframe:dword; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + ReadID3v2(f,Info); + + BlockRead(f,tmp,SizeOf(tmp)); + if ((tmp[0] and $FFFFFF)=DefID) and + (((tmp[0] shr 24) and $0F)>=7) then // sv7-sv8 + begin + Info.kbps:=0; + if (tmp[2] and 2)<>0 then + Info.channels:=2 + else + Info.channels:=1; + case (tmp[2] and $3000) shr 12 of //C000-14? + 00: Info.khz:=44100; + 01: Info.khz:=48000; + 02: Info.khz:=37800; + 03: Info.khz:=32000; + end; + lastframe:=(tmp[5] and $FFF) shr 1; + samples:=tmp[1]*1152+lastframe; + end + else + begin //4-6 + if not ((tmp[0] and $1FFF) and $3FF) in [4..6] then + exit; + Info.khz:=44100; + Info.kbps:=tmp[1] and $1F; + if ((tmp[0] and $1FFF) and $3FF)=4 then + TotalFrames:=loword(tmp[2]) + else + TotalFrames:=tmp[2]; + samples:=TotalFrames*1152; + end; + + if Info.khz<>0 then + Info.total:=samples div Info.khz; + Info.khz:=Info.khz div 1000; + if (Info.kbps=0) and (samples<>0) then +// if fs=samples*channels*deep/8 then kbps=khz*deep*channels/1152 +// Info.kbps:=(Info.khz*8)*taginfo.FileSize/1152/samples; + + Info.kbps:=(Info.khz div 8)*FileSize(f) div samples; //!! + ReadAPEv2(f,Info); + ReadID3v1(f,Info); + CloseHandle(f); + result:=true; +end; + +var + LocalFormatLink:twFormat; + +procedure InitLink; +begin + LocalFormatLink.Next:=FormatLink; + + LocalFormatLink.This.proc :=@ReadMPC; + LocalFormatLink.This.ext :='MPC'; + LocalFormatLink.This.flags:=0; + + FormatLink:=@LocalFormatLink; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_ofr.pas b/plugins/Watrack/formats/fmt_ofr.pas new file mode 100644 index 0000000000..73d58b68ff --- /dev/null +++ b/plugins/Watrack/formats/fmt_ofr.pas @@ -0,0 +1,74 @@ +{OFR file} +unit fmt_OFR; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadOFR(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,tags,srv_format; + +type + tMain = packed record + ID :dword; // 'OFR ' + Size :dword; //15 + SamplesLo :dword; + SamplesHi :word; + SampleType :byte; + ChannelsMap:byte; + Samplerate :dword; + Encoder :word; + Compression:byte; + end; + +function ReadOFR(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + Hdr:tMain; + Samples:int64; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + ReadID3v2(f,Info); + BlockRead(f,Hdr,SizeOf(Hdr)); + Samples:=Hdr.SamplesLo+Hdr.SamplesHi*$10000; + Info.channels:=Hdr.ChannelsMap+1; + Info.khz :=Hdr.Samplerate div 1000; + Info.total :=(Samples div Info.channels)*Info.khz; + + ReadAPEv2(f,Info); + ReadID3v1(f,Info); + CloseHandle(f); + result:=true; +end; + +var + LocalFormatLinkOFR, + LocalFormatLinkOFS:twFormat; + +procedure InitLink; +begin + LocalFormatLinkOFR.Next:=FormatLink; + + LocalFormatLinkOFR.This.proc :=@ReadOFR; + LocalFormatLinkOFR.This.ext :='OFR'; + LocalFormatLinkOFR.This.flags:=0; + + FormatLink:=@LocalFormatLinkOFR; + + LocalFormatLinkOFS.Next:=FormatLink; + + LocalFormatLinkOFS.This.proc :=@ReadOFR; + LocalFormatLinkOFS.This.ext :='OFS'; + LocalFormatLinkOFS.This.flags:=0; + + FormatLink:=@LocalFormatLinkOFS; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_ogg.pas b/plugins/Watrack/formats/fmt_ogg.pas new file mode 100644 index 0000000000..4b05b80c2c --- /dev/null +++ b/plugins/Watrack/formats/fmt_ogg.pas @@ -0,0 +1,522 @@ +{OGG, SPX and FLAC file formats} +unit fmt_OGG; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadOGG(var Info:tSongInfo):boolean; cdecl; +function ReadSPX(var Info:tSongInfo):boolean; cdecl; +function ReadfLaC(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,tags,srv_format,base64,utils; + +const + OGGSign = $5367674F; //OggS +const + SpeexID = 'Speex '; +type + tSPEXHeader = packed record + speex_string :array [0..7] of AnsiChar; + speex_version :array [0..19] of AnsiChar; + speex_version_id:dword; + header_size :dword; //sizeof(tSPEXHeader) + rate :dword; + mode :dword; + bitstrm_version :dword; + nb_channels :dword; + bitrate :dword; + frame_size :dword; + vbr :dword; + fpp :dword; //frames_per_packet + extra_headers :dword; + reserved1 :dword; + reserved2 :dword; + end; +type + pOGGHdr = ^tOGGHdr; + tOGGHdr = packed record + ID :dword; + Version :byte; + HdrType :byte; + Granule :Int64; // absolute position + BitStrmSN:dword; + PageSeqN :dword; + CRC :dword; + PageSegs :byte; + end; +const + strmOGG = 1; + strmOGM = 2; +const + VideoD = $65646976; + VideoW = $006F; + VorbisD = $62726F76; + VorbisW = $7369; +type + tOGMInfo = packed record + padding :word; // 0 + codec :dword; + size :dword; + time_unit :int64; // 1/10000000 sec + samples_per_unit:int64; // fps = 10000000*spu/time_unit + default_len :dword; // 1 + buffersize :dword; + bit_per_sample :dword; + width :dword; + height :dword; + dummy :dword; // 0 + end; + +//const VorbisStream:array [0..5] of byte = ($76,$6F,$72,$62,$69,$73); // 'vorbis' + +type + tOGGInfo = packed record + version :dword; + Channels :byte; + samplerate:dword; + maxkbps :dword; + nominal :dword; + minkbps :dword; + BlockSizes:byte; + dummy :byte; + end; + +//--------------- fLaC section --------------- +const + fLaCSign = $43614C66; //fLaC +{ +0 : STREAMINFO +1 : PADDING +2 : APPLICATION +3 : SEEKTABLE +4 : VORBIS_COMMENT +5 : CUESHEET +} +type + MetaHdr = packed record + blocktype:byte; + blocklen:array [0..2] of byte; + end; +type + StreamInfo = packed record + MinBlockSize:word; + MaxBlocksize:word; + MinFrameSize:array [0..2] of byte; + MaxFrameSize:array [0..2] of byte; + heap:array [0..7] of byte; + MD5:array [0..15] of byte; + end; + +procedure OGGGetComment(ptr:PAnsiChar;size:integer;var Info:tSongInfo); +var + clen,alen,len,values:dword; + ls:PAnsiChar; + value:PAnsiChar; + cover:pByte; + ext:dword; + extw:int64; + c:AnsiChar; +begin + inc(ptr,pdword(ptr)^+4); //vendor + values:=pdword(ptr)^; inc(ptr,4); + ext:=0; + cover:=nil; + clen:=0; + while values>0 do + begin + len:=pdword(ptr)^; + if len>cardinal(size) then + break; + dec(size,len); + inc(ptr,4); + ls:=ptr; + c:=ls[len]; + ls[len]:=#0; + alen:=StrScan(ls,'=')-ls+1; + if alen>0 then + begin + ls[alen-1]:=#0; + value:=ls+alen; + + if (Info.title =nil) and (lstrcmpia(ls,'TITLE' )=0) then UTF8ToWide(value,Info.title) + else if (Info.artist =nil) and (lstrcmpia(ls,'ARTIST' )=0) then UTF8ToWide(value,Info.artist) + else if (Info.album =nil) and (lstrcmpia(ls,'ALBUM' )=0) then UTF8ToWide(value,Info.album) + else if (Info.genre =nil) and (lstrcmpia(ls,'GENRE' )=0) then UTF8ToWide(value,Info.genre) + else if (Info.year =nil) and (lstrcmpia(ls,'DATE' )=0) then UTF8ToWide(value,Info.year) + else if (Info.comment=nil) and (lstrcmpia(ls,'COMMENT')=0) then UTF8ToWide(value,Info.comment) + else if (Info.lyric =nil) and (lstrcmpia(ls,'LYRICS' )=0) then UTF8ToWide(value,Info.lyric) + + else if (Info.track=0) and (lstrcmpia(ls,'TRACKNUMBER')=0) then Info.track:=StrToInt(value) + + else if (cover=nil) and (lstrcmpia(ls,'COVERART')=0) then clen:=Base64Decode(value,cover) + else if lstrcmpia(ls,'COVERARTMIME')=0 then ext:=GetImageType(nil,value); + end; + dec(values); + inc(ptr,len); + ptr^:=c; + end; + + if cover<>nil then + begin + if ext=0 then + ext:=GetImageType(cover); + if ext<>0 then + begin + FastAnsiToWideBuf(PAnsiChar(@ext),pWideChar(@extw)); + Info.cover:=SaveTemporaryW(cover,clen,PWideChar(@extw)); + end; + mFreeMem(cover); + end; + +end; + +function CalcSize(num:integer;var arr:array of byte):integer; +var + i:integer; +begin + result:=0; + for i:=0 to num-1 do + begin + inc(result,arr[i]); + if arr[i]<$FF then break; + end; +end; + +function ReadSPX(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + OGGHdr:tOGGHdr; + SPXHdr:tSPEXHeader; + buf:array [0..255] of byte; + ptr:PAnsiChar; + size:integer; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + BlockRead(f,OGGHdr,SizeOf(tOGGHdr)); + Skip(f,OGGHdr.PageSegs); + if OGGHdr.ID=OGGSign then + begin + BlockRead(f,SPXHdr,SizeOf(SPXHdr)); + if SPXHdr.speex_string<>SpeexID then + begin + CloseHandle(f); + exit; + end; + Info.khz:=SPXHdr.rate div 1000; + Info.vbr:=SPXHdr.vbr; + if integer(SPXHdr.bitrate)<>-1 then + Info.kbps:=SPXHdr.bitrate div 1000; + + BlockRead(f,OGGHdr,SizeOf(tOGGHdr)); + BlockRead(f,buf,OGGHdr.PageSegs); + size:=CalcSize(OGGHdr.PageSegs,buf); + GetMem(ptr,size+1); + BlockRead(f,ptr^,size); + OGGGetComment(ptr,size,Info); + FreeMem(ptr); + + result:=true; + end; + CloseHandle(f); +end; + +function Compare(const sign:array of byte):integer; +type + conv=packed record + d:dword;w:word; + end; +var + p:^conv; +begin + p:=@sign; + if (p^.d=VideoD) and (p^.w=VideoW) then + result:=strmOGM + else if (p^.d=VorbisD) and (p^.w=VorbisW) then + result:=strmOGG + else + result:=0; +end; + +function ReadOGG(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + OGGHdr:tOGGHdr; + tmp:packed record + paktype:byte; + sign:array [0..5] of byte; + end; + OGGInfo:tOGGInfo; + OGMInfo:tOGMInfo; + fpos:dword; + SPXHdr:tSPEXHeader; + i,j:integer; + DataIndex:integer; + buf:array [0..255] of byte; + fsize:dword; + done:integer; + ptr:PAnsiChar; + size:integer; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + tmp.paktype:=0; + fsize:=FileSize(f); + done:=0; + while (done<>3) and (tmp.paktype<>5) and (FilePos(f)0 then + Info.kbps :=OGGInfo.nominal div 1000; + Info.khz :=OGGInfo.samplerate; + Info.channels:=OGGInfo.Channels; + done:=done or 1; + end; + strmOGM: begin + BlockRead(f,OGMInfo,SizeOf(OGMInfo)); + Info.codec :=OGMInfo.codec; + Info.fps :=round(((10000000*OGMInfo.samples_per_unit) / OGMInfo.time_unit)*100); + Info.width :=OGMInfo.width; + Info.height:=OGMInfo.height; + done:=done or 1; + end; + end; + end + else if tmp.paktype=ORD('S') then //maybe SPX + begin + Seek(f,fpos); + BlockRead(f,SPXHdr,SizeOf(SPXHdr)); + if SPXHdr.speex_string<>SpeexID then + begin + CloseHandle(f); + exit; + end; + Info.khz:=SPXHdr.rate div 1000; + if integer(SPXHdr.bitrate)<>-1 then + Info.kbps:=SPXHdr.bitrate div 1000; + done:=done or 1; + end + else if tmp.paktype=3 then + begin + GetMem(ptr,size+1); + BlockRead(f,ptr^,size); + OGGGetComment(ptr,size,Info); + FreeMem(ptr); + done:=done or 2; + end + else + continue; + result:=true; + end; + end; + end; + // try to get length + DataIndex:=FileSize(f)-10; + for i:=1 to 50 do + begin + dec(DataIndex,SizeOf(buf)-10); + Seek(f,DataIndex); + BlockRead(f,buf,SizeOf(buf)); + { Get number of PCM samples from last Ogg packet header } + j:=SizeOf(buf)-10; + repeat + if pOGGHdr(@buf[j])^.ID=OGGSign then + begin + if j>(SizeOf(buf)-SizeOf(tOGGHdr)) then + begin + Seek(f,DataIndex+j); + BlockRead(f,buf,SizeOf(tOGGHdr)); + j:=0; + end; + if Info.fps>0 then + begin + Info.total:=(pOGGHdr(@buf[j])^.Granule*100) div Info.fps; + end + else if Info.khz<>0 then + Info.total:=pOGGHdr(@buf[j])^.Granule div Info.khz; + break; + end; + dec(j); + until j=0; + if Info.total>0 then break; + end; + Info.khz:=Info.khz div 1000; + CloseHandle(f); +end; + +function ReadfLaC(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + data64:int64; + hdr:MetaHdr; + frm:StreamInfo; + id:dword; + flag:integer; + size:dword; + buf,ptr:PAnsiChar; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + ReadID3v2(f,Info); + BlockRead(f,id,SizeOf(id)); + if id=fLaCSign then + begin + flag:=0; + repeat + BlockRead(f,hdr,SizeOf(hdr)); + size:=hdr.blocklen[2]+(hdr.blocklen[1] shl 8)+(hdr.blocklen[0] shl 16); + case (hdr.blocktype and $7F) of + 0: begin + if flag=0 then + begin + BlockRead(f,frm,SizeOf(frm)); + //samplerate eg.44100 + Info.khz:=((frm.heap[0] shl 12)+(frm.heap[1] shl 4)+(frm.heap[2] shr 4)); + Info.channels:=((frm.heap[2] and $F) shr 1)+1; + //bits per SAMPLE now + Info.kbps:=(frm.heap[2] and 1) shl 4+(frm.heap[3] shr 4)+1; + data64:=((frm.heap[3] and $F) shl 32)+(frm.heap[4] shl 24)+ + (frm.heap[5] shl 16)+(frm.heap[6] shl 8)+frm.heap[7]; + + if (data64<>0) and (Info.khz<>0) then + Info.total:=data64 div Info.khz; + Info.kbps:=Info.kbps*8; +Info.kbps:=trunc(FileSize(f)*8/1000); + Info.khz:=Info.khz div 1000; + flag:=1; + end; + end; + 4: begin + GetMem(buf,size); + BlockRead(f,buf^,size); + OGGGetComment(buf,size,Info); + FreeMem(buf); + end; + 6: begin + if Info.cover=nil then + begin + GetMem(buf,size); + BlockRead(f,buf^,size); + ptr:=buf; + id:=BSwap(pdword(ptr)^); + case id of + 0,3,4,6: begin + inc(ptr,4); + id:=BSwap(pdword(ptr)^); // mime size + inc(ptr,4); + flag:=GetImageType(nil,ptr); + inc(ptr,id+4*5); // width, height, depth etc. + id:=BSwap(pdword(ptr)^); // image size + inc(ptr,4); + if flag=0 then + flag:=GetImageType(pByte(ptr)); + FastAnsiToWideBuf(PAnsiChar(@flag),pWideChar(@data64)); + Info.cover:=SaveTemporaryW(ptr,id,PWideChar(@data64)); + end; + end; + FreeMem(buf); + end + else + Skip(f,size); + end + else + begin + if (hdr.blocktype and $80)<>0 then + break; + Skip(f,size); + end; + end; + until (hdr.blocktype and $80)<>0; + end; + ReadID3v1(f,Info); + CloseHandle(f); + result:=true; +end; + +var + LocalFormatLinkOGG, + LocalFormatLinkOGA, + LocalFormatLinkOGM, + LocalFormatLinkSPX, + LocalFormatLinkFLA, + LocalFormatLinkFLAC:twFormat; + +procedure InitLink; +begin + LocalFormatLinkOGG.Next:=FormatLink; + + LocalFormatLinkOGG.This.proc :=@ReadOGG; + LocalFormatLinkOGG.This.ext :='OGG'; + LocalFormatLinkOGG.This.flags:=0; + + FormatLink:=@LocalFormatLinkOGG; + + LocalFormatLinkOGA.Next:=FormatLink; + + LocalFormatLinkOGA.This.proc :=@ReadOGG; + LocalFormatLinkOGA.This.ext :='OGA'; + LocalFormatLinkOGA.This.flags:=0; + + FormatLink:=@LocalFormatLinkOGA; + + LocalFormatLinkOGM.Next:=FormatLink; + + LocalFormatLinkOGM.This.proc :=@ReadOGG; + LocalFormatLinkOGM.This.ext :='OGM'; + LocalFormatLinkOGM.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLinkOGM; + + LocalFormatLinkSPX.Next:=FormatLink; + + LocalFormatLinkSPX.This.proc :=@ReadSPX; + LocalFormatLinkSPX.This.ext :='SPX'; + LocalFormatLinkSPX.This.flags:=0; + + FormatLink:=@LocalFormatLinkSPX; + + LocalFormatLinkFLA.Next:=FormatLink; + + LocalFormatLinkFLA.This.proc :=@ReadfLaC; + LocalFormatLinkFLA.This.ext :='FLA'; + LocalFormatLinkFLA.This.flags:=0; + + FormatLink:=@LocalFormatLinkFLA; + + LocalFormatLinkFLAC.Next:=FormatLink; + + LocalFormatLinkFLAC.This.proc :=@ReadfLaC; + LocalFormatLinkFLAC.This.ext :='FLAC'; + LocalFormatLinkFLAC.This.flags:=0; + + FormatLink:=@LocalFormatLinkFLAC; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_real.pas b/plugins/Watrack/formats/fmt_real.pas new file mode 100644 index 0000000000..8d5f5bf72d --- /dev/null +++ b/plugins/Watrack/formats/fmt_real.pas @@ -0,0 +1,335 @@ +{Real file} +unit fmt_Real; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadReal(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,tags,srv_format; + +const + blk_RMF = $464D522E; // '.RMF' + blkPROP = $504F5250; // 'PROP' + blkCONT = $544E4F43; // 'CONT' - content + blkMDPR = $5250444D; // 'MDPR' + blkDATA = $41544144; // 'DATA' + blkINDX = $58444E49; // 'INDX' + blkRMMD = $444D4D52; // 'RMMD' - comment block + blkRMJD = $444A4D52; // 'RMJD' + blkRMJE = $454A4D52; // 'RMJE' +type + tChunk = packed record + ID:dword; + Len:dword; //with Chunk; + end; + +type + pPROP = ^tPROP; + tPROP = packed record + w1 :word; + l1,l2 :dword; + l3,l4 :dword; + un1 :dword; // or 2+2 + filetotal :dword; // msec + l5 :dword; + InfoDataSize:dword; + Infosize :dword; + w2 :word; // always 2 ? + w :word; // chunks+1? + end; + +procedure SkipStr(var p:PAnsiChar;alen:integer); +var + len:integer; +begin + if alen=2 then + len:=(ord(p[0]) shl 8)+ord(p[1]) + else + len:=ord(p[0]); + inc(p,alen); +// if len>0 then + inc(p,len); +end; + +function ReadStr(var p:PAnsiChar;alen:integer):PAnsiChar; +var + len:integer; +begin + if alen=2 then + len:=(ord(p[0]) shl 8)+ord(p[1]) + else + len:=ord(p[0]); + inc(p,alen); + if len>0 then + begin + mGetMem(result,len+1); + move(p^,result^,len); + result[len]:=#0; + inc(p,len); + end + else + result:=nil; +end; + +function GetWord(var p:PAnsiChar):word; +begin + result:=(ord(p[0]) shl 8)+ord(p[1]); + inc(p,2); +end; + +function GetLong(var p:PAnsiChar):dword; +begin + result:=(ord(p[0]) shl 24)+(ord(p[1]) shl 16)+(ord(p[2]) shl 8)+ord(p[3]); + inc(p,4); +end; + +function ReadReal(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + chunk:tChunk; + p,buf:PAnsiChar; + ls:PAnsiChar; + ver:integer; + fsize:cardinal; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + fsize:=FileSize(f); + while FilePos(f)SizeOf(chunk) then // channels-1: ofs=$0A + break; + Skip(f,chunk.Len-SizeOf(chunk)); + end; + end; + ReadID3v1(f,Info); + CloseHandle(f); + result:=true; +end; + +var + LocalFormatLinkRM, + LocalFormatLinkRA, + LocalFormatLinkRAM:twFormat; + +procedure InitLink; +begin + LocalFormatLinkRM.Next:=FormatLink; + + LocalFormatLinkRM.This.proc :=@ReadReal; + LocalFormatLinkRM.This.ext :='RM'; + LocalFormatLinkRM.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLinkRM; + + LocalFormatLinkRA.Next:=FormatLink; + + LocalFormatLinkRA.This.proc :=@ReadReal; + LocalFormatLinkRA.This.ext :='RA'; + LocalFormatLinkRA.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLinkRA; + + LocalFormatLinkRAM.Next:=FormatLink; + + LocalFormatLinkRAM.This.proc :=@ReadReal; + LocalFormatLinkRAM.This.ext :='RAM'; + LocalFormatLinkRAM.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLinkRAM; +end; + +initialization + InitLink; + +end. diff --git a/plugins/Watrack/formats/fmt_tta.pas b/plugins/Watrack/formats/fmt_tta.pas new file mode 100644 index 0000000000..c13b329fe2 --- /dev/null +++ b/plugins/Watrack/formats/fmt_tta.pas @@ -0,0 +1,65 @@ +{TTA file} +unit fmt_TTA; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadTTA(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,tags,srv_format; + +const + TTA1_SIGN = $31415454; +type + tTTAHeader = packed record + id :dword; + format :word; + channels :word; + bitspersample:word; + samplerate :dword; + datalength :dword; + crc32 :dword; + end; + +function ReadTTA(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + hdr:tTTAHeader; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + ReadID3v2(f,Info); + BlockRead(f,hdr,SizeOf(tTTAHeader)); + if hdr.id<>TTA1_SIGN then + exit; + Info.channels:=hdr.channels; + Info.khz :=hdr.samplerate; + Info.kbps :=hdr.bitspersample div 1000; //!! + if hdr.samplerate<>0 then + Info.total:=hdr.datalength div hdr.samplerate; + ReadID3v1(f,Info); + CloseHandle(f); + result:=true; +end; + +var + LocalFormatLink:twFormat; + +procedure InitLink; +begin + LocalFormatLink.Next:=FormatLink; + + LocalFormatLink.This.proc :=@ReadTTA; + LocalFormatLink.This.ext :='TTA'; + LocalFormatLink.This.flags:=0; + + FormatLink:=@LocalFormatLink; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_wav.pas b/plugins/Watrack/formats/fmt_wav.pas new file mode 100644 index 0000000000..98d8e18fb8 --- /dev/null +++ b/plugins/Watrack/formats/fmt_wav.pas @@ -0,0 +1,146 @@ +{WAV processing} +unit fmt_WAV; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadWAV(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,tags,srv_format; + +const + wavRIFF = $46464952; + wavWAVE = $45564157; + wavfmt_ = $20746D66; + wavfact = $74636166; + wavdata = $61746164; +type + tWAVChunk = packed record + id :dword; + size:dword; + end; +type + tWAVFormatChunk = packed record + Codec :word; + Channels :word; + SampleRate :dword; + AvgBPS :dword; + BlockAlign :word; + BitsPerSample:word; + end; + +const + WavPackID = $6B707677; +type +// ckID :dword; // "wvpk" +// ckSize :dword; // size of entire frame (minus 8, of course) + tWavPackHeader = packed record + version :word; // 0x403 for now + track_no :byte; // track number (0 if not used, like now) + index_no :byte; // track sub-index (0 if not used, like now) + total_samples:dword; // for entire file (-1 if unknown) + block_index :dword; // index of first sample in block (to file begin) + block_samples:dword; // # samples in This block + flags :dword; // various flags for id and decoding + crc :dword; // crc for actual decoded data + end; + +function ReadWAV(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + chunk:tWAVChunk; + fmtchunk:tWAVFormatChunk; + tmp:dword; + WPH:tWavPackHeader; + fsize:dword; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + BlockRead(f,chunk,SizeOf(chunk)); + if chunk.id=WavPackID then + begin + BlockRead(f,WPH,SizeOf(tWavPackHeader)); + BlockRead(f,tmp,2); //!! $1621 33,22 + BlockRead(f,chunk,SizeOf(chunk)); + end + else + begin + WPH.version:=0; + integer(WPH.total_samples):=-1; + end; + if chunk.id<>wavRIFF then + exit; + BlockRead(f,chunk,SizeOf(dword)); + if chunk.id<>wavWAVE then + exit; + BlockRead(f,chunk,SizeOf(chunk)); + if chunk.id<>wavfmt_ then + exit; + BlockRead(f,fmtchunk,SizeOf(tWAVFormatChunk)); + Info.channels:=fmtchunk.Channels; + Info.khz :=fmtchunk.SampleRate div 1000; + if chunk.size>SizeOf(tWAVFormatChunk) then + Skip(f,chunk.size-SizeOf(tWAVFormatChunk)); + fsize:=FileSize(f); + while FilePos(f)0 then + begin + ReadAPEv2(f,Info); + ReadID3v1(f,Info); + end; + if integer(WPH.total_samples)=-1 then + if (fmtchunk.BitsPerSample<>0) and (fmtchunk.Channels<>0) then + WPH.total_samples:=(tmp*8) div (fmtchunk.Channels*fmtchunk.BitsPerSample); + if fmtchunk.SampleRate<>0 then + Info.total:= WPH.total_samples div fmtchunk.SampleRate; + if Info.total<>0 then + Info.kbps:=tmp*8 div Info.total div 1000; + + CloseHandle(f); + result:=true; +end; + +var + LocalFormatLinkWAV, + LocalFormatLinkWV:twFormat; + +procedure InitLink; +begin + LocalFormatLinkWAV.Next:=FormatLink; + + LocalFormatLinkWAV.This.proc :=@ReadWAV; + LocalFormatLinkWAV.This.ext :='WAV'; + LocalFormatLinkWAV.This.flags:=0; + + FormatLink:=@LocalFormatLinkWAV; + + LocalFormatLinkWV.Next:=FormatLink; + + LocalFormatLinkWV.This.proc :=@ReadWAV; + LocalFormatLinkWV.This.ext :='WV'; + LocalFormatLinkWV.This.flags:=0; + + FormatLink:=@LocalFormatLinkWV; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/fmt_wma.pas b/plugins/Watrack/formats/fmt_wma.pas new file mode 100644 index 0000000000..ed575147ac --- /dev/null +++ b/plugins/Watrack/formats/fmt_wma.pas @@ -0,0 +1,438 @@ +{WMA file format} +unit fmt_WMA; +{$include compilers.inc} + +interface +uses wat_api; + +function ReadWMA(var Info:tSongInfo):boolean; cdecl; + +implementation +uses windows,common,io,srv_format,utils; + +const + ASF_Header_Object :tGUID='{75B22630-668E-11CF-A6D9-00AA0062CE6C}'; + + ASF_Header_Extension_Object :tGUID='{5FBF03B5-A92E-11CF-8EE3-00C00C205365}'; + ASF_Content_Description_Object :tGUID='{75B22633-668E-11CF-A6D9-00AA0062CE6C}'; + ASF_Extended_Content_Description_Object:tGUID='{D2D0A440-E307-11D2-97F0-00A0C95EA850}'; + ASF_File_Properties_Object :tGUID='{8CABDCA1-A947-11CF-8EE4-00C00C205365}'; + ASF_Stream_Properties_Object :tGUID='{B7DC0791-A9B7-11CF-8EE6-00C00C205365}'; + + ASF_Metadata_Library_Object :tGUID='{44231C94-9498-49D1-A141-1D134E457054}'; + ASF_Audio_Media :tGUID='{F8699E40-5B4D-11CF-A8FD-00805F5C442B}'; + ASF_Video_Media :tGUID='{BC19EFC0-5B4D-11CF-A8FD-00805F5C442B}'; + +type + tSize=Int64; + +function CompareGUID(const guid1,guid2:tGUID):boolean; +var + i:integer; + p1,p2:PAnsiChar; +begin + p1:=PAnsiChar(@guid1); + p2:=PAnsiChar(@guid2); + for i:=0 to 15 do + begin + if p1^<>p2^ then + begin + result:=false; + exit; + end; + inc(p1); + inc(p2); + end; + result:=true; +end; + +function ReadGUID(var buf:PAnsiChar; var guid:pGUID):dword; +var + size:tSize; +begin + guid:=pointer(buf); + inc(buf,SizeOf(tGUID)); + move(buf^,size,SizeOf(size)); + inc(buf,SizeOf(size)); + result:=size-SizeOf(tGUID)-SizeOf(size); +end; + +procedure ReadWMATagStr(var dst:pWideChar;ptr:PAnsiChar;alen:word); +begin + if pword(ptr)^<>0 then + begin + mGetMem(dst,alen); + move(pWideChar(ptr{+2})^,dst^,alen); + end; +end; + +function ReadWMATagStr1(var dst:pWideChar;var ptr:PAnsiChar;value:boolean=true):integer; +var + len,typ:word; +begin + if value then + begin + typ:=pword(ptr)^; + inc(ptr,2); //value type + end + else + typ:=0; + len:=pword(ptr)^; + result:=-1; + dst:=nil; + if len<>0 then + begin + if typ=0 then + begin + mGetMem(dst,len); + move(PAnsiChar(ptr+2)^,PAnsiChar(dst)^,len); + end + else + begin + result:=pword(ptr+2)^; + if typ<5 then + result:=pword(ptr+4)^*$10000+result; + end; + end; + inc(ptr,len+2); +end; + +procedure ProcessPicture(ptr:PAnsiChar;var Info:tSongInfo); +var + extw:int64; + aSize:dword; +begin + if Info.cover<>nil then exit; + case ptr^ of + #0,#3,#4,#6: ; + else + exit; + end; + inc(ptr); + aSize:=pdword(ptr)^; inc(ptr,4); + extw:=GetImageTypeW(nil,pWideChar(ptr)); + while pWideChar(ptr)^<>#0 do inc(ptr,2); inc(ptr,2); // mime + while pWideChar(ptr)^<>#0 do inc(ptr,2); inc(ptr,2); // descr + + if extw=0 then + extw:=GetImageTypeW(pByte(ptr)); + Info.cover:=SaveTemporaryW(ptr,aSize,pWideChar(@extw)); +end; + +procedure ReadHdrExtended(ptr:PAnsiChar;size:dword;var Info:tSongInfo); +var + buf:PAnsiChar; + ls:pWideChar; + cnt,tmp:integer; + tmpguid:pGUID; + lsize:dword; +begin + inc(ptr,SizeOf(tGUID)+2); + size:=pdword(ptr)^; inc(ptr,4); + while size>0 do + begin + if Info.cover<>nil then break; + lsize:=ReadGUID(ptr,tmpguid); + dec(size,lsize+SizeOf(tGUID)+SizeOf(tSize)); + if CompareGUID(tmpguid^,ASF_Metadata_Library_Object) then + begin + buf:=ptr; + cnt:=pdword(buf)^; inc(buf,2); + while cnt>0 do + begin + inc(buf,4); // lang & stream + {tmp:=pword (buf)^;} inc(buf,2); // namelen + {tmp:=pword (buf)^;} inc(buf,2); // datatype + tmp:=pdword(buf)^; inc(buf,4); // datalen + ls:=PWideChar(buf); + while pWideChar(buf)^<>#0 do inc(buf,2); inc(buf,2); + if lstrcmpiw(ls,'WM/Picture')=0 then + begin + ProcessPicture(buf,Info); + inc(buf,tmp); + end; + dec(cnt); + end; + end; + inc(ptr,lsize); + end; +end; + +procedure ReadExtended(ptr:PAnsiChar;size:dword;var Info:tSongInfo); +var + ls,ls1,ls2:pWideChar; + cnt,tmp:integer; +begin + cnt:=pword(ptr)^; inc(ptr,2); + while cnt>0 do + begin + dec(cnt); + ReadWMATagStr1(ls,ptr,false); + if lstrcmpiw(ls,'WM/AlbumTitle')=0 then + ReadWMATagStr1(Info.album,ptr) + else if (Info.lyric=nil) and (lstrcmpiw(ls,'WM/Lyrics')=0) then + ReadWMATagStr1(Info.lyric,ptr) + else if (Info.lyric=nil) and (lstrcmpiw(ls,'WM/Lyrics_Synchronised')=0) then + begin + inc(ptr,2+2); + inc(ptr); // timestamp type + if ptr^=#1 then // lyric + begin + inc(ptr); + tmp:=pdword(ptr)^; inc(ptr,4); + mGetMem(ls2,tmp); + Info.lyric:=ls2; + ls1:=pWideChar(ptr); + inc(ptr,tmp); + while ls1^<>#0 do // description + begin + inc(ls1); + dec(tmp,SizeOf(WideChar)); + end; + inc(ls1); + dec(tmp,SizeOf(WideChar)); + while tmp>0 do + begin + if PAnsiChar(ls1)^=#$0A then + begin + inc(PAnsiChar(ls1)); + ls2^:=#$0A; + dec(tmp); + inc(ls2); + end; + while ls1^<>#0 do + begin + ls2^:=ls1^; inc(ls2); inc(ls1); + dec(tmp,SizeOf(WideChar)); + end; + inc(ls1,1+2); // terminator + timestamp + dec(tmp,SizeOf(WideChar)+4); + end; + ls2^:=#0; +// ptr:=PAnsiChar(ls1); + end + end + else if lstrcmpiw(ls,'WM/Genre')=0 then + ReadWMATagStr1(Info.genre,ptr) + else if lstrcmpiw(ls,'WM/Year')=0 then + begin + tmp:=ReadWMATagStr1(Info.year,ptr); + if tmp<>-1 then + IntToStr(Info.year,tmp); + end + else if lstrcmpiw(ls,'WM/Track')=0 then + begin + tmp:=ReadWMATagStr1(ls1,ptr); + if tmp=-1 then + begin + Info.track:=StrToInt(ls1)+1; + mFreeMem(ls1); + end + else + Info.track:=tmp; + end + else if lstrcmpiw(ls,'WM/TrackNumber')=0 then + begin + tmp:=ReadWMATagStr1(ls1,ptr); + if tmp=-1 then + begin + Info.track:=StrToInt(ls1); + mFreeMem(ls1); + end + else + Info.track:=tmp; + end + else if lstrcmpiw(ls,'WM/Picture')=0 then + begin + inc(ptr,2); // data type + tmp:=pword(ptr)^; inc(ptr,2); + ProcessPicture(ptr,Info); + inc(ptr,tmp); + end + else + inc(ptr,4+pword(ptr+2)^); + mFreeMem(ls); + end; +end; + +procedure ReadFileProp(ptr:PAnsiChar;var Info:tSongInfo); +type + pFileProp = ^tFileProp; + tFileProp = packed record + FileGUID :tGUID; + FileSize :tSize; + Creation :tSize; + Packets :tSize; + Play :tSize; + Send :tSize; + PreRoll :tSize; + Flags :dword; + minpacket :dword; + maxpacket :dword; + maxbitrate:dword; + end; +begin + Info.total:=pFileProp(ptr)^.Play div 10000000; +end; + +procedure ReadStreamProp(ptr:PAnsiChar;size:dword;var Info:tSongInfo); +type + pAudio = ^tAudio; + tAudio=packed record // WAVEFORMATEX + Codec :word; + Channels :word; + Samples :dword; + AvgBPS :dword; + BlockAlign :word; + BitsPerSample:word; + size :word; + end; + pVideo = ^tVideo; + tVideo = packed record + width :dword; + height :dword; + reserved:byte; + size :word; + bitmap :BITMAPINFOHEADER; + end; + Prefix = packed record + StreamType :tGUID; + ECGUID :tGUID; // Error Correction + TimeOffset :int64; + DataLength :dword; + ECDataLength:dword; + Flags :word; + Reserved :dword; + end; + +var + tmpguid:pGUID; +begin + tmpguid:=pointer(ptr); + inc(ptr,SizeOf(Prefix)); //ofset to Type-Specific Data + if CompareGUID(tmpguid^,ASF_Audio_Media) then + begin + Info.channels:=pAudio(ptr)^.Channels; + Info.khz :=pAudio(ptr)^.Samples div 1000; + Info.kbps :=(pAudio(ptr)^.AvgBPS*8) div 1000; + end + else if CompareGUID(tmpguid^,ASF_Video_Media) then + begin + Info.width :=pVideo(ptr)^.bitmap.biWidth; // pVideo(ptr)^.width + Info.height:=pVideo(ptr)^.bitmap.biHeight; // pVideo(ptr)^.height + Info.codec :=pVideo(ptr)^.bitmap.biCompression; + end +end; + +procedure ReadContent(ptr:PAnsiChar;var Info:tSongInfo); +type + pContent = ^tContent; + tContent = packed record + TitleLength :word; + AuthorLength :word; + CopyrightLength :word; + DescriptionLength:word; + RatingLength :word; + end; +var + cont:pContent; +begin + cont:=pointer(ptr); + inc(ptr,SizeOf(tContent)); + if cont^.TitleLength>0 then //title + begin + ReadWMATagStr(Info.title,ptr,cont^.TitleLength); + inc(ptr,cont^.TitleLength); + end; + if cont^.AuthorLength>0 then //artist + begin + ReadWMATagStr(Info.artist,ptr,cont^.AuthorLength); + inc(ptr,cont^.AuthorLength); + end; + inc(ptr,cont^.CopyrightLength); //copyright + if cont^.DescriptionLength>0 then //comment + ReadWMATagStr(Info.comment,ptr,cont^.DescriptionLength); +end; + +function ReadWMA(var Info:tSongInfo):boolean; cdecl; +var + f:THANDLE; + tmpguid:pGUID; + size:int64; + buf1,buf2:PAnsiChar; + HdrObjects:dword; + base:tGUID; +begin + result:=false; + f:=Reset(Info.mfile); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + + BlockRead(f,base,SizeOf(tGUID)); + if CompareGUID(base,ASF_Header_Object) then + begin + BlockRead(f,size,SizeOf(size)); + dec(size,SizeOf(tGUID)+SizeOf(size)); + + GetMem(buf1,size); + buf2:=buf1; + BlockRead(f,buf1^,size); + HdrObjects:=pdword(buf2)^; inc(buf2,6); + while HdrObjects>0 do + begin + size:=ReadGUID(buf2,tmpguid); + if CompareGUID(tmpguid^,ASF_Content_Description_Object) then + ReadContent(buf2,Info) + else if CompareGUID(tmpguid^,ASF_Extended_Content_Description_Object) then + ReadExtended(buf2,size,Info) + else if CompareGUID(tmpguid^,ASF_Header_Extension_Object) then + ReadHdrExtended(buf2,size,Info) + else if CompareGUID(tmpguid^,ASF_File_Properties_Object) then + ReadFileProp(buf2,Info) + else if CompareGUID(tmpguid^,ASF_Stream_Properties_Object) then + ReadStreamProp(buf2,size,Info); + inc(buf2,size); + dec(HdrObjects); + end; + FreeMem(buf1); + + result:=true; + end; + CloseHandle(f); +end; + +var + LocalFormatLinkWMA, + LocalFormatLinkWMV, + LocalFormatLinkASF:twFormat; + +procedure InitLink; +begin + LocalFormatLinkWMA.Next:=FormatLink; + + LocalFormatLinkWMA.This.proc :=@ReadWMA; + LocalFormatLinkWMA.This.ext :='WMA'; + LocalFormatLinkWMA.This.flags:=0; + + FormatLink:=@LocalFormatLinkWMA; + + LocalFormatLinkWMV.Next:=FormatLink; + + LocalFormatLinkWMV.This.proc :=@ReadWMA; + LocalFormatLinkWMV.This.ext :='WMV'; + LocalFormatLinkWMV.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLinkWMV; + + LocalFormatLinkASF.Next:=FormatLink; + + LocalFormatLinkASF.This.proc :=@ReadWMA; + LocalFormatLinkASF.This.ext :='ASF'; + LocalFormatLinkASF.This.flags:=WAT_OPT_VIDEO; + + FormatLink:=@LocalFormatLinkASF; +end; + +initialization + InitLink; +end. diff --git a/plugins/Watrack/formats/tag_apev2.inc b/plugins/Watrack/formats/tag_apev2.inc new file mode 100644 index 0000000000..34ab7f2ad7 --- /dev/null +++ b/plugins/Watrack/formats/tag_apev2.inc @@ -0,0 +1,124 @@ +{APE tag} +{$IFDEF Interface} +function ReadAPEv2(buf:PAnsiChar;var Info:tSongInfo;count:integer=0):longint; overload; +function ReadAPEv2(f:THANDLE;var Info:tSongInfo):longint; overload; +{$ELSE} +const + APESign = 'APETAGEX'; +type + pAPEHeader = ^tAPEHeader; + tAPEHeader = packed record + ID:array [0..7] of AnsiChar; + Version:dword; + TagSize:dword; //footer + all items + ItemCount:dword; + TagFlags:dword; + Reserved:array [0..7] of byte; + end; + +procedure ReadAPEValue(const buf:PAnsiChar;var dst:pWideChar;ver:dword); +begin + if dst=nil then + if ver>1000 then + UTF8ToWide(buf,dst) + else + AnsiToWide(buf,dst); +end; + +function ReadAPEv2(buf:PAnsiChar;var Info:tSongInfo;count:integer=0):longint; +var + APE:pAPEHeader; + len:integer; + ptr,key:PAnsiChar; + flag:dword; + cf:THANDLE; + buf0,buf1:array [0..MAX_PATH-1] of AnsiChar; + b:AnsiChar; +// extw:array [0..7] of WideChar; +begin + result:=0; + APE:=pointer(buf); + if APE.ID=APESign then + begin + inc(buf,SizeOf(tAPEHeader)); + count:=APE.ItemCount; + end; + while count>0 do + begin + len :=pdword(buf)^; inc(buf,4); + flag:=pdword(buf)^; inc(buf,4); + key:=buf; + while buf^<>#0 do inc(buf); inc(buf); + + ptr:=buf+len; + b:=ptr^; + ptr^:=#0; + if lstrcmpia(key,'TITLE' )=0 then ReadAPEValue(buf,Info.title ,APE.Version) + else if lstrcmpia(key,'ARTIST' )=0 then ReadAPEValue(buf,Info.artist ,APE.Version) + else if lstrcmpia(key,'ALBUM' )=0 then ReadAPEValue(buf,Info.album ,APE.Version) + else if lstrcmpia(key,'COMMENT')=0 then ReadAPEValue(buf,Info.comment,APE.Version) + else if lstrcmpia(key,'GENRE' )=0 then ReadAPEValue(buf,Info.genre ,APE.Version) + else if lstrcmpia(key,'YEAR' )=0 then ReadAPEValue(buf,Info.year ,APE.Version) + else if lstrcmpia(key,'TRACK' )=0 then if Info.track=0 then Info.track:=StrToInt(buf) + else if lstrcmpia(key,'LYRICS' )=0 then ReadAPEValue(buf,Info.lyric ,APE.Version) + //!! must preserve multipart lyric + else if (lstrcmpia(key,'Cover Art (Front)')=0) or + (lstrcmpia(key,'Cover Art (Back)' )=0) or + (lstrcmpia(key,'APIC' )=0) then + begin + if Info.cover=nil then + begin + while buf^<>#0 do inc(buf); inc(buf); // point to data now + flag:=GetImageType(pByte(buf)); + if flag<>0 then + begin +{ + FastAnsiToWideBuf(PAnsiChar(@flag),pWideChar(@extw)); + Info.Cover:=SaveTemporaryW(buf,ptr-buf,PWideChar(@extw)); +} + GetTempPathA(SizeOf(buf0),buf0); + GetTempFileNameA(buf0,'wat',GetCurrentTime,buf1); + ChangeExt(buf1,PAnsiChar(@flag)); + + cf:=ReWrite(PAnsiChar(@buf1)); + BlockWrite(cf,buf^,ptr-buf); + CloseHandle(cf); + AnsiToWide(PAnsiChar(@buf1),Info.cover); + end; + end; + end; + ptr^:=b; + buf:=ptr; + dec(count); + end; +end; + +function ReadAPEv2(f:THANDLE;var Info:tSongInfo):longint; +var + APE:tAPEHeader; + buf:PAnsiChar; + fpos:dword; + TagID:array [1..3] of AnsiChar; +begin + result:=0; + fpos:=FileSize(f); + Seek(f,fpos-SizeOf(TID3v1Tag)); + BlockRead(f,TagID,3); + if TagID=TAG1Sign then + dec(fpos,SizeOf(TID3v1Tag)); + Seek(f,fpos-SizeOf(APE)); + BlockRead(f,APE,SizeOf(APE)); + // footer must be copied as header + if APE.ID=APESign then + begin + if (APE.TagFlags and $20000000)=0 then //Footer + begin + Seek(f,fpos-APE.TagSize{-SizeOf(APE)});// without header but with footer + GetMem(buf,APE.TagSize); + BlockRead(f,buf^,APE.TagSize); + result:=ReadAPEv2(buf,Info,APE.ItemCount); + FreeMem(buf); + end; + end; +end; +{$ENDIF} diff --git a/plugins/Watrack/formats/tag_id3v1.inc b/plugins/Watrack/formats/tag_id3v1.inc new file mode 100644 index 0000000000..bd1db906bb --- /dev/null +++ b/plugins/Watrack/formats/tag_id3v1.inc @@ -0,0 +1,175 @@ +{ID3v1 tag} +{$IFDEF Interface} +const + TAG1Sign = 'TAG'; +type + TID3v1Tag = packed record + ID: array [0..2] of AnsiChar; + Title: array [0..29] of AnsiChar; + Artist: array [0..29] of AnsiChar; + Album: array [0..29] of AnsiChar; + Year: array [0..3] of AnsiChar; + Comment: array [0..28] of AnsiChar; + Track: byte; + Genre: byte; + end; + +function ReadID3v1(f:THANDLE; var Info:tSongInfo):longint; +{$ELSE} +const + Lyric1End = 'LYRICSEND'; + LyricStart = 'LYRICSBEGIN'; + Lyric2End = 'LYRICS200'; + LyricEndLen = Length(Lyric1End); +const + fIND = $494E44; + fLYR = $4C5952; + fEAL = $45414C; + fEAR = $454152; + fETT = $455454; + fIMG = $494D47; + fINF = $494E46; + +procedure ID3v1_TagCorrect(var dst:pWideChar;const tag:array of AnsiChar); +var + i:integer; + s:array [0..31] of AnsiChar; +begin + i:=High(tag); + move(tag,s,i+1); + while (i>0) and (tag[i]<=' ') do dec(i); + if i>0 then + begin + s[i+1]:=#0; + AnsiToWide(s,dst); + end; +end; + +procedure ID3v1_GetField(ptr:PAnsiChar; var dst:pWideChar; len:integer); +var + txtfield:array [0..250] of AnsiChar; +begin + if dst=nil then + begin + move(ptr^,txtfield,len); + txtfield[len]:=#0; + AnsiToWide(txtfield,dst); + end; +end; + +procedure ID3v1_CheckLyric(var Info:tSongInfo;f:THANDLE;ofs:integer); +const + maxlen = 5100; +var + tagHdr:array [0..9] of AnsiChar; + buf:array [0..maxlen] of AnsiChar; + ptr,ptr1:PAnsiChar; + i,size:integer; + field:dword; + c:dword; +begin + Seek(f,ofs); + BlockRead(f,tagHdr,LyricEndLen); + tagHdr[9]:=#0; + if StrCmp(tagHdr,Lyric1End,LyricEndLen)=0 then + begin + if Info.lyric=nil then + begin + Seek(f,ofs-maxlen); + BlockRead(f,buf,maxlen); + buf[maxlen]:=#0; + ptr:=@buf; + for i:=0 to maxlen-Length(LyricStart) do + begin + if ptr^='L' then + if StrCmp(ptr,LyricStart,Length(LyricStart))=0 then + begin + AnsiToWide(ptr+Length(LyricStart),Info.lyric); + break; + end; + inc(ptr); + end; + end; + end + else if StrCmp(tagHdr,Lyric2End,LyricEndLen)=0 then + begin + Seek(f,ofs-6); + BlockRead(f,buf,6); + size:=StrToInt(buf); + if size=32 then Info.track:=0; + end; + dec(ofs,9); + result:=1; + end + else + inc(ofs,SizeOf(tag)-9); + ID3v1_CheckLyric(Info,f,ofs); // +skipAPEtag +end; +{$ENDIF} diff --git a/plugins/Watrack/formats/tag_id3v2.inc b/plugins/Watrack/formats/tag_id3v2.inc new file mode 100644 index 0000000000..b1f833ea2a --- /dev/null +++ b/plugins/Watrack/formats/tag_id3v2.inc @@ -0,0 +1,545 @@ +{ID3v2 tag} + +{$IFDEF Interface} +function ReadID3v2(f:THANDLE; var Info:tSongInfo):longint; +{$ELSE} +const + frmTRK = $4B5254; + frmTT2 = $325454; + frmTP1 = $315054; + frmTAL = $4C4154; + frmTYE = $455954; + frmCOM = $4D4F43; + frmTCO = $4F4354; +// frmTCM = $;'; New: 'TCOM'), +// frmTEN = $;'; New: 'TENC'), +// frmTCR = $;'; New: 'TCOP'), +// frmWXX = $;'; New: 'WXXX'), + frmTT1 = $315454; +// frmTLA = $;'; New: 'TLAN'), + frmTOA = $414F54; + frmULT = $544C55; + frmSLT = $544C53; + frmTXX = $585854; + frmPIC = $434950; + + frmTIT1 = $31544954; // Content group description + frmTIT2 = $32544954; // Title/songname/content description + frmTIT3 = $33544954; // Subtitle/Description refinement + frmTALB = $424C4154; // Album/Movie/Show title + frmTOAL = $4C414F54; // Original album/movie/show title + frmTRCK = $4B435254; // Track number/Position in set + frmTYER = $52455954; // Year + frmTDRC = $43524454; // Year + frmTORY = $59524F54; // Original release year + frmTPE1 = $31455054; // Lead performer(s)/Soloist(s) + frmTPE2 = $32455054; // Band/orchestra/accompaniment + frmTPE3 = $33455054; // Conductor/performer refinement + frmTPE4 = $34455054; // Interpreted, remixed, or otherwise modified by + frmTOPE = $45504F54; // Original artist(s)/performer(s) + frmTCON = $4E4F4354; // Content type + frmCOMM = $4D4D4F43; // Comments + frmUSLT = $544C5355; // Unsynchronised lyrics + frmSYLT = $544C5953; // Synchronised lyrics + frmTXXX = $58585854; // User defined text + frmAPIC = $43495041; // Attached picture +const + TAG2Sign = 'ID3'; +const + ExtIDHdrMask=$40; + FooterPresent=$10; +type + TID3v2TagHdr = packed record + ID :array [0..2] of AnsiChar; + Version:word; + Flags :byte; + TagSize:dword; + end; + PID3v2TagHdr = ^TID3v2TagHdr; +type + tID3v2FrameHdr = packed record + ID:dword; + Size:dword; + Flags:word; + end; + pID3v2FrameHdr = ^tID3v2FrameHdr; + tID3v2FrameHdrOld = packed record + ID : array [0..2] of byte; { Frame ID } + Size: array [0..2] of Byte; { Size excluding header } + end; + pID3v2FrameHdrOld = ^tID3v2FrameHdrOld; + +var + Unsync:boolean; + +function ID3v2_Correct(data:dword):dword; +type + l2b=packed record + b:array [0..3] of byte; + end; +begin + result:=l2b(data).b[3]; + inc(result,dword(l2b(data).b[0]) shl 21); + inc(result,dword(l2b(data).b[1]) shl 14); + inc(result,dword(l2b(data).b[2]) shl 7); +end; + +procedure ID3v2_ReadTagStr1(var dst:PWideChar;ptr:PAnsiChar;alen:integer;enc:integer); +var + buf:PAnsiChar; +begin + if (enc=0) or (enc=3) then // ANSI or UTF8 + begin + if ptr^=#0 then + alen:=0 + else + while (alen>0) and (ptr[alen-1]=#0) do dec(alen); + + if alen>0 then + begin +{ + if enc=0 then + begin + StrDup(buf,ptr,alen); + AnsiToWide(buf,dst) + mFreeMem(buf); + end + else + UTF8ToWide(buf,dst,alen); +} + StrDup(buf,ptr,alen); + if enc=0 then + AnsiToWide(buf,dst) + else + UTF8ToWide(buf,dst); + mFreeMem(buf); + end + end + else {if enc<3 then} //Unicode + begin + if pword(ptr)^>0 then + begin + alen:=alen div SizeOf(WideChar); + + StrDupW(dst,pWideChar(ptr),alen); + ChangeUnicode(dst); + end; + end; +end; + +procedure ID3v2_ReadTagStr(var dst:PWideChar;ptr:PAnsiChar;alen:integer); +var + enc:byte; +begin + enc:=ORD(ptr^); + inc(ptr); + dec(alen); + if alen>0 then + ID3v2_ReadTagStr1(dst,ptr,alen,enc) + else + dst:=nil; +end; + +procedure ID3v2_CheckLyric(tag:integer; var dst:PWideChar;ptr:PAnsiChar;len:integer); +var + org,org1:PAnsiChar; + orgw,ptrw:pWideChar; + buf:array [0..127] of AnsiChar; + enc:byte; +begin + if dst<>NIL then exit; + enc:=ord(ptr^); + inc(ptr); + if tag=frmUSLT then + begin + org:=ptr; + inc(ptr,3); // language + if (enc=0) or (enc=3) then + begin + while ptr^<>#0 do inc(ptr); + inc(ptr); + end + else + begin + while pWord(ptr)^<>0 do inc(ptr,2); + inc(ptr,2); + end; + dec(len,ptr-org); + ID3v2_ReadTagStr1(dst,ptr,len,enc); + end + else if tag=frmSYLT then + begin + inc(ptr,4); + if ptr^<>#1 then exit; // 1 - lyric + inc(ptr); + mGetMem(dst,len-6); + FillChar(dst^,len-6,0); + + if (enc=0) or (enc=3) then + begin + while ptr^<>#0 do + begin + inc(ptr); + dec(len); + end; + inc(ptr); + dec(len); + org:=PAnsiChar(dst); + while len>0 do + begin + while ptr^<>#0 do + begin + org^:=ptr^; inc(org); inc(ptr); + dec(len); + end; + inc(ptr,1+4); // terminator+timestamp + dec(len,1+4); + end; + org:=PAnsiChar(dst); + if enc=0 then + AnsiToWide(org,dst) + else + UTF8ToWide(org,dst); + mFreeMem(org); + end + else + begin + orgw:=dst; + ptrw:=pWideChar(ptr); + while ptrw^<>#0 do + begin + inc(ptrw); + dec(len,SizeOf(WideChar)); + end; + inc(ptrw); + dec(len,SizeOf(WideChar)); + while len>0 do + begin + while ptrw^<>#0 do + begin + orgw^:=ptrw^; inc(orgw); inc(ptrw); + dec(len,SizeOf(WideChar)); + end; + inc(ptrw,1+2); // terminator + timestamp + dec(len,SizeOf(WideChar)+4); + end; + end; + end + else if tag=frmTXXX then + begin + FillChar(buf,SizeOf(buf),0); + org1:=ptr; + if (enc=0) or (enc=3) then + begin + org:=@buf; + while ptr^<>#0 do + begin + org^:=ptr^; + inc(org); + inc(ptr); + end; + inc(ptr); + if StrCmp(buf,'LYRICS')<>0 then + exit; + end + else + begin + orgw:=@buf; + ptrw:=pWideChar(ptr); + while ptrw^<>#0 do + begin + orgw^:=ptrw^; + inc(orgw); + inc(ptrw); + end; + inc(ptrw); + if StrCmpW(pWideChar(@buf),'LYRICS')<>0 then + exit; + ptr:=PAnsiChar(ptrw); + end; + dec(len,ptr-org1); + ID3v2_ReadTagStr1(dst,ptr,len,enc); + end; +end; + +procedure ID3v2_CheckCover(tag:integer; var dst:pWideChar;ptr:PAnsiChar;len:integer); +var + org:PAnsiChar; + ext:dword; + extw:int64; + enc:byte; +begin + if dst<>nil then exit; + org:=ptr; + enc:=ord(ptr^); inc(ptr); + if (pdword(ptr)^ and $FFFFFF)=$3E2D2D then exit; // as '-->' + if tag=frmAPIC then + begin + ext:=GetImageType(nil,ptr); + repeat inc(ptr) until ptr^=#0; inc(ptr); + end + else + begin + ext:=pdword(ptr)^ and $FFFFFF; + inc(ptr,3); + end; + + if not ord(ptr^) in [0,3,4,6] then exit; + inc(ptr); + if (enc=0) or (enc=3) then + begin + while ptr^<>#0 do inc(ptr); + inc(ptr); + end + else + begin + while pWord(ptr)^<>0 do inc(ptr,2); + inc(ptr,2); + end; + dec(len,ptr-org); + + if ext=0 then + ext:=GetImageType(pByte(ptr)); + if ext<>0 then + begin + FastAnsiToWideBuf(PAnsiChar(@ext),pWideChar(@extw)); + dst:=SaveTemporaryW(ptr,len,PWideChar(@extw)); + end; +end; + +function ID3v2_PreReadTag(var frm:tID3v2FrameHdr;var src:PAnsiChar;ver:integer):PAnsiChar; +var + i:cardinal; + dst:PAnsiChar; +begin + mGetMem(result,frm.Size); + if Unsync or ((frm.Flags and $0200)<>0) then + begin + dst:=result; + i:=0; + while i0 then + begin + Frm.Size:=ID3v2_Correct(pdword(tag)^); + inc(tag,4); + end; + end; + end; + + if Frm.ID=0 then + break; + if Frm.Size=0 then + continue; + if (tag+Frm.Size)>lp then + break; + buf:=ID3v2_PreReadTag(Frm,tag,ver); + + enc:=ord(buf^); + case enc of // set priority + 0: enc:=1; + 1,2: enc:=3; + 3: enc:=3; // or 2 if you want + end; + case Frm.ID of + frmUSLT,frmULT: ID3v2_CheckLyric(frmUSLT,Info.lyric,buf,Frm.Size); + frmSYLT,frmSLT: ID3v2_CheckLyric(frmSYLT,Info.lyric,buf,Frm.Size); + frmTXX,frmTXXX: ID3v2_CheckLyric(frmTXXX,Info.lyric,buf,Frm.Size); + frmAPIC,frmPIC: ID3v2_CheckCover(Frm.ID ,Info.cover,buf,Frm.Size); + + frmTPE1,frmTP1: begin + if fArtist<(enc+10) then + begin + fArtist:=enc+10; + mFreeMem(Info.artist); + ID3v2_ReadTagStr(Info.artist,buf,Frm.Size); + end + end; + frmTIT2,frmTT2: begin + if fTitle<(enc+10) then + begin + fTitle:=enc+10; + mFreeMem(Info.title); + ID3v2_ReadTagStr(Info.title,buf,Frm.Size); + end + end; + frmTALB,frmTAL: begin + if fAlbum<(enc+10) then + begin + fAlbum:=enc+10; + mFreeMem(Info.album); + ID3v2_ReadTagStr(Info.album,buf,Frm.Size); + end + end; + frmTYER,frmTDRC,frmTYE: begin + if Info.year<>nil then + mFreeMem(Info.year); + ID3v2_ReadTagStr(Info.year,buf,Frm.Size); + end; + + frmTOPE,frmTPE2,frmTOA,frmTPE4: begin + if fArtistnil then + if Info.genre[0]='(' then + begin + tmp:=StrScanW(Info.genre,')')-Info.genre+1; + if tmp=integer(StrLenW(Info.genre)) then + begin + ls:=GenreName(StrToInt(Info.genre+1)); + mFreeMem(Info.genre); + Info.genre:=ls; + end + else if tmp>0 then + StrCopyW(Info.genre,Info.genre+tmp); + end; + end; + end; + frmCOMM,frmCOM: begin //!! + if Info.comment=nil then + begin + ptr:=buf; + inc(ptr,3+1); // language + if (buf^=#0) or (buf^=#3) then + begin + while ptr^<>#0 do inc(ptr); + inc(ptr); + end + else + begin + while pWord(ptr)^<>0 do inc(ptr,2); + inc(ptr,2); + end; + dec(Frm.Size,ptr-buf); + ID3v2_ReadTagStr1(Info.comment,ptr,Frm.Size,ord(buf^)); + end; + end; + frmTRCK,frmTRK: begin + if Info.track=0 then + begin + ID3v2_ReadTagStr(ls,buf,Frm.Size); + Info.track:=StrToInt(ls); + mFreeMem(ls); + end; + end; + end; + mFreeMem(buf); + end; +end; + +function ReadID3v2(f:THANDLE; var Info:tSongInfo):longint; +var + TagHdr:TID3v2TagHdr; + Tag2:PAnsiChar; + ExtTagSize:dword; +begin + BlockRead(f,TagHdr,SizeOf(TagHdr)); + if TagHdr.ID=TAG2Sign then + begin + TagHdr.TagSize:=ID3v2_Correct(TagHdr.TagSize); + Unsync:=(TagHdr.Flags and $80)<>0; + result:=TagHdr.TagSize; +// if TagHdr.Version>2 then + begin + GetMem(Tag2,TagHdr.TagSize); + BlockRead(f,Tag2^,TagHdr.TagSize); + ID3v2_ReadTag2(TagHdr.Version,Tag2,TagHdr.TagSize,Info); + FreeMem(Tag2); + end; + if (TagHdr.Flags and ExtIDHdrMask)<>0 then + begin + BlockRead(f,ExtTagSize,SizeOf(ExtTagSize)); + inc(result,4+ExtTagSize); + end; + if (TagHdr.Flags and FooterPresent)<>0 then + inc(result,10); + end + else + result:=0; + Seek(f,result); +end; +{$ENDIF} diff --git a/plugins/Watrack/formats/tags.pas b/plugins/Watrack/formats/tags.pas new file mode 100644 index 0000000000..fbe0576c59 --- /dev/null +++ b/plugins/Watrack/formats/tags.pas @@ -0,0 +1,21 @@ +unit tags; +{$include compilers.inc} +interface + +uses wat_api,windows; + +{$DEFINE Interface} +{$include tag_id3v2.inc} +{$include tag_id3v1.inc} +{$include tag_apev2.inc} + +implementation + +uses common,io,utils; + +{$UNDEF Interface} +{$include tag_id3v2.inc} +{$include tag_id3v1.inc} +{$include tag_apev2.inc} + +end. \ No newline at end of file diff --git a/plugins/Watrack/global.pas b/plugins/Watrack/global.pas new file mode 100644 index 0000000000..14d915a973 --- /dev/null +++ b/plugins/Watrack/global.pas @@ -0,0 +1,86 @@ +{WATrack global datas} +unit Global; + +interface + +uses windows,messages,wat_api; + +const + hwndTooltip:HWND=0; + +var + UserCP:dword; + +const + DLGED_INIT = $1000; // dialog init, not activate Apply button + +const + dsWait = -1; + dsEnabled = 0; + dsTemporary = 1; + dsPermanent = 2; + +// --- type definition --- +type + pwModule = ^twModule; + twModule = record + Next :pwModule; + Init :function(aGetStatus:boolean=false):integer; + DeInit :procedure(aSetDisable:boolean); + AddOption :function(var tmpl:pAnsiChar;var proc:pointer;var name:pAnsiChar):integer; + ModuleName:pWideChar; + ModuleStat:integer; // filling by the way + Button :HWND; // checkboxes for switch on/off +// AddOption:function(parent:HWND;var Dlg:integer;var name:pWideChar):integer; + end; + +const + PluginName = 'Winamp Track'; + PluginShort:PAnsiChar = 'WATrack'; + +const + ModuleLink:pwModule=nil; + +const + DisablePlugin :integer=0; + hHookWATStatus:THANDLE=0; + +// --- global functions --- + +procedure MakeHint (wnd:HWND;id:integer;txt:pAnsiChar); +procedure MakeHintW(wnd:HWND;id:integer;txt:pWideChar); + +implementation + +uses common,commctrl,mirutils,m_api;//,templates; + +procedure MakeHint(wnd:HWND;id:integer;txt:pAnsiChar); +var + ti:TTOOLINFOW; +begin +// FillChar(ti,SizeOf(ti),0); + ti.cbSize :=sizeof(TTOOLINFOW); + ti.uFlags :=TTF_IDISHWND or TTF_SUBCLASS; + ti.hwnd :=wnd; + ti.hinst :=hInstance; + ti.uId :=GetDlgItem(wnd,id); + ti.lpszText:=TranslateA2W(txt); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); + mFreeMem(ti.lpszText); +end; + +procedure MakeHintW(wnd:HWND;id:integer;txt:pWideChar); +var + ti:TTOOLINFOW; +begin +// FillChar(ti,SizeOf(ti),0); + ti.cbSize :=sizeof(TTOOLINFOW); + ti.uFlags :=TTF_IDISHWND or TTF_SUBCLASS; + ti.hwnd :=wnd; + ti.hinst :=hInstance; + ti.uId :=GetDlgItem(wnd,id); + ti.lpszText:=TranslateW(txt); + SendMessageW(hwndTooltip,TTM_ADDTOOLW,0,lparam(@ti)); +end; + +end. diff --git a/plugins/Watrack/i_cover.inc b/plugins/Watrack/i_cover.inc new file mode 100644 index 0000000000..48f515882a --- /dev/null +++ b/plugins/Watrack/i_cover.inc @@ -0,0 +1,90 @@ +{any utils} +function GetCover(var dst:pWideChar;mfile:pWideChar):boolean; +var + line,line1:array [0..511] of WideChar; + p,p1:PWideChar; + i:integer; + fdata:WIN32_FIND_DATAW; + hTmp:THANDLE; + wr,wr1:pWideChar; +begin + result:=false; + dst:=nil; + if (CoverPaths=nil) or (CoverPaths^=#0) then exit; + p:=CoverPaths; + repeat + p1:=p; + while p^>=' ' do inc(p); + i:=p-p1; + if i>0 then + begin + move(p1^,line,i*SizeOf(WideChar)); + line[i]:=#0; + if ServiceExists(MS_WAT_REPLACETEXT)<>0 then + wr:=pWideChar(CallService(MS_WAT_REPLACETEXT,0,lparam(@line))) + else + wr:=@line; + + if isPathAbsolute(wr) then + begin + hTmp:=FindFirstFileW(wr,fdata); + end + else + begin + wr1:=ExtractW(mfile,false); + StrCopyW(line,wr1); + mFreeMem(wr1); + StrCatW(line,wr); + hTmp:=FindFirstFileW(line,fdata); + end; + if dword(hTmp)<>INVALID_HANDLE_VALUE then + begin + wr1:=ExtractW(line,false); + StrCopyW(line1,wr1); + mFreeMem(wr1); + StrCatW(line1,pWideChar(@fdata.cFileName)); + + GetFullPathNameW(line1,SizeOf(line) div SizeOf(WideChar),line,wr1); + StrDupW(dst,line); + result:=true; + FindClose(hTmp); //!! + end; + if wr<>@line then mFreeMem(wr); + if result then break; + end; + while p^<' ' do + begin + if p^=#0 then break; + inc(p); + end; + until p^=#0; +end; + +function GetLyric(var dst:pWideChar;mfile:pWideChar):boolean; +var + buf:array [0..511] of WideChar; + f:THANDLE; + size:integer; + tmp:PAnsiChar; +begin + StrCopyW(buf,mfile); + ChangeExtW(buf,'txt'); + f:=Reset(buf); + if f=THANDLE(INVALID_HANDLE_VALUE) then + begin + dst:=nil; + result:=false; + exit; + end; + size:=FileSize(f); + if size>0 then + begin + mGetMem(tmp,size+1); + BlockRead(f,tmp^,size); + tmp[size]:=#0; + AnsiToWide(tmp,dst); + mFreeMem(tmp); + end; + CloseHandle(f); + result:=true; +end; diff --git a/plugins/Watrack/i_gui.inc b/plugins/Watrack/i_gui.inc new file mode 100644 index 0000000000..dc79632b1e --- /dev/null +++ b/plugins/Watrack/i_gui.inc @@ -0,0 +1,114 @@ +{some visual stuff} + +function OnTTBLoaded(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + ttb:m_api.TTBButton; +begin + UnhookEvent(onloadhook); + + FillChar(ttb,SizeOf(ttb),0); + ttb.cbSize :=SizeOf(ttb); + ttb.dwFlags:=TTBBF_VISIBLE or TTBBF_SHOWTOOLTIP; + + // plugin status button + if DisablePlugin<>dsPermanent then + ttb.dwFlags:=ttb.dwFlags or TTBBF_PUSHED; + + ttb.hIconDn :=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnEnable)); + ttb.hIconUp :=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnDisable)); + ttb.wParamUp :=1; +// ttb.wParamDown :=0; + ttb.pszService:=MS_WAT_PLUGINSTATUS; + ttb.name :='WATrack status'; +// ttb.tooltipDn:='Disable Plugin'; +// ttb.tooltipUp:='Enable Plugin'; + ttbState:=TopToolbar_AddButton(@ttb); + if ttbState=THANDLE(-1) then + ttbState:=0 + else + CallService(MS_TTB_SETBUTTONOPTIONS,(ttbState shl 16)+TTBO_TIPNAME, + tlparam(Translate('Disable Plugin'))); + result:=0; +end; + +procedure CreateMenus; +var + mi:TCListMenuItem; +begin + FillChar(mi, sizeof(mi), 0); + mi.cbSize :=sizeof(mi); + mi.szPopupName.a:=PluginShort; + + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(IcoBtnEnable)); + mi.szName.a :='Disable Plugin'; + mi.pszService :=MS_WAT_PLUGINSTATUS; + mi.popupPosition:=MenuDisablePos; + hMenuDisable:=Menu_AddMainMenuItem(@mi); +end; + +procedure ChangeMenuIcons(f1:cardinal); +var + mi:tClistMenuItem; + p:PAnsiChar; +begin + FillChar(mi,sizeof(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_NAME+CMIM_FLAGS+CMIM_ICON+f1; + if f1<>0 then + begin + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(IcoBtnDisable)); + mi.szName.a:='Enable Plugin'; + end + else + begin + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(IcoBtnEnable)); + mi.szName.a:='Disable Plugin'; + end; + CallService(MS_CLIST_MODIFYMENUITEM,hMenuDisable,lparam(@mi)); + + if ServiceExists(MS_TTB_SETBUTTONSTATE)<>0 then + begin + if f1<>0 then + begin + p:='Enable Plugin'; + CallService(MS_TTB_SETBUTTONSTATE,ttbState,TTBST_RELEASED) + end + else + begin + p:='Disable Plugin'; + CallService(MS_TTB_SETBUTTONSTATE,ttbState,TTBST_PUSHED); + end; + CallService(MS_TTB_SETBUTTONOPTIONS,(ttbState shl 16)+TTBO_TIPNAME, + lparam(Translate(p))); + end; +end; + +function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; + ttb:m_api.TTBButton; +begin + result:=0; + FillChar(mi,SizeOf(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_ICON; + + mi.hIcon:=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnEnable)); + CallService(MS_CLIST_MODIFYMENUITEM,hMenuDisable,tlparam(@mi)); + +// toptoolbar + if ServiceExists(MS_TTB_GETBUTTONOPTIONS)<>0 then + begin +{ + CallService(MS_TTB_GETBUTTONOPTIONS,(ttbInfo shl 16)+TTBO_ALLDATA,tlparam(@ttb)); + ttb.hIconUp:=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnInfo)); + ttb.hIconDn:=ttb.hIconUp; + CallService(MS_TTB_SETBUTTONOPTIONS,(ttbInfo shl 16)+TTBO_ALLDATA,tlparam(@ttb)); +} + CallService(MS_TTB_GETBUTTONOPTIONS,(ttbState shl 16)+TTBO_ALLDATA,tlparam(@ttb)); + ttb.hIconDn:=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnEnable)); + ttb.hIconUp:=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnDisable)); + CallService(MS_TTB_SETBUTTONOPTIONS,(ttbState shl 16)+TTBO_ALLDATA,tlparam(@ttb)); + end; + +end; diff --git a/plugins/Watrack/i_opt_0.inc b/plugins/Watrack/i_opt_0.inc new file mode 100644 index 0000000000..ab17d6ec0d --- /dev/null +++ b/plugins/Watrack/i_opt_0.inc @@ -0,0 +1,91 @@ +{special tab: parts settings} + +function DlgProcOptions0(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):LRESULT; stdcall; +const + hasApply:boolean=false; +var + i:integer; + ptr:pwModule; + wnd:HWND; + rc:TRECT; +begin + result:=0; + case hMessage of + WM_DESTROY: begin + if hasApply then + begin + ptr:=ModuleLink; + while ptr<>nil do + begin + if ptr^.ModuleName<>nil then + begin + i:=SendMessageW(ptr^.Button,BM_GETCHECK,0,0); + if (i=BST_CHECKED) xor (ptr^.ModuleStat<>0) then + begin + if i=BST_CHECKED then + begin + ptr^.ModuleStat:=1; + if @ptr^.Init<>nil then + if ptr^.Init(false)=0 then + ptr^.ModuleStat:=0; + end + else + begin + ptr^.ModuleStat:=0; + if @ptr^.DeInit<>nil then + ptr^.DeInit(true); + end; + end; +// if ptr^.ModuleStat then + end; + ptr:=ptr^.Next; + end; + end; + end; + + WM_INITDIALOG: begin + + hasApply:=false; + + ptr:=ModuleLink; + i:=0; + while ptr<>nil do + begin + if ptr^.ModuleName<>nil then + begin + ptr^.Button:=CreateWindowW('BUTTON',TranslateW(ptr^.ModuleName), + WS_CHILD+WS_VISIBLE+BS_AUTOCHECKBOX, + 14,20+i*20,150,14,Dialog,0,hInstance,nil); + SendMessageW(ptr^.Button,WM_SETFONT,GetStockObject(DEFAULT_GUI_FONT),0); + if ptr^.ModuleStat<>0 then + SendMessageW(ptr^.Button,BM_SETCHECK,BST_CHECKED,0); + inc(i); + end; + ptr:=ptr^.Next; + end; + if i>0 then + begin + wnd:=GetDlgItem(Dialog,IDC_MODULEGROUP); + GetWindowRect(wnd,rc); + SetWindowPos (wnd,0,0,0,rc.Right-rc.Left,(i+1)*20, + SWP_NOMOVE+SWP_NOZORDER+SWP_NOACTIVATE); + end; + + TranslateDialogDefault(Dialog); + end; + + WM_COMMAND: begin + if (wParam shr 16)=BN_CLICKED then + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + + WM_NOTIFY: begin + if integer(PNMHdr(lParam)^.code)=PSN_APPLY then + begin + hasApply:=true; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/i_opt_1.inc b/plugins/Watrack/i_opt_1.inc new file mode 100644 index 0000000000..a41d07d554 --- /dev/null +++ b/plugins/Watrack/i_opt_1.inc @@ -0,0 +1,256 @@ +{common options} +const + ChkFmtStr:array [0..3] of pWideChar = ('None','Audio','Video','All'); + +type + TCPTABLE = packed record + cpId :cardinal; + cpName:PAnsiChar; + end; +const + cpNum = 15; + cpTable:array [0..cpNum-1] of TCPTABLE = ( + (cpId: 874;cpName:'Thai'), + (cpId: 932;cpName:'Japanese'), + (cpId: 936;cpName:'Simplified Chinese'), + (cpId: 949;cpName:'Korean'), + (cpId: 950;cpName:'Traditional Chinese'), + (cpId:1250;cpName:'Central European'), + (cpId:1251;cpName:'Cyrillic'), + (cpId:1252;cpName:'Latin I'), + (cpId:1253;cpName:'Greek'), + (cpId:1254;cpName:'Turkish'), + (cpId:1255;cpName:'Hebrew'), + (cpId:1256;cpName:'Arabic'), + (cpId:1257;cpName:'Baltic'), + (cpId:1258;cpName:'Vietnamese'), + (cpId:1361;cpName:'Korean (Johab)')); + +var + hCpCombo:hwnd; + +function FillCpCombo(astr:PAnsiChar):boolean; stdcall; +var + i:integer; + cp:cardinal; + iIndex:integer; + buf:array [0..63] of WideChar; +begin + result:=true; // MUST be at start + cp:=StrToInt(astr); + i:=0; + while i=1000) and (i mod 1000=0) then + i:=i div 1000; + + MakeHint(Dialog,IDC_TIMER, + 'Refresh time (sec) is time to refresh music info, statistic and'+ + ' status messages. If zero, automatic refresh is disabled. If '+ + 'value greater than 499, time signify as milliseconds.'); + SetDlgItemInt(Dialog,IDC_TIMER,i,false); + + MakeHint(Dialog,IDC_CHECKTIME, + 'Check file date and time to tag updates while playing.'); + CheckDlgButton(Dialog,IDC_CHECKTIME,CheckTime); + + MakeHint(Dialog,IDC_IMPLANTANT, + 'Use player process injection to obtain info easier. Can provoke antivirus '+ + 'or firewall alarm.'); + CheckDlgButton(Dialog,IDC_IMPLANTANT,UseImplant); + + MakeHint(Dialog,IDC_MTHCHECK, + 'Use this option if WATrack freeze while player running. Slower processing.'); + CheckDlgButton(Dialog,IDC_MTHCHECK,MTHCheck); + + MakeHint(Dialog,IDC_TIMEOUT, + 'Timeout (msec) for separate thread handles checking.'); + SetDlgItemInt(Dialog,IDC_TIMEOUT,TimeoutForThread,false); + + MakeHint(Dialog,IDC_KEEPOLD, + 'Keep opened file as active, not newly founded.'); + CheckDlgButton(Dialog,IDC_KEEPOLD,KeepOld); + + MakeHint(Dialog,IDC_CHECKALL, + 'Check all marked players for active (started and playing) or stop at first founded'); + CheckDlgButton(Dialog,IDC_CHECKALL,CheckAll); + +// MakeHint(Dialog,IDC_COVERFN, +// 'Cover filename searching templates'); + SetDlgItemTextW(Dialog,IDC_COVERFN,CoverPaths); + + MakeHint(Dialog,IDC_APPCOMMAND, + 'Emulate multimedia keys presses to control palyer'); + CheckDlgButton(Dialog,IDC_APPCOMMAND,mmkeyemu); + + hCpCombo:=GetDlgItem(Dialog,IDC_CODEPAGE); + EnumSystemCodePages(@FillCpCombo,CP_INSTALLED); + SendDlgItemMessageW(Dialog,IDC_CODEPAGE,CB_INSERTSTRING,0, + tlparam(TranslateW('System default codepage'))); + + CB_SelectData(Dialog,IDC_CODEPAGE,UserCP); + + if UserCP=0 then + i:=0 + else + begin + i:=SendDlgItemMessage(Dialog,IDC_CODEPAGE,CB_GETCOUNT,0,0)-1; + while i>0 do + begin + if dword(SendDlgItemMessage(Dialog,IDC_CODEPAGE,CB_GETITEMDATA,dword(i),0))=UserCP then + break; + dec(i); + end + end; + SendDlgItemMessage(Dialog,IDC_CODEPAGE,CB_SETCURSEL,i,0); + + result:=0; + end; + + WM_HELP: begin + with pHelpInfo(lParam)^ do + begin + if (iContextType=HELPINFO_WINDOW) and (iCtrlId=IDC_PLAYERLIST) then + begin + ListView_GetItemTextA(hItemHandle, + SendMessage(hItemHandle,LVM_GETNEXTITEM,-1,LVNI_FOCUSED),0, + @pldescr,HIGH(pldescr)); + p:=GetPlayerNote(pldescr); + if p=nil then + p:='No any special notes for this player'; + MessageBoxW(0,TranslateW(p),FastAnsiToWideBuf(pldescr,pldescw),0); + end; + end; + end; + + WM_COMMAND: begin + case wParam shr 16 of + EN_CHANGE, + BN_CLICKED, + CBN_SELCHANGE: begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + result:=1; + end; + end; + if (wParam shr 16)=BN_CLICKED then + begin + case loword(wParam) of + IDC_CHK_PLAYER: begin + btnChkPlayer:=not btnChkPlayer; + if btnChkPlayer then + begin + SetWindowTextW(GetDlgItem(Dialog,IDC_CHK_PLAYER),TranslateW('All')); + tmp:=false; + end + else + begin + SetWindowTextW(GetDlgItem(Dialog,IDC_CHK_PLAYER),TranslateW('None')); + tmp:=true; + end; + wnd:=GetDlgItem(Dialog,IDC_PLAYERLIST); + j:=ListView_GetItemCount(wnd)-1; + for i:=0 to j do + ListView_SetCheckState(wnd,i,tmp); + end; + + IDC_CHK_FORMAT: begin + wnd:=GetDlgItem(Dialog,IDC_FORMATLIST); + j:=ListView_GetItemCount(wnd)-1; + + tmp:=btnChkFormat=3; + for i:=0 to j do + begin + if (btnChkFormat=1) or (btnChkFormat=2) then + begin + if (LV_GetLParam(wnd,i) and WAT_OPT_VIDEO)<>0 then + tmp:=btnChkFormat=2 + else + tmp:=btnChkFormat=1; + end; + ListView_SetCheckState(wnd,i,tmp); + end; + inc(btnChkFormat); + if btnChkFormat=4 then btnChkFormat:=0; + SetWindowTextW(GetDlgItem(Dialog,IDC_CHK_FORMAT),TranslateW(ChkFmtStr[btnChkFormat])); + end; + end; + end; + end; + + WM_NOTIFY: begin + case integer(PNMHdr(lParam)^.code) of + LVN_ITEMCHANGED: begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + + PSN_APPLY: begin + UserCP:=CB_GetData(GetDlgItem(Dialog,IDC_CODEPAGE)); + i:=GetDlgItemInt(Dialog,IDC_TIMER,tmp,false); + if i<500 then + i:=i*1000; + if i<>mTimer then + begin + mTimer:=i; + StopTimer; + StartTimer; + end; + + TimeoutForThread:=GetDlgItemInt(Dialog,IDC_TIMEOUT,tmp,false); + if TimeoutForThread>=100 then + TimeoutForThread:=SysWin.ThreadTimeout; + + CheckTime :=IsDlgButtonChecked(Dialog,IDC_CHECKTIME); + UseImplant:=IsDlgButtonChecked(Dialog,IDC_IMPLANTANT); + MTHCheck :=IsDlgButtonChecked(Dialog,IDC_MTHCHECK); + KeepOld :=IsDlgButtonChecked(Dialog,IDC_KEEPOLD); + mmkeyemu :=IsDlgButtonChecked(Dialog,IDC_APPCOMMAND); + CheckAll :=IsDlgButtonChecked(Dialog,IDC_CHECKALL); + + mFreeMem(CoverPaths); + CoverPaths:=GetDlgText(Dialog,IDC_COVERFN); + + DefCheckPlayerList(GetDlgItem(Dialog,IDC_PLAYERLIST)); + DefCheckFormatList(GetDlgItem(Dialog,IDC_FORMATLIST)); + saveopt; + + result:=1; + end; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/i_opt_dlg.inc b/plugins/Watrack/i_opt_dlg.inc new file mode 100644 index 0000000000..e97a3df5f5 --- /dev/null +++ b/plugins/Watrack/i_opt_dlg.inc @@ -0,0 +1,57 @@ +{$include i_opt_0.inc} +{$include i_opt_1.inc} + +function OnOptInitialise(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + odp:TOPTIONSDIALOGPAGE; + ptr:pwModule; + tmpl:pAnsiChar; + name:pansiChar; + proc:pointer; + i:integer; +begin + if hwndTooltip<>0 then + DestroyWindow(hwndTooltip); + hwndTooltip:=CreateWindowW(TOOLTIPS_CLASS,nil,TTS_ALWAYSTIP, + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + integer(CW_USEDEFAULT),integer(CW_USEDEFAULT), + 0,0,hInstance,nil); + + SendMessage(hwndTooltip,TTM_SETMAXTIPWIDTH,0,300); + + FillChar(odp,SizeOf(odp),0); + odp.cbSize :=SizeOf(odp); + odp.Position :=900003000; + odp.hInstance :=hInstance; + odp.szTitle.a :=PluginName; + odp.szGroup.a :='Plugins'; + + odp.flags :=ODPF_BOLDGROUPS or ODPF_EXPERTONLY; + odp.pszTemplate:='PARTS'; + odp.pfnDlgProc :=@DlgProcOptions0; + odp.szTab.a :='Modules'; + CallService(MS_OPT_ADDPAGE,wParam,tlparam(@odp)); + + odp.flags :=ODPF_BOLDGROUPS; + odp.pszTemplate:='BASIC'; + odp.pfnDlgProc :=@DlgProcOptions1; + odp.szTab.a :='Basic'; + CallService(MS_OPT_ADDPAGE,wParam,tlparam(@odp)); + + ptr:=ModuleLink; + while ptr<>nil do + begin + if (ptr^.ModuleStat<>0) and (@ptr^.AddOption<>nil) then + begin + i:=ptr^.AddOption(tmpl,proc,name); + odp.pszTemplate:=tmpl; + odp.pfnDlgProc :=proc; + odp.szTab.a :=name; + CallService(MS_OPT_ADDPAGE,wParam,tlparam(@odp)); + if i>0 then continue; + end; + ptr:=ptr^.Next; + end; + + result:=0; +end; diff --git a/plugins/Watrack/i_options.inc b/plugins/Watrack/i_options.inc new file mode 100644 index 0000000000..060751966c --- /dev/null +++ b/plugins/Watrack/i_options.inc @@ -0,0 +1,171 @@ +{Database options} +const + DefaultXStatus = $080B; // TV + Music +const + defhotkey = (HOTKEYF_CONTROL+HOTKEYF_ALT )*256+VK_F5; + definshotkey = (HOTKEYF_CONTROL+HOTKEYF_SHIFT)*256+VK_F7; + +const + defcoverpaths = 'cover.jpg'#13#10'..\cover.jpg'#13#10'*.jpg'#13#10'..\*.jpg'; + +const + WATFormats:PAnsiChar = 'formats/'; +const + WATPlayers :PAnsiChar = 'players/'; + +const + opt_disable :PAnsiChar = 'disableplugin'; + + opt_InsHotKey :PAnsiChar = 'inshotkey'; + opt_HotKey :PAnsiChar = 'hotkey'; + opt_Timer :PAnsiChar = 'timer'; + opt_UserCP :PAnsiChar = 'usercp'; + opt_CheckTime :PAnsiChar = 'checktime'; + opt_coverpaths:PAnsiChar = 'coverpaths'; + opt_Implantant:PAnsiChar = 'useimplantant'; + opt_MTHCheck :PAnsiChar = 'mthcheck'; + opt_KeepOld :PAnsiChar = 'keepold'; + opt_mmkeyemu :PAnsiChar = 'mmkeyemu'; + opt_CheckAll :PAnsiChar = 'checkall'; + + opt_ThTimeout :PAnsiChar = 'thtimeout'; + +procedure _loadopt; +begin + DisablePlugin:=DBReadByte(0,PluginShort,opt_disable,0); + if DisablePlugin<>dsPermanent then + DisablePlugin:=dsEnabled; + + inshotkey :=DBReadWord(0,PluginShort,opt_InsHotKey ,definshotkey); + globhotkey :=DBReadWord(0,PluginShort,opt_HotKey ,defhotkey); + CheckTime :=DBReadByte(0,PluginShort,opt_CheckTime ,BST_CHECKED); + UseImplant :=DBReadByte(0,PluginShort,opt_Implantant,BST_UNCHECKED); + MTHCheck :=DBReadByte(0,PluginShort,opt_MTHCheck ,BST_CHECKED); + KeepOld :=DBReadByte(0,PluginShort,opt_KeepOld ,BST_UNCHECKED); + CheckAll :=DBReadByte(0,PluginShort,opt_CheckAll ,BST_UNCHECKED); + mTimer :=DBReadWord(0,PluginShort,opt_Timer ,3000); + if mTimer<500 then + mTimer:=mTimer*1000; + UserCP :=DBReadWord(0,PluginShort,opt_UserCP ,CP_ACP); + CoverPaths :=DBReadUnicode(0,PluginShort,opt_coverpaths,defcoverpaths); + + mmkeyemu :=DBReadByte (0,PluginShort,opt_mmkeyemu ,BST_UNCHECKED); + + TimeoutForThread:=DBReadByte(0,PluginShort,opt_ThTimeout,SysWin.ThreadTimeout); +end; + +procedure _saveopt; +begin + DBWriteWord(0,PluginShort,opt_InsHotKey ,inshotkey); + DBWriteWord(0,PluginShort,opt_HotKey ,globhotkey); + DBWriteByte(0,PluginShort,opt_ThTimeout ,TimeoutForThread); + DBWriteByte(0,PluginShort,opt_CheckTime ,CheckTime); + DBWriteByte(0,PluginShort,opt_Implantant,UseImplant); + DBWriteByte(0,PluginShort,opt_MTHCheck ,MTHCheck); + DBWriteByte(0,PluginShort,opt_KeepOld ,KeepOld); + DBWriteByte(0,PluginShort,opt_CheckAll ,CheckAll); + DBWriteWord(0,PluginShort,opt_Timer ,mTimer); + DBWriteWord(0,PluginShort,opt_UserCP ,UserCP); + + DBWriteUnicode(0,PluginShort,opt_coverpaths,CoverPaths); + + DBWriteByte (0,PluginShort,opt_mmkeyemu ,mmkeyemu); +end; + +function enumwp(desc:PAnsiChar;lParam:LPARAM):bool; stdcall; +var + i:integer; + buf:array [0..63] of AnsiChar; +begin + i:=CallService(MS_WAT_PLAYER,WAT_ACT_GETSTATUS,tlparam(desc)); + if i=WAT_RES_ENABLED then + i:=1 + else + i:=0; + StrCopy(StrCopyE(buf,WATPlayers),desc); + DBWriteByte(0,PluginShort,buf,i); + result:=true; +end; + +procedure WritePlayers; +begin + EnumPlayers(@enumwp,0); +end; + +function enumrp(desc:PAnsiChar;lParam:LPARAM):bool; stdcall; +var + i:integer; + buf:array [0..63] of AnsiChar; +begin + StrCopy(StrCopyE(buf,WATPlayers),desc); + i:=DBReadByte(0,PluginShort,buf,1); + if i=1 then + i:=WAT_ACT_ENABLE + else + i:=WAT_ACT_DISABLE; + CallService(MS_WAT_PLAYER,i,tlparam(desc)); + result:=true; +end; + +procedure ReadPlayers; +begin + EnumPlayers(@enumrp,0); +{!! p:=DBReadString(0,PluginShort,opt_DefPlayer,nil); + CallService(MS_WAT_PLAYER,WAT_ACT_SETACTIVE,dword(p)); + mFreeMem(p); +} +end; + +function enumwf(ext:PAnsiChar;lParam:LPARAM):bool; stdcall; +var + i:integer; + buf:array [0..63] of AnsiChar; +begin + i:=CallService(MS_WAT_FORMAT,WAT_ACT_GETSTATUS,tlparam(ext)); + if i=WAT_RES_ENABLED then + i:=1 + else + i:=0; + StrCopy(StrCopyE(buf,WATFormats),ext); + DBWriteByte(0,PluginShort,buf,i); + result:=true; +end; + +procedure WriteFormats; +begin + EnumFormats(@enumwf,0); +end; + +function enumrf(ext:PAnsiChar;lParam:LPARAM):bool; stdcall; +var + i:integer; + buf:array [0..63] of AnsiChar; +begin + StrCopy(StrCopyE(buf,WATFormats),ext); + i:=DBReadByte(0,PluginShort,buf,1); + if i=1 then + i:=WAT_ACT_ENABLE + else + i:=WAT_ACT_DISABLE; + CallService(MS_WAT_FORMAT,i,tlparam(ext)); + result:=true; +end; + +procedure ReadFormats; +begin + EnumFormats(@enumrf,0); +end; + +procedure saveopt; +begin + _saveopt; + WriteFormats; + WritePlayers; +end; + +procedure loadopt; +begin + _loadopt; + ReadPlayers; + ReadFormats; +end; diff --git a/plugins/Watrack/i_timer.inc b/plugins/Watrack/i_timer.inc new file mode 100644 index 0000000000..f37092291b --- /dev/null +++ b/plugins/Watrack/i_timer.inc @@ -0,0 +1,26 @@ +{Timer related procedures} + +procedure TimerProc(wnd:HWND;uMsg:uint;idEvent:uint_ptr;dwTime:dword); stdcall; +begin + case DisablePlugin of + dsEnabled : CallService(MS_WAT_GETMUSICINFO,WAT_INF_CHANGES,0); + dsTemporary: DisablePlugin:=dsWait; + end; +end; + +procedure StartTimer; +begin + if mTimer>0 then + hTimer:=SetTimer(0,0,mTimer,@TimerProc) + else + hTimer:=0; +end; + +procedure StopTimer; +begin + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; +end; diff --git a/plugins/Watrack/i_vars.inc b/plugins/Watrack/i_vars.inc new file mode 100644 index 0000000000..955170fdfa --- /dev/null +++ b/plugins/Watrack/i_vars.inc @@ -0,0 +1,37 @@ +{variables} +var + SongInfoA:tSongInfoA; + SongInfo :tSongInfo; + WorkSI :tSongInfo; +var + hEvent:THANDLE; + hGFI, + hWI, + hGMI, + hPS, + hPB, + hWATI, + hWC, + hFMT, + hPLR, + hRGS, + wsic, + hHookWATLoaded:THANDLE; + opthook:cardinal; + onloadhook:cardinal; + hHookShutdown:cardinal; + inshotkey:cardinal; + globhotkey:cardinal; + hTimer:cardinal; + ttbState, + hMenuDisable:THANDLE; +var + CoverPaths:PWideChar; + MTHCheck, + KeepOld, + UseImplant, + CheckAll, + CheckTime:dword; + mmkeyemu: dword; + mTimer:dword; + TimeoutForThread:cardinal; diff --git a/plugins/Watrack/icons/GO/GoAsm.Exe b/plugins/Watrack/icons/GO/GoAsm.Exe new file mode 100644 index 0000000000..cb0f7e8c92 Binary files /dev/null and b/plugins/Watrack/icons/GO/GoAsm.Exe differ diff --git a/plugins/Watrack/icons/GO/GoLink.exe b/plugins/Watrack/icons/GO/GoLink.exe new file mode 100644 index 0000000000..01e2964d6d Binary files /dev/null and b/plugins/Watrack/icons/GO/GoLink.exe differ diff --git a/plugins/Watrack/icons/GO/GoRC.exe b/plugins/Watrack/icons/GO/GoRC.exe new file mode 100644 index 0000000000..10ea26c30f Binary files /dev/null and b/plugins/Watrack/icons/GO/GoRC.exe differ diff --git a/plugins/Watrack/icons/GO/icons.bat b/plugins/Watrack/icons/GO/icons.bat new file mode 100644 index 0000000000..e45dfd4ab9 --- /dev/null +++ b/plugins/Watrack/icons/GO/icons.bat @@ -0,0 +1,8 @@ +:@echo off +GoRC /r /d incpath="%2" icons.rc +:GoRC /r icons.rc +GoAsm watrack_buttons.asm +GoLink /dll watrack_buttons.obj icons.res +del *.obj +del *.res +move watrack_buttons.dll ..\..\..\bin \ No newline at end of file diff --git a/plugins/Watrack/icons/GO/icons.rc b/plugins/Watrack/icons/GO/icons.rc new file mode 100644 index 0000000000..b50bba6a22 --- /dev/null +++ b/plugins/Watrack/icons/GO/icons.rc @@ -0,0 +1,58 @@ +#include "waticons.h" +LANGUAGE 0,0 + +IDI_PREV_NORMAL ICON "previous.ico" +IDI_PLAY_NORMAL ICON "play.ico" +IDI_PAUSE_NORMAL ICON "pause.ico" +IDI_STOP_NORMAL ICON "stop.ico" +IDI_NEXT_NORMAL ICON "next.ico" + +IDI_PREV_HOVERED ICON "previous_hovered.ico" +IDI_PLAY_HOVERED ICON "play_hovered.ico" +IDI_PAUSE_HOVERED ICON "pause_hovered.ico" +IDI_STOP_HOVERED ICON "stop_hovered.ico" +IDI_NEXT_HOVERED ICON "next_hovered.ico" + +IDI_PREV_PRESSED ICON "previous_pressed.ico" +IDI_PLAY_PRESSED ICON "play_pressed.ico" +IDI_PAUSE_PRESSED ICON "pause_pressed.ico" +IDI_STOP_PRESSED ICON "stop_pressed.ico" +IDI_NEXT_PRESSED ICON "next_pressed.ico" + +IDI_VOLDN_NORMAL ICON "volume_down.ico" +IDI_VOLUP_NORMAL ICON "volume_up.ico" +IDI_VOLDN_HOVERED ICON "volume_down_hovered.ico" +IDI_VOLUP_HOVERED ICON "volume_up_hovered.ico" +IDI_VOLDN_PRESSED ICON "volume_down_pressed.ico" +IDI_VOLUP_PRESSED ICON "volume_up_pressed.ico" + +IDI_SLIDER_NORMAL ICON "slider.ico" +IDI_SLIDER_HOVERED ICON "slider_hovered.ico" +IDI_SLIDER_PRESSED ICON "slider_pressed.ico" + +IDI_PLUGIN_ENABLE ICON "enable.ico" +IDI_PLUGIN_DISABLE ICON "disable.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,0,2 + PRODUCTVERSION 0,0,0,2 + FILEFLAGSMASK 0x3F + FILEOS 4 + FILETYPE 2 + FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "FileDescription", "Solid indexed and truecolor" + VALUE "FileVersion", "0.0.0.2" + VALUE "OriginalFilename", "watrack_buttons.dll" + VALUE "ProductName", "WATrack buttons icons" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation",0,1200 + END +END diff --git a/plugins/Watrack/icons/GO/waticons.h b/plugins/Watrack/icons/GO/waticons.h new file mode 100644 index 0000000000..bad8cadea2 --- /dev/null +++ b/plugins/Watrack/icons/GO/waticons.h @@ -0,0 +1,35 @@ +#define IDI_PREV_NORMAL 1 +#define IDI_PREV_HOVERED 2 +#define IDI_PREV_PRESSED 3 + +#define IDI_PLAY_NORMAL 4 +#define IDI_PLAY_HOVERED 5 +#define IDI_PLAY_PRESSED 6 + +#define IDI_PAUSE_NORMAL 7 +#define IDI_PAUSE_HOVERED 8 +#define IDI_PAUSE_PRESSED 9 + +#define IDI_STOP_NORMAL 10 +#define IDI_STOP_HOVERED 11 +#define IDI_STOP_PRESSED 12 + +#define IDI_NEXT_NORMAL 13 +#define IDI_NEXT_HOVERED 14 +#define IDI_NEXT_PRESSED 15 + +#define IDI_VOLDN_NORMAL 16 +#define IDI_VOLDN_HOVERED 17 +#define IDI_VOLDN_PRESSED 18 + +#define IDI_VOLUP_NORMAL 19 +#define IDI_VOLUP_HOVERED 20 +#define IDI_VOLUP_PRESSED 21 + +#define IDI_SLIDER_NORMAL 22 +#define IDI_SLIDER_HOVERED 23 +#define IDI_SLIDER_PRESSED 24 + + +#define IDI_PLUGIN_ENABLE 100 +#define IDI_PLUGIN_DISABLE 101 diff --git a/plugins/Watrack/icons/GO/watrack_buttons.asm b/plugins/Watrack/icons/GO/watrack_buttons.asm new file mode 100644 index 0000000000..27ed04d7b5 --- /dev/null +++ b/plugins/Watrack/icons/GO/watrack_buttons.asm @@ -0,0 +1,5 @@ +.code +start: + mov al, 1 + ret + diff --git a/plugins/Watrack/icons/MASM/icons.bat b/plugins/Watrack/icons/MASM/icons.bat new file mode 100644 index 0000000000..9cb2911d33 --- /dev/null +++ b/plugins/Watrack/icons/MASM/icons.bat @@ -0,0 +1,8 @@ +@echo off +if /i '%1' == 'buttons' (set iconres=icons) else set iconres=iconspl +porc /i%2 %iconres%.rc /Foicons.res +poasm watrack.asm +polink /DLL /RELEASE /NODEFAULTLIB /NOENTRY /NOLOGO /OUT:watrack_%1.dll watrack.obj icons.res +del *.obj +del *.res +move watrack_%1.dll ..\..\..\bin \ No newline at end of file diff --git a/plugins/Watrack/icons/MASM/icons.rc b/plugins/Watrack/icons/MASM/icons.rc new file mode 100644 index 0000000000..b50bba6a22 --- /dev/null +++ b/plugins/Watrack/icons/MASM/icons.rc @@ -0,0 +1,58 @@ +#include "waticons.h" +LANGUAGE 0,0 + +IDI_PREV_NORMAL ICON "previous.ico" +IDI_PLAY_NORMAL ICON "play.ico" +IDI_PAUSE_NORMAL ICON "pause.ico" +IDI_STOP_NORMAL ICON "stop.ico" +IDI_NEXT_NORMAL ICON "next.ico" + +IDI_PREV_HOVERED ICON "previous_hovered.ico" +IDI_PLAY_HOVERED ICON "play_hovered.ico" +IDI_PAUSE_HOVERED ICON "pause_hovered.ico" +IDI_STOP_HOVERED ICON "stop_hovered.ico" +IDI_NEXT_HOVERED ICON "next_hovered.ico" + +IDI_PREV_PRESSED ICON "previous_pressed.ico" +IDI_PLAY_PRESSED ICON "play_pressed.ico" +IDI_PAUSE_PRESSED ICON "pause_pressed.ico" +IDI_STOP_PRESSED ICON "stop_pressed.ico" +IDI_NEXT_PRESSED ICON "next_pressed.ico" + +IDI_VOLDN_NORMAL ICON "volume_down.ico" +IDI_VOLUP_NORMAL ICON "volume_up.ico" +IDI_VOLDN_HOVERED ICON "volume_down_hovered.ico" +IDI_VOLUP_HOVERED ICON "volume_up_hovered.ico" +IDI_VOLDN_PRESSED ICON "volume_down_pressed.ico" +IDI_VOLUP_PRESSED ICON "volume_up_pressed.ico" + +IDI_SLIDER_NORMAL ICON "slider.ico" +IDI_SLIDER_HOVERED ICON "slider_hovered.ico" +IDI_SLIDER_PRESSED ICON "slider_pressed.ico" + +IDI_PLUGIN_ENABLE ICON "enable.ico" +IDI_PLUGIN_DISABLE ICON "disable.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,0,2 + PRODUCTVERSION 0,0,0,2 + FILEFLAGSMASK 0x3F + FILEOS 4 + FILETYPE 2 + FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "FileDescription", "Solid indexed and truecolor" + VALUE "FileVersion", "0.0.0.2" + VALUE "OriginalFilename", "watrack_buttons.dll" + VALUE "ProductName", "WATrack buttons icons" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation",0,1200 + END +END diff --git a/plugins/Watrack/icons/MASM/iconspl.rc b/plugins/Watrack/icons/MASM/iconspl.rc new file mode 100644 index 0000000000..3b98761d8d --- /dev/null +++ b/plugins/Watrack/icons/MASM/iconspl.rc @@ -0,0 +1,83 @@ +LANGUAGE 0,0 +// Winamp clone +WANY ICON "wany.ico" +// 1BY1 +1BY1 ICON "1by1.ico" +// ALShow +ALSHOW ICON "alshow.ico" +// ALSong +ALSONG ICON "alsong.ico" +// Apollo +APOLLO ICON "apollo.ico" +// AudioPlayer +AUDIO ICON "audio.ico" +// BSPlayer +BS ICON "bs.ico" +// Core Media Player +CMP ICON "cmp.ico" +// Creative Music Source +CMS ICON "cms.ico" +// Cowon JetAudio +COWON ICON "cowon.ico" +// FLVPlayer +FLV ICON "flv.ico" +// Foobar +FOOBAR ICON "foobar.ico" +//GOMPlayer +GOM ICON "gom.ico" +// Helium +HELIUM ICON "helium.ico" +// iTunes +ITUNES ICON "itunes.ico" +// JRiver Media Center +JRMC ICON "jrmc.ico" +// LightAlloy +LA ICON "la.ico" +// Last.fm Player +LFM ICON "lfm.ico" +// MusicCube One +MCONE ICON "mcone.ico" +// MusikCube +MCUBE ICON "mcube.ico" +// Media Commander Express +MCX ICON "mcx.ico" +// Music Match Jukebox +MMATCH ICON "mmatch.ico" +// Media Monkey +MMONKEY ICON "mmonkey.ico" +// Media Player Classic +MPC ICON "mpc.ico" +// MPlayer +MPLAYER ICON "mplayer.ico" +// MRadio +MRADIO ICON "mradio.ico" +// PlayNow +PLAY ICON "play.ico" +// Pluton +PLUTON ICON "pluton.ico" +// CyberLink PowerDVD +POWERDVD ICON "powerdvd.ico" +// Quintessential Player +QCD ICON "qcd.ico" +// Quicktime Player +QT ICON "qt.ico" +// Real Player Gold +REAL ICON "real.ico" +// SAPS +SAPS ICON "saps.ico" +// SongBird +SONGBIRD ICON "songbird.ico" +// VideoLAN media player +VLC ICON "vlc.ico" +// ViPlay +VP3 ICON "vp3.ico" +// WiFiRadio +WIFI ICON "wifi.ico" +// Winamp +WINAMP ICON "winamp.ico" +// Windows Media Player +WMP ICON "wmp.ico" +// XM Player +XM ICON "xm.ico" +// Zoom Player +ZOOM ICON "zoom.ico" diff --git a/plugins/Watrack/icons/MASM/poasm.exe b/plugins/Watrack/icons/MASM/poasm.exe new file mode 100644 index 0000000000..a5062d4823 Binary files /dev/null and b/plugins/Watrack/icons/MASM/poasm.exe differ diff --git a/plugins/Watrack/icons/MASM/polink.exe b/plugins/Watrack/icons/MASM/polink.exe new file mode 100644 index 0000000000..2338218457 Binary files /dev/null and b/plugins/Watrack/icons/MASM/polink.exe differ diff --git a/plugins/Watrack/icons/MASM/porc.dll b/plugins/Watrack/icons/MASM/porc.dll new file mode 100644 index 0000000000..18390000ee Binary files /dev/null and b/plugins/Watrack/icons/MASM/porc.dll differ diff --git a/plugins/Watrack/icons/MASM/porc.exe b/plugins/Watrack/icons/MASM/porc.exe new file mode 100644 index 0000000000..ae28631b40 Binary files /dev/null and b/plugins/Watrack/icons/MASM/porc.exe differ diff --git a/plugins/Watrack/icons/MASM/waticons.h b/plugins/Watrack/icons/MASM/waticons.h new file mode 100644 index 0000000000..bad8cadea2 --- /dev/null +++ b/plugins/Watrack/icons/MASM/waticons.h @@ -0,0 +1,35 @@ +#define IDI_PREV_NORMAL 1 +#define IDI_PREV_HOVERED 2 +#define IDI_PREV_PRESSED 3 + +#define IDI_PLAY_NORMAL 4 +#define IDI_PLAY_HOVERED 5 +#define IDI_PLAY_PRESSED 6 + +#define IDI_PAUSE_NORMAL 7 +#define IDI_PAUSE_HOVERED 8 +#define IDI_PAUSE_PRESSED 9 + +#define IDI_STOP_NORMAL 10 +#define IDI_STOP_HOVERED 11 +#define IDI_STOP_PRESSED 12 + +#define IDI_NEXT_NORMAL 13 +#define IDI_NEXT_HOVERED 14 +#define IDI_NEXT_PRESSED 15 + +#define IDI_VOLDN_NORMAL 16 +#define IDI_VOLDN_HOVERED 17 +#define IDI_VOLDN_PRESSED 18 + +#define IDI_VOLUP_NORMAL 19 +#define IDI_VOLUP_HOVERED 20 +#define IDI_VOLUP_PRESSED 21 + +#define IDI_SLIDER_NORMAL 22 +#define IDI_SLIDER_HOVERED 23 +#define IDI_SLIDER_PRESSED 24 + + +#define IDI_PLUGIN_ENABLE 100 +#define IDI_PLUGIN_DISABLE 101 diff --git a/plugins/Watrack/icons/MASM/watrack.asm b/plugins/Watrack/icons/MASM/watrack.asm new file mode 100644 index 0000000000..27ed04d7b5 --- /dev/null +++ b/plugins/Watrack/icons/MASM/watrack.asm @@ -0,0 +1,5 @@ +.code +start: + mov al, 1 + ret + diff --git a/plugins/Watrack/icons/TASM/RLINK32.DLL b/plugins/Watrack/icons/TASM/RLINK32.DLL new file mode 100644 index 0000000000..17c21b29e1 Binary files /dev/null and b/plugins/Watrack/icons/TASM/RLINK32.DLL differ diff --git a/plugins/Watrack/icons/TASM/TASM32.EXE b/plugins/Watrack/icons/TASM/TASM32.EXE new file mode 100644 index 0000000000..edf16463b9 Binary files /dev/null and b/plugins/Watrack/icons/TASM/TASM32.EXE differ diff --git a/plugins/Watrack/icons/TASM/TLINK32.EXE b/plugins/Watrack/icons/TASM/TLINK32.EXE new file mode 100644 index 0000000000..11ced1158c Binary files /dev/null and b/plugins/Watrack/icons/TASM/TLINK32.EXE differ diff --git a/plugins/Watrack/icons/TASM/brcc32.exe b/plugins/Watrack/icons/TASM/brcc32.exe new file mode 100644 index 0000000000..88795df846 Binary files /dev/null and b/plugins/Watrack/icons/TASM/brcc32.exe differ diff --git a/plugins/Watrack/icons/TASM/icons.bat b/plugins/Watrack/icons/TASM/icons.bat new file mode 100644 index 0000000000..5dd69d1433 --- /dev/null +++ b/plugins/Watrack/icons/TASM/icons.bat @@ -0,0 +1,9 @@ +@echo off +if /i '%1' == 'buttons' (set iconres=icons) else set iconres=iconspl +brcc32 %iconres%.rc -i%2 -foicons.res +tasm32 watrack.asm +tlink32 -Tpd watrack.obj,watrack_%1.dll,,,,icons.res +del *.map +del *.obj +del *.res +move watrack_%1.dll ..\..\..\bin \ No newline at end of file diff --git a/plugins/Watrack/icons/TASM/icons.rc b/plugins/Watrack/icons/TASM/icons.rc new file mode 100644 index 0000000000..586210d05a --- /dev/null +++ b/plugins/Watrack/icons/TASM/icons.rc @@ -0,0 +1,58 @@ +#include "waticons.h" +LANGUAGE 0,0 + +IDI_PREV_NORMAL ICON "previous.ico" +IDI_PLAY_NORMAL ICON "play.ico" +IDI_PAUSE_NORMAL ICON "pause.ico" +IDI_STOP_NORMAL ICON "stop.ico" +IDI_NEXT_NORMAL ICON "next.ico" + +IDI_PREV_HOVERED ICON "previous_hovered.ico" +IDI_PLAY_HOVERED ICON "play_hovered.ico" +IDI_PAUSE_HOVERED ICON "pause_hovered.ico" +IDI_STOP_HOVERED ICON "stop_hovered.ico" +IDI_NEXT_HOVERED ICON "next_hovered.ico" + +IDI_PREV_PRESSED ICON "previous_pressed.ico" +IDI_PLAY_PRESSED ICON "play_pressed.ico" +IDI_PAUSE_PRESSED ICON "pause_pressed.ico" +IDI_STOP_PRESSED ICON "stop_pressed.ico" +IDI_NEXT_PRESSED ICON "next_pressed.ico" + +IDI_VOLDN_NORMAL ICON "volume_down.ico" +IDI_VOLUP_NORMAL ICON "volume_up.ico" +IDI_VOLDN_HOVERED ICON "volume_down_hovered.ico" +IDI_VOLUP_HOVERED ICON "volume_up_hovered.ico" +IDI_VOLDN_PRESSED ICON "volume_down_pressed.ico" +IDI_VOLUP_PRESSED ICON "volume_up_pressed.ico" + +IDI_SLIDER_NORMAL ICON "slider.ico" +IDI_SLIDER_HOVERED ICON "slider_hovered.ico" +IDI_SLIDER_PRESSED ICON "slider_pressed.ico" + +IDI_PLUGIN_ENABLE ICON "enable.ico" +IDI_PLUGIN_DISABLE ICON "disable.ico" + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,0,2 + PRODUCTVERSION 0,0,0,2 + FILEFLAGSMASK $3F + FILEOS 4 + FILETYPE 2 + FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "FileDescription", "Solid indexed and truecolor" + VALUE "FileVersion", "0.0.0.2" + VALUE "OriginalFilename", "watrack_buttons.dll" + VALUE "ProductName", "WATrack buttons icons" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation",0,1200 + END +END diff --git a/plugins/Watrack/icons/TASM/iconspl.rc b/plugins/Watrack/icons/TASM/iconspl.rc new file mode 100644 index 0000000000..ab7a362869 --- /dev/null +++ b/plugins/Watrack/icons/TASM/iconspl.rc @@ -0,0 +1,61 @@ +LANGUAGE 0,0 + +Player_1BY1 ICON "1by1.ico" +Player_AIMP ICON "aimp.ico" +Player_ALSHOW ICON "alshow.ico" +Player_ALSONG ICON "alsong.ico" +Player_APOLLO ICON "apollo.ico" +Player_ASHAMPOO_MEDIA_PLAYER ICON "Ashampoo Media Player.ico" +Player_AUDIOPLAYER ICON "audio.ico" +Player_BEHOLDTV ICON "BeholdTV.ico" +Player_BILLY ICON "Billy.ico" +Player_BSPLAYER ICON "bsplayer.ico" +Player_CORE_MEDIA_PLAYER ICON "Core Media Player.ico" +Player_COWON_JETAUDIO ICON "JetAudio.ico" +Player_CREATIVE_MEDIA_SOURCE ICON "cms.ico" +Player_CRYSTAL_PLAYER ICON "Crystal Player.ico" +Player_CYBERLINK_POWERDVD ICON "Cyberlink PowerDVD.ico" +Player_EVIL_PLAYER ICON "Evil Player.ico" +Player_FLVPLAYER ICON "flv.ico" +Player_FOOBAR2000 ICON "foobar2000.ico" +Player_GOMPLAYER ICON "GOMPlayer.ico" +Player_HELIUM_MUSIC_MANAGER ICON "Helium Music Manager.ico" +Player_ITUNES ICON "iTunes.ico" +Player_J_RIVER_MEDIA_CENTER ICON "J.River Media Center.ico" +Player_KMPLAYER ICON "KMPlayer.ico" +Player_LAST_FM ICON "lastfm.ico" +Player_LIGHTALLOY ICON "LA.ico" +Player_MEDIA_COMMANDER_EXPRESS ICON "mcx.ico" +Player_MEDIAMONKEY ICON "MediaMonkey.ico" +Player_MOREAMP ICON "MoreAmp.ico" +Player_MPC ICON "MPC.ico" +Player_MPLAYER ICON "MPlayer.ico" +Player_MUSICCUBE_ONE ICON "mcone.ico" +Player_MUSICMATCH_JUKEBOX ICON "mmatch.ico" +Player_MUSIKCUBE ICON "MusikCube.ico" +Player_PLUTON ICON "pluton.ico" +Player_QCD ICON "QCDPlayer.ico" +Player_QUICKTIME_PLAYER ICON "QuickTime Player.ico" +Player_RADLIGHT ICON "RadLight.ico" +Player_REAL_PLAYER ICON "Real Player.ico" +Player_SAPS ICON "saps.ico" +Player_SONGBIRD ICON "SongBird.ico" +Player_SPIDER_PLAYER ICON "Spider Player.ico" +Player_ULTRA_PLAYER ICON "Ultra player.ico" +Player_VIDEOLAN_PLAYER ICON "VLC.ico" +Player_VIPLAY ICON "vp3.ico" +Player_VUPLAYER ICON "VUPlayer.ico" +Player_WIFIRADIO_PLAYER ICON "wifi.ico" +Player_WINAMP ICON "winamp.ico" +Player_WINAMP_CLONE ICON "wany.ico" +Player_WINDVD ICON "WinDVD.ico" +Player_WMP ICON "WMP 9.ico" +Player_XMPLAY ICON "XMPlay.ico" +Player_ZOOM ICON "Zoom Player.ico" + +/* +Player_ ICON "" +Player_ ICON "" +Player_ ICON "" +Player_ ICON "" +*/ diff --git a/plugins/Watrack/icons/TASM/rw32core.dll b/plugins/Watrack/icons/TASM/rw32core.dll new file mode 100644 index 0000000000..29ec016027 Binary files /dev/null and b/plugins/Watrack/icons/TASM/rw32core.dll differ diff --git a/plugins/Watrack/icons/TASM/waticons.h b/plugins/Watrack/icons/TASM/waticons.h new file mode 100644 index 0000000000..bad8cadea2 --- /dev/null +++ b/plugins/Watrack/icons/TASM/waticons.h @@ -0,0 +1,35 @@ +#define IDI_PREV_NORMAL 1 +#define IDI_PREV_HOVERED 2 +#define IDI_PREV_PRESSED 3 + +#define IDI_PLAY_NORMAL 4 +#define IDI_PLAY_HOVERED 5 +#define IDI_PLAY_PRESSED 6 + +#define IDI_PAUSE_NORMAL 7 +#define IDI_PAUSE_HOVERED 8 +#define IDI_PAUSE_PRESSED 9 + +#define IDI_STOP_NORMAL 10 +#define IDI_STOP_HOVERED 11 +#define IDI_STOP_PRESSED 12 + +#define IDI_NEXT_NORMAL 13 +#define IDI_NEXT_HOVERED 14 +#define IDI_NEXT_PRESSED 15 + +#define IDI_VOLDN_NORMAL 16 +#define IDI_VOLDN_HOVERED 17 +#define IDI_VOLDN_PRESSED 18 + +#define IDI_VOLUP_NORMAL 19 +#define IDI_VOLUP_HOVERED 20 +#define IDI_VOLUP_PRESSED 21 + +#define IDI_SLIDER_NORMAL 22 +#define IDI_SLIDER_HOVERED 23 +#define IDI_SLIDER_PRESSED 24 + + +#define IDI_PLUGIN_ENABLE 100 +#define IDI_PLUGIN_DISABLE 101 diff --git a/plugins/Watrack/icons/TASM/watrack.asm b/plugins/Watrack/icons/TASM/watrack.asm new file mode 100644 index 0000000000..cab1fa249f --- /dev/null +++ b/plugins/Watrack/icons/TASM/watrack.asm @@ -0,0 +1,8 @@ +.386 +.model flat, stdcall +.code +start: + mov al, 1 + ret +end start +end \ No newline at end of file diff --git a/plugins/Watrack/icons/iconsets/players/1by1.ico b/plugins/Watrack/icons/iconsets/players/1by1.ico new file mode 100644 index 0000000000..e8f3e4ae82 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/1by1.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/AIMP.ico b/plugins/Watrack/icons/iconsets/players/AIMP.ico new file mode 100644 index 0000000000..a0f99889b9 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/AIMP.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Ashampoo Media Player.ico b/plugins/Watrack/icons/iconsets/players/Ashampoo Media Player.ico new file mode 100644 index 0000000000..8496bf2eb0 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Ashampoo Media Player.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/BeholdTV.ico b/plugins/Watrack/icons/iconsets/players/BeholdTV.ico new file mode 100644 index 0000000000..8430b7723c Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/BeholdTV.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Billy.ico b/plugins/Watrack/icons/iconsets/players/Billy.ico new file mode 100644 index 0000000000..655f2d97f6 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Billy.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Core Media Player.ico b/plugins/Watrack/icons/iconsets/players/Core Media Player.ico new file mode 100644 index 0000000000..f5edff45d5 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Core Media Player.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Crystal Player.ico b/plugins/Watrack/icons/iconsets/players/Crystal Player.ico new file mode 100644 index 0000000000..0f0a8d894b Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Crystal Player.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Cyberlink PowerDVD.ico b/plugins/Watrack/icons/iconsets/players/Cyberlink PowerDVD.ico new file mode 100644 index 0000000000..7a26e8c05c Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Cyberlink PowerDVD.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Evil Player.ico b/plugins/Watrack/icons/iconsets/players/Evil Player.ico new file mode 100644 index 0000000000..d11cda81c5 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Evil Player.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/GOMPlayer.ico b/plugins/Watrack/icons/iconsets/players/GOMPlayer.ico new file mode 100644 index 0000000000..9a2f0fb960 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/GOMPlayer.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Helium Music Manager.ico b/plugins/Watrack/icons/iconsets/players/Helium Music Manager.ico new file mode 100644 index 0000000000..abdc4ef2b0 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Helium Music Manager.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/J.River Media Center.ico b/plugins/Watrack/icons/iconsets/players/J.River Media Center.ico new file mode 100644 index 0000000000..2a092c2c7e Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/J.River Media Center.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/JetAudio.ico b/plugins/Watrack/icons/iconsets/players/JetAudio.ico new file mode 100644 index 0000000000..9e3f536fca Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/JetAudio.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/KMPlayer.ico b/plugins/Watrack/icons/iconsets/players/KMPlayer.ico new file mode 100644 index 0000000000..aca7ba1514 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/KMPlayer.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/LastFM.ico b/plugins/Watrack/icons/iconsets/players/LastFM.ico new file mode 100644 index 0000000000..934e7090e2 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/LastFM.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/MediaMonkey.ico b/plugins/Watrack/icons/iconsets/players/MediaMonkey.ico new file mode 100644 index 0000000000..490e5c10b9 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/MediaMonkey.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/MoreAmp.ico b/plugins/Watrack/icons/iconsets/players/MoreAmp.ico new file mode 100644 index 0000000000..8b8e560495 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/MoreAmp.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/MusikCube.ico b/plugins/Watrack/icons/iconsets/players/MusikCube.ico new file mode 100644 index 0000000000..36d266a3d0 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/MusikCube.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/QCDPlayer.ico b/plugins/Watrack/icons/iconsets/players/QCDPlayer.ico new file mode 100644 index 0000000000..385282a192 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/QCDPlayer.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Quicktime Player.ico b/plugins/Watrack/icons/iconsets/players/Quicktime Player.ico new file mode 100644 index 0000000000..35268906c1 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Quicktime Player.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/RadLight.ico b/plugins/Watrack/icons/iconsets/players/RadLight.ico new file mode 100644 index 0000000000..be5a1c1499 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/RadLight.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Real Player.ico b/plugins/Watrack/icons/iconsets/players/Real Player.ico new file mode 100644 index 0000000000..99dc2d4f34 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Real Player.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Spider Player.ico b/plugins/Watrack/icons/iconsets/players/Spider Player.ico new file mode 100644 index 0000000000..c649b35d8b Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Spider Player.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Ultra player.ico b/plugins/Watrack/icons/iconsets/players/Ultra player.ico new file mode 100644 index 0000000000..4a54035ecc Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Ultra player.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/VUPlayer.ico b/plugins/Watrack/icons/iconsets/players/VUPlayer.ico new file mode 100644 index 0000000000..1648195b15 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/VUPlayer.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/WMP 9.ico b/plugins/Watrack/icons/iconsets/players/WMP 9.ico new file mode 100644 index 0000000000..124a27aea0 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/WMP 9.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/WinDVD.ico b/plugins/Watrack/icons/iconsets/players/WinDVD.ico new file mode 100644 index 0000000000..79cd1c7391 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/WinDVD.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/XMPlay.ico b/plugins/Watrack/icons/iconsets/players/XMPlay.ico new file mode 100644 index 0000000000..40952b26a1 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/XMPlay.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/Zoom Player.ico b/plugins/Watrack/icons/iconsets/players/Zoom Player.ico new file mode 100644 index 0000000000..fa62cb0d68 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/Zoom Player.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/alshow.ico b/plugins/Watrack/icons/iconsets/players/alshow.ico new file mode 100644 index 0000000000..d01d8846a3 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/alshow.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/alsong.ico b/plugins/Watrack/icons/iconsets/players/alsong.ico new file mode 100644 index 0000000000..b7585afbfe Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/alsong.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/apollo.ico b/plugins/Watrack/icons/iconsets/players/apollo.ico new file mode 100644 index 0000000000..b8a76d4569 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/apollo.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/audio.ico b/plugins/Watrack/icons/iconsets/players/audio.ico new file mode 100644 index 0000000000..7ad8262c54 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/audio.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/bsplayer.ico b/plugins/Watrack/icons/iconsets/players/bsplayer.ico new file mode 100644 index 0000000000..9d40734e4d Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/bsplayer.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/cms.ico b/plugins/Watrack/icons/iconsets/players/cms.ico new file mode 100644 index 0000000000..7b71b4cad5 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/cms.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/flv.ico b/plugins/Watrack/icons/iconsets/players/flv.ico new file mode 100644 index 0000000000..ba0d4cba83 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/flv.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/foobar2000.ico b/plugins/Watrack/icons/iconsets/players/foobar2000.ico new file mode 100644 index 0000000000..a1b0e4b7a1 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/foobar2000.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/itunes.ico b/plugins/Watrack/icons/iconsets/players/itunes.ico new file mode 100644 index 0000000000..d4694d2969 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/itunes.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/la.ico b/plugins/Watrack/icons/iconsets/players/la.ico new file mode 100644 index 0000000000..27c045931c Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/la.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/mcone.ico b/plugins/Watrack/icons/iconsets/players/mcone.ico new file mode 100644 index 0000000000..be73f7cd30 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/mcone.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/mcx.ico b/plugins/Watrack/icons/iconsets/players/mcx.ico new file mode 100644 index 0000000000..3532fa5da2 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/mcx.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/mmatch.ico b/plugins/Watrack/icons/iconsets/players/mmatch.ico new file mode 100644 index 0000000000..ffd2b8ed0a Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/mmatch.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/mpc.ico b/plugins/Watrack/icons/iconsets/players/mpc.ico new file mode 100644 index 0000000000..4e5d09966d Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/mpc.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/mplayer.ico b/plugins/Watrack/icons/iconsets/players/mplayer.ico new file mode 100644 index 0000000000..219d59b7b9 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/mplayer.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/pluton.ico b/plugins/Watrack/icons/iconsets/players/pluton.ico new file mode 100644 index 0000000000..10397ba1f8 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/pluton.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/saps.ico b/plugins/Watrack/icons/iconsets/players/saps.ico new file mode 100644 index 0000000000..41263a4ef7 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/saps.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/songbird.ico b/plugins/Watrack/icons/iconsets/players/songbird.ico new file mode 100644 index 0000000000..2876b1ca46 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/songbird.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/vlc.ico b/plugins/Watrack/icons/iconsets/players/vlc.ico new file mode 100644 index 0000000000..7caef3b91e Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/vlc.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/vp3.ico b/plugins/Watrack/icons/iconsets/players/vp3.ico new file mode 100644 index 0000000000..b8227fe7e5 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/vp3.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/wany.ico b/plugins/Watrack/icons/iconsets/players/wany.ico new file mode 100644 index 0000000000..4349576c82 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/wany.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/wifi.ico b/plugins/Watrack/icons/iconsets/players/wifi.ico new file mode 100644 index 0000000000..022cd7adee Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/wifi.ico differ diff --git a/plugins/Watrack/icons/iconsets/players/winamp.ico b/plugins/Watrack/icons/iconsets/players/winamp.ico new file mode 100644 index 0000000000..7dc5a2a3d9 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/players/winamp.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/disable.ico b/plugins/Watrack/icons/iconsets/true+256-solid/disable.ico new file mode 100644 index 0000000000..390f0852a2 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/disable.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/enable.ico b/plugins/Watrack/icons/iconsets/true+256-solid/enable.ico new file mode 100644 index 0000000000..0e20d3a616 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/enable.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/next.ico b/plugins/Watrack/icons/iconsets/true+256-solid/next.ico new file mode 100644 index 0000000000..5d85a0cbfb Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/next.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/next_hovered.ico b/plugins/Watrack/icons/iconsets/true+256-solid/next_hovered.ico new file mode 100644 index 0000000000..58dfc4e78b Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/next_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/next_pressed.ico b/plugins/Watrack/icons/iconsets/true+256-solid/next_pressed.ico new file mode 100644 index 0000000000..304e67c42c Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/next_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/pause.ico b/plugins/Watrack/icons/iconsets/true+256-solid/pause.ico new file mode 100644 index 0000000000..b719b08229 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/pause.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/pause_hovered.ico b/plugins/Watrack/icons/iconsets/true+256-solid/pause_hovered.ico new file mode 100644 index 0000000000..6f83916a8f Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/pause_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/pause_pressed.ico b/plugins/Watrack/icons/iconsets/true+256-solid/pause_pressed.ico new file mode 100644 index 0000000000..8455a55231 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/pause_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/play.ico b/plugins/Watrack/icons/iconsets/true+256-solid/play.ico new file mode 100644 index 0000000000..e7b8c0360b Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/play.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/play_hovered.ico b/plugins/Watrack/icons/iconsets/true+256-solid/play_hovered.ico new file mode 100644 index 0000000000..973e042a78 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/play_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/play_pressed.ico b/plugins/Watrack/icons/iconsets/true+256-solid/play_pressed.ico new file mode 100644 index 0000000000..75c3119eb3 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/play_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/previous.ico b/plugins/Watrack/icons/iconsets/true+256-solid/previous.ico new file mode 100644 index 0000000000..0b38110f84 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/previous.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/previous_hovered.ico b/plugins/Watrack/icons/iconsets/true+256-solid/previous_hovered.ico new file mode 100644 index 0000000000..b1e25de6b0 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/previous_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/previous_pressed.ico b/plugins/Watrack/icons/iconsets/true+256-solid/previous_pressed.ico new file mode 100644 index 0000000000..0b0accd00e Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/previous_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/slider.ico b/plugins/Watrack/icons/iconsets/true+256-solid/slider.ico new file mode 100644 index 0000000000..785bd748af Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/slider.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/slider_hovered.ico b/plugins/Watrack/icons/iconsets/true+256-solid/slider_hovered.ico new file mode 100644 index 0000000000..0e20d3a616 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/slider_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/slider_pressed.ico b/plugins/Watrack/icons/iconsets/true+256-solid/slider_pressed.ico new file mode 100644 index 0000000000..390f0852a2 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/slider_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/stop.ico b/plugins/Watrack/icons/iconsets/true+256-solid/stop.ico new file mode 100644 index 0000000000..444302bd67 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/stop.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/stop_hovered.ico b/plugins/Watrack/icons/iconsets/true+256-solid/stop_hovered.ico new file mode 100644 index 0000000000..00eadcab2a Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/stop_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/stop_pressed.ico b/plugins/Watrack/icons/iconsets/true+256-solid/stop_pressed.ico new file mode 100644 index 0000000000..81ae38790f Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/stop_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/volume_down.ico b/plugins/Watrack/icons/iconsets/true+256-solid/volume_down.ico new file mode 100644 index 0000000000..44e89abcb3 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/volume_down.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/volume_down_hovered.ico b/plugins/Watrack/icons/iconsets/true+256-solid/volume_down_hovered.ico new file mode 100644 index 0000000000..082c9c1bf9 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/volume_down_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/volume_down_pressed.ico b/plugins/Watrack/icons/iconsets/true+256-solid/volume_down_pressed.ico new file mode 100644 index 0000000000..ca48da4d03 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/volume_down_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/volume_up.ico b/plugins/Watrack/icons/iconsets/true+256-solid/volume_up.ico new file mode 100644 index 0000000000..ebe32ac085 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/volume_up.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/volume_up_hovered.ico b/plugins/Watrack/icons/iconsets/true+256-solid/volume_up_hovered.ico new file mode 100644 index 0000000000..76bb840dd8 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/volume_up_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true+256-solid/volume_up_pressed.ico b/plugins/Watrack/icons/iconsets/true+256-solid/volume_up_pressed.ico new file mode 100644 index 0000000000..b9a0e2c9d1 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true+256-solid/volume_up_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/next.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/next.ico new file mode 100644 index 0000000000..b716875893 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/next.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/next_hovered.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/next_hovered.ico new file mode 100644 index 0000000000..6a41ff71d4 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/next_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/next_pressed.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/next_pressed.ico new file mode 100644 index 0000000000..5766059f10 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/next_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/pause.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/pause.ico new file mode 100644 index 0000000000..612030f3f2 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/pause.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/pause_hovered.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/pause_hovered.ico new file mode 100644 index 0000000000..681f7e4a24 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/pause_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/pause_pressed.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/pause_pressed.ico new file mode 100644 index 0000000000..d1f4421b20 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/pause_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/play.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/play.ico new file mode 100644 index 0000000000..e35113cced Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/play.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/play_hovered.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/play_hovered.ico new file mode 100644 index 0000000000..591e186361 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/play_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/play_pressed.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/play_pressed.ico new file mode 100644 index 0000000000..029c30076b Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/play_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/previous.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/previous.ico new file mode 100644 index 0000000000..4f57e43af3 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/previous.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/previous_hovered.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/previous_hovered.ico new file mode 100644 index 0000000000..c456ca427f Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/previous_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/previous_pressed.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/previous_pressed.ico new file mode 100644 index 0000000000..68aa16a1c9 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/previous_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/slider.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/slider.ico new file mode 100644 index 0000000000..1f5df0b577 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/slider.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/stop.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/stop.ico new file mode 100644 index 0000000000..c17432d894 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/stop.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/stop_hovered.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/stop_hovered.ico new file mode 100644 index 0000000000..899030c9c7 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/stop_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/stop_pressed.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/stop_pressed.ico new file mode 100644 index 0000000000..65f3c17517 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/stop_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/ver.res b/plugins/Watrack/icons/iconsets/true-solid-faith/ver.res new file mode 100644 index 0000000000..aafbd00b59 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/ver.res differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/volume_down.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_down.ico new file mode 100644 index 0000000000..95ce39a7d7 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_down.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/volume_down_hovered.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_down_hovered.ico new file mode 100644 index 0000000000..a1195d1034 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_down_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/volume_down_pressed.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_down_pressed.ico new file mode 100644 index 0000000000..9ebd49660b Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_down_pressed.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/volume_up.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_up.ico new file mode 100644 index 0000000000..e7875083af Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_up.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/volume_up_hovered.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_up_hovered.ico new file mode 100644 index 0000000000..94332014fa Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_up_hovered.ico differ diff --git a/plugins/Watrack/icons/iconsets/true-solid-faith/volume_up_pressed.ico b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_up_pressed.ico new file mode 100644 index 0000000000..edfab79326 Binary files /dev/null and b/plugins/Watrack/icons/iconsets/true-solid-faith/volume_up_pressed.ico differ diff --git a/plugins/Watrack/icons/make-buttons.bat b/plugins/Watrack/icons/make-buttons.bat new file mode 100644 index 0000000000..dbca3ae634 --- /dev/null +++ b/plugins/Watrack/icons/make-buttons.bat @@ -0,0 +1,4 @@ +:@echo off +if /i '%1' == '' (set asm=tasm) else set asm=%1 +if /i '%2' == '' (set iconpack=true+256-solid) else set iconpack=%2 +call make.bat buttons %iconpack% %asm% \ No newline at end of file diff --git a/plugins/Watrack/icons/make-players.bat b/plugins/Watrack/icons/make-players.bat new file mode 100644 index 0000000000..ec90aa49bb --- /dev/null +++ b/plugins/Watrack/icons/make-players.bat @@ -0,0 +1,2 @@ +@echo off +call make.bat icons players tasm \ No newline at end of file diff --git a/plugins/Watrack/icons/make.bat b/plugins/Watrack/icons/make.bat new file mode 100644 index 0000000000..95f90dcca6 --- /dev/null +++ b/plugins/Watrack/icons/make.bat @@ -0,0 +1,16 @@ +:first parameter - 'icons' or 'buttons' - type of iconpack () +:second parameter - iconpack name (for buttons mainly) +:third parameter - assembler? (tasm) +:@echo off +if /i '%1' == '' (set pack=buttons) else set pack=%1 +if '%pack%' == 'icons' goto players +if /i '%2' == '' (set iconpack=true+256-solid) else set iconpack=%2 +goto next +:players +if /i '%2' == '' (set iconpack=players) else set iconpack=%2 +:next +if /i '%3' == '' (set asm=tasm) else set asm=%3 +:@echo off +cd %asm% +call icons.bat %pack% ..\iconsets\%iconpack% %4 %5 %6 %7 %8 %9 +cd ..\ diff --git a/plugins/Watrack/icons/waticons.inc b/plugins/Watrack/icons/waticons.inc new file mode 100644 index 0000000000..0c3c423f0e --- /dev/null +++ b/plugins/Watrack/icons/waticons.inc @@ -0,0 +1,35 @@ +const + IDI_PREV_NORMAL = 1; + IDI_PREV_HOVERED = 2; + IDI_PREV_PRESSED = 3; + + IDI_PLAY_NORMAL = 4; + IDI_PLAY_HOVERED = 5; + IDI_PLAY_PRESSED = 6; + + IDI_PAUSE_NORMAL = 7; + IDI_PAUSE_HOVERED = 8; + IDI_PAUSE_PRESSED = 9; + + IDI_STOP_NORMAL = 10; + IDI_STOP_HOVERED = 11; + IDI_STOP_PRESSED = 12; + + IDI_NEXT_NORMAL = 13; + IDI_NEXT_HOVERED = 14; + IDI_NEXT_PRESSED = 15; + + IDI_VOLDN_NORMAL = 16; + IDI_VOLDN_HOVERED = 17; + IDI_VOLDN_PRESSED = 18; + + IDI_VOLUP_NORMAL = 19; + IDI_VOLUP_HOVERED = 20; + IDI_VOLUP_PRESSED = 21; + + IDI_SLIDER_NORMAL = 22; + IDI_SLIDER_HOVERED = 23; + IDI_SLIDER_PRESSED = 24; + + IDI_PLUGIN_ENABLE = 100; + IDI_PLUGIN_DISABLE = 101; diff --git a/plugins/Watrack/kolframe/frm.rc b/plugins/Watrack/kolframe/frm.rc new file mode 100644 index 0000000000..50180b4b53 --- /dev/null +++ b/plugins/Watrack/kolframe/frm.rc @@ -0,0 +1,84 @@ +#include "frm_rc.inc" + +LANGUAGE 0,0 + +FRAME DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + AUTOCHECKBOX "Use buttons gap" , IDC_BTNGAP , 3, 44, 146, 14, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + + LTEXT "Frame refresh time", -1, 47, 2, 100, 14, SS_CENTERIMAGE + EDITTEXT IDC_TIMER , 3, 3, 40, 12, ES_RIGHT | ES_NUMBER + + AUTOCHECKBOX "Hide when no player", IDC_HIDEFRAMEPLAYER, 3, 16, 146, 14, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Hide when no music" , IDC_HIDEFRAMEMUSIC , 3, 30, 146, 14, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + + AUTOCHECKBOX "Show info in the frame" , IDC_SHOWTEXT , 155, 2, 144, 14, BS_VCENTER | BS_MULTILINE | BS_NOTIFY | BS_RIGHT | BS_LEFTTEXT + AUTOCHECKBOX "Show controls in the frame", IDC_SHOWCTRLS, 155, 16, 144, 14, BS_VCENTER | BS_MULTILINE | BS_NOTIFY | BS_RIGHT | BS_LEFTTEXT + AUTOCHECKBOX "Show volume controls" , IDC_SHOWVOLUM, 155, 30, 144, 14, BS_VCENTER | BS_MULTILINE | BS_NOTIFY | BS_RIGHT | BS_LEFTTEXT + AUTOCHECKBOX "Show trackbar" , IDC_SHOWBAR , 155, 44, 144, 14, BS_VCENTER | BS_MULTILINE | BS_NOTIFY | BS_RIGHT | BS_LEFTTEXT + + AUTOCHECKBOX "Use Picture",IDC_FRMUSEPIC,3,65,91,14,BS_VCENTER | BS_MULTILINE | BS_NOTIFY + EDITTEXT IDC_FRMBKPIC, 96, 65, 185, 14 + PUSHBUTTON "...", IDC_FRMPICBTN, 284, 65, 16, 14 + + GROUPBOX "Picture transform", -1, 2, 82, 298, 59 + AUTOCHECKBOX "Center horizontally" , IDC_CENTERX , 6, 91, 96, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Center vertically" , IDC_CENTERY , 6, 107, 96, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Bottom" , IDC_BOTTOM , 6, 123, 96, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Tile horizontally" , IDC_TILEX , 104, 91, 96, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Tile vertically" , IDC_TILEY , 104, 107, 96, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Right" , IDC_RIGHT , 104, 123, 96, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Stretch to width" , IDC_STRETCHX, 202, 91, 96, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Stretch to height" , IDC_STRETCHY, 202, 107, 96, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Stretch proportionally", IDC_PROP , 202, 123, 96, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + + CTEXT "Cover padding", -1, 6, 152, 142, 14, SS_CENTERIMAGE + EDITTEXT IDC_PADDING_TOP , 64, 168, 24, 14, ES_RIGHT | ES_NUMBER + EDITTEXT IDC_PADDING_LEFT , 50, 184, 24, 14, ES_RIGHT | ES_NUMBER + EDITTEXT IDC_PADDING_RIGHT , 78, 184, 24, 14, ES_RIGHT | ES_NUMBER + EDITTEXT IDC_PADDING_BOTTOM, 64, 200, 24, 14, ES_RIGHT | ES_NUMBER + + AUTOCHECKBOX "Manual element placement", IDC_MANUALPLACE, 155,144,144,16, BS_VCENTER | BS_MULTILINE | BS_RIGHT | BS_LEFTTEXT + +// TBS_TOOLTIPS + CONTROL "",IDC_FRMALPHA,"msctls_trackbar32", TBS_BOTTOM|TBS_NOTICKS|$100,160,168,68,11 + LTEXT "Alpha",-1,230,168,75,11, SS_CENTERIMAGE + + CONTROL "",IDC_FRMCOLOR, "ColourPicker", WS_TABSTOP, 162, 181, 14, 14 + LTEXT "Background color",-1,178,181,126,14, SS_CENTERIMAGE + + AUTOCHECKBOX "Use cover instead of picture", IDC_USECOVER, 155, 196, 142, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY +} + +FRAME2 DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + PUSHBUTTON "Choose font...", IDC_FRMFONT, 84, 90, 64, 12 + + GROUPBOX "Text effect",-1,154,6,142,76 + AUTORADIOBUTTON "Cut", IDC_EFF_CUT , 158, 16, 136, 12, NOT WS_TABSTOP + AUTORADIOBUTTON "Wrap", IDC_EFF_WRAP, 158, 28, 136, 12, NOT WS_TABSTOP + AUTORADIOBUTTON "Roll", IDC_EFF_ROLL, 158, 40, 136, 12, NOT WS_TABSTOP + AUTORADIOBUTTON "PingPong", IDC_EFF_PONG, 158, 52, 136, 12, NOT WS_TABSTOP + AUTOCHECKBOX "Align text to center", IDC_ALCENTER, 158, 66, 136, 12, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + + GROUPBOX "Text movement", -1, 6, 6, 142, 76, WS_TABSTOP + LTEXT "Text rotation speed (1-20)", -1, 32, 17, 114, 12, SS_CENTERIMAGE + LTEXT "Scroll step" , -1, 32, 33, 114, 12, SS_CENTERIMAGE + LTEXT "Scroll gap" , -1, 32, 49, 114, 12, SS_CENTERIMAGE +// LTEXT "Minimum scroll tail" , -1, 32, 65, 114, 12, SS_CENTERIMAGE + EDITTEXT IDC_TIMER , 10, 17, 20, 12, ES_RIGHT | ES_NUMBER + EDITTEXT IDC_ROLLSTEP, 10, 33, 20, 12, ES_RIGHT | ES_NUMBER + EDITTEXT IDC_ROLLGAP , 10, 49, 20, 12, ES_RIGHT | ES_NUMBER +// EDITTEXT IDC_ROLLTAIL, 10, 65, 20, 12, ES_RIGHT | ES_NUMBER + + CONTROL "M" ,IDC_MACRO_HELP ,"MButtonClass",WS_TABSTOP,284,156,16,16,$18000000 + RTEXT "Frame Text", -1 , 4, 163, 274, 10 + EDITTEXT IDC_FRAME_TEXT , 4, 174, 296, 48, + ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN +} diff --git a/plugins/Watrack/kolframe/frm.res b/plugins/Watrack/kolframe/frm.res new file mode 100644 index 0000000000..b978cdb07e Binary files /dev/null and b/plugins/Watrack/kolframe/frm.res differ diff --git a/plugins/Watrack/kolframe/frm_data.inc b/plugins/Watrack/kolframe/frm_data.inc new file mode 100644 index 0000000000..52535d15b2 --- /dev/null +++ b/plugins/Watrack/kolframe/frm_data.inc @@ -0,0 +1,37 @@ +{Frame data} + +const + //show controls + scButtons = $0001; + scTrackBar = $0002; + scText = $0004; + scVolume = $0008; + scGap = $0010; + scAll = $000F; + + ppLeft = 0; + ppRight = 1; + //effects + effCut = 0; + effWrap = 1; + effRoll = 2; + effPong = 3; + + // Back bitmap mode + frbkCenterX = $0001; + frbkCenterY = $0002; + frbkCenter = frbkCenterX or frbkCenterY; + frbkTileX = $0004; + frbkTileY = $0008; + frbkTile = frbkTileX or frbkTileY; + frbkStretchX = $0010; + frbkStretchY = $0020; + frbkStretch = frbkStretchX or frbkStretchY; + frbkProportional = $0040; + frbkBottom = $0080; + frbkRight = $0100; + +const + numbuttons = 7; + VolBtnDist = 6; + BtnGap = 3; diff --git a/plugins/Watrack/kolframe/frm_designer.inc b/plugins/Watrack/kolframe/frm_designer.inc new file mode 100644 index 0000000000..f12c01f05d --- /dev/null +++ b/plugins/Watrack/kolframe/frm_designer.inc @@ -0,0 +1,164 @@ +{Frame designer} +const + // trackbar + opt_tbleft :pAnsiChar='frame/designer/trackbar/left'; + opt_tbtop :pAnsiChar='frame/designer/trackbar/top'; + opt_tbwidth :pAnsiChar='frame/designer/trackbar/width'; + opt_tbheight:pAnsiChar='frame/designer/trackbar/height'; + // text block + opt_tleft :pAnsiChar='frame/designer/text/left'; + opt_ttop :pAnsiChar='frame/designer/text/top'; + opt_twidth :pAnsiChar='frame/designer/text/width'; + opt_theight :pAnsiChar='frame/designer/text/height'; + // buttons (with number) + opt_bleft :pAnsiChar='frame/designer/buttons/left'; + opt_btop :pAnsiChar='frame/designer/buttons/top'; + +procedure TWATFrame.DesignerSaveSettings; +var + i:integer; + D:PWATFrameData; + lleft,ltop:array [0..63] of AnsiChar; + pleft,ptop:PAnsiChar; +begin + D:=CustomData; + if D.TrackBar<>nil then + begin + DBWriteWord(0,PluginShort,opt_tbleft ,D.Trackbar.Left); + DBWriteWord(0,PluginShort,opt_tbtop ,D.Trackbar.Top); + DBWriteWord(0,PluginShort,opt_tbwidth ,D.Trackbar.Width); + DBWriteWord(0,PluginShort,opt_tbheight,D.Trackbar.Height); + end; + + if D.TextBlock<>nil then + begin + DBWriteWord(0,PluginShort,opt_tleft ,D.TextBlock.Left); + DBWriteWord(0,PluginShort,opt_ttop ,D.TextBlock.Top); + DBWriteWord(0,PluginShort,opt_twidth ,D.TextBlock.Width); + DBWriteWord(0,PluginShort,opt_theight,D.TextBlock.Height); + end; + + if (D.ShowControls and scButtons)<>0 then + begin + if D.btnarray[0]<>nil then + begin + pleft:=StrCopyE(lleft,opt_bleft); + ptop :=StrCopyE(ltop ,opt_btop); + for i:=0 to HIGH(D.btnarray) do + begin + IntToStr(pleft,i); DBWriteWord(0,PluginShort,lleft,D.btnarray[i].Left); + IntToStr(ptop ,i); DBWriteWord(0,PluginShort,ltop ,D.btnarray[i].Top); + end; + end; + end; +end; + +procedure TWATFrame.DesignerLoadSettings; +var + i:integer; + D:PWATFrameData; + lleft,ltop:array [0..63] of AnsiChar; + pleft,ptop:PAnsiChar; + for_check:integer; +begin + D:=CustomData; + + if (D.TrackBar<>nil) and + ((D.ShowControls and scTrackbar)<>0) and + ((D.Loaded and scTrackbar)=0) then + begin + D.Loaded:=D.Loaded or scTrackbar; + for_check:=DBReadWord(0,PluginShort,opt_tbwidth); + if for_check<>0 then + begin + D.Trackbar.SetPosition( + DBReadWord(0,PluginShort,opt_tbleft), + DBReadWord(0,PluginShort,opt_tbtop)); + D.Trackbar.SetSize( + for_check, + {18}DBReadWord(0,PluginShort,opt_tbheight)); + end; + end; + + if (D.TextBlock<>nil) and + ((D.ShowControls and scText)<>0) and + ((D.Loaded and scText)=0) then + begin + D.Loaded:=D.Loaded or scText; + for_check:=DBReadWord(0,PluginShort,opt_twidth); + if for_check<>0 then + begin + D.TextBlock.SetPosition( + DBReadWord(0,PluginShort,opt_tleft), + DBReadWord(0,PluginShort,opt_ttop)); + D.TextBlock.SetSize( + for_check, + DBReadWord(0,PluginShort,opt_theight)); + end; + end; + + if ((D.ShowControls and scButtons)<>0) and + ((D.Loaded and scButtons)=0) then + begin + if D.btnarray[0]<>nil then + begin + D.Loaded:=D.Loaded or scButtons; + pleft:=StrCopyE(lleft,opt_bleft); + pleft^:='0'; (pleft+1)^:=#0; + for_check:=SmallInt(DBReadWord(0,PluginShort,lleft,word(-1))); + if for_check>=0 then + begin + ptop :=StrCopyE(ltop,opt_btop); + for i:=0 to HIGH(D.btnarray) do + begin + IntToStr(pleft,i); + IntToStr(ptop ,i); + D.btnarray[i].SetPosition( + DBReadWord(0,PluginShort,lleft,word(-1)), + DBReadWord(0,PluginShort,ltop ,word(-1))); + end; + end; + end; + end; +end; + +procedure TWATFrame.CreateDesigner(Sender:PControl;var Mouse:TMouseEventData); +var + D:PWATFrameData; +begin + D:=CustomData; + if not D.ManualPlacement then exit; + + if D.Designer=nil then + D.Designer:=NewDesigner(@self); + + if not D.Designer.Active then + begin + // Trackbar + if D.Trackbar<>nil then + begin + D.Trackbar.Anchor(false,false,false,false); + D.Designer.Connect('Trackbar',D.Trackbar); + end; + // TextBlock + if D.TextBlock<>nil then + begin + D.TextBlock.Anchor(false,false,false,false); + D.Designer.Connect('Panel',D.TextBlock); + end; + // Icons + if (D.ShowControls and scButtons)<>0 then MakeButtonsDesigner; + + D.Designer.Active:=true; + end + else + begin + D.Designer.Active:=False; + + DesignerSaveSettings; + if D.Trackbar <>nil then D.Designer.Disconnect(D.Trackbar); + if D.TextBlock<>nil then D.Designer.Disconnect(D.TextBlock); + if (D.ShowControls and scButtons)<>0 then FreeButtonsDesigner; + Sender.Update; + end; +end; diff --git a/plugins/Watrack/kolframe/frm_dlg1.inc b/plugins/Watrack/kolframe/frm_dlg1.inc new file mode 100644 index 0000000000..19f590af66 --- /dev/null +++ b/plugins/Watrack/kolframe/frm_dlg1.inc @@ -0,0 +1,283 @@ +{Frame} +const + FSC_BACKGROUND = 1; + FSC_BEHAVIOUR = 2; + FSC_SHOW = 4; +// FSC_ALPHA = 8; + +function MakePicFilter:PWideChar; +var + buf:array [0..255] of WideChar; + size:integer; + pc:pWideChar; +begin + FillChar(buf,SizeOf(buf),0); + pc:=StrCopyEW(StrCopyEW(buf,TranslateW('All Bitmaps')),' (*.bmp;*.jpg;*.gif;*.png)'); + pc:=StrCopyEW(pc+1,'*.BMP;*.RLE;*.JPG;*.JPEG;*.GIF;*.PNG'); + size:=(pc+2-@buf)*SizeOf(WideChar); + mGetMem(result,size); + move(buf,result^,size); +end; + +procedure SwitchBk(Dialog:hwnd); +var + en:boolean; +begin + en:=IsDlgButtonChecked(Dialog,IDC_FRMUSEPIC)<>BST_UNCHECKED; + EnableWindow(GetDlgItem(Dialog,IDC_FRMBKPIC ),en); + EnableWindow(GetDlgItem(Dialog,IDC_FRMPICBTN),en); + EnableWindow(GetDlgItem(Dialog,IDC_CENTERX ),en); + EnableWindow(GetDlgItem(Dialog,IDC_CENTERY ),en); + EnableWindow(GetDlgItem(Dialog,IDC_TILEX ),en); + EnableWindow(GetDlgItem(Dialog,IDC_TILEY ),en); + EnableWindow(GetDlgItem(Dialog,IDC_STRETCHX ),en); + EnableWindow(GetDlgItem(Dialog,IDC_STRETCHY ),en); + EnableWindow(GetDlgItem(Dialog,IDC_PROP ),en); + EnableWindow(GetDlgItem(Dialog,IDC_BOTTOM ),en); + EnableWindow(GetDlgItem(Dialog,IDC_RIGHT ),en); + EnableWindow(GetDlgItem(Dialog,IDC_USECOVER ),en); +end; + +function FrameViewDlg(Dialog:HWnd; hMessage,wParam,lParam:DWord):integer; stdcall; +const + DlgInited:boolean=false; +var + tmp:cardinal; + buf1:PAnsiChar; + buf:PAnsiChar; + p:PAnsiChar; + tmpb:longbool; + pcw,tmpPicName:pWideChar; + D:PWATFrameData; +begin + result:=0; + case hMessage of + WM_INITDIALOG: begin + DlgInited:=false; + + TranslateDialogDefault(Dialog); + D:=FrameCtrl.CustomData; + + SendDlgItemMessage(Dialog,IDC_FRMALPHA,TBM_SETRANGE,0,MAKELONG(0,255)); + SendDlgItemMessage(Dialog,IDC_FRMALPHA,TBM_SETPOS,1,D.FrmAlpha); + + if (D.ShowControls and scButtons )<>0 then CheckDlgButton(Dialog,IDC_SHOWCTRLS,BST_CHECKED); + if (D.ShowControls and scTrackBar)<>0 then CheckDlgButton(Dialog,IDC_SHOWBAR ,BST_CHECKED); + if (D.ShowControls and scText )<>0 then CheckDlgButton(Dialog,IDC_SHOWTEXT ,BST_CHECKED); + if (D.ShowControls and scVolume )<>0 then CheckDlgButton(Dialog,IDC_SHOWVOLUM,BST_CHECKED); + if (D.ShowControls and scGap )<>0 then CheckDlgButton(Dialog,IDC_BTNGAP ,BST_CHECKED); + + MakeHint(Dialog,IDC_MANUALPLACE, + 'Use manual frame elements placement. Doubleclick on free space to start designer.'); + CheckDlgButton(Dialog,IDC_MANUALPLACE,ORD(D.ManualPlacement)); + + CheckDlgButton(Dialog,IDC_HIDEFRAMEPLAYER,ORD(D.HideNoPlayer)); + CheckDlgButton(Dialog,IDC_HIDEFRAMEMUSIC ,ORD(D.HideNoMusic)); + EnableWindow(GetDlgItem(Dialog,IDC_HIDEFRAMEMUSIC),D.HideNoPlayer); + + SendDlgItemMessage(Dialog,IDC_FRMCOLOR,CPM_SETCOLOUR,0,D.BkColor); + SendDlgItemMessage(Dialog,IDC_FRMCOLOR,CPM_SETDEFAULTCOLOUR,0,GetSysColor(COLOR_BTNFACE)); + SetDlgItemInt(Dialog,IDC_FRMCOLOR,D.BkColor,false); + + if D.UseBkPicture then + CheckDlgButton(Dialog,IDC_FRMUSEPIC,ORD(D.UseBkPicture)); + if D.BkDefFile=nil then + p:='' + else + p:=D.BkDefFile; + SetDlgItemTextA(Dialog,IDC_FRMBKPIC,p); + CheckDlgButton(Dialog,IDC_USECOVER,ORD(D.UseCover)); + + tmp:=D.UpdInterval; + if (tmp>=1000) and (tmp mod 1000=0) then + tmp:=tmp div 1000; + SetDlgItemInt(Dialog,IDC_TIMER,tmp,false); + + SetDlgItemInt(Dialog,IDC_PADDING_LEFT ,D.padding.left ,false); + SetDlgItemInt(Dialog,IDC_PADDING_TOP ,D.padding.top ,false); + SetDlgItemInt(Dialog,IDC_PADDING_RIGHT ,D.padding.right ,false); + SetDlgItemInt(Dialog,IDC_PADDING_BOTTOM,D.padding.bottom,false); + + if (D.BkMode and frbkCenterX )<>0 then CheckDlgButton(Dialog,IDC_CENTERX ,BST_CHECKED); + if (D.BkMode and frbkCenterY )<>0 then CheckDlgButton(Dialog,IDC_CENTERY ,BST_CHECKED); + if (D.BkMode and frbkTileX )<>0 then CheckDlgButton(Dialog,IDC_TILEX ,BST_CHECKED); + if (D.BkMode and frbkTileY )<>0 then CheckDlgButton(Dialog,IDC_TILEY ,BST_CHECKED); + if (D.BkMode and frbkStretchX )<>0 then CheckDlgButton(Dialog,IDC_STRETCHX,BST_CHECKED); + if (D.BkMode and frbkStretchY )<>0 then CheckDlgButton(Dialog,IDC_STRETCHY,BST_CHECKED); + if (D.BkMode and frbkProportional)<>0 then CheckDlgButton(Dialog,IDC_PROP ,BST_CHECKED); + if (D.BkMode and frbkBottom )<>0 then CheckDlgButton(Dialog,IDC_BOTTOM ,BST_CHECKED); + if (D.BkMode and frbkRight )<>0 then CheckDlgButton(Dialog,IDC_RIGHT ,BST_CHECKED); + + SwitchBk(Dialog); + + DlgInited:=true; + end; + + WM_HSCROLL: begin + if DlgInited then + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + + WM_COMMAND: begin + if (wParam shr 16)=BN_CLICKED then + begin + case LoWord(wParam) of + IDC_HIDEFRAMEPLAYER: begin + EnableWindow(GetDlgItem(Dialog,IDC_HIDEFRAMEMUSIC), + IsDlgButtonChecked(Dialog,IDC_HIDEFRAMEPLAYER)<>BST_UNCHECKED); + end; + + IDC_FRMUSEPIC: begin + SwitchBk(Dialog); + end; + + IDC_FRMPICBTN: begin + pcw:=MakePicFilter; + tmpPicName:=GetDlgText(Dialog,IDC_FRMBKPIC); + mGetMem(buf,1024); + if ShowDlgW(pWideChar(buf),tmpPicName,pcw) then + SetDlgItemTextW(Dialog,IDC_FRMBKPIC,pWideChar(buf)); + mFreeMem(buf); + mFreeMem(tmpPicName); + mFreeMem(pcw); + end; + end; + end; + + if DlgInited then + if ((wParam shr 16)=BN_CLICKED) or + ((wParam shr 16)=EN_CHANGE) or + ((wParam shr 16)=CPN_COLOURCHANGED) then + begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + + WM_NOTIFY: begin + if integer(PNMHdr(lParam)^.code)=PSN_APPLY then + begin + D:=FrameCtrl.CustomData; + // Alpha channel + tmp:=SendDlgItemMessage(Dialog,IDC_FRMALPHA,TBM_GETPOS,0,0); + if tmp<>Cardinal(D.FrmAlpha) then + begin + D.FrmAlpha:=tmp; + if D.FrameId>=0 then + FrameCtrl.SetAlpha(D.FrmAlpha); + end; + + // show/hide controls + tmp:=0; + if IsDlgButtonChecked(Dialog,IDC_SHOWCTRLS)<>BST_UNCHECKED then tmp:=tmp or scButtons; + if IsDlgButtonChecked(Dialog,IDC_SHOWBAR )<>BST_UNCHECKED then tmp:=tmp or scTrackBar; + if IsDlgButtonChecked(Dialog,IDC_SHOWTEXT )<>BST_UNCHECKED then tmp:=tmp or scText; + if IsDlgButtonChecked(Dialog,IDC_SHOWVOLUM)<>BST_UNCHECKED then tmp:=tmp or scVolume; + if IsDlgButtonChecked(Dialog,IDC_BTNGAP )<>BST_UNCHECKED then tmp:=tmp or scGap; + D.ShowControls:=tmp; + + tmp:=IsDlgButtonChecked(Dialog,IDC_MANUALPLACE); + // From Auto to Manual = keep position + if (tmp<>BST_UNCHECKED) and not D.ManualPlacement then D.Loaded:=$FFFF; + D.ManualPlacement:=tmp<>BST_UNCHECKED; + + // Frame background + tmpb:=IsDlgButtonChecked(Dialog,IDC_USECOVER)<>BST_UNCHECKED; + if tmpb<>D.UseCover then + begin + D.UseCover:=tmpb; + end; + tmpb:=IsDlgButtonChecked(Dialog,IDC_FRMUSEPIC)<>BST_UNCHECKED; + if tmpb<>D.UseBkPicture then + begin + D.UseBkPicture:=tmpb; + end; + tmp:=SendDlgItemMessage(Dialog,IDC_FRMCOLOR,CPM_GETCOLOUR,0,0); + if tmp<>D.BkColor then + begin + D.BkColor:=tmp; + end; + + mGetMem(buf1,1024{*SizeOf(WideChar)}); + buf1^:=#0; + buf:=GetDlgText(Dialog,IDC_FRMBKPIC,true); + CallService(MS_UTILS_PATHTORELATIVE,dword(buf),dword(buf1)); + if StrCmp(buf1,D.BkDefFile)<>0 then + begin + mFreeMem(D.BkDefFile); + StrDup(D.BkDefFile,buf1); + end; + mFreeMem(buf); + mFreeMem(buf1); + + // Picture effects + tmp:=0; + if IsDlgButtonchecked(Dialog,IDC_CENTERX )<>BST_UNCHECKED then tmp:=tmp or frbkCenterX; + if IsDlgButtonchecked(Dialog,IDC_CENTERY )<>BST_UNCHECKED then tmp:=tmp or frbkCenterY; + if IsDlgButtonchecked(Dialog,IDC_BOTTOM )<>BST_UNCHECKED then tmp:=tmp or frbkBottom; + if IsDlgButtonchecked(Dialog,IDC_RIGHT )<>BST_UNCHECKED then tmp:=tmp or frbkRight; + if IsDlgButtonchecked(Dialog,IDC_TILEX )<>BST_UNCHECKED then tmp:=tmp or frbkTileX; + if IsDlgButtonchecked(Dialog,IDC_TILEY )<>BST_UNCHECKED then tmp:=tmp or frbkTileY; + if IsDlgButtonchecked(Dialog,IDC_STRETCHX)<>BST_UNCHECKED then tmp:=tmp or frbkStretchX; + if IsDlgButtonchecked(Dialog,IDC_STRETCHY)<>BST_UNCHECKED then tmp:=tmp or frbkStretchY; + if IsDlgButtonchecked(Dialog,IDC_PROP )<>BST_UNCHECKED then tmp:=tmp or frbkProportional; + + if tmp<>D.BkMode then + begin + D.BkMode:=tmp; + end; + + // Hide frame option + tmpb :=IsDlgButtonChecked(Dialog,IDC_HIDEFRAMEPLAYER)<>BST_UNCHECKED; + if tmpb<>D.HideNoPlayer then + begin + D.HideNoPlayer:=tmpb; + end; + tmpb:=IsDlgButtonChecked(Dialog,IDC_HIDEFRAMEMUSIC)<>BST_UNCHECKED; + if tmpb<>D.HideNoMusic then + begin + D.HideNoMusic:=tmpb; + end; + + // Padding + tmp:=GetDlgItemInt(Dialog,IDC_PADDING_LEFT,tmpb,false); + if integer(tmp)<>D.padding.left then + begin + D.padding.left:=tmp; + end; + tmp:=GetDlgItemInt(Dialog,IDC_PADDING_TOP,tmpb,false); + if integer(tmp)<>D.padding.top then + begin + D.padding.top:=tmp; + end; + tmp:=GetDlgItemInt(Dialog,IDC_PADDING_RIGHT,tmpb,false); + if integer(tmp)<>D.padding.right then + begin + D.padding.right:=tmp; + end; + tmp:=GetDlgItemInt(Dialog,IDC_PADDING_BOTTOM,tmpb,false); + if integer(tmp)<>D.padding.bottom then + begin + D.padding.bottom:=tmp; + end; + + tmp:=GetDlgItemInt(Dialog,IDC_TIMER,tmpb,false); + if tmp>0 then + begin + if tmp<100 then + tmp:=tmp*1000; + if tmp<200 then + tmp:=200; + end; + + if tmp<>D.UpdInterval then + begin + D.UpdInterval:=tmp; + end; + + FrameCtrl.SaveSettings; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/kolframe/frm_dlg2.inc b/plugins/Watrack/kolframe/frm_dlg2.inc new file mode 100644 index 0000000000..6325e05fcd --- /dev/null +++ b/plugins/Watrack/kolframe/frm_dlg2.inc @@ -0,0 +1,172 @@ +{Frame text} +const + MaxTxtScrollSpeed = 20; + +function FrameTextDlg(Dialog:HWnd; hMessage,wParam,lParam:DWord):integer; stdcall; +const + DlgInited :boolean=false; + TemplateChanged:Boolean=false; +var + tmp,tmp1:integer; + tmpb:longbool; + pcf:TCHOOSEFONT; + lf:LOGFONTW; +begin + result:=0; + + case hMessage of + WM_DESTROY: begin + // new - if Apply, old - if cancel + if FrameCtrl<>nil then // for case when FrameCtrl was destryed already + if PWATFrameData(FrameCtrl.CustomData).TextBlock<>nil then + PWATFrameData(FrameCtrl.CustomData).TextBlock.FontData:=TextLF; + end; + + WM_INITDIALOG: begin + DlgInited:=false; + TranslateDialogDefault(Dialog); + with PWATFrameData(FrameCtrl.CustomData).TextBlock^ do + begin + case LoByte(Effects) of + effWrap: tmp:=IDC_EFF_WRAP; + effRoll: tmp:=IDC_EFF_ROLL; + effPong: tmp:=IDC_EFF_PONG; + else // like effCut + tmp:=IDC_EFF_CUT; + end; + CheckDlgButton(Dialog,tmp,BST_CHECKED); + + SetDlgItemInt(Dialog,IDC_TIMER,UpdateTime,false); + + SetDlgItemInt(Dialog,IDC_ROLLSTEP,RollStep,false); + SetDlgItemInt(Dialog,IDC_ROLLGAP ,RollGap ,false); + // SetDlgItemInt(Dialog,IDC_ROLLTAIL,RollTail,false); + + CheckDlgButton(Dialog,IDC_ALCENTER,ord((Effects and effCenter)<>0)); + + SetDlgItemTextW(Dialog,IDC_FRAME_TEXT,PWATFrameData(FrameCtrl.CustomData).Template); + end; + + SendDlgItemMessage(Dialog,IDC_MACRO_HELP,BM_SETIMAGE,IMAGE_ICON, + CallService(MS_SKIN_LOADICON,SKINICON_OTHER_HELP,0)); + + TemplateChanged:=false; + DlgInited:=true; + end; + + WM_COMMAND: begin + case (wParam shr 16) of + EN_CHANGE: begin + if Loword(wParam)=IDC_FRAME_TEXT then + TemplateChanged:=True; + end; + + BN_CLICKED: begin + case LoWord(wParam) of + IDC_MACRO_HELP: CallService(MS_WAT_MACROHELP,Dialog,0); + IDC_FRMFONT: begin + with PWATFrameData(FrameCtrl.CustomData).TextBlock^ do + begin + lf:=FontData; + // lf:=TextLF; + FillChar(pcf,sizeOf(pcf),0); + with pcf do + begin + lStructSize:=SizeOf(pcf); + lpLogFont:=@lf; + Flags:=CF_EFFECTS+CF_FORCEFONTEXIST+CF_LIMITSIZE+CF_NOVERTFONTS+ + CF_SCREENFONTS+CF_INITTOLOGFONTSTRUCT; + rgbColors:=TextColor; + nSizeMin:=6; + nSizeMax:=32; + end; + if ChooseFont(pcf) then + begin + FontData:=lf; // paint directly + TextColor:=pcf.rgbColors; + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end + else + exit; + end; + end; + end; + end; + end; + + if DlgInited then + case wParam shr 16 of + BN_CLICKED, + EN_CHANGE: begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + end; + + WM_NOTIFY: begin + if integer(PNMHdr(lParam)^.code)=PSN_APPLY then + begin +// redraw:=false; + with PWATFrameData(FrameCtrl.CustomData).TextBlock^ do + begin + tmp:=GetDlgItemInt(Dialog,IDC_TIMER,tmpb,false); + if tmp>MaxTxtScrollSpeed then + tmp:=MaxTxtScrollSpeed; + + if tmp<>UpdateTime then + begin + UpdateTime:=tmp; +{ + if UpdTimer<>0 then + KillTimer(FrameWnd,UpdTimer); + if (UpdInterval>0) and (FrameWnd<>0) then + UpdTimer:=SetTimer(FrameWnd,TMR_TEXT,(MaxTxtScrollSpeed+1-UpdInterval)*100,nil) + else + UpdTimer:=0; +} + end; + + // Text effects + if IsDlgButtonChecked(Dialog,IDC_EFF_CUT )<>BST_UNCHECKED then tmp:=effCut + else if IsDlgButtonChecked(Dialog,IDC_EFF_WRAP)<>BST_UNCHECKED then tmp:=effWrap + else if IsDlgButtonChecked(Dialog,IDC_EFF_ROLL)<>BST_UNCHECKED then tmp:=effRoll + else if IsDlgButtonChecked(Dialog,IDC_EFF_PONG)<>BST_UNCHECKED then tmp:=effPong; + if IsDlgButtonChecked(Dialog,IDC_ALCENTER)<>BST_UNCHECKED then + tmp:=tmp or effCenter; + Effects:=tmp; + + tmp1:=GetDlgItemInt(Dialog,IDC_ROLLSTEP,tmpb,false); + if tmp1<>RollStep then + begin + RollStep:=tmp1; + end; + tmp1:=GetDlgItemInt(Dialog,IDC_ROLLGAP ,tmpb,false); + if tmp1<>RollGap then + begin + RollGap:=tmp1; + end; + { + tmp1:=GetDlgItemInt(Dialog,IDC_ROLLTAIL,tmpb,false); + if tmp1<>RollTail then + begin + RollTail:=tmp1; + end; + } + + if TemplateChanged then + begin + mFreeMem(PWATFrameData(FrameCtrl.CustomData).Template); + PWATFrameData(FrameCtrl.CustomData).Template:=GetDlgText(Dialog,IDC_FRAME_TEXT); + end; + + TextLF:=FontData; // OK - saving for future? + + SaveTextSettings(TemplateChanged); + TemplateChanged:=false; + end; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/kolframe/frm_frame.inc b/plugins/Watrack/kolframe/frm_frame.inc new file mode 100644 index 0000000000..8c3034327c --- /dev/null +++ b/plugins/Watrack/kolframe/frm_frame.inc @@ -0,0 +1,497 @@ +{Frame + background} + +const + WS_EX_LAYERED = $00080000; + +function SetLayeredWindowAttributes(Hwnd: THandle; crKey: COLORREF; bAlpha: Byte; dwFlags: DWORD): Boolean; stdcall; + external user32 name 'SetLayeredWindowAttributes'; + +const + defFrameText = '%artist% - %title%'; + +const +// opt_HiddenByMe:PAnsiChar = 'frame/hiddenbyme'; + opt_ShowCtrls :PAnsiChar = 'frame/showcontrols'; + opt_FrmUsePic :PAnsiChar = 'frame/frmusepic'; + opt_FrmUseCvr :PAnsiChar = 'frame/frmusecover'; + opt_FrmBkColor:PAnsiChar = 'frame/frmbkcolor'; + opt_FrmBkPic :PAnsiChar = 'frame/frmbkpic'; + opt_FrmBkMode :PAnsiChar = 'frame/frmbkmode'; + opt_FrmAlpha :PAnsiChar = 'frame/frmalpha'; + opt_HideFrameM:PAnsiChar = 'frame/hideframem'; + opt_HideFrameP:PAnsiChar = 'frame/hideframep'; + opt_FrmTimer :PAnsiChar = 'frame/frametimer'; + opt_PadLeft :PAnsiChar = 'frame/paddingleft'; + opt_PadTop :PAnsiChar = 'frame/paddingtop'; + opt_PadRight :PAnsiChar = 'frame/paddingright'; + opt_PadBottom :PAnsiChar = 'frame/paddingbottom'; + opt_Manual :PAnsiChar = 'frame/manualplacement'; + +procedure TWATFrame.ResetFrame; +var + D:PWATFrameData; +begin + D:=CustomData; + if D.Trackbar <>nil then ResetTrackbar(D.Trackbar); + if D.TextBlock<>nil then D.TextBlock.BlockText:=nil; +// frame back to default + RefreshPicture(nil); +end; + +procedure FrameTimerProc(wnd:HWND;uMsg:uint;idEvent:uint_ptr;dwTime:dword); stdcall; +var + psi:pSongInfo; + D:PWATFrameData; +begin + D:=FrameCtrl.CustomData; + + if IsFrameHidden(D.FrameId) then + begin + if not D.wasHidden then + begin + D.wasHidden:=true; + D.TextBlock.UpdateTime:=0; + end; + exit; + end + else if D.wasHidden and (D.TextBlock.UpdateTime=0) then + begin + D.wasHidden:=false; + if (D.ShowControls and scText)<>0 then + D.TextBlock.UpdateTime:=DBReadWord(0,PluginShort,opt_TxtTimer,10); + end; + + if D.Trackbar<>nil then + begin + if (CallService(MS_WAT_GETMUSICINFO,WAT_INF_CHANGES,dword(@psi))<>WAT_PLS_NOTFOUND) then + begin + SetTrackBarPosition(D.Trackbar,(psi^.time*1000) div D.UpdInterval) + end; + end; + + UpdateTextBlock(D,false); // false - check for %percent%/%time% + + FrameCtrl.Update; +end; + +procedure TWATFrame.AdjustFrame; +var + h:integer; + D:PWATFrameData; +begin + D:=CustomData; + + if D.ManualPlacement then + begin + if D.Trackbar <>nil then D.Trackbar .Anchor(false,false,false,false); + if D.TextBlock<>nil then D.TextBlock.Anchor(false,false,false,false); + DesignerLoadSettings; + exit; + end; + + h:=Height; // or need to get FRAME height + + if D.Trackbar<>nil then + begin + D.Trackbar.SetSize(Width-16,18); + dec(h,D.Trackbar.Height); + D.Trackbar.SetPosition(8,h); + D.Trackbar.Anchor(true,false,true,true); + end; + + if (D.ShowControls and scButtons)<>0 then + begin + AdjustButtons(h-16-BtnGap); + dec(h,16+2*BtnGap); + end; + + if D.TextBlock<>nil then + begin + D.TextBlock.Top :=awkTextPad; + D.TextBlock.Height:=h-D.TextBlock.Top; + D.TextBlock.Anchor(true,true,true,true); + end; +end; + +procedure TWATFrame.SaveSettings; +var + D:PWATFrameData; +begin + D:=CustomData; + DBWriteByte (0,PluginShort,opt_Manual ,ord(D.ManualPlacement)); + DBWriteByte (0,PluginShort,opt_HideFrameM,ord(D.HideNoMusic)); + DBWriteByte (0,PluginShort,opt_HideFrameP,ord(D.HideNoPlayer)); + DBWriteByte (0,PluginShort,opt_FrmUsePic ,ord(D.UseBkPicture)); + DBWriteByte (0,PluginShort,opt_FrmUseCvr ,ord(D.UseCover)); + DBWriteDWord (0,PluginShort,opt_FrmBkColor,D.BkColor); + DBWriteWord (0,PluginShort,opt_FrmBkMode ,D.BkMode); + DBWriteDWord (0,PluginShort,opt_ShowCtrls ,D.ShowControls); + DBWriteByte (0,PluginShort,opt_FrmAlpha ,D.FrmAlpha); + DBWriteWord (0,PluginShort,opt_FrmTimer ,D.UpdInterval); + DBWriteWord (0,PluginShort,opt_PadLeft ,D.padding.left); + DBWriteWord (0,PluginShort,opt_PadTop ,D.padding.top); + DBWriteWord (0,PluginShort,opt_PadRight ,D.padding.right); + DBWriteWord (0,PluginShort,opt_PadBottom ,D.padding.bottom); + DBWriteString(0,PluginShort,opt_FrmBkPic ,D.BkDefFile); + + CheckControls; + AdjustFrame; + RefreshPicture; + InvalidateRect(FrameCtrl.GetWindowHandle,nil,true); + FrameCtrl.Update; + + if D.UpdTimer<>0 then // FrameWnd MUST be present + begin + KillTimer(0,D.UpdTimer); + D.UpdTimer:=0; + end; + if D.UpdInterval>0 then + begin + D.UpdTimer:=SetTimer(0,0,D.UpdInterval,@FrameTimerProc); + end; +end; + +procedure TWATFrame.LoadSettings; +var + D:PWATFrameData; +begin + D:=CustomData; + D.ManualPlacement:=DBReadByte (0,PluginShort,opt_Manual ,0)<>0; + D.HideNoMusic :=DBReadByte (0,PluginShort,opt_HideFrameM,0)<>0; + D.HideNoPlayer :=DBReadByte (0,PluginShort,opt_HideFrameP,0)<>0; + D.UseBkPicture :=DBReadByte (0,PluginShort,opt_FrmUsePic ,0)<>0; + D.UseCover :=DBReadByte (0,PluginShort,opt_FrmUseCvr ,0)<>0; + D.BkColor :=DBReadDWord(0,PluginShort,opt_FrmBkColor,$00E0E0E0); + D.BkMode :=DBReadWord (0,PluginShort,opt_FrmBkMode ,frbkCenter); + D.ShowControls :=DBReadDWord(0,PluginShort,opt_ShowCtrls ,scAll); + D.FrmAlpha :=DBReadByte (0,PluginShort,opt_FrmAlpha ,255); + + D.UpdInterval:=DBReadWord(0,PluginShort,opt_FrmTimer,200); + if D.UpdInterval<100 then + D.UpdInterval:=D.UpdInterval*1000; + + D.padding.left :=DBReadWord(0,PluginShort,opt_PadLeft ,0); + D.padding.top :=DBReadWord(0,PluginShort,opt_PadTop ,0); + D.padding.right :=DBReadWord(0,PluginShort,opt_PadRight ,0); + D.padding.bottom:=DBReadWord(0,PluginShort,opt_PadBottom,0); + + D.BkDefFile:=DBReadString(0,PluginShort,opt_FrmBkPic,nil); + //!!!! saving NOT in TextBlock + D.Template:=DBReadUnicode(0,PluginShort,opt_FrameText,DefFrameText); +end; + +{$include i_bitmap.inc} + +procedure TWATFrame.SetAlpha(value:integer); +const + LWA_COLORKEY = $00000001; + LWA_ALPHA = $00000002; +var + wnd:HWND; + x:cardinal; +begin + if IsFrameFloated(PWATFrameData(CustomData).FrameId) then + begin + wnd:=GetParent(FrameCtrl.GetWindowHandle); + x:=GetWindowLongW(wnd,GWL_EXSTYLE); + if value<>255 then + begin + if (x and WS_EX_LAYERED)=0 then + SetWindowLongW(wnd,GWL_EXSTYLE,x or WS_EX_LAYERED); + SetLayeredWindowAttributes(wnd,0,value,LWA_ALPHA); + end + else if (x and WS_EX_LAYERED)<>0 then + SetWindowLongW(wnd,GWL_EXSTYLE,x and not WS_EX_LAYERED); + end; +end; + +procedure TWATFrame.FrameResize(Sender: PObj); +var + tmpBmp:HBITMAP; + D:PWATFrameData; +begin + D:=CustomData; + if D.BkDC<>0 then + begin + tmpBmp:=GetCurrentObject(D.BkDC,OBJ_BITMAP); + DeleteDC(D.BkDC); + D.BkDC:=0; + DeleteObject(tmpBmp); + end; + AdjustFrame; +end; + +procedure BkTimerProc(wnd:HWND;uMsg:uint;idEvent:uint_ptr;dwTime:dword); stdcall; +var + D:PWATFrameData; +begin + D:=FrameCtrl.CustomData; + KillTimer(0,D.BkTimer); + D.BkTimer:=0; + DeleteObject(D.BkBitmap); + D.BkBitmap:=0; +end; + +procedure TWATFrame.RefreshPicture(cover:PAnsiChar=nil); +var + D:PWATFrameData; +begin + D:=CustomData; + if D.BkBitmap<>0 then + BkTimerProc(0,0,0,0); // remove old picture + + FrameResize(nil); // clear frame bitmap buffer + + if D.UseBkPicture then + D.BkBitmap:=LoadBkPicture(cover,true,D.BkDefFile); + + if D.BkBitmap=HBITMAP(-1) then // same file + D.BkBitmap:=0; + Update; +end; + +procedure TWATFrame.Paint(Sender: PControl; DC: HDC); +var + rc: TRect; + br:HBRUSH; + D:PWATFrameData; +begin + D:=CustomData; + GetClientRect(Sender.Handle,rc); + if D.UseBkPicture then + begin + if D.BkDC=0 then + begin + if D.BkBitmap=0 then + begin + if (D.BkFile<>nil) and (D.BkFile^<>#0) then + D.BkBitmap:=CallService(MS_UTILS_LOADBITMAP,0,dword(D.BkFile)); + end; + + if D.BkBitmap<>0 then + begin + PreparePicture(dc,rc); + D.BkTimer:=SetTimer(0,0,10000,@BkTimerProc); + end; + end; + if D.BkDC<>0 then + begin + BitBlt(dc,rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top, + D.BkDC,rc.left,rc.top,SRCCOPY); + exit; + end; + end; + + InflateRect(rc,1,1); + br:=CreateSolidBrush(D.BkColor); + FillRect(dc,rc,br); + DeleteObject(br); +end; + +// JUST LOAD picture, no matter, which transforms +// Backname = from settings, Covername = from data (higher priority) +// -1 - same file, 0 - can't load, other - new bitmap +function TWATFrame.LoadBkPicture(CoverFName:PAnsiChar;check:boolean=false; + BackFName:PAnsiChar=nil):integer; +var + tmpstr:PAnsiChar; + D:PWATFrameData; +begin + result:=0; + D:=CustomData; + + // check the same file, ie only 'next pic' + if (CoverFName<>nil) and (CoverFName^<>#0) then + begin + if check and (StrCmp(CoverFName,D.BkFile)=0) then + begin + result:=-1; + Exit; + end; + + result:=CallService(MS_UTILS_LOADBITMAP,0,dword(CoverFName)); + if result<>0 then + begin + mFreeMem(D.BkFile); + StrDup(D.BkFile,CoverFName); + Exit; + end; + end; + + if (BackFName<>nil) and (BackFName^<>#0) then + begin + tmpstr:=ParseVarString(BackFName); + if (tmpstr<>nil) and (tmpstr^<>#0) then + begin + if (not check) or (StrCmp(tmpstr,D.BkFile)<>0) then + begin + result:=CallService(MS_UTILS_LOADBITMAP,0,dword(tmpstr)); + if result<>0 then + begin + mFreeMem(D.BkFile); + StrDup(D.BkFile,tmpstr); + end; + end + else + result:=-1; + end; + mFreeMem(tmpstr); + end; +end; + +procedure TWATFrame.ClearBitmapData; +var + D:PWATFrameData; + tmpBmp:HBITMAP; +begin + D:=CustomData; + + if D.BkTimer<>0 then + begin + KillTimer(0,D.BkTimer); + D.BkTimer:=0; + end; + if D.BkDC<>0 then + begin + tmpBmp:=GetCurrentObject(D.BkDC,OBJ_BITMAP); + DeleteDC(D.BkDC); + D.BkDC:=0; + DeleteObject(tmpBmp); + end; + if D.BkBitmap<>0 then + begin + DeleteObject(D.BkBitmap); + D.BkBitmap:=0; + end; + mFreeMem(D.BkFile); +end; + +procedure TWATFrame.MyDestroy(sender:PObj); +var + D:PWATFrameData; +begin + D:=CustomData; + if D.UpdTimer<>0 then + begin + KillTimer(0,D.UpdTimer); + D.UpdTimer:=0; + end; + + mFreeMem(D.Template); + mFreeMem(D.BkDefFile); + ClearBitmapData; + + if D.Designer<>nil then + begin + D.Designer.Free; + D.Designer:=nil; + end; + +end; + +procedure TWATFrame.RefreshAllFrameIcons; +var + D:PWATFrameData; +begin + D:=CustomData; + if (D.ShowControls and scButtons)<>0 then RefreshButtonIcons; + if D.Trackbar<>nil then RefreshTrackbarIcons(D.Trackbar); +end; + +procedure TWATFrame.CheckControls; +var + D:PWATFrameData; + psi:pSongInfo; +begin + D:=CustomData; + + if (D.ShowControls and scTrackBar)<>0 then + begin + if D.Trackbar=nil then + begin + RegisterButtonIcons; + D.Trackbar:=MakeNewTrackbar(@self); + // for case when TB creating after track start (fastest way) + // can use (CallService(MS_WAT_GETMUSICINFO,WAT_INF_CHANGES,dword(@psi))<>WAT_PLS_NOTFOUND) + psi:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,1)); + TrackbarSetRange(D.Trackbar,D.UpdInterval,psi^.total); + end; + end + else if D.Trackbar<>nil then + begin + D.Trackbar.Free; + D.Trackbar:=nil; + end; + + if (D.ShowControls and scButtons)<>0 then + begin + if D.btnarray[0]=nil then + begin + if RegisterButtonIcons then + MakeNewButtonGroup; + end + end + else if D.btnarray[0]<>nil then + FreeButtons; +{ + if (D.ShowControls and scText)<>0 then + begin +} + if D.TextBlock=nil then + begin + D.TextBlock:=MakeTextBlock(@self,D.BkColor); + end; + + if (D.ShowControls and scText)<>0 then + D.TextBlock.UpdateTime:=DBReadWord(0,PluginShort,opt_TxtTimer,10); +{ + end + else if D.TextBlock<>nil then + begin + D.TextBlock.Free; + D.TextBlock:=nil; + end; +} + if D.UseBkPicture then + begin + D.BkBitmap:=LoadBkPicture(nil,true,D.BkDefFile); + if D.BkBitmap=HBITMAP(-1) then + D.BkBitmap:=0; + end + else + ClearBitmapData; +end; + +function CreateFrameWindow(parent:HWND):THANDLE; +var + D:PWATFrameData; +begin + result:=0; + + FrameCtrl:=PWATFrame(NewAlienPanel(parent,esNone)); + if FrameCtrl<>nil then + begin + GetMem (D ,SizeOf(TWATFrameData)); + FillChar(D^,SizeOf(TWATFrameData),0); // clear all including buttons + with FrameCtrl^ do + begin + CustomData:=D; + LoadSettings; + + result:=GetWindowHandle; + + CheckControls; + + MinWidth :=80; + MinHeight:=30; + + OnPaint :=FrameCtrl.Paint; + OnResize :=FrameCtrl.FrameResize; +// OnMouseDown :=TOnMouse(MakeMethod(nil, @MouseDown)); + OnMouseDblClk:=FrameCtrl.CreateDesigner; + end; + FrameCtrl.OnDestroy:=FrameCtrl.MyDestroy; +// theoretically, must get Resize here.... or after +// FrameCtrl.AdjustFrame; + end; +end; diff --git a/plugins/Watrack/kolframe/frm_icogroup.inc b/plugins/Watrack/kolframe/frm_icogroup.inc new file mode 100644 index 0000000000..2b6e9de6f9 --- /dev/null +++ b/plugins/Watrack/kolframe/frm_icogroup.inc @@ -0,0 +1,115 @@ +{Panel = group of icons} + +procedure TWATFrame.AdjustButtons(atop:integer); +var + i,lWidth,lOffs,gap:integer; + lleft:integer; + D:PWATFrameData; +begin + D:=CustomData; + + if D.btnarray[0]=nil then exit; + + if (D.ShowControls and scGap)<>0 then + gap:=BtnGap + else + gap:=0; + + D.btnarray[0].Visible:=(D.ShowControls and scVolume)<>0; + D.btnarray[1].Visible:=(D.ShowControls and scVolume)<>0; + + lWidth:=(Length(D.btnarray)-2)*(16+gap)-gap; + if (D.ShowControls and scVolume)<>0 then + Inc(lWidth, VolBtnDist+2*(16+gap)); + lLeft:=(Width-lWidth) div 2; + + lOffs:=0; + if (D.ShowControls and scVolume)<>0 then + begin + D.btnarray[0].Left:=lleft+lOffs; + D.btnarray[0].Top :=atop; + Inc(lOffs,16+gap); + D.btnarray[1].Left:=lleft+lOffs; + D.btnarray[1].Top :=atop; + Inc(lOffs,16+gap+VolBtnDist); + end; + + for i:=2 to HIGH(D.btnarray) do + begin + D.btnarray[i].Left:=lleft+lOffs; + D.btnarray[i].Top :=atop; + Inc(lOffs,16+gap); + end; + +end; + +procedure TWATFrame.RefreshButtonIcons; +var + i:integer; + D:PWATFrameData; +begin + D:=CustomData; + + if D.btnarray[0]<>nil then exit; + + for i:=0 to HIGH(D.btnarray) do + D.btnarray[i].RefreshIcon; +end; + +procedure TWATFrame.FreeButtonsDesigner; +var + i:integer; + D:PWATFrameData; +begin + D:=CustomData; + + if D.btnarray[0]<>nil then exit; + + for i:=0 to HIGH(D.btnarray) do + D.Designer.Disconnect(D.btnarray[i]); +end; + +procedure TWATFrame.MakeButtonsDesigner; +var + i:integer; + D:PWATFrameData; +begin + D:=CustomData; + + if D.btnarray[0]<>nil then exit; + + for i:=0 to HIGH(D.btnarray) do + D.Designer.Connect('Button',D.btnarray[i],DESIGNER_NORESIZE); +end; + +procedure TWATFrame.FreeButtons; +var + i:integer; + D:PWATFrameData; +begin + D:=CustomData; + + if D.btnarray[0]<>nil then exit; + + for i:=0 to HIGH(D.btnarray) do + begin + D.btnarray[i].Free; + D.btnarray[i]:=nil; + end; +end; + +procedure TWATFrame.MakeNewButtonGroup; +var + D:PWATFrameData; +begin + D:=CustomData; + + D.btnarray[0]:=CreateIcoButton(@self,waticons.GetIcon,DoAction,WAT_CTRL_VOLDN,300); + D.btnarray[1]:=CreateIcoButton(@self,waticons.GetIcon,DoAction,WAT_CTRL_VOLUP,300); + D.btnarray[2]:=CreateIcoButton(@self,waticons.GetIcon,DoAction,WAT_CTRL_PREV,2000); + D.btnarray[3]:=CreateIcoButton(@self,waticons.GetIcon,DoAction,WAT_CTRL_PLAY); + D.btnarray[4]:=CreateIcoButton(@self,waticons.GetIcon,DoAction,WAT_CTRL_PAUSE); + D.btnarray[5]:=CreateIcoButton(@self,waticons.GetIcon,DoAction,WAT_CTRL_STOP); + D.btnarray[6]:=CreateIcoButton(@self,waticons.GetIcon,DoAction,WAT_CTRL_NEXT,2000); +end; + diff --git a/plugins/Watrack/kolframe/frm_rc.inc b/plugins/Watrack/kolframe/frm_rc.inc new file mode 100644 index 0000000000..25ac437b3b --- /dev/null +++ b/plugins/Watrack/kolframe/frm_rc.inc @@ -0,0 +1,56 @@ +{DLG 5 - frame} +const + IDC_HELP_FORMAT = 1025; + IDC_HELP_COLOR = 1026; + IDC_HELP_VARIABLES = 1027; +const + IDC_TIMER = 1028; + IDC_SHOWCTRLS = 1032; + IDC_SHOWTEXT = 1033; + IDC_SHOWVOLUM = 1034; + IDC_FRMCOLOR = 1036; + IDC_FRMUSEPIC = 1037; + IDC_FRMBKPIC = 1038; + IDC_FRMPICBTN = 1039; + IDC_CENTERX = 1040; + IDC_CENTERY = 1041; + IDC_TILEX = 1042; + IDC_TILEY = 1043; + IDC_STRETCHX = 1044; + IDC_STRETCHY = 1045; + IDC_PROP = 1046; + IDC_BOTTOM = 1047; + IDC_RIGHT = 1048; + IDC_FRMALPHA = 1049; + IDC_TRACKBAR = 1050; + IDC_BTNGAP = 1051; + IDC_SHOWBAR = 1052; + IDC_USECOVER = 1053; + + IDC_HIDEFRAMEMUSIC = 1054; + IDC_HIDEFRAMEPLAYER = 1055; + + IDC_PADDING_LEFT = 1056; + IDC_PADDING_TOP = 1057; + IDC_PADDING_RIGHT = 1058; + IDC_PADDING_BOTTOM = 1059; + + IDC_MANUALPLACE = 1060; + +{DLG 51 - frame 2} + IDC_FRMTXT = 1031; + IDC_EFF_CUT = 1032; + IDC_EFF_WRAP = 1033; + IDC_EFF_ROLL = 1034; + IDC_EFF_PONG = 1035; + IDC_ROLLSTEP = 1036; + IDC_ROLLGAP = 1037; +// IDC_ROLLTAIL = 1038; + IDC_ALCENTER = 1039; + IDC_FRMFONT = 1040; + + IDC_FRAME_TEXT = 1041; + IDC_MACRO_HELP = 1042; + +{Frame} + IDC_FRM_POS = 1032; diff --git a/plugins/Watrack/kolframe/frm_text.inc b/plugins/Watrack/kolframe/frm_text.inc new file mode 100644 index 0000000000..66c00a1b2b --- /dev/null +++ b/plugins/Watrack/kolframe/frm_text.inc @@ -0,0 +1,90 @@ +{Text} + +const + TextLF:TLOGFONTW = ( + lfHeight :-10; + lfWidth :0; + lfEscapement :0; + lfOrientation :0; + lfWeight :FW_DONTCARE; + lfItalic :0; + lfUnderline :0; + lfStrikeOut :0; + lfCharSet :DEFAULT_CHARSET; + lfOutPrecision :OUT_DEFAULT_PRECIS; + lfClipPrecision :CLIP_DEFAULT_PRECIS; + lfQuality :DEFAULT_QUALITY; + lfPitchAndFamily:DEFAULT_PITCH or FF_DONTCARE{; + lfFaceName :#0}); + +const + opt_FrmTxtClr :PAnsiChar = 'frame/frametextcolor'; + opt_FrmFont :PAnsiChar = 'frame/framefont'; + opt_FrmEffect :PAnsiChar = 'frame/txteffect'; + opt_RollStep :PAnsiChar = 'frame/rollstep'; + opt_RollGap :PAnsiChar = 'frame/rollgap'; +// opt_RollTail :PAnsiChar = 'frame/rolltail'; + opt_AlgnCenter:PAnsiChar = 'frame/aligncenter'; + opt_TxtTimer :PAnsiChar = 'frame/texttimer'; + opt_FrameText :PAnsiChar = 'frame/frametext'; + +procedure UpdateTextBlock(D:PWATFrameData;force:boolean); +var + tmp:pWideChar; +begin + if (D.ShowControls and scText)=0 then exit; + if D.TextBlock=nil then exit; + + if not force then + begin + if (StrPosW(D.Template,'%percent%')=nil) and + (StrPosW(D.Template,'%time%' )=nil) then // need to |remake + exit; + end; + tmp:=pWideChar(CallService(MS_WAT_REPLACETEXT,0,dword(D.Template))); + D.TextBlock.BlockText:=tmp; + mFreeMem(tmp); +end; + +procedure SaveTextSettings(withtemplate:boolean); +var + D:PWATFrameData; +begin + D:=FrameCtrl.CustomData; + if D.TextBlock=nil then exit; + +// DBWriteByte (0,PluginShort,opt_RollTail ,RollTail); + DBWriteDWord(0,PluginShort,opt_FrmTxtClr,D.TextBlock.TextColor); // reaction on chunk? + DBWriteByte (0,PluginShort,opt_RollStep ,D.TextBlock.RollStep); + DBWriteByte (0,PluginShort,opt_RollGap ,D.TextBlock.RollGap); + DBWriteWord (0,PluginShort,opt_FrmEffect,D.TextBlock.Effects); + DBWriteWord (0,PluginShort,opt_TxtTimer ,D.TextBlock.UpdateTime); + + DBWriteStruct(0,PluginShort,opt_FrmFont,@TextLF,SizeOf(TLOGFONT)); + + if withtemplate then + begin + DBWriteUnicode(0,PluginShort,opt_FrameText,D.Template); + UpdateTextBlock(D,true); + end; +end; + +procedure LoadTextSettings(TB:pTextBlock); +begin + if TB=nil then exit; +// RollTail :=DBReadByte (0,PluginShort,opt_RollTail ,20); + TB.RollStep :=DBReadByte (0,PluginShort,opt_RollStep ,2); + TB.RollGap :=DBReadByte (0,PluginShort,opt_RollGap ,16); + TB.TextColor :=DBReadDWord(0,PluginShort,opt_FrmTxtClr,0); + TB.Effects :=DBReadWord (0,PluginShort,opt_FrmEffect,effCut or effCenter); + DBReadStruct(0,PluginShort,opt_FrmFont,@TextLF,SizeOf(TextLF)); + TB.FontData :=TextLF; + TB.UpdateTime:=DBReadWord (0,PluginShort,opt_TxtTimer ,10); +end; + +function MakeTextBlock(AOwner:PControl;BkColor:TCOLORREF):pTextBlock; +begin + result:=MakeNewTextBlock(AOwner,BkColor); +// result.OnMouseDown:=TOnMouse(MakeMethod(nil, @MouseDown)); + LoadTextSettings(result); +end; diff --git a/plugins/Watrack/kolframe/frm_trackbar.inc b/plugins/Watrack/kolframe/frm_trackbar.inc new file mode 100644 index 0000000000..d6e08c56a7 --- /dev/null +++ b/plugins/Watrack/kolframe/frm_trackbar.inc @@ -0,0 +1,229 @@ +{Trackbar} +type + pAWKTrackbar = ^tAWKTrackbar; + tAWKTrackbar = object(TObj) + total:integer; + UpdInterval:integer; + OldMouseDown, + OldMouseUp:TOnMouse; + + procedure CtrlResize(Sender: PObj); + procedure Erase(Sender: PControl; DC: HDC); + procedure Paint(Sender: PControl; DC: HDC); + procedure Scroll(Sender:PTrackbar; Code:Integer); + procedure PressButton (Sender: PControl;var Mouse: TMouseEventData); + procedure UnPressButton(Sender: PControl;var Mouse: TMouseEventData); + procedure DragButton (Sender: PControl;var Mouse: TMouseEventData); + end; + +procedure ResetTrackbar(Trackbar:PControl); +begin + if Trackbar=nil then exit; + + with pTrackbar(Trackbar)^ do + begin + RangeMin:=0; + RangeMax:=0; + Position:=0; + end; +end; + +procedure TrackbarSetRange(Trackbar:PTrackbar;timer:integer;total:integer=-1); +var + D:pAWKTrackbar; + lpercent:real; +begin + if Trackbar=nil then exit; + + with Trackbar^ do + begin + D:=pointer(CustomObj); + if total<0 then // changing timer only + begin + total:=D.total; + if RangeMax>0 then + lpercent:=position/RangeMax + else + lpercent:=0; + end + else // for new track + begin + D.total:=total; + lpercent:=0; + end; + D.UpdInterval:=timer; + total:=(total*1000) div timer; + RangeMax:=total; + LineSize:=total div 100; + PageSize:=total div 10; + Position:=round(lpercent*total); + end; +end; + +procedure SetTrackbarPosition(Trackbar:PTrackbar;pos:integer); +begin + if Trackbar=nil then exit; +//?? if Sender.ChildCount=0 then exit; + if pIcoButton(Trackbar.Children[0]).State<>AST_PRESSED then + Trackbar.Position:=pos; + + Trackbar.Update; +end; + +function CoordToPos(Trackbar:PTrackbar;x:integer):integer; +var + range:integer; + rmin,rmax:integer; + offsetthumb,width:integer; + rc:TRect; +begin + result:=0; + if Trackbar=nil then exit; + + rmin:=Trackbar.RangeMin; + rmax:=Trackbar.RangeMax; + range:=rmax-rmin; // logic width + + offsetthumb:=Trackbar.ThumbLen div 2; + + rc:=Trackbar.ChannelRect; + width:= (rc.right-rc.left)-(offsetthumb*2)-1; + result:=(range*(x-rc.left-offsetthumb)) div width; + + inc(result,rmin); + if result>rmax then + result:=rmax + else if resultpos then + begin + Action:=pos; + PTrackbar(Sender.Parent).Position:=pos; + end; + end; +end; + +procedure tAWKTrackbar.Scroll(Sender:PTrackbar; Code:Integer); +begin + if code=TB_ENDTRACK then + begin + CallService(MS_WAT_PRESSBUTTON,WAT_CTRL_SEEK, + Sender.Position*pAWKTrackbar(Sender.CustomObj).UpdInterval div 1000); + end; +end; + +procedure tAWKTrackbar.CtrlResize(Sender: PObj); +var + tmp:integer; +begin + tmp:=PControl(Sender).Parent.Width-16; + if (PTrackbar(Sender)^.Width)>tmp then + PTrackbar(Sender)^.Width:=tmp; + //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + // need to move slider here +// PControl(Sender).Update; +end; + +procedure tAWKTrackbar.Erase(Sender: PControl; DC: HDC); +begin +// Sender.Parent.Update; +end; + +procedure tAWKTrackbar.Paint(Sender: PControl; DC: HDC); +var + rc, rc1:TRECT; + w:integer; +begin + SendMessage(Sender.Handle,TBM_GETTHUMBRECT,0,dword(@rc)); + + w:=rc.right-rc.left; + if w<>16 then + rc.left:=rc.left+(w div 2)-8; + + copyRect(rc1,Sender.BoundsRect); + rc1.Right :=rc1.Right-rc1.Left-8; + rc1.Left :=4; + rc1.Top :=7{((rc1.Bottom-rc1.Top) div 2)-2}; + rc1.Bottom:=rc1.Top+4; + DrawEdge(DC,rc1,EDGE_SUNKEN,BF_RECT or BF_ADJUST); + if Sender.ChildCount>0 then + Sender.Children[0].Left:=rc.Left + else + begin + rc.right:=rc.left+8; + DrawFrameControl(DC,rc,DFC_BUTTON,DFCS_BUTTONPUSH); + end; +end; + +procedure RefreshTrackbarIcons(Owner:PControl); +begin + if Owner.ChildCount>0 then + pIcoButton(Owner.Children[0]).RefreshIcon; +end; + +function MakeNewTrackBar(AOwner:PControl):PTrackbar; +var + D:pAWKTrackbar; + btn:pIcoButton; +begin + New(D, Create); + result:=NewTrackbar(AOwner,[trbNoTicks,trbBoth,trbNoBorder],D.Scroll); + + with result^ do + begin + Transparent:=true; + CustomObj:=D; + SetSize(AOwner.Width-16,18); + SetPosition({AOwner.Left+}8,{AOwner.Top+}AOwner.Height-18); + Anchor(true,false,true,true); + ThumbLen:=16; + + RangeMin:=0; + RangeMax:=100; + + btn:=CreateIcoButton(result,GetIcon,DoAction,WAT_CTRL_SEEK); + + if btn<>nil then + begin + btn.ResetEvent(idx_fOnClick); + D.OldMouseDown:=btn.OnMouseDown; + btn.OnMouseDown:=D.PressButton; + D.OldMouseUp:=btn.OnMouseUp; + btn.OnMouseUp :=D.UnPressButton; + btn.OnMouseMove:=D.DragButton; + end; + + OnResize :=D.CtrlResize; + OnEraseBkGnd:=D.Erase; + OnPaint :=D.Paint; + +// OnScroll :=D.Scroll; + end; + +end; diff --git a/plugins/Watrack/kolframe/frm_vars.inc b/plugins/Watrack/kolframe/frm_vars.inc new file mode 100644 index 0000000000..88dd71f0d1 --- /dev/null +++ b/plugins/Watrack/kolframe/frm_vars.inc @@ -0,0 +1,80 @@ +{Frame variables} +var + sic, + PlStatusHook:cardinal; + + HiddenByMe:bool; + + FrameHeight:dword; + +type + PWATFrameData = ^TWATFrameData; + TWATFrameData = record + BkDC :HDC; // "buffer" DC and associated bitmap + BkBitmap :HBITMAP; // original bitmap + BkFile :PAnsiChar; // original bitmap filename + BkDefFile :PAnsiChar; // default background picture filename + BkMode :cardinal; + BkTimer :cardinal; // timer to free original picture buffer + BkColor :TCOLORREF; + padding :TRect; + + ShowControls:dword; + UseBkPicture:bool; + UseCover :bool; + HideNoMusic :bool; + HideNoPlayer:bool; + + WasHidden :bool; + // not sure what will keep here + FrameId :integer; + FrmAlpha :integer; + UpdInterval :cardinal; + UpdTimer :cardinal; + + Template :PWideChar; + + Trackbar :PTrackbar; + TextBlock:PTextBlock; + + // Designer section + Designer :PDesigner; + ManualPlacement:bool; + Loaded :dword; + + btnarray:array [0..numbuttons-1] of pIcoButton; + end; + + PWATFrame = ^TWATFrame; + TWATFrame = object(TControl) + procedure Paint(Sender: PControl; DC: HDC); + procedure FrameResize(Sender: PObj); + procedure RefreshAllFrameIcons; + procedure ResetFrame; + + procedure CreateDesigner(Sender:PControl;var Mouse:TMouseEventData); + procedure DesignerSaveSettings; + procedure DesignerLoadSettings; + + procedure PreparePicture(dc:HDC;rc:TRECT); + function LoadBkPicture(CoverFName:PAnsiChar;check:boolean=false; + BackFName:PAnsiChar=nil):integer; + procedure SaveSettings; + procedure LoadSettings; + procedure CheckControls; + procedure SetAlpha(value:integer); + procedure RefreshPicture(cover:PAnsiChar=nil); + procedure ClearBitmapData; + procedure AdjustFrame; + procedure MyDestroy(Sender:PObj); + + procedure AdjustButtons(atop:integer); + procedure RefreshButtonIcons; + procedure FreeButtonsDesigner; + procedure MakeButtonsDesigner; + procedure FreeButtons; + procedure MakeNewButtonGroup; + end; + +var + FrameCtrl:PWATFrame; diff --git a/plugins/Watrack/kolframe/i_bitmap.inc b/plugins/Watrack/kolframe/i_bitmap.inc new file mode 100644 index 0000000000..bee15fdda7 --- /dev/null +++ b/plugins/Watrack/kolframe/i_bitmap.inc @@ -0,0 +1,290 @@ +{} +procedure CalcRect(var src,dst:TRECT;mode:dword); +var + dh, dw:integer; +begin + if (Mode and frbkStretch)=frbkStretch then + begin + if (Mode and frbkProportional)<>0 then + begin + if (dst.right*src.bottom)>(src.right*dst.bottom) then + begin + dh:=dst.bottom; + dw:=dh*src.right div src.bottom + end + else + begin + dw:=dst.right; + dh:=dw*src.bottom div src.right; + end; + end + else + begin + dw:=dst.right; + dh:=dst.bottom; + end; + end + else if (Mode and frbkStretchX)<>0 then + begin + dw:=dst.right; + if (Mode and frbkProportional)<>0 then + dh:=dw*src.bottom div src.right + else + dh:=src.bottom; + end + else if (Mode and frbkStretchY)<>0 then + begin + dh:=dst.bottom; + if (Mode and frbkProportional)<>0 then + dw:=dh*src.right div src.bottom + else + dw:=src.right; + end + else + begin + dw:=src.right; + dh:=src.bottom; + end; + + if (Mode and frbkBottom)<>0 then + begin + if dh<=dst.bottom then + begin + dst.top:=(dst.bottom-dh); + end + else + begin + src.top:=(dh-dst.bottom); + dh:=dst.bottom; + src.bottom:=src.top+dh; + end; + end; + + if (Mode and frbkRight)<>0 then + begin + if dw<=dst.right then + begin + dst.left:=(dst.right-dw); + end + else + begin + src.left:=(dw-dst.right); + dw:=dst.right; + src.right:=src.left+dw; + end; + end; + + if (Mode and frbkCenterX)<>0 then + begin + if dw<=dst.right then + begin + dst.left:=(dst.right-dw) div 2; + end + else + begin + src.left:=(dw-dst.right) div 2; + dw:=dst.right; + src.right:=src.left+dw; + end; + end; + + if (Mode and frbkCenterY)<>0 then + begin + if dh<=dst.bottom then + begin + dst.top:=(dst.bottom-dh) div 2; + end + else + begin + src.top:=(dh-dst.bottom) div 2; + dh:=dst.bottom; + src.bottom:=src.top+dh; + end; + end; + dst.right:=dst.left+dw; + dst.bottom:=dst.top+dh; +end; + +function CreateDIB32(dc:HDC;w,h:integer):HBITMAP; +var + pt:pointer; + bi:TBITMAPINFO; +begin + FillChar(bi,SizeOf(TBITMAPINFO),0); + bi.bmiHeader.biSize :=SizeOf(TBITMAPINFOHEADER); + bi.bmiHeader.biWidth :=w; + bi.bmiHeader.biHeight :=h; + bi.bmiHeader.biPlanes :=1; + bi.bmiHeader.biBitCount:=32; + result:=CreateDIBSection(dc,bi,DIB_RGB_COLORS,pt,0,0); +end; + +procedure PreMultiplyChanells(hbmp:HBITMAP); +type + tPixel=array [0..3] of Byte; +var + bmp:windows.TBITMAP; + flag:bool; + pBitmapBits:PByte; + Len:dword; + bh,bw,y,x,z:integer; + pPixel:^tPixel; + alpha:dword; +//f:THANDLE; +begin + GetObject(hbmp,SizeOf(bmp),@bmp); + bh:=bmp.bmHeight; + bw:=bmp.bmWidth; + z:=bw*4; + Len:=bh*z; + + mGetMem(pBitmapBits,Len); + GetBitmapBits(hbmp,Len,pBitmapBits); + flag:=true; + for y:=0 to bh-1 do + begin + pointer(pPixel):=PAnsiChar(pBitmapBits)+z*y; + + for x:=0 to bw-1 do + begin + if pPixel^[3]<>0 then + flag:=false + else + pPixel^[3]:=255; + inc(pByte(pPixel),4); + end + end; + + if not flag then + begin + GetBitmapBits(hbmp,Len,pBitmapBits); // alpha not changed + for y:=0 to bh-1 do + begin + pointer(pPixel):=PAnsiChar(pBitmapBits)+z*y; + + for x:=0 to bw-1 do + begin + alpha:=pPixel^[3]; + if alpha<255 then + begin + pPixel^[0]:=dword(pPixel^[0])*alpha div 255; + pPixel^[1]:=dword(pPixel^[1])*alpha div 255; + pPixel^[2]:=dword(pPixel^[2])*alpha div 255; + end; + inc(pByte(pPixel),4); + end + end; + end; + SetBitmapBits(hbmp,Len,pBitmapBits); + mFreeMem(pBitmapBits); +end; + +function FixBitmap(dc:HDC;var hBmp:HBITMAP):HBITMAP; +var + dc24,dc32:HDC; + hBitmap32,obmp24,obmp32:HBITMAP; + bmpInfo:windows.TBITMAP; +begin + GetObject(hBmp,SizeOf(bmpInfo),@bmpInfo); + if bmpInfo.bmBitsPixel<>32 then + begin + dc32:=CreateCompatibleDC(dc); + dc24:=CreateCompatibleDC(dc); + hBitmap32:=CreateDIB32(dc,bmpInfo.bmWidth,bmpInfo.bmHeight); + obmp24:=SelectObject(dc24,hBmp); + obmp32:=SelectObject(dc32,hBitmap32); + BitBlt(dc32,0,0,bmpInfo.bmWidth,bmpInfo.bmHeight,dc24,0,0,SRCCOPY); + DeleteObject(SelectObject(dc24,obmp24)); + SelectObject(dc32,obmp32); + DeleteDC(dc24); + DeleteDC(dc32); + hBmp:=hBitmap32; + end; + PreMultiplyChanells(hBmp); + result:=hBmp; +end; + +procedure TWATFrame.PreparePicture(dc:HDC;rc:TRECT); +var + bmpinfo:windows.TBITMAP; + src,dst:TRECT; + x,y,w,h,dh:integer; + br:HBRUSH; + hdcbmp:HDC; + bf:BLENDFUNCTION; + hOld:THANDLE; + D:PWATFrameData; +begin + D:=CustomData; + D.BkDC:=CreateCompatibleDC(dc); + + FixBitmap(dc,D.BkBitmap); + + DeleteObject(SelectObject(D.BkDC,CreateDIB32(dc,rc.right-rc.left,rc.bottom-rc.top))); + + //fill empty space by BK color + br:=CreateSolidBrush(D.BkColor); + FillRect(D.BkDC,rc,br); + DeleteObject(br); + + CopyRect(dst,rc); + hdcbmp:=CreateCompatibleDC(D.BkDC); + GetObject(D.BkBitmap,SizeOf(bmpinfo),@bmpinfo); + hOld:=SelectObject(hdcbmp,D.BkBitmap); + + SetRect(src,0,0,bmpinfo.bmWidth,bmpinfo.bmHeight); + + if (D.padding.top+D.padding.bottom)<(dst.bottom-dst.top) then + dec(dst.bottom,D.padding.top+D.padding.bottom); + if (D.padding.left+D.padding.right)<(dst.right-dst.left) then + dec(dst.right,D.padding.left+D.padding.right); + + CalcRect(src,dst,D.BkMode); // calculate final picture rect + + w:=1; + if (D.BkMode and frbkTileX)<>0 then + begin + x:=dst.right; + while x0 then + begin + y:=dst.bottom; + while y0 do + begin + dh:=h; + y:=dst.top+D.padding.top; + if y0 do + begin + Windows.AlphaBlend(D.BkDC,x,y,dst.right-dst.left,dst.bottom-dst.top, + hdcbmp,src.left,src.top,src.right-src.left,src.bottom-src.top,bf); + inc(y,dst.bottom); + dec(dh); + end; + inc(x,dst.right); + dec(w); + end; + + SelectObject(hdcbmp,hOld); + DeleteDC(hdcbmp); +end; diff --git a/plugins/Watrack/kolframe/kolframe.pas b/plugins/Watrack/kolframe/kolframe.pas new file mode 100644 index 0000000000..615991d810 --- /dev/null +++ b/plugins/Watrack/kolframe/kolframe.pas @@ -0,0 +1,327 @@ +{CList frame} +unit KOLFrame; + +interface + +implementation + +uses windows,kol,commdlg,messages,common,commctrl, KOLCCtrls, + wat_api,wrapper,global,m_api,dbsettings,waticons,mirutils, + icobuttons,textblock,kolsizer; + +{$R frm.res} + +{$include frm_data.inc} +{$include frm_vars.inc} + +procedure MouseDown(DummySelf, Sender:PControl;var Mouse:TMouseEventData); +var + wnd:HWND; +begin + wnd:=GetParent(Sender.GetWindowHandle); + SendMessage(wnd,WM_SYSCOMMAND, + SC_MOVE or HTCAPTION,MAKELPARAM(Mouse.x,Mouse.y)); +end; + +// ---------------- frame functions ---------------- + +procedure SetFrameTitle(title:pointer;icon:HICON;addflag:integer=FO_UNICODETEXT); +var + D:PWATFrameData; +begin + D:=FrameCtrl.CustomData; + CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, + (D.FrameId shl 16)+FO_TBNAME+addflag,dword(title)); + CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS,(D.FrameId shl 16)+FO_ICON,icon); + CallService(MS_CLIST_FRAMES_UPDATEFRAME,D.FrameId,FU_TBREDRAW); +end; + +// ----------------------- + +function IsFrameMinimized(FrameId:integer):bool; +begin + result:=(CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, + (FrameId shl 16)+FO_FLAGS,0) and F_UNCOLLAPSED)=0; +end; + +function IsFrameFloated(FrameId:integer):bool; +begin + result:=CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, + (FrameId shl 16)+FO_FLOATING,0)>0; +end; + +function IsFrameHidden(FrameId:integer):bool; +begin + result:=(CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, + (FrameId shl 16)+FO_FLAGS,0) and F_VISIBLE)=0; +end; + +procedure HideFrame(FrameId:integer); +begin + if not IsFrameHidden(FrameId) then + begin + CallService(MS_CLIST_FRAMES_SHFRAME,FrameId,0); + HiddenByMe:=true; + end; +end; + +function ShowFrame(FrameId:integer):integer; +begin + result:=0; + if IsFrameHidden(FrameId) then + if HiddenByMe then + begin + CallService(MS_CLIST_FRAMES_SHFRAME,FrameId,0); + HiddenByMe:=false; + end + else + result:=1; +end; + +{$include frm_rc.inc} +{$include frm_icogroup.inc} +{$include frm_trackbar.inc} +{$include frm_text.inc} +{$include frm_frame.inc} +{$include frm_designer.inc} + +{$include frm_dlg1.inc} +{$include frm_dlg2.inc} + +// ---------------- basic frame functions ---------------- + +function NewPlStatus(wParam:WPARAM;lParam:LPARAM):int;cdecl; +const + needToChange:boolean=true; +var + bufw:array [0..511] of WideChar; +// FrameWnd:HWND; + Cover:pAnsiChar; + D:PWATFrameData; +begin + result:=0; +// FrameWnd:=FrameCtrl.Form.GetWindowHandle; + D:=FrameCtrl.CustomData; + + case wParam of + WAT_EVENT_PLAYERSTATUS: begin + case Integer(loword(lParam)) of + WAT_PLS_NORMAL : exit; + WAT_PLS_NOMUSIC : begin + if D.HideNoMusic then + HideFrame(D.FrameId) + else + ShowFrame(D.FrameId); // if was hidden with "no player" + end; + WAT_PLS_NOTFOUND: begin + if D.HideNoPlayer then + HideFrame(D.FrameId); + + SetFrameTitle(PluginShort,0,0); // frame update code there + end; + end; + FrameCtrl.ResetFrame; + end; + + WAT_EVENT_NEWTRACK: begin + // cover + if D.UseCover then + if (pSongInfo(lParam)^.Cover<>nil) and (pSongInfo(lParam)^.Cover^<>#0) then + begin + GetShortPathNameW(pSongInfo(lParam)^.Cover,bufw,SizeOf(bufw)); + WideToAnsi(bufw,Cover); + FrameCtrl.RefreshPicture(Cover); + mFreeMem(Cover); + end; + + // trackbar + TrackbarSetRange(D.Trackbar,D.UpdInterval,pSongInfo(lParam)^.total); + + if (D.UpdTimer=0) and (D.UpdInterval>0) then + D.UpdTimer:=SetTimer(0,0,D.UpdInterval,@FrameTimerProc); + + // text + UpdateTextBlock(D,true); + + ShowFrame(D.FrameId); + end; + + WAT_EVENT_NEWPLAYER: begin + SetFrameTitle(pSongInfo(lParam)^.player,pSongInfo(lParam)^.icon); + // new player must call "no music" at least, so we have chance to show frame + end; + + WAT_EVENT_PLUGINSTATUS: begin + case lParam of + dsEnabled: begin + ShowFrame(D.FrameId); + // plus - start frame and text timers + if D.UpdInterval>0 then + D.UpdTimer:=SetTimer(0,0,D.UpdInterval,@FrameTimerProc); + end; + + dsPermanent: begin + HideFrame(D.FrameId); + + // plus - stop frame and text timers + if D.UpdTimer<>0 then + begin + KillTimer(0,D.UpdTimer); + D.UpdTimer:=0; + end; + end; + end; + end; + end; +end; + +function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + result:=0; + if PWATFrameData(FrameCtrl.CustomData).FrameId<>0 then + begin + FrameCtrl.RefreshAllFrameIcons; + ShowWindow(FrameCtrl.GetWindowHandle,SW_HIDE); + ShowWindow(FrameCtrl.GetWindowHandle,SW_SHOW); + end; +end; + +//??const opt_FrmHeight :PAnsiChar = 'frame/frmheight'; + +function CreateFrame(parent:HWND):boolean; +var + CLFrame:TCLISTFrame; + rc:TRECT; + FrameWnd:HWND; +begin + result:=false; + if ServiceExists(MS_CLIST_FRAMES_ADDFRAME)=0 then + exit; + + if parent=0 then + parent:=CallService(MS_CLUI_GETHWND,0,0); + + FrameWnd:=CreateFrameWindow(parent); + + if FrameWnd<>0 then + begin + FillChar(CLFrame,SizeOf(CLFrame),0); + with CLFrame do + begin + cbSize :=SizeOf(CLFrame); + hWnd :=FrameWnd; + hIcon :=0; + align :=alTop; + GetClientRect(FrameWnd,rc); +//?? height :=DBReadWord(0,PluginShort,opt_FrmHeight,rc.bottom-rc.top); + Flags :=0;//{F_VISIBLE or} F_SHOWTB; + name.a :=PluginShort; + TBName.a:=PluginShort; + end; + FrameHeight:=CLFrame.height; + + PWATFrameData(FrameCtrl.CustomData).FrameId:=CallService(MS_CLIST_FRAMES_ADDFRAME,dword(@CLFrame),0); + if PWATFrameData(FrameCtrl.CustomData).FrameId>=0 then + begin + plStatusHook:=HookEvent(ME_WAT_NEWSTATUS,@NewPlStatus); + end; + end; + result:=FrameWnd<>0; +end; + +procedure DestroyFrame; +var + id:Integer; +begin + if (FrameCtrl<>nil) and (PWATFrameData(FrameCtrl.CustomData).FrameId>=0) then + begin + UnhookEvent(plStatusHook); + + id:=PWATFrameData(FrameCtrl.CustomData).FrameId; + FrameCtrl.Free; + FrameCtrl:=nil; + CallService(MS_CLIST_FRAMES_REMOVEFRAME,Id,0); + end; +end; + +const + opt_ModStatus:PAnsiChar = 'module/frame'; + +function GetModStatus:integer; +begin + result:=DBReadByte(0,PluginShort,opt_ModStatus,1); +end; + +procedure SetModStatus(stat:integer); +begin + DBWriteByte(0,PluginShort,opt_modStatus,stat); +end; + +// ---------------- base interface procedures ---------------- + +function InitProc(aGetStatus:boolean=false):integer; +begin + FrameCtrl:=nil; + result:=0; + if aGetStatus then + begin + if GetModStatus=0 then + exit; + end + else + SetModStatus(1); + + result:=ord(CreateFrame(0)); + if result<>0 then + sic:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged); +end; + +procedure DeInitProc(aSetDisable:boolean); +begin + if aSetDisable then + SetModStatus(0); + + if sic<>0 then UnhookEvent(sic); + sic:=0; + DestroyFrame; +end; + +function AddOptionsPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +const + count:integer=2; +begin + if count=0 then + count:=2; + if count=2 then + begin + tmpl:='FRAME'; + proc:=@FrameViewDlg; + name:='Frame (main)'; + end + else + begin + tmpl:='FRAME2'; + proc:=@FrameTextDlg; + name:='Frame (text)'; + end; + + dec(count); + result:=count; +end; + +var + Frame:twModule; + +procedure Init; +begin + Frame.Next :=ModuleLink; + Frame.Init :=@InitProc; + Frame.DeInit :=@DeInitProc; + Frame.AddOption :=@AddOptionsPage; + Frame.ModuleName:='Frame'; + ModuleLink :=@Frame; +end; + +begin + Init; +end. diff --git a/plugins/Watrack/lastfm/i_const.inc b/plugins/Watrack/lastfm/i_const.inc new file mode 100644 index 0000000000..9a0365e506 --- /dev/null +++ b/plugins/Watrack/lastfm/i_const.inc @@ -0,0 +1,17 @@ +const + IDC_LOGIN = 1025; + IDC_PASS = 1026; + IDC_TRIES = 1027; + + IDC_INFO_ARTIST = 1030; + IDC_INFO_TRACK = 1031; + IDC_INFO_ALBUM = 1032; + IDC_LANGUAGE = 1033; + + IDC_DATA_PIC = 1040; + IDC_DATA_ARTIST = 1041; + IDC_DATA_ALBUM = 1042; + IDC_DATA_TRACK = 1043; + IDC_DATA_TAGS = 1044; + IDC_DATA_INFO = 1045; + IDC_ALT = 1046; diff --git a/plugins/Watrack/lastfm/i_last_api.inc b/plugins/Watrack/lastfm/i_last_api.inc new file mode 100644 index 0000000000..73328366ba --- /dev/null +++ b/plugins/Watrack/lastfm/i_last_api.inc @@ -0,0 +1,599 @@ +{} + +const + client_id = 'wat';//'wat'; 'tst' + client_ver = '1.0'; + api_key = '51f5d25159da31b0814609c3a12900e2'; + +const + defreq = 'http://post.audioscrobbler.com/?hs=true&p=1.2.1&c=&v=&u=&t=&a='; + +function GetMD5Str(digest:TMD5Hash; buf:pAnsiChar):PAnsiChar; +begin + buf[00]:=HexDigitChrLo[digest[00] shr 4]; buf[01]:=HexDigitChrLo[digest[00] and $0F]; + buf[02]:=HexDigitChrLo[digest[01] shr 4]; buf[03]:=HexDigitChrLo[digest[01] and $0F]; + buf[04]:=HexDigitChrLo[digest[02] shr 4]; buf[05]:=HexDigitChrLo[digest[02] and $0F]; + buf[06]:=HexDigitChrLo[digest[03] shr 4]; buf[07]:=HexDigitChrLo[digest[03] and $0F]; + buf[08]:=HexDigitChrLo[digest[04] shr 4]; buf[09]:=HexDigitChrLo[digest[04] and $0F]; + buf[10]:=HexDigitChrLo[digest[05] shr 4]; buf[11]:=HexDigitChrLo[digest[05] and $0F]; + buf[12]:=HexDigitChrLo[digest[06] shr 4]; buf[13]:=HexDigitChrLo[digest[06] and $0F]; + buf[14]:=HexDigitChrLo[digest[07] shr 4]; buf[15]:=HexDigitChrLo[digest[07] and $0F]; + buf[16]:=HexDigitChrLo[digest[08] shr 4]; buf[17]:=HexDigitChrLo[digest[08] and $0F]; + buf[18]:=HexDigitChrLo[digest[09] shr 4]; buf[19]:=HexDigitChrLo[digest[09] and $0F]; + buf[20]:=HexDigitChrLo[digest[10] shr 4]; buf[21]:=HexDigitChrLo[digest[10] and $0F]; + buf[22]:=HexDigitChrLo[digest[11] shr 4]; buf[23]:=HexDigitChrLo[digest[11] and $0F]; + buf[24]:=HexDigitChrLo[digest[12] shr 4]; buf[25]:=HexDigitChrLo[digest[12] and $0F]; + buf[26]:=HexDigitChrLo[digest[13] shr 4]; buf[27]:=HexDigitChrLo[digest[13] and $0F]; + buf[28]:=HexDigitChrLo[digest[14] shr 4]; buf[29]:=HexDigitChrLo[digest[14] and $0F]; + buf[30]:=HexDigitChrLo[digest[15] shr 4]; buf[31]:=HexDigitChrLo[digest[15] and $0F]; + buf[32]:=#0; + result:=@buf; +end; + +function GetMD5(const data;datalen:integer;var digest:TMD5Hash):TMD5Hash; +begin + FillChar(digest,16,0); + + mir_md5_hash(pmir_md5_byte_t(data),datalen,digest); + + result:=digest; +end; + +function HandShake(login, password:PAnsiChar; notify:bool=false):bool; +var + buf:array [0..32] of AnsiChar; + digest:TMD5Hash; + stat:mir_md5_state_t; + timestamp:array [0..31] of AnsiChar; + request:array [0..511] of AnsiChar; + tmp,res:pAnsiChar; +begin + result:=false; + GetMD5Str(GetMD5(password,StrLen(password),digest),buf); + mir_md5_init(@stat); + mir_md5_append(@stat,@buf,32); + IntToStr(timestamp,GetCurrentTime); + mir_md5_append(@stat,@timestamp,StrLen(timestamp)); + mir_md5_finish(@stat,digest); + GetMD5Str(digest,buf); + StrCopy(request,defreq); + StrReplace(request,'' ,client_id); + StrReplace(request,'',client_ver); + StrReplace(request,'' ,login); + StrReplace(request,'' ,timestamp); + StrReplace(request,'' ,buf); + + res:=SendRequest(request,REQUEST_GET); + if (res<>nil) and (uint_ptr(res)>$0FFF) then + begin + if StrCmp(CharReplace(res,#10,#0),'OK')=0 then + begin + result:=true; + tmp:=StrEnd(res)+1; StrDup(session_id,tmp); + tmp:=StrEnd(tmp)+1; StrDup(np_url ,tmp); + tmp:=StrEnd(tmp)+1; StrDup(sub_url ,tmp); + end + else if notify then + begin + tmp:=StrCopyE(request,Translate('Last.fm error: ')); + if StrCmp(res,'BANNED' )=0 then StrCopy(tmp,Translate('Client is banned')) + else if StrCmp(res,'BADAUTH' )=0 then StrCopy(tmp,Translate('Bad Auth. Check login and password')) + else if StrCmp(res,'BADTIME' )=0 then StrCopy(tmp,Translate('Bad TimeStamp')) + else if StrCmp(res,'FAILED',6)=0 then StrCopy(tmp,res+7); + CallService(MS_POPUP_SHOWMESSAGEW,wparam(@request),SM_ERROR); + end; + mFreeMem(res); + end; +end; + +function encode(dst,src:pAnsiChar):PAnsiChar; +begin + while src^<>#0 do + begin + if not (src^ in [' ','%','+','&','?',#128..#255]) then + dst^:=src^ + else + begin + dst^:='%'; inc(dst); + dst^:=HexDigitChr[ord(src^) shr 4]; inc(dst); + dst^:=HexDigitChr[ord(src^) and $0F]; + end; + inc(src); + inc(dst); + end; + dst^:=#0; + result:=dst; +end; + +function SendNowPlaying:integer; +var + si:pSongInfoA; + buf :array [0..31 ] of AnsiChar; + args :array [0..1023] of AnsiChar; + res,pc:PAnsiChar; +begin + result:=-1; + if session_id<>nil then + begin + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UTF8,0)); + + pc:=@args; + pc:=StrCopyE(pc,'s='); pc:=StrCopyE(pc,session_id); //'?s=' + pc:=StrCopyE(pc,'&a='); + if si^.artist=nil then pc:=StrCopyE(pc,'Unknown') + else pc:=encode(pc,si^.artist); + pc:=StrCopyE(pc,'&t='); + if si^.title =nil then pc:=StrCopyE(pc,'Unknown') + else pc:=encode(pc,si^.title); + pc:=StrCopyE(pc,'&l='); if si^.total>0 then pc:=StrCopyE(pc,IntToStr(buf,si^.total)); + pc:=StrCopyE(pc,'&b='); pc:=encode(pc,si^.album); + pc:=StrCopyE(pc,'&n='); + if si^.track<>0 then + {pc:=}StrCopyE(pc,IntToStr(buf,si^.track)); + + res:=SendRequest(np_url,REQUEST_POST,args); + if (res<>nil) and (uint_ptr(res)>$0FFF) then + begin + if StrCmp(CharReplace(res,#10,#0),'OK')=0 then + result:=1 + else if StrCmp(res,'BADSESSION')=0 then + result:=-1; + mFreeMem(res); + end; + end; +end; + +function Scrobble:integer; +var + si:pSongInfoA; + buf,timestamp:array [0..31] of AnsiChar; + args :array [0..1023] of AnsiChar; + res,pc:PAnsiChar; +begin + result:=-1; + if session_id<>nil then + begin + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UTF8,0)); + IntToStr(timestamp,GetCurrentTime); + + pc:=@args; + pc:=StrCopyE(pc,'s=' ); pc:=StrCopyE(pc,session_id); + pc:=StrCopyE(pc,'&a[0]='); + if si^.artist=nil then pc:=StrCopyE(pc,'Unknown') + else pc:=encode(pc,si^.artist); + pc:=StrCopyE(pc,'&t[0]='); + if si^.title =nil then pc:=StrCopyE(pc,'Unknown') + else pc:=encode(pc,si^.title); + pc:=StrCopyE(pc,'&i[0]='); pc:=StrCopyE(pc,timestamp); + pc:=StrCopyE(pc,'&r[0]=&m[0]='); + pc:=StrCopyE(pc,'&l[0]='); + if si^.total>0 then + begin + pc:=StrCopyE(pc,IntToStr(buf,si^.total)); + pc:=StrCopyE(pc,'&o[0]=P'); + end + else + begin + pc:=StrCopyE(pc,'&o[0]=R'); + end; + pc:=StrCopyE(pc,'&b[0]='); pc:=encode(pc,si^.album); + pc:=StrCopyE(pc,'&n[0]='); + if si^.track<>0 then + {pc:=}StrCopyE(pc,IntToStr(buf,si^.track)); + + res:=SendRequest(sub_url,REQUEST_POST,args); + if (res<>nil) and (uint_ptr(res)>$0FFF) then + begin + if StrCmp(CharReplace(res,#10,#0),'OK')=0 then + result:=1 + else if StrCmp(res,'BADSESSION')=0 then + begin + result:=-1; + end + else if StrCmp(res,'FAILED',6)=0 then + begin + StrCopy(StrCopyE(args,Translate('Last.fm error: ')),res+7); + CallService(MS_POPUP_SHOWMESSAGE,wparam(@args),SM_NOTIFY); + result:=0; + end; + mFreeMem(res); + end; + end; +end; + +//----- Get Info service functions ----- + +function FullEncode(dst,src:pAnsiChar):PAnsiChar; +begin + while src^<>#0 do + begin + if src^ in ['A'..'Z','a'..'z','0'..'9'] then + dst^:=src^ + else + begin + dst^:='%'; inc(dst); + dst^:=HexDigitChr[ord(src^) shr 4]; inc(dst); + dst^:=HexDigitChr[ord(src^) and $0F]; + end; + inc(src); + inc(dst); + end; + dst^:=#0; + result:=dst; +end; + +var + xmlparser:XML_API_W; + +function FixInfo(info:pWideChar):pWideChar; +var + pc,ppc:pWideChar; + cnt:cardinal; + need:boolean; +begin + pc:=info; + cnt:=0; + need:=false; + while pc^<>#0 do + begin + if pc^=#$0D then + begin + inc(cnt); + inc(pc); + if pc^<>#$0A then + need:=true; + end + else + inc(pc); + end; + if need then + begin + mGetMem(result,(StrLenW(info)+1+cnt)*SizeOf(WideChar)); + pc:=info; + ppc:=result; + while pc^<>#0 do + begin + ppc^:=pc^; + if pc^=#$0D then + begin + inc(ppc); + ppc^:=#$0A; + end; + inc(pc); + inc(ppc); + end; + ppc^:=#0; + end + else + StrDupW(result,info); +end; + +function GetArtistInfo(var data:tLastFMInfo;lang:integer):int; +var + si:pSongInfo; + res,pc:pAnsiChar; + request:array [0..1023] of AnsiChar; + root,actnode,node,nnode:HXML; + i:integer; + pcw,p,pp:PWideChar; + artist:pAnsiChar; +begin + result:=0; + if data.artist=nil then + begin + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + pWideChar(artist):=si^.artist; + end + else + pWideChar(artist):=data.artist; + if artist=nil then + exit; + WideToUTF8(pWideChar(artist),artist); + pc:=FullEncode(StrCopyE(request, + 'http://ws.audioscrobbler.com/2.0/?method=artist.getinfo&api_key='+api_key+'&artist='), + artist); + mFreeMem(artist); + if lang<>0 then + StrCopyE(StrCopyE(pc,'&lang='),pAnsiChar(@lang)); + res:=SendRequest(request,REQUEST_GET); + if (res<>nil) and (uint_ptr(res)>$0FFF) then + begin + UTF8ToWide(res,pcw); + mFreeMem(res); + xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W); + CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser)); + with xmlparser do + begin + i:=StrLenW(pcw)*SizeOf(WideChar); + root:=parseString(pcw,@i,nil); + + actnode:=getChild(getChild(root,0),0); // "artist" + + if data.artist=nil then + StrDupW(data.artist,getText(GetNthChild(actnode,'name',0))); + + i:=0; + repeat + node:=GetNthChild(actnode,'image',i); + if node=0 then break; + if StrCmpW(GetAttrValue(node,'size'),'medium')=0 then + begin + WideToUTF8(GetText(node),data.image); + break; + end; + inc(i); + until false; + + // bio + p:=StrPosW(pcw,'nil then + begin + inc(p,18); + pp:=StrPosW(p,']]'); + if pp<> nil then pp^:=#0; + data.info:=FixInfo(p); + end; + + // similar + i:=0; + pcw:=pWideChar(@request); pcw^:=#0; + node:=GetNthChild(actnode,'similar',0); + repeat + nnode:=GetNthChild(GetNthChild(node,'artist',i),'name',0); + if nnode=0 then break; + if pcw<>@request then + begin + pcw^:=','; inc(pcw); + pcw^:=' '; inc(pcw); + end; + pcw:=StrCopyEW(pcw,GetText(nnode)); + inc(i); + until false; + pcw:=#0; + StrDupW(data.similar,pWideChar(@request)); + + // tags + i:=0; + pcw:=pWideChar(@request); pcw^:=#0; + node:=GetNthChild(actnode,'tags',0); + repeat + nnode:=GetNthChild(GetNthChild(node,'tag',i),'name',0); + if nnode=0 then break; + if pcw<>@request then + begin + pcw^:=','; inc(pcw); + pcw^:=' '; inc(pcw); + end; + pcw:=StrCopyEW(pcw,GetText(nnode)); + inc(i); + until false; + pcw:=#0; + StrDupW(data.tags,pWideChar(@request)); + DestroyNode(root); + mFreeMem(pcw); + end; + end; +end; + +function GetAlbumInfo(var data:tLastFMInfo;lang:integer):int; +var + si:pSongInfo; + res,pc:pAnsiChar; + request:array [0..1023] of AnsiChar; + root,actnode,node,nnode:HXML; + i:integer; + p,pp,pcw:PWideChar; + album,artist:pAnsiChar; +begin + result:=0; + si:=nil; + if data.album=nil then + begin + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + pWideChar(album):=si^.album; + end + else + pWideChar(album):=data.album; + if album=nil then + exit; + WideToUTF8(pWideChar(album),album); + pc:=FullEncode(StrCopyE(request, + 'http://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key='+api_key+'&album='), + album); + mFreeMem(album); + if data.artist=nil then + begin + if si=nil then + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + pWideChar(artist):=si^.artist; + end + else + pWideChar(artist):=data.artist; + if artist<>nil then + begin + WideToUTF8(pWideChar(artist),artist); + pc:=FullEncode(StrCopyE(pc,'&artist='),artist); + mFreeMem(artist); + end; + + if lang<>0 then + StrCopyE(StrCopyE(pc,'&lang='),pAnsiChar(@lang)); + + res:=SendRequest(request,REQUEST_GET); + if res<>nil then + begin + UTF8ToWide(res,pcw); + mFreeMem(res); + xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W); + CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser)); + with xmlparser do + begin + i:=StrLenW(pcw)*SizeOf(WideChar); + root:=parseString(pcw,@i,nil); + + actnode:=getChild(getChild(root,0),0); // "album" + + if data.album=nil then + StrDupW(data.album,getText(GetNthChild(actnode,'name',0))); + StrDupW(data.release,getText(GetNthChild(actnode,'releasedate',0))); + if data.artist=nil then + StrDupW(data.artist,getText(GetNthChild(actnode,'artist',0))); + + i:=0; + repeat + node:=GetNthChild(actnode,'image',i); + if node=0 then break; + if StrCmpW(GetAttrValue(node,'size'),'medium')=0 then + begin + WideToUTF8(GetText(node),data.image); + break; + end; + inc(i); + until false; + + p:=StrPosW(pcw,'nil then + begin + inc(p,18); + pp:=StrPosW(p,']]'); + if pp<> nil then pp^:=#0; + data.info:=FixInfo(p); + end; + + // tags + i:=0; + pcw:=pWideChar(@request); pcw^:=#0; + node:=GetNthChild(actnode,'toptags',0); + repeat + nnode:=GetNthChild(GetNthChild(node,'tag',i),'name',0); + if nnode=0 then break; + if pcw<>@request then + begin + pcw^:=','; inc(pcw); + pcw^:=' '; inc(pcw); + end; + pcw:=StrCopyEW(pcw,GetText(nnode)); + inc(i); + until false; + pcw:=#0; + StrDupW(data.tags,pWideChar(@request)); + + DestroyNode(root); + mFreeMem(pcw); + end; + end; +end; + +function GetTrackInfo(var data:tLastFMInfo;lang:integer):int; +var + si:pSongInfo; + res,pc:pAnsiChar; + request:array [0..1023] of AnsiChar; + root,actnode,node,anode:HXML; + i:integer; + p,pp,pcw:PWideChar; + title,artist:pAnsiChar; +begin + result:=0; + si:=nil; + if data.album=nil then + begin + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + pWideChar(title):=si^.title; + end + else + pWideChar(title):=data.title; + if title=nil then + exit; + WideToUTF8(pWideChar(title),title); + pc:=FullEncode(StrCopyE(request, + 'http://ws.audioscrobbler.com/2.0/?method=track.getinfo&api_key='+api_key+'&track='), + title); + mFreeMem(title); + if data.artist=nil then + begin + if si=nil then + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + pWideChar(artist):=si^.artist; + end + else + pWideChar(artist):=data.artist; + if artist<>nil then + begin + WideToUTF8(pWideChar(artist),artist); + pc:=FullEncode(StrCopyE(pc,'&artist='),artist); + mFreeMem(artist); + end; + + if lang<>0 then + StrCopyE(StrCopyE(pc,'&lang='),pAnsiChar(@lang)); + + res:=SendRequest(request,REQUEST_GET); + if res<>nil then + begin + UTF8ToWide(res,pcw); + mFreeMem(res); + xmlparser.cbSize:={XML_API_SIZEOF_V1;//}SizeOf(XML_API_W); + CallService(MS_SYSTEM_GET_XI,0,lparam(@xmlparser)); + with xmlparser do + begin + i:=StrLenW(pcw)*SizeOf(WideChar); + root:=parseString(pcw,@i,nil); + + actnode:=getChild(getChild(root,0),0); // "track" + if data.artist=nil then + StrDupW(data.artist,getText(GetNthChild(GetNthChild(actnode,'artist',0),'name',0))); + + anode:=GetNthChild(actnode,'album',i); + + if data.album=nil then + StrDupW(data.album,getText(GetNthChild(anode,'title',0))); + + data.trknum:=StrToInt(getAttrValue(anode,'position')); + if data.title=nil then + StrDupW(data.title,getText(GetNthChild(actnode,'name',0))); + + i:=0; + repeat + node:=GetNthChild(anode,'image',i); + if node=0 then break; + if StrCmpW(GetAttrValue(node,'size'),'medium')=0 then + begin + WideToUTF8(GetText(node),data.image); + break; + end; + inc(i); + until false; + + p:=StrPosW(pcw,'nil then + begin + inc(p,18); + pp:=StrPosW(p,']]'); + if pp<> nil then pp^:=#0; + data.info:=FixInfo(p); + end; + + // tags + i:=0; + pcw:=pWideChar(@request); pcw^:=#0; + node:=GetNthChild(actnode,'toptags',0); + repeat + anode:=GetNthChild(GetNthChild(node,'tag',i),'name',0); + if anode=0 then break; + if pcw<>@request then + begin + pcw^:=','; inc(pcw); + pcw^:=' '; inc(pcw); + end; + pcw:=StrCopyEW(pcw,GetText(anode)); + inc(i); + until false; + pcw:=#0; + StrDupW(data.tags,pWideChar(@request)); + + DestroyNode(root); + mFreeMem(pcw); + end; + end; +end; diff --git a/plugins/Watrack/lastfm/i_last_dlg.inc b/plugins/Watrack/lastfm/i_last_dlg.inc new file mode 100644 index 0000000000..b72545843e --- /dev/null +++ b/plugins/Watrack/lastfm/i_last_dlg.inc @@ -0,0 +1,120 @@ +{} +const + MaxLangs = 11; + LangArray:array [0..MaxLangs-1] of record + code:array [0..1] of AnsiChar; + name:pWideChar; + end= ( + (code:#0#0 ; name: 'no language';), + (code:'zh' ; name: 'Chinese' ;), + (code:'en' ; name: 'English' ;), + (code:'fr' ; name: 'French' ;), + (code:'de' ; name: 'German' ;), + (code:'hi' ; name: 'Hindi' ;), + (code:'it' ; name: 'Italian' ;), + (code:'ja' ; name: 'Japanese' ;), + (code:'pt' ; name: 'Portuguese' ;), + (code:'ru' ; name: 'Russian' ;), + (code:'es' ; name: 'Spanish' ;) + ); + +procedure ClearInfo(dlg:HWND); +begin + SetDlgItemTextW(dlg,IDC_DATA_ARTIST,''); + SetDlgItemTextW(dlg,IDC_DATA_ALBUM ,''); + SetDlgItemTextW(dlg,IDC_DATA_TRACK ,''); + SetDlgItemTextW(dlg,IDC_DATA_TAGS ,''); + SetDlgItemTextW(dlg,IDC_DATA_INFO ,''); +end; + +procedure ClearData(var data:tLastFMInfo); +begin + mFreeMem(data.artist); + mFreeMem(data.album); + mFreeMem(data.title); + mFreeMem(data.tags); + mFreeMem(data.info); + mFreeMem(data.image); +end; + +function DlgProcOptions(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + tmp:longbool; + bmp,wnd:HWND; + lang:integer; + data:tLastFMInfo; +begin + result:=0; + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + SetDlgItemTextA(Dialog,IDC_LOGIN,lfm_login); + SetDlgItemTextA(Dialog,IDC_PASS ,lfm_password); + SetDlgItemInt (Dialog,IDC_TRIES,lfm_tries,false); + wnd:=GetDlgItem(Dialog,IDC_LANGUAGE); + for lang:=0 to MaxLangs-1 do + with LangArray[lang] do + CB_AddStrDataW(wnd,TranslateW(name), + ord(code[0])+(ord(code[1]) shl 8),lang); + CB_SelectData(wnd,lfm_lang); + end; + + WM_COMMAND: begin + case wParam shr 16 of + BN_CLICKED: begin + ClearInfo(Dialog); + FillChar(data,SizeOf(data),0); + lfm_lang:=CB_GetData(GetDlgItem(Dialog,IDC_LANGUAGE)); + + if loword(wParam)=IDC_INFO_ARTIST then + begin + SetDlgItemTextW(Dialog,IDC_ALT,TranslateW('Similar artists')); + GetArtistInfo(data,lfm_lang); + SetDlgItemTextW(Dialog,IDC_DATA_ALBUM,data.similar); + end + else + begin + SetDlgItemTextW(Dialog,IDC_ALT,TranslateW('Album')); + if loword(wParam)=IDC_INFO_TRACK then + GetTrackInfo (data,lfm_lang) + else + GetAlbumInfo (data,lfm_lang); + SetDlgItemTextW(Dialog,IDC_DATA_ALBUM,data.album); + end; + + SetDlgItemTextW(Dialog,IDC_DATA_ARTIST,data.artist); + SetDlgItemTextW(Dialog,IDC_DATA_TRACK ,data.title); + SetDlgItemTextW(Dialog,IDC_DATA_TAGS ,data.tags); + SetDlgItemTextW(Dialog,IDC_DATA_INFO ,data.info); + bmp:=LoadImageURL(data.image,64); + if bmp<>0 then + DeleteObject(SendDlgItemMessage(Dialog,IDC_DATA_PIC,STM_SETIMAGE,IMAGE_BITMAP,bmp)); + + ClearData(data); + end; + EN_CHANGE: + case loword(wParam) of + IDC_LOGIN,IDC_PASS,IDC_TRIES: + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + end; + + WM_NOTIFY: begin + if integer(PNMHdr(lParam)^.code)=PSN_APPLY then + begin + mFreeMem(lfm_login ); lfm_login :=GetDlgText(Dialog,IDC_LOGIN,true); + mFreeMem(lfm_password); lfm_password:=GetDlgText(Dialog,IDC_PASS ,true); + mFreeMem(session_id); + mFreeMem(np_url); + mFreeMem(sub_url); + lfm_tries:=GetDlgItemInt(Dialog,IDC_TRIES,tmp,false); + lfm_lang:=CB_GetData(GetDlgItem(Dialog,IDC_LANGUAGE)); + + SaveOpt; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/lastfm/i_last_opt.inc b/plugins/Watrack/lastfm/i_last_opt.inc new file mode 100644 index 0000000000..f18b590a87 --- /dev/null +++ b/plugins/Watrack/lastfm/i_last_opt.inc @@ -0,0 +1,44 @@ +{} +const + optLogin :pAnsiChar='lfm/login'; + optPassword:pAnsiChar='lfm/password'; + optTries :pAnsiChar='lfm/tries'; + optScrobble:pAnsiChar='lfm/scrobble'; + optLanguage:pAnsiChar='lfm/language'; + +procedure SaveOpt; +var + tmppass:array [0..255] of AnsiChar; +begin + if lfm_password<>nil then + begin + StrCopy(tmppass,lfm_password); + CallService(MS_DB_CRYPT_ENCODESTRING,StrLen(tmppass)+1,lparam(@tmppass)); + end; + DBWriteString(0,PluginShort,optPassword,tmppass); + DBWriteString(0,PluginShort,optLogin ,lfm_login); + DBWriteByte (0,PluginShort,optTries ,lfm_tries); + DBWriteByte (0,PluginShort,optScrobble,lfm_on and 1); + DBWriteWord (0,PluginShort,optLanguage,lfm_lang); +end; + +procedure LoadOpt; +begin + lfm_lang :=DBReadWord(0,PluginShort,optLanguage,0); + lfm_tries:=DBReadByte(0,PluginShort,optTries ,3); + lfm_on :=DBReadByte(0,PluginShort,optScrobble,0); + mFreeMem(lfm_login ); lfm_login :=DBReadString(0,PluginShort,optLogin); + mFreeMem(lfm_password); lfm_password:=DBReadString(0,PluginShort,optPassword); + if lfm_password<>nil then + CallService(MS_DB_CRYPT_DECODESTRING,StrLen(lfm_password)+1,lparam(lfm_password)); + if (lfm_login=nil) or (lfm_password=nil) then + CallService(MS_POPUP_SHOWMESSAGEW, + wparam(TranslateW('Don''t forget to enter Login and Password to use Last.fm service')), + SM_WARNING); +end; + +procedure FreeOpt; +begin + mFreeMem(lfm_login); + mFreeMem(lfm_password); +end; diff --git a/plugins/Watrack/lastfm/lastfm.ico b/plugins/Watrack/lastfm/lastfm.ico new file mode 100644 index 0000000000..6ed701e2a5 Binary files /dev/null and b/plugins/Watrack/lastfm/lastfm.ico differ diff --git a/plugins/Watrack/lastfm/lastfm.pas b/plugins/Watrack/lastfm/lastfm.pas new file mode 100644 index 0000000000..7f2d90b0dd --- /dev/null +++ b/plugins/Watrack/lastfm/lastfm.pas @@ -0,0 +1,300 @@ +unit lastfm; +{$include compilers.inc} +interface +{$Resource lastfm.res} +implementation + +uses windows, messages, commctrl, + common, + m_api,dbsettings,wrapper,mirutils, + wat_api,global; + +const + opt_ModStatus:PAnsiChar = 'module/lastfm'; +const + IcoLastFM:pAnsiChar = 'WATrack_lasfm'; +var + lfm_tries:integer; + sic:THANDLE; + slastinf:THANDLE; + slast:THANDLE; +const + lfm_lang :integer=0; + lfm_on :integer=0; + hMenuLast :HMENU = 0; + lfm_login :pAnsiChar=nil; + lfm_password:pAnsiChar=nil; + session_id :pAnsiChar=nil; + np_url :pAnsiChar=nil; + sub_url :pAnsiChar=nil; + +function GetModStatus:integer; +begin + result:=DBReadByte(0,PluginShort,opt_ModStatus,1); +end; + +procedure SetModStatus(stat:integer); +begin + DBWriteByte(0,PluginShort,opt_ModStatus,stat); +end; + +{$i i_const.inc} +{$i i_last_opt.inc} +{$i i_last_api.inc} + +procedure ThScrobble(param:LPARAM); cdecl; +var + count:integer; + npisok:bool; +begin + count:=lfm_tries; + npisok:=false; + while count>0 do + begin + if not npisok then + npisok:=SendNowPlaying>=0; + if Scrobble>=0 then break; + HandShake(lfm_login,lfm_password, count=1); // just last time + dec(count); + end; + if count=0 then ; +end; + +const + hTimer:THANDLE=0; + +procedure TimerProc(wnd:HWND;uMsg:uint;idEvent:uint_ptr;dwTime:dword); stdcall; +begin + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + + if (lfm_login <>nil) and (lfm_login^ <>#0) and + (lfm_password<>nil) and (lfm_password^<>#0) then + CloseHandle(mir_forkthread(@ThScrobble,nil)); +end; + +function NewPlStatus(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + flag:integer; + mi:TCListMenuItem; +begin + result:=0; + case wParam of + WAT_EVENT_NEWTRACK: begin + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + if lfm_on=0 then + hTimer:=SetTimer(0,0,30000,@TimerProc) + end; + + WAT_EVENT_PLUGINSTATUS: begin + case lParam of + dsEnabled: begin + lfm_on:=lfm_on and not 2; + flag:=0; + end; + dsPermanent: begin + lfm_on:=lfm_on or 2; + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + flag:=CMIF_GRAYED; + end; + else // like 1 + exit + end; + FillChar(mi,sizeof(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_FLAGS+flag; + CallService(MS_CLIST_MODIFYMENUITEM,hMenuLast,tlparam(@mi)); + end; + + WAT_EVENT_PLAYERSTATUS: begin + case Integer(loword(lParam)) of + WAT_PLS_NOMUSIC,WAT_PLS_NOTFOUND: begin + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + end; + end; + end; + end; +end; + +{$i i_last_dlg.inc} + +function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; +begin + result:=0; + FillChar(mi,SizeOf(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_ICON; + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,tlparam(IcoLastFM)); + CallService(MS_CLIST_MODIFYMENUITEM,hMenuLast,tlparam(@mi)); +end; + +function SrvLastFMInfo(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + data:tLastFMInfo; +begin + case wParam of + 0: result:=GetArtistInfo(data,lParam); + 1: result:=GetAlbumInfo (data,lParam); + 2: result:=GetTrackInfo (data,lParam); + else + result:=0; + end; +end; + +function SrvLastFM(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; +begin + FillChar(mi,sizeof(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_NAME; + if odd(lfm_on) then + begin + mi.szName.a:='Disable scrobbling'; + lfm_on:=lfm_on and not 1; + end + else + begin + mi.szName.a:='Enable scrobbling'; + lfm_on:=lfm_on or 1; + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + end; + CallService(MS_CLIST_MODIFYMENUITEM,hMenuLast,tlparam(@mi)); + result:=ord(not odd(lfm_on)); +end; + +procedure CreateMenus; +var + mi:TCListMenuItem; + sid:TSKINICONDESC; +begin + FillChar(sid,SizeOf(TSKINICONDESC),0); + sid.cbSize:=SizeOf(TSKINICONDESC); + sid.cx:=16; + sid.cy:=16; + sid.szSection.a:='WATrack'; + + sid.hDefaultIcon :=LoadImage(hInstance,'IDI_LAST',IMAGE_ICON,16,16,0); + sid.pszName :=IcoLastFM; + sid.szDescription.a:='LastFM'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + FillChar(mi, sizeof(mi), 0); + mi.cbSize :=sizeof(mi); + mi.szPopupName.a:=PluginShort; + + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(IcoLastFM)); + mi.szName.a :='Disable scrobbling'; + mi.pszService :=MS_WAT_LASTFM; + mi.popupPosition:=500050000; + hMenuLast:=Menu_AddMainMenuItem(@mi); +end; + +// ------------ base interface functions ------------- + +function AddOptionsPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +begin + tmpl:='LASTFM'; + proc:=@DlgProcOptions; + name:='LastFM'; + result:=0; +end; + +var + plStatusHook:THANDLE; + +function InitProc(aGetStatus:boolean=false):integer; +begin + slastinf:=CreateServiceFunction(MS_WAT_LASTFMINFO,@SrvLastFMInfo); + if aGetStatus then + begin + if GetModStatus=0 then + begin + result:=0; + exit; + end; + end + else + begin + SetModStatus(1); + lfm_on:=lfm_on and not 4; + end; + result:=1; + + LoadOpt; + + slast:=CreateServiceFunction(MS_WAT_LASTFM,@SrvLastFM); + if hMenuLast=0 then + CreateMenus; + sic:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged); + if (lfm_on and 4)=0 then + plStatusHook:=HookEvent(ME_WAT_NEWSTATUS,@NewPlStatus); +end; + +procedure DeInitProc(aSetDisable:boolean); +begin + if aSetDisable then + SetModStatus(0) + else + DestroyServiceFunction(slastinf); + + CallService(MS_CLIST_REMOVEMAINMENUITEM,hMenuLast,0); + hMenuLast:=0; + DestroyServiceFunction(slast); + UnhookEvent(plStatusHook); + UnhookEvent(sic); + + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + + FreeOpt; + + mFreeMem(session_id); + mFreeMem(np_url); + mFreeMem(sub_url); + + lfm_on:=lfm_on or 4; +end; + +var + last:twModule; + +procedure Init; +begin + last.Next :=ModuleLink; + last.Init :=@InitProc; + last.DeInit :=@DeInitProc; + last.AddOption:=@AddOptionsPage; + last.ModuleName:='Last.FM'; + ModuleLink :=@last; + +end; + +begin + Init; +end. diff --git a/plugins/Watrack/lastfm/lastfm.rc b/plugins/Watrack/lastfm/lastfm.rc new file mode 100644 index 0000000000..320eebe8cc --- /dev/null +++ b/plugins/Watrack/lastfm/lastfm.rc @@ -0,0 +1,38 @@ +#include "i_const.inc" + +LANGUAGE 0,0 + +LASTFM DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + LTEXT "Login" , -1, 108, 2, 70, 16, SS_CENTERIMAGE + EDITTEXT IDC_LOGIN , 4, 4, 100, 12, + LTEXT "Password", -1, 108, 18, 70, 16, SS_CENTERIMAGE + EDITTEXT IDC_PASS , 4, 20, 100, 12, ES_PASSWORD + LTEXT "Attempts", -1, 40, 34, 64, 16, SS_CENTERIMAGE + EDITTEXT IDC_TRIES , 4, 36, 32, 12, ES_RIGHT | ES_NUMBER + + LTEXT "Content language", -1, 80, 52, 76, 16, SS_CENTERIMAGE + COMBOBOX IDC_LANGUAGE, 160, 53, 74, 96, CBS_DROPDOWNLIST | WS_VSCROLL + + PUSHBUTTON "Get Artist Info", IDC_INFO_ARTIST, 4, 166, 72, 16 + PUSHBUTTON "Get Track Info" , IDC_INFO_TRACK , 4, 186, 72, 16 + PUSHBUTTON "Get Album Info" , IDC_INFO_ALBUM , 4, 206, 72, 16 + + CONTROL "", IDC_DATA_PIC, "STATIC", SS_BITMAP | WS_BORDER, 236, 2, 64, 64 + RTEXT "Artist", -1 , 0, 70, 76, 16, SS_CENTERIMAGE + EDITTEXT IDC_DATA_ARTIST, 80, 71, 220, 14, ES_READONLY | ES_AUTOHSCROLL + RTEXT "Album",IDC_ALT, 0, 86, 76, 16, SS_CENTERIMAGE + EDITTEXT IDC_DATA_ALBUM , 80, 87, 220, 14, ES_READONLY | ES_AUTOHSCROLL + RTEXT "Track" , -1 , 0, 102, 76, 16, SS_CENTERIMAGE + EDITTEXT IDC_DATA_TRACK , 80, 103, 220, 14, ES_READONLY | ES_AUTOHSCROLL + RTEXT "Tags" , -1 , 0, 118, 76, 16, SS_CENTERIMAGE + EDITTEXT IDC_DATA_TAGS , 80, 119, 220, 14, ES_READONLY | ES_AUTOHSCROLL + RTEXT "Info" , -1 , 0, 134, 76, 16, SS_CENTERIMAGE + EDITTEXT IDC_DATA_INFO , 80, 135, 220, 88, + ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | WS_VSCROLL +} + +IDI_LAST ICON "lastfm.ico" diff --git a/plugins/Watrack/lastfm/lastfm.res b/plugins/Watrack/lastfm/lastfm.res new file mode 100644 index 0000000000..0ed756fb33 Binary files /dev/null and b/plugins/Watrack/lastfm/lastfm.res differ diff --git a/plugins/Watrack/lst_formats.inc b/plugins/Watrack/lst_formats.inc new file mode 100644 index 0000000000..19db34ee40 --- /dev/null +++ b/plugins/Watrack/lst_formats.inc @@ -0,0 +1,16 @@ +,fmt_dummy in 'formats\fmt_dummy.pas' +,fmt_mpc in 'formats\fmt_mpc.pas' +,fmt_ofr in 'formats\fmt_ofr.pas' +,fmt_tta in 'formats\fmt_tta.pas' +,fmt_real in 'formats\fmt_real.pas' +,fmt_ape in 'formats\fmt_ape.pas' +,fmt_wav in 'formats\fmt_wav.pas' +,fmt_flv in 'formats\fmt_flv.pas' +,fmt_aac in 'formats\fmt_aac.pas' +,fmt_mkv in 'formats\fmt_mkv.pas' +,fmt_m4a in 'formats\fmt_m4a.pas' +,fmt_wma in 'formats\fmt_wma.pas' +,fmt_avi in 'formats\fmt_avi.pas' +,fmt_ogg in 'formats\fmt_ogg.pas' +,fmt_mp3 in 'formats\fmt_mp3.pas' +,tags in 'formats\tags.pas' diff --git a/plugins/Watrack/lst_players.inc b/plugins/Watrack/lst_players.inc new file mode 100644 index 0000000000..759b06cf51 --- /dev/null +++ b/plugins/Watrack/lst_players.inc @@ -0,0 +1,17 @@ +,pl_apollo in 'players\pl_apollo.pas' +,pl_behold in 'players\pl_behold.pas' +,pl_mradio in 'players\pl_mradio.pas' +,pl_lastfm in 'players\pl_lastfm.pas' +,pl_1by1 in 'players\pl_1by1.pas' +,pl_bs in 'players\pl_bs.pas' +,pl_la in 'players\pl_la.pas' +,pl_mmonkey in 'players\pl_mmonkey.pas' +,pl_itunes in 'players\pl_itunes.pas' +,pl_cowon in 'players\pl_cowon.pas' +,pl_vlc in 'players\pl_vlc.pas' +// keep file for check in future +//,pl_wmp in 'players\pl_wmp.pas' +,pl_mpc in 'players\pl_mpc.pas' +,pl_aimp in 'players\pl_aimp.pas' +,pl_foobar in 'players\pl_foobar.pas' +,pl_winamp in 'players\pl_winamp.pas' diff --git a/plugins/Watrack/m_music.inc b/plugins/Watrack/m_music.inc new file mode 100644 index 0000000000..aba0bd27f6 --- /dev/null +++ b/plugins/Watrack/m_music.inc @@ -0,0 +1,419 @@ +{$IFNDEF M_MUSIC} +{$DEFINE M_MUSIC} + +// defined in interfaces.inc +//const MIID_WATRACK:MUUID='{FC6C81F4-837E-4430-9601-A0AA43177AE3}'; + +type + pSongInfoA = ^tSongInfoA; + tSongInfoA = record + artist :PAnsiChar; + title :PAnsiChar; + album :PAnsiChar; + genre :PAnsiChar; + comment :PAnsiChar; + year :PAnsiChar; + mfile :PAnsiChar; // media file + kbps :dword; + khz :dword; + channels :dword; + track :dword; + total :dword; // music length + time :dword; // elapsed time + wndtext :PAnsiChar; // window title + player :PAnsiChar; // player name + plyver :dword; // player version + icon :THANDLE; // player icon + fsize :dword; // media file size + vbr :dword; + status :integer; // WAT_MES_* const + plwnd :HWND; // player window + // video part + codec :dword; + width :dword; + height :dword; + fps :dword; + date :int64; + txtver :PAnsiChar; + lyric :PAnsiChar; + cover :PAnsiChar; + volume :dword; + url :PAnsiChar; // player homepage + winampwnd:HWND; + end; +type + pSongInfo=^tSongInfo; + tSongInfo = record + artist :pWideChar; + title :pWideChar; + album :pWideChar; + genre :pWideChar; + comment :pWideChar; + year :pWideChar; + mfile :pWideChar; // media file + kbps :dword; + khz :dword; + channels :dword; + track :dword; + total :dword; // music length + time :dword; // elapsed time + wndtext :pWideChar; // window title + player :pWideChar; // player name + plyver :dword; // player version + icon :THANDLE; // player icon + fsize :dword; // media file size + vbr :dword; + status :integer; // WAT_MES_* const + plwnd :HWND; // player window + // video part + codec :dword; + width :dword; + height :dword; + fps :dword; + date :int64; + txtver :pWideChar; + lyric :pWideChar; + cover :pWideChar; // cover path + volume :dword; + url :PWideChar; // player homepage + winampwnd:HWND; + end; + pSongInfoW = pSongInfo; + tSongInfoW = tSongInfo; + +const + // result codes + WAT_RES_UNKNOWN = -2; + WAT_RES_NOTFOUND = -1; + WAT_RES_ERROR = WAT_RES_NOTFOUND; + WAT_RES_OK = 0; + WAT_RES_ENABLED = WAT_RES_OK; + WAT_RES_DISABLED = 1; + // internal + WAT_RES_NEWFILE = 3; + WAT_RES_NEWPLAYER = 4; + +// result for MS_WAT_GETMUSICINFO service +const + WAT_PLS_NORMAL = WAT_RES_OK; + WAT_PLS_NOMUSIC = WAT_RES_DISABLED; + WAT_PLS_NOTFOUND = WAT_RES_NOTFOUND; + +const + WAT_INF_UNICODE = 0; + WAT_INF_ANSI = 1; + WAT_INF_UTF8 = 2; + WAT_INF_CHANGES = $100; + +const + MS_WAT_INSERT:PAnsiChar = 'WATrack/Insert'; + MS_WAT_EXPORT:PAnsiChar = 'WATrack/Export'; + +const +{ + wParam : WAT_INF_* constant + lParam : pointer to pSongInfo (Unicode) or pSongInfoA (ANSI/UTF8) + Affects: Fill structure by currently played music info + returns: WAT_PLS_* constant + note: pointer will be point to global SongInfo structure of plugin + warning: Non-Unicode data filled only by request + if lParam=0 only internal SongInfo structure will be filled + Example: + var p:pSongInfo; + CallService(MS_WAT_GETMUSICINFO,0,dword(@p)); +} + MS_WAT_GETMUSICINFO:PAnsiChar = 'WATrack/GetMusicInfo'; +{ + wParam:0 + lParam : pointer to pSongInfo (Unicode) + Affects: Fill structure by info from file named in SongInfo.mfile + returns: 0, if success + note: fields, which values can't be obtained, leaves old values. + you must free given strings by miranda mir_free +} + MS_WAT_GETFILEINFO:PAnsiChar = 'WATrack/GetFileInfo'; + +{ + wParam: encoding (WAT_INF_* consts, 0 = WAT_INF_UNICODE) + lParam: codepage (0 = ANSI) + Returns Global unicode SongInfo pointer or tranlated to Ansi/UTF8 structure +} + MS_WAT_RETURNGLOBAL:PAnsiChar = 'WATrack/GetMainStructure'; + +//!! DON'T CHANGE THESE VALUES! +const + WAT_CTRL_FIRST = 1; + + WAT_CTRL_PREV = 1; + WAT_CTRL_PLAY = 2; + WAT_CTRL_PAUSE = 3; + WAT_CTRL_STOP = 4; + WAT_CTRL_NEXT = 5; + WAT_CTRL_VOLDN = 6; + WAT_CTRL_VOLUP = 7; + WAT_CTRL_SEEK = 8; // lParam is new position (sec) + + WAT_CTRL_LAST = 8; + +{ + wParam: button code (WAT_CTRL_* const) + lParam: 0, or value (see WAT_CTRL_* const comments) + Affects: emulate player button pressing + returns: 0 if unsuccesful +} + MS_WAT_PRESSBUTTON:PAnsiChar = 'WATrack/PressButton'; + +{ + Get user's Music Info +} + MS_WAT_GETCONTACTINFO:PAnsiChar = 'WATrack/GetContactInfo'; + +// ------------ Plugin/player status ------------ + +{ + wParam: 1 - switch off plugin + 0 - switch on plugin + -1 - switch plugin status + 2 - get plugin version + other - get plugin status + lParam: 0 + Affects: Switch plugin status to enabled or disabled + returns: version, old plugin status, 0, if was enabled +} + MS_WAT_PLUGINSTATUS:PAnsiChar = 'WATrack/PluginStatus'; + + ME_WAT_MODULELOADED:PAnsiChar = 'WATrack/ModuleLoaded'; + +const + WAT_EVENT_PLAYERSTATUS = 1; // WAT_PLS_* in loword, WAT_MES_* in hiword + WAT_EVENT_NEWTRACK = 2; // SongInfo ptr + WAT_EVENT_PLUGINSTATUS = 3; // 0-enabled; 1-dis.temporary; 2-dis.permanent + WAT_EVENT_NEWPLAYER = 4; // + WAT_EVENT_NEWTEMPLATE = 5; // TM_* constant + +{ + Plugin or player status changed: + wParam: type of event (see above) + lParam: value +} + ME_WAT_NEWSTATUS:PAnsiChar = 'WATrack/NewStatus'; + +// ---------- Popup module ------------ + +{ + wParam: not used + lParam: not used + Affects: Show popup or Info window with current music information + note: Only Info window will be showed if Popup plugin disabled +} + MS_WAT_SHOWMUSICINFO:PAnsiChar = 'WATrack/ShowMusicInfo'; + +// --------- Statistic (report) module ------------- + +{ + wParam: pointer to log file name or NIL + lParam: pointer to report file name or NIL + Affects: Create report from log and run it (if option is set) + returns: 0 if unsuccesful + note: if wParam or lParam is a NIL then file names from options are used +} + MS_WAT_MAKEREPORT :PAnsiChar = 'WATrack/MakeReport'; +// MS_WAT_MAKEREPORTW:PAnsiChar = 'WATrack/MakeReportW'; + +{ + wParam, lParam - not used + Affects: pack statistic file +} + MS_WAT_PACKLOG:PAnsiChar = 'WATrack/PackLog'; + +{ + wParam: not used + lParam: pointer to SongInfo +} + MS_WAT_ADDTOLOG:PAnsiChar = 'WATrack/AddToLog'; + +// ----------- Formats and players ----------- + +// media file status + +const + WAT_MES_STOPPED = 0; + WAT_MES_PLAYING = 1; + WAT_MES_PAUSED = 2; + WAT_MES_UNKNOWN = -1; + +const + WAT_ACT_REGISTER = 1; + WAT_ACT_UNREGISTER = 2; + WAT_ACT_DISABLE = 3; + WAT_ACT_ENABLE = 4; + WAT_ACT_GETSTATUS = 5; // not found/enabled/disabled + WAT_ACT_SETACTIVE = 6; + WAT_ACT_REPLACE = $10000; // can be combined with WAT_REGISTERFORMAT + +const + // flags + WAT_OPT_DISABLED = $00000001; // [formats,players,options] registered but disabled + WAT_OPT_ONLYONE = $00000002; // [formats,players] code can't be overwriten + WAT_OPT_PLAYERINFO = $00000004; // [players] song info from player + WAT_OPT_WINAMPAPI = $00000008; // [players] Winamp API support + WAT_OPT_CHECKTIME = $00000010; // [options] check file time for changes + WAT_OPT_VIDEO = $00000020; // [formats,options] format is video + WAT_OPT_LAST = $00000040; // (internal-Winamp Clone) put to the end of queue + WAT_OPT_FIRST = $00000080; // (internal) + WAT_OPT_TEMPLATE = $00000100; // (internal) + WAT_OPT_IMPLANTANT = $00000200; // [options] use process implantation + WAT_OPT_HASURL = $00000400; // [players] URL field present + WAT_OPT_CHANGES = $00000800; // (internal) obtain only chaged values + // (volume, status, window text, elapsed time) + WAT_OPT_APPCOMMAND = $00001000; // [options] Special (multimedia) key support + WAT_OPT_CHECKALL = $00002000; // [options] Check all players + WAT_OPT_KEEPOLD = $00004000; // [options] Keep Old opened file + WAT_OPT_MULTITHREAD = $00008000; // [options] Use multithread scan + WAT_OPT_SINGLEINST = $00010000; // [players] Single player instance + WAT_OPT_PLAYERDATA = $00020000; // (internal) to obtain player data + WAT_OPT_CONTAINER = $00040000; // [formats] format is container (need to check full) + +type + tReadFormatProc = function(var Info:tSongInfo):boolean; cdecl; + pMusicFormat = ^tMusicFormat; + tMusicFormat = record + proc :tReadFormatProc; + ext :array [0..7] of AnsiChar; + flags:cardinal; + end; + +const +{ + wParam: action + lParam: pointer to tMusicFormat if wParam = WAT_ACT_REGISTER, + else - pointer to extension string (ANSI) + returns: see result codes +} + MS_WAT_FORMAT:PAnsiChar = 'WATrack/Format'; + +{ + wParam: pointer to SongInfo structure (plwind field must be initialized) + lParam: flags + Affects: trying to fill SongInfo using Winamp API +} + MS_WAT_WINAMPINFO:PAnsiChar = 'WATrack/WinampInfo'; + +{ + wParam: window + lParam: LoWord - command; HiWord - value +} + MS_WAT_WINAMPCOMMAND:PAnsiChar = 'WATrack/WinampCommand'; + +type + tInitProc = function():integer;cdecl; + tDeInitProc = function():integer;cdecl; + tStatusProc = function(wnd:HWND):integer;cdecl; + tNameProc = function(wnd:HWND;flags:integer):pWideChar;cdecl; + tCheckProc = function(wnd:HWND;flags:integer):HWND;cdecl; + tInfoProc = function(var SongInfo:tSongInfo;flags:integer):integer;cdecl; + tCommandProc = function(wnd:HWND;command:integer;value:integer):integer;cdecl; + + pPlayerCell = ^tPlayerCell; + tPlayerCell = record + Desc :PAnsiChar; // Short player name + flags :cardinal; + Icon :HICON; // can be 0. for registration only + Init :pointer; // tInitProc; can be NIL. initialize any data + DeInit :pointer; // tDeInitProc; can be NIL. finalize player processing + Check :pointer; // tCheckProc; check player + GetStatus:pointer; // tStatusProc; can be NIL. get player status + GetName :pointer; // tNameProc; can be NIL. get media filename + GetInfo :pointer; // tInfoProc; can be NIL. get info from player + Command :pointer; // tCommandProc; can be NIL. send command to player + URL :PAnsiChar; // only if WAT_OPT_HASURL flag present + Notes :PWideChar; // any tips, notes etc for this player + end; + +const +{ + wParam: action + lParam: pointer to tPlayerCell if wParam = WAT_ACT_REGISTER, + else - pointer to player description string (ANSI) + returns: player window handle or value>0 if found + note: If you use GetName or GetInfo field, please, do not return empty + filename even when mediafile is remote! +} + MS_WAT_PLAYER:PAnsiChar = 'WATrack/Player'; + +// --------- MyShows.ru --------- + +{ + Toggle MyShows scrobbling status + wParam,lParam=0 + Returns: previous state +} +const + MS_WAT_MYSHOWS:pAnsiChar = 'WATrack/MyShows'; + + +const + MS_WAT_MYSHOWSINFO:pAnsiChar = 'WATrack/MyShowsInfo'; + +// --------- Last FM --------- + +{ + Toggle LastFM scrobbling status + wParam,lParam=0 + Returns: previous state +} +const + MS_WAT_LASTFM:pAnsiChar = 'WATrack/LastFM'; + +{ + Get Info based on currently played song + wParam: pLastFMInfo + lParam: int language (first 2 bytes - 2-letters language code) +} +type + pLastFMInfo = ^tLastFMInfo; + tLastFMInfo = record + request:cardinal; // 0 - artist, 1 - album, 2 - track + artist :pWideChar; // artist + album :pWideChar; // album or similar artists for Artist info request + title :pWideChar; // track title + tags :pWideChar; // tags + info :pWideChar; // artist bio or wiki article + image :pAnsiChar; // photo/cover link + similar:pWideChar; + release:pWideChar; + trknum :cardinal; + end; +const + MS_WAT_LASTFMINFO:pAnsiChar = 'WATrack/LastFMInfo'; + +// --------- Templates ---------- + +const +{ + wParam: 0 (standard Info) or pSongInfo + lParam: Unicode template + returns: New Unicode (replaced) string +} + MS_WAT_REPLACETEXT:PAnsiChar = 'WATrack/ReplaceText'; + +{ + event types for History + Blob structure for EVENTTYPE_WAT_ANSWER: + Uniciode artist#0title#0album#0answer +} +const + EVENTTYPE_WAT_REQUEST = 9601; + EVENTTYPE_WAT_ANSWER = 9602; + EVENTTYPE_WAT_ERROR = 9603; + EVENTTYPE_WAT_MESSAGE = 9604; + +const +{ + wParam: 0 or parent window + lParam: 0 + note: Shows Macro help window with edit aliases ability +} + MS_WAT_MACROHELP:pAnsiChar = 'WATrack/MacroHelp'; + +{$ENDIF M_MUSIC} diff --git a/plugins/Watrack/macros.pas b/plugins/Watrack/macros.pas new file mode 100644 index 0000000000..cdbe52991e --- /dev/null +++ b/plugins/Watrack/macros.pas @@ -0,0 +1,93 @@ +{to Variables plugin and Help dialog} +unit macros; + +interface + +type + pvar = ^tvar; + tvar = packed record + name :PWideChar; + alias:PWideChar; + help :PAnsiChar; + end; + +// --- data --- +const + numvars = 35; + + mn_wndtext = 0; + mn_artist = 1; + mn_title = 2; + mn_album = 3; + mn_genre = 4; + mn_file = 5; + mn_kbps = 6; + mn_bitrate = 7; + mn_track = 8; + mn_channels = 9; + mn_mono = 10; + mn_khz = 11; + mn_samplerate = 12; + mn_total = 13; + mn_length = 14; + mn_year = 15; + mn_time = 16; + mn_percent = 17; + mn_comment = 18; + mn_player = 19; + mn_version = 20; + mn_size = 21; + mn_type = 22; + mn_vbr = 23; + mn_status = 24; + mn_fps = 25; + mn_codec = 26; + mn_width = 27; + mn_height = 28; + mn_txtver = 29; + mn_lyric = 30; + mn_cover = 31; + mn_volume = 32; + mn_playerhome = 33; + mn_nstatus = 34; + vars:array [0..numvars-1] of tvar = ( +{00} (name:'wndtext' ;alias:nil;help:'player window title'), +{01} (name:'artist' ;alias:nil;help:'artist'), +{02} (name:'title' ;alias:nil;help:'song title'), +{03} (name:'album' ;alias:nil;help:'album'), +{04} (name:'genre' ;alias:nil;help:'genre'), +{05} (name:'file' ;alias:nil;help:'media file name'), +{06} (name:'kbps' ;alias:nil;help:'bitrate'), +{07} (name:'bitrate' ;alias:nil;help:nil), +{08} (name:'track' ;alias:nil;help:'track number'), +{09} (name:'channels' ;alias:nil;help:'number of channels'), +{10} (name:'mono' ;alias:nil;help:'"mono"/"stereo"'), +{11} (name:'khz' ;alias:nil;help:'samplerate'), +{12} (name:'samplerate';alias:nil;help:nil), +{13} (name:'total' ;alias:nil;help:'total song length (sec)'), +{14} (name:'length' ;alias:nil;help:nil), +{15} (name:'year' ;alias:nil;help:'song year (date)'), +{16} (name:'time' ;alias:nil;help:'current song position (sec)'), +{17} (name:'percent' ;alias:nil;help:'time/length * 100%'), +{18} (name:'comment' ;alias:nil;help:'comment from tag'), +{19} (name:'player' ;alias:nil;help:'player name'), +{20} (name:'version' ;alias:nil;help:'player version'), +{21} (name:'size' ;alias:nil;help:'media file size'), +{22} (name:'type' ;alias:nil;help:'media file type'), +{23} (name:'vbr' ;alias:nil;help:'VBR or not (empty)'), +{24} (name:'status' ;alias:nil;help:'player status (stopped,playing,paused)'), +{25} (name:'fps' ;alias:nil;help:'FPS (frames per second), video only'), +{26} (name:'codec' ;alias:nil;help:'codec, video only'), +{27} (name:'width' ;alias:nil;help:'width, video only'), +{28} (name:'height' ;alias:nil;help:'height, video only'), +{29} (name:'txtver' ;alias:nil;help:'player version in text format'), +{30} (name:'lyric' ;alias:nil;help:'Lyric from ID3v2 tag'), +{31} (name:'cover' ;alias:nil;help:'Cover file path'), +{32} (name:'volume' ;alias:nil;help:'Player volume (0-15)'), +{33} (name:'playerhome';alias:nil;help:'Player homepage URL'), +{34} (name:'nstatus' ;alias:nil;help:'player status (not translated)') + ); + +implementation + +end. \ No newline at end of file diff --git a/plugins/Watrack/make.bat b/plugins/Watrack/make.bat new file mode 100644 index 0000000000..cfaf1df3e1 --- /dev/null +++ b/plugins/Watrack/make.bat @@ -0,0 +1,26 @@ +@echo off +set myopts=-dMiranda +set dprname=watrack.dpr + +..\delphi\brcc32.exe res\watrack.rc -fores\watrack.res +..\delphi\brcc32.exe lastfm\lastfm.rc -folastfm\lastfm.res +..\delphi\brcc32.exe myshows\myshows.rc -fomyshows\myshows.res +..\delphi\brcc32.exe players\mradio.rc -foplayers\mradio.res +..\delphi\brcc32.exe kolframe\frm.rc -fokolframe\frm.res +..\delphi\brcc32.exe popup\popup.rc -fopopup\popup.res +..\delphi\brcc32.exe proto\proto.rc -foproto\proto.res +..\delphi\brcc32.exe stat\stat.rc -fostat\stat.res +..\delphi\brcc32.exe status\status.rc -fostatus\status.res +..\delphi\brcc32.exe templates\templates.rc -fotemplates\templates.res + +if /i '%1' == 'fpc' ( + ..\FPC\bin\fpc.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else if /i '%1' == 'fpc64' ( + ..\FPC\bin64\ppcrossx64.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else if /i '%1' == 'xe2' ( + ..\XE2\BIN\dcc32.exe%myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else if /i '%1' == 'xe64' ( + ..\XE2\BIN\dcc64.exe %myopts% %dprname% %2 %3 %4 %5 %6 %7 %8 %9 +) else ( + ..\delphi\dcc32 -b -dKOL_MCK -dUNICODE_CTRLS %myopts% %dprname% %1 %2 %3 %4 %5 %6 %7 %8 %9 +) diff --git a/plugins/Watrack/myrtf.pas b/plugins/Watrack/myrtf.pas new file mode 100644 index 0000000000..7a6bf2255f --- /dev/null +++ b/plugins/Watrack/myrtf.pas @@ -0,0 +1,219 @@ +{RTF related code} +unit MyRTF; +{$include compilers.inc} + +interface +uses windows; + +procedure SendRTF(wnd:hwnd;txt:PWideChar;isUnicode:Boolean;CP:integer=CP_ACP); + +implementation +uses richedit,common,messages,m_api; + +const + RTFBufferSize = 16384; +const + CTableHdr = '{\colortbl'; +const +(* + ColorTable = '{\colortbl;'+ + '\red255\green255\blue255;'+ + '\red0\green0\blue0;'+ + '\red0\green0\blue127;'+ + '\red0\green147\blue0;'+ + '\red255\green0\blue0;'+ + '\red127\green0\blue0;'+ + '\red156\green0\blue156;'+ + '\red252\green127\blue0;'+ + '\red255\green255\blue0;'+ + '\red0\green252\blue0;'+ + '\red0\green147\blue147;'+ + '\red0\green255\blue255;'+ + '\red0\green0\blue252;'+ + '\red255\green0\blue255;'+ + '\red127\green127\blue127;'+ + '\red210\green210\blue210;}'; +*) + ColorTableD = + '\red255\green255\blue255;'+ + '\red0\green0\blue0;'+ + '\red0\green0\blue127;'+ + '\red0\green147\blue0;'+ + '\red255\green0\blue0;'+ + '\red127\green0\blue0;'+ + '\red156\green0\blue156;'+ + '\red252\green127\blue0;'+ + '\red255\green255\blue0;'+ + '\red0\green252\blue0;'+ + '\red0\green147\blue147;'+ + '\red0\green255\blue255;'+ + '\red0\green0\blue252;'+ + '\red255\green0\blue255;'+ + '\red127\green127\blue127;'+ + '\red210\green210\blue210;'; + +function StreamWriteCallback(dwCookie:dword_ptr;pbBuff:PAnsiChar;cb:long;var pcb:long):dword;stdcall; +begin + pcb:=StrLen(PAnsiChar(dwCookie)); + if cbnil then + begin + src:=p; + if src[StrLen(what)] in ['A'..'Z','a'..'z'] then + begin + inc(src); + continue; + end; + i:=1; + if block then + begin + while src[i]<>'}' do inc(i); inc(i); + end + else + begin + while not (src[i] in ['}',' ','\',';',#13]) do + inc(i); + end; + StrCopy(src,src+i); + if new<>nil then + StrInsert(new,src,0); + end + else + break; + if not recurse then break; + until false; +end; + +procedure ReplaceTags(var src:PAnsiChar); +var + i:integer; +begin + ReplaceTag(src,'\b' ,nil,false); + ReplaceTag(src,'\i' ,nil,false); + ReplaceTag(src,'\ul' ,nil,false); + if (StrPos(src,'\{cf')<>nil) or (StrPos(src,'\{bg')<>nil) then + begin + ReplaceTag(src,'\cf' ,nil,false); + ReplaceTag(src,'\highlight',nil,false); + StrReplace(src,'\{/cf\}','\cf17 '); + StrReplace(src,'\{/bg\}','\highlight0 '); + i:=StrIndex(src,CTableHdr); + StrInsert(ColorTableD,src,i+integer(StrLen(CTableHdr))+1); + ReplaceTag(src,'\pard','\pard\cf17',false); + end; + + StrReplace(src,'\{b\}' ,'\b1 '); + StrReplace(src,'\{/b\}' ,'\b0 '); + StrReplace(src,'\{i\}' ,'\i1 '); + StrReplace(src,'\{/i\}' ,'\i0 '); + StrReplace(src,'\{u\}' ,'\ul '); + StrReplace(src,'\{/u\}' ,'\ul0 '); + + repeat + i:=StrIndex(src,'\{cf'); + if i>0 then + begin + StrCopy(src+i,src+i+1); + i:=StrIndex(src,'\}'); + if i>0 then + begin + StrCopy(src+i,src+i+1); + src[i-1]:=' '; + end; + end; + until i=0; + repeat + i:=StrIndex(src,'\{bg'); + if i>0 then + begin + StrCopy(src+i,src+i+3); + StrInsert('highlight',src,i); + i:=StrIndex(src,'\}'); + if i>0 then + begin + StrCopy(src+i,src+i+1); + src[i-1]:=' '; + end; + end; + until i=0; +end; + +function CharCount(p:PWideChar):integer; +begin + result:=0; + while p^<>#0 do + begin + if p^=#10 then inc(result); + inc(p); + end; +end; + +procedure SendRTF(wnd:hwnd;txt:PWideChar;isUnicode:Boolean;CP:integer=CP_ACP); +var + tmp:PAnsiChar; + sstart:integer; + ls:PAnsiChar; +begin + SendMessage(wnd,EM_GETSEL,wparam(@sstart),0); + if isUnicode then + SendMessagew(wnd,EM_REPLACESEL,0,lparam(txt)) + else + begin + SendMessageA(wnd,EM_REPLACESEL,0,lparam(WideToAnsi(txt,ls,CP))); + mFreeMem(ls); + end; + + SendMessage(wnd,EM_SETSEL,sstart,sstart+integer(StrLenW(txt))-CharCount(txt)); + mGetMem(tmp,RTFBufferSize); + FillChar(tmp^,RTFBufferSize,0); + ReadRTF(wnd,tmp); + ReplaceTags(tmp); + WriteRTF(wnd,tmp); + mFreeMem(tmp); + SendMessage(wnd,EM_SETSEL,-1,0); +end; + +end. diff --git a/plugins/Watrack/myshows/i_const.inc b/plugins/Watrack/myshows/i_const.inc new file mode 100644 index 0000000000..47c4b52618 --- /dev/null +++ b/plugins/Watrack/myshows/i_const.inc @@ -0,0 +1,14 @@ +const + IDC_LOGIN = 1025; + IDC_PASS = 1026; + IDC_TRIES = 1027; + IDC_TIME = 1028; + IDC_SCROBPOS = 1029; + + IDC_INFO_SERIES = 1039; + IDC_DATA_PIC = 1040; + IDC_DATA_SERIES = 1041; + IDC_DATA_EPISODE = 1042; + IDC_DATA_TAGS = 1044; + IDC_DATA_INFO = 1045; + IDC_KINOPOISK = 1046; diff --git a/plugins/Watrack/myshows/i_cookies.inc b/plugins/Watrack/myshows/i_cookies.inc new file mode 100644 index 0000000000..1258490199 --- /dev/null +++ b/plugins/Watrack/myshows/i_cookies.inc @@ -0,0 +1,91 @@ +{} +const + cookies:pAnsiChar=nil; + +function ExtractCookies(resp:PNETLIBHTTPREQUEST):integer; +var + cnt,len:integer; + p,pc:pAnsiChar; +begin + result:=0; + + mFreeMem(cookies); + mGetMem(cookies,1024); + + pc:=cookies; + for cnt:=0 to resp^.headersCount-1 do + begin + with resp^.headers[cnt] do + if StrCmp(szName,'Set-Cookie')=0 then + begin + len:=0; + p:=szValue; + while (p^<>#0) and (p^<>';') do + begin + inc(p); + inc(len); + end; + if pc<>cookies then + begin + pc^:=';'; inc(pc); + pc^:=' '; inc(pc); + end; + pc:=StrCopyE(pc,szValue,len); + inc(result); + end; + end; +end; + +function SendRequestCookies(url:PAnsiChar;useCookies:boolean):pAnsiChar; +var + nlu:TNETLIBUSER; + req :TNETLIBHTTPREQUEST; + resp:PNETLIBHTTPREQUEST; + hTmpNetLib:THANDLE; + nlh:array [0..10] of TNETLIBHTTPHEADER; +begin + result:=nil; + + FillChar(req,SizeOf(req),0); + req.cbSize :=NETLIBHTTPREQUEST_V1_SIZE;//SizeOf(req); + req.requestType:=REQUEST_GET; + req.szUrl :=url; + req.flags :=NLHRF_NODUMP or NLHRF_HTTP11; + + if useCookies and (cookies<>nil) then + begin + nlh[0].szName :='Cookie'; + nlh[0].szValue:=cookies; + + req.headers :=@nlh; + req.headersCount:=1; + end; + + FillChar(nlu,SizeOf(nlu),0); + nlu.cbSize :=SizeOf(nlu); + nlu.flags :=NUF_HTTPCONNS or NUF_NOHTTPSOPTION or NUF_OUTGOING or NUF_NOOPTIONS; + nlu.szSettingsModule:='dummy'; + hTmpNetLib:=CallService(MS_NETLIB_REGISTERUSER,0,lparam(@nlu)); + + resp:=pointer(CallService(MS_NETLIB_HTTPTRANSACTION,hTmpNetLib,lparam(@req))); + + if resp<>nil then + begin + if resp^.resultCode=200 then + begin + if resp.pData<>nil then + StrDup(result,resp.pData,resp.dataLength) + else + result:=PAnsiChar(200); + if not useCookies then + ExtractCookies(resp); + end + else + begin + result:=pAnsiChar(int_ptr(resp^.resultCode and $0FFF)); + end; + CallService(MS_NETLIB_FREEHTTPREQUESTSTRUCT,0,lparam(resp)); + end; + + CallService(MS_NETLIB_CLOSEHANDLE,hTmpNetLib,0); +end; diff --git a/plugins/Watrack/myshows/i_myshows_api.inc b/plugins/Watrack/myshows/i_myshows_api.inc new file mode 100644 index 0000000000..572cc3ee31 --- /dev/null +++ b/plugins/Watrack/myshows/i_myshows_api.inc @@ -0,0 +1,247 @@ +{} +//type tDigest = array [0..15] of byte; +(* +const + client_id = 'wat';//'wat'; 'tst' + client_ver = '1.0'; + api_key = '51f5d25159da31b0814609c3a12900e2'; +*) +{$include i_cookies.inc} + +const API_URL = 'http://api.myshows.ru/'; + +const + defreq = API_URL+'profile/login?login=&password='; + +procedure ShowError(code:integer); +var + buf:array [0..511] of WideChar; + ppc:pWideChar; +begin + case code of + 401: begin // Òðåáóåòñÿ àâòîðèçàöèÿ + ppc:='Authorization required'; + end; + 403: begin // Èìÿ ïîëüçîâàòåëÿ èëè ïàðîëü íå ïîäîøëè + ppc:='User name of password wrong'; + end; + 404: begin // Íå íàéäåíî, íåïðàâèëüíûå ïàðàìåòðû + ppc:='Not found / wrong parameters'; + end; + 500: begin // ïàðàìåòð çàïðîñà îòñóòñòâóåò + ppc:='Wrong query parameters'; + end; + else + ppc:='something wrong!'; + end; + StrCopyW(StrCopyEW(buf,'MyShows: '),TranslateW(ppc)); + + if ServiceExists(MS_POPUP_SHOWMESSAGEW)<>0 then + CallService(MS_POPUP_SHOWMESSAGEW,TWPARAM(@buf),SM_WARNING) + else + MessageBoxW(0,@buf,'ERROR',MB_ICONERROR) +end; + +function GetMD5Str(digest:TMD5Hash; buf:pAnsiChar):PAnsiChar; +begin + buf[00]:=HexDigitChrLo[digest[00] shr 4]; buf[01]:=HexDigitChrLo[digest[00] and $0F]; + buf[02]:=HexDigitChrLo[digest[01] shr 4]; buf[03]:=HexDigitChrLo[digest[01] and $0F]; + buf[04]:=HexDigitChrLo[digest[02] shr 4]; buf[05]:=HexDigitChrLo[digest[02] and $0F]; + buf[06]:=HexDigitChrLo[digest[03] shr 4]; buf[07]:=HexDigitChrLo[digest[03] and $0F]; + buf[08]:=HexDigitChrLo[digest[04] shr 4]; buf[09]:=HexDigitChrLo[digest[04] and $0F]; + buf[10]:=HexDigitChrLo[digest[05] shr 4]; buf[11]:=HexDigitChrLo[digest[05] and $0F]; + buf[12]:=HexDigitChrLo[digest[06] shr 4]; buf[13]:=HexDigitChrLo[digest[06] and $0F]; + buf[14]:=HexDigitChrLo[digest[07] shr 4]; buf[15]:=HexDigitChrLo[digest[07] and $0F]; + buf[16]:=HexDigitChrLo[digest[08] shr 4]; buf[17]:=HexDigitChrLo[digest[08] and $0F]; + buf[18]:=HexDigitChrLo[digest[09] shr 4]; buf[19]:=HexDigitChrLo[digest[09] and $0F]; + buf[20]:=HexDigitChrLo[digest[10] shr 4]; buf[21]:=HexDigitChrLo[digest[10] and $0F]; + buf[22]:=HexDigitChrLo[digest[11] shr 4]; buf[23]:=HexDigitChrLo[digest[11] and $0F]; + buf[24]:=HexDigitChrLo[digest[12] shr 4]; buf[25]:=HexDigitChrLo[digest[12] and $0F]; + buf[26]:=HexDigitChrLo[digest[13] shr 4]; buf[27]:=HexDigitChrLo[digest[13] and $0F]; + buf[28]:=HexDigitChrLo[digest[14] shr 4]; buf[29]:=HexDigitChrLo[digest[14] and $0F]; + buf[30]:=HexDigitChrLo[digest[15] shr 4]; buf[31]:=HexDigitChrLo[digest[15] and $0F]; + buf[32]:=#0; + result:=@buf; +end; + +function GetMD5(const data;datalen:integer;var digest:TMD5Hash):TMD5Hash; +begin + FillChar(digest,16,0); + + mir_md5_hash(pmir_md5_byte_t(data),datalen,digest); + + result:=digest; +end; + +function Handshake(login, password:PAnsiChar):boolean; +var + buf:array [0..32] of AnsiChar; + digest:TMD5Hash; + request:array [0..511] of AnsiChar; + res:pAnsiChar; + stat:mir_md5_state_t; +begin + result:=false; + GetMD5Str(GetMD5(password,StrLen(password),digest),buf); + mir_md5_init(@stat); + mir_md5_append(@stat,@buf,32); + mir_md5_finish(@stat,digest); + StrCopy(request,defreq); + StrReplace(request,'' ,login); + StrReplace(request,'',buf); + + res:=SendRequestCookies(request,false); +// res:=SendRequest(request,REQUEST_GET); + if res<>nil then + begin + if uint_ptr(res)<$0FFF then + begin + ShowError(int_ptr(res)); + end + else + begin + result:=true; + mFreeMem(res); + end; + end; +end; + +function Encode(dst,src:pAnsiChar):PAnsiChar; +begin + while src^<>#0 do + begin + if not (src^ in [' ','%','+','&','?',#128..#255]) then + dst^:=src^ + else + begin + dst^:='%'; inc(dst); + dst^:=HexDigitChr[ord(src^) shr 4]; inc(dst); + dst^:=HexDigitChr[ord(src^) and $0F]; + end; + inc(src); + inc(dst); + end; + dst^:=#0; + result:=dst; +end; + +function SendMSRequest(request:pAnsiChar;doShowError:boolean):boolean; +var + res:pAnsiChar; +begin + result:=true; + res:=SendRequestCookies(request,true); + if (uint_ptr(res)<>200) and (uint_ptr(res)<$0FFF) then + begin +//!! if int_ptr(res)=401 then + begin + Handshake(msh_login,msh_password); + + res:=SendRequestCookies(request,true); + end; + if (uint_ptr(res)<$0FFF) then + if (uint_ptr(res)<>200) and doShowError then + begin + ShowError(int_ptr(res)); + result:=false; + end; + end; +end; + +function Scrobble(show:boolean):boolean; +var + si:pSongInfoA; + buf:array [0..511] of AnsiChar; +// bufw:array [0..511] of WideChar; + res,pc:PAnsiChar; + {img,}shId,epId:pAnsiChar; +// imgw:pWideChar; + json:TJSONSERVICEINTERFACE; + jn,jroot:PJSONNODE; +begin + result:=false; + + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UTF8,0)); + Encode(buf,si.mfile); + pc:=Extract(buf,true); + + // Episode search by filename + StrCopy(StrCopyE(buf,API_URL+'shows/search/file/?q='),pc); + mFreeMem(pc); + res:=SendRequest(buf,REQUEST_GET); + if uint_ptr(res)>$0FFF then + begin + CallService(MS_JSON_GETINTERFACE,wparam(@json),0); + + jroot:=json.parse(res); + + jn:=json.get(jroot,'show'); + shId:=json.as_string(json.get(jn,'id')); + + jn:=json.get(jn,'episodes'); + epId:=json.name(json.at(jn,0)); +{ +kinopoiskId +image +ruTitle +episodes:{:{id: +} + end + else + begin + if show and (res<>nil) then + ShowError(int_ptr(res)); + exit; + end; + + // Show mark as "watching" + StrCopy(StrCopyE(StrCopyE(buf,API_URL+'profile/shows/'),shId),'/watching'); + if SendMSRequest(buf,show) then + begin + // Episode check + StrCopy(StrCopyE(buf,API_URL+'profile/episodes/check/'),epId); + // StrCopy(request,API_URL+'profile/shows/'); + if SendMSRequest(buf,show) then + begin +{ + if si.cover=nil then + begin + jn:=json.get(jroot,'show'); + img:=json.as_string(json.get(jn,'image')); + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,WAT_INF_UNICODE,0)); + FastAnsiToWide(img,pSongInfoW(si)^.cover); + json.free(img); + end; +} + //!! add option to show it?? + if ServiceExists(MS_POPUP_SHOWMESSAGE)<>0 then + begin + json.free(shId); + json.free(epId); + + jn:=json.get(jroot,'show'); + shId:=json.as_string(json.get(jn,'title')); + + jn:=json.get(jn,'episodes'); + epId:=json.as_string(json.get(jn,'title')); + + StrCopy( + StrCopyE( + StrCopyE( + StrCopyE( + StrCopyE(buf,'Show "'), + shId), + '"'#13#10'episode "'), + epId), + '" checked'); + CallService(MS_POPUP_SHOWMESSAGE,TWPARAM(@buf),SM_NOTIFY); + end; + result:=true; + end; + end; + json.free(shId); + json.free(epId); + + json.delete_(jroot); +end; + diff --git a/plugins/Watrack/myshows/i_myshows_dlg.inc b/plugins/Watrack/myshows/i_myshows_dlg.inc new file mode 100644 index 0000000000..13740d5a34 --- /dev/null +++ b/plugins/Watrack/myshows/i_myshows_dlg.inc @@ -0,0 +1,111 @@ +{} + +const + kinopoisk_info = 'http://www.kinopoisk.ru/level/1/film/'; + +procedure ClearInfo(dlg:HWND); +begin + SetDlgItemTextW(dlg,IDC_DATA_SERIES ,''); + SetDlgItemTextW(dlg,IDC_DATA_EPISODE,''); + SetDlgItemTextW(dlg,IDC_DATA_TAGS ,''); + SetDlgItemTextW(dlg,IDC_DATA_TAGS ,''); + SetDlgItemTextW(dlg,IDC_DATA_INFO ,''); +end; + +function DlgProcOptions(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +const + inited:bool=false; +var + tmp:longbool; +// bmp,wnd:HWND; +// buf:array [0..255] of AnsiChar; +begin + result:=0; + case hMessage of + WM_INITDIALOG: begin + inited:=false; + TranslateDialogDefault(Dialog); + + SetDlgItemTextA(Dialog,IDC_LOGIN,msh_login); + SetDlgItemTextA(Dialog,IDC_PASS ,msh_password); + SetDlgItemInt (Dialog,IDC_TRIES,msh_tries,false); +// SetDlgItemInt (Dialog,IDC_TIME ,msh_timeout,false); +// ClearInfo(Dialog); +// EnableWindow(GetDlgItem(Dialog,IDC_KINOPOISK),false); + + SendDlgItemMessage(Dialog,IDC_SCROBPOS,TBM_SETRANGE,0,MAKELONG(0,100)); + SendDlgItemMessage(Dialog,IDC_SCROBPOS,TBM_SETPOS,1,msh_scrobpos); + inited:=true; + end; + + WM_HSCROLL: begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + + WM_COMMAND: begin + if inited then + begin + (* + case Loword(wParam) of + IDC_KINOPOISK: begin + StrCopy(StrCopyE(buf,kinopoisk_info),MSData.kinopoisk_id); + CallService(MS_UTILS_OPENURL,TWPARAM(True),TLPARAM(@buf)); + result:=1; + exit; + end; + end; + *) + case wParam shr 16 of + BN_CLICKED: begin + (* + case LoWord(wParam) of + IDC_INFO_SERIES: begin + ClearInfo(Dialog); + ClearData; + + SetDlgItemTextW(Dialog,IDC_DATA_SERIES ,MSData.series); + SetDlgItemTextW(Dialog,IDC_DATA_EPISODE,MSData.episode); + // SetDlgItemTextW(Dialog,IDC_DATA_TAGS ,data.genre); + SetDlgItemTextW(Dialog,IDC_DATA_INFO ,MSData.info); + + bmp:=LoadImageURL(MSData.image,80); + if bmp<>0 then + DeleteObject(SendDlgItemMessage(Dialog,IDC_DATA_PIC,STM_SETIMAGE,IMAGE_BITMAP,bmp)); + + EnableWindow(GetDligItem(Dialog,IDC_KINOPOISK),true); + end; + *) + end; + + EN_CHANGE: begin + case loword(wParam) of + IDC_LOGIN,IDC_PASS,IDC_TRIES{,IDC_TIME}: + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + end; + end; + end; + + WM_NOTIFY: begin + case integer(PNMHdr(lParam)^.code) of + PSN_APPLY: begin + msh_scrobpos:=SendDlgItemMessage(Dialog,IDC_SCROBPOS,TBM_GETPOS,0,0); + msh_tries :=GetDlgItemInt(Dialog,IDC_TRIES,tmp,false); + mFreeMem(msh_login ); msh_login :=GetDlgText(Dialog,IDC_LOGIN,true); + mFreeMem(msh_password); msh_password:=GetDlgText(Dialog,IDC_PASS ,true); + { + mFreeMem(session_id); + mFreeMem(np_url); + mFreeMem(sub_url); + } + // msh_timeout:=GetDlgItemInt(Dialog,IDC_TIME ,tmp,false); + + SaveOpt; + end; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/myshows/i_myshows_opt.inc b/plugins/Watrack/myshows/i_myshows_opt.inc new file mode 100644 index 0000000000..f3287aba05 --- /dev/null +++ b/plugins/Watrack/myshows/i_myshows_opt.inc @@ -0,0 +1,47 @@ +{} +const + optLogin :pAnsiChar='myshows/login'; + optPassword:pAnsiChar='myshows/password'; + optTries :pAnsiChar='myshows/tries'; +// optTimeout :PAnsiChar='myshows/timeout'; + optScrobPos:pAnsiChar='myshows/scrobpos'; + optScrobble:pAnsiChar='myshows/scrobble'; + +procedure SaveOpt; +var + tmppass:array [0..255] of AnsiChar; +begin + if msh_password<>nil then + begin + StrCopy(tmppass,msh_password); + CallService(MS_DB_CRYPT_ENCODESTRING,StrLen(tmppass)+1,LPARAM(@tmppass)); + end; + DBWriteString(0,PluginShort,optPassword,tmppass); + DBWriteString(0,PluginShort,optLogin ,msh_login); + DBWriteByte (0,PluginShort,optTries ,msh_tries); + DBWriteByte (0,PluginShort,optScrobPos,msh_scrobpos); +// DBWriteWord (0,PluginShort,optTries ,msh_timeout); + DBWriteByte (0,PluginShort,optScrobble,msh_on and 1); +end; + +procedure LoadOpt; +begin +// msh_timeout :=DBReadWord(0,PluginShort,optTimeout ,0); + msh_scrobpos:=DBReadByte(0,PluginShort,optScrobPos,30); + msh_tries :=DBReadByte(0,PluginShort,optTries ,3); + msh_on :=DBReadByte(0,PluginShort,optScrobble,0); + mFreeMem(msh_login ); msh_login :=DBReadString(0,PluginShort,optLogin); + mFreeMem(msh_password); msh_password:=DBReadString(0,PluginShort,optPassword); + if msh_password<>nil then + CallService(MS_DB_CRYPT_DECODESTRING,StrLen(msh_password)+1,LPARAM(msh_password)); + if (msh_login=nil) or (msh_password=nil) then + CallService(MS_POPUP_SHOWMESSAGEW, + WPARAM(TranslateW('Don''t forget to enter Login and Password to use MyShows service')), + SM_WARNING); +end; + +procedure FreeOpt; +begin + mFreeMem(msh_login); + mFreeMem(msh_password); +end; diff --git a/plugins/Watrack/myshows/myshows.ico b/plugins/Watrack/myshows/myshows.ico new file mode 100644 index 0000000000..ab34e43a20 Binary files /dev/null and b/plugins/Watrack/myshows/myshows.ico differ diff --git a/plugins/Watrack/myshows/myshows.pas b/plugins/Watrack/myshows/myshows.pas new file mode 100644 index 0000000000..ce07ee0d68 --- /dev/null +++ b/plugins/Watrack/myshows/myshows.pas @@ -0,0 +1,333 @@ +unit myshows; +{$include compilers.inc} +interface +{$Resource myshows.res} +implementation + +uses windows, messages, commctrl, + common, + m_api,dbsettings,wrapper, mirutils, + wat_api,global; + +const + DefTimerValue = 10*60*1000; // 10 minutes +const + opt_ModStatus:PAnsiChar = 'module/myshows'; +const + IcoMyShows:pAnsiChar = 'WATrack_myshows'; +type + tMyShowsData = record + series :PAnsiChar; + series_id :PAnsiChar; + kinopoisk_id:PAnsiChar; + episode :PAnsiChar; + episode_id :PAnsiChar; + info :PAnsiChar; + image :PAnsiChar; + end; +var + msh_tries, +// msh_timeout, + msh_scrobpos:integer; + sic:THANDLE; +// slastinf:THANDLE; + slast:THANDLE; + MSData:tMyShowsData; +const + msh_on :integer=0; + hMenuMyShows:HMENU = 0; + msh_login :pAnsiChar=nil; + msh_password:pAnsiChar=nil; + session_id :pAnsiChar=nil; + np_url :pAnsiChar=nil; + sub_url :pAnsiChar=nil; + +procedure ClearData; +begin + mFreeMem(MSData.series); + mFreeMem(MSData.series_id); + mFreeMem(MSData.kinopoisk_id); + mFreeMem(MSData.episode); + mFreeMem(MSData.episode_id); + mFreeMem(MSData.info); + mFreeMem(MSData.image); + FillChar(MSData,SizeOf(MSData),0); +end; + +function GetModStatus:integer; +begin + result:=DBReadByte(0,PluginShort,opt_ModStatus,1); +end; + +procedure SetModStatus(stat:integer); +begin + DBWriteByte(0,PluginShort,opt_ModStatus,stat); +end; + +{$i i_const.inc} +{$i i_myshows_opt.inc} +{$i i_myshows_api.inc} + +procedure ThScrobble(param:LPARAM); cdecl; +var + count:integer; +begin + count:=msh_tries; + repeat + dec(count); + if Scrobble(count<=0) then break; + until count<=0; +end; + +const + hTimer:THANDLE=0; + +procedure TimerProc(wnd:HWND;uMsg:uint;idEvent:uint_ptr;dwTime:dword); stdcall; +begin + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + + if (msh_login <>nil) and (msh_login^ <>#0) and + (msh_password<>nil) and (msh_password^<>#0) then + CloseHandle(mir_forkthread(@ThScrobble,nil)); +end; + +function NewPlStatus(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + flag:integer; + mi:TCListMenuItem; + timervalue:integer; +begin + result:=0; + case wParam of + WAT_EVENT_NEWTRACK: begin + if hTimer<>0 then + KillTimer(0,hTimer); + // need to use half of movie len if presents + if msh_on=0 then + begin + if pSongInfo(lParam).width>0 then // for video only + begin + if ServiceExists(MS_JSON_GETINTERFACE)<>0 then + begin + timervalue:=integer(pSongInfo(lParam).total)*10*msh_scrobpos; // 1000(msec) div 100(%) + if timervalue=0 then + timervalue:=DefTimerValue; + hTimer:=SetTimer(0,0,timervalue,@TimerProc); + end; + end; + end; + end; + + WAT_EVENT_PLUGINSTATUS: begin + case lParam of + dsEnabled: begin + msh_on:=msh_on and not 2; + flag:=0; + end; + dsPermanent: begin + msh_on:=msh_on or 2; + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + flag:=CMIF_GRAYED; + end; + else // like 1 + exit + end; + FillChar(mi,sizeof(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_FLAGS+flag; + CallService(MS_CLIST_MODIFYMENUITEM,hMenuMyShows,tlParam(@mi)); + end; + + WAT_EVENT_PLAYERSTATUS: begin + case Integer(loword(lParam)) of + WAT_PLS_NOMUSIC,WAT_PLS_NOTFOUND: begin + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + end; + end; + end; + end; +end; + +{$i i_myshows_dlg.inc} + +function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; +begin + result:=0; + FillChar(mi,SizeOf(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_ICON; + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,tLParam(IcoMyShows)); + CallService(MS_CLIST_MODIFYMENUITEM,hMenuMyShows,tlParam(@mi)); +end; + +(* kinopoisk link, cover, series? +function SrvMyShowsInfo(wParam:WPARAM;lParam:LPARAM):int;cdecl; +//var +// data:tMyShowsInfo; +begin + result:=0; +{ + case wParam of + 0: result:=GetArtistInfo(data,lParam); + 1: result:=GetAlbumInfo (data,lParam); + 2: result:=GetTrackInfo (data,lParam); + else + result:=0; + end; +} +end; +*) +function SrvMyShows(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; +begin + FillChar(mi,sizeof(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_NAME; + if odd(msh_on) then + begin + mi.szName.a:='Disable scrobbling'; + msh_on:=msh_on and not 1; + end + else + begin + mi.szName.a:='Enable scrobbling'; + msh_on:=msh_on or 1; + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + end; + CallService(MS_CLIST_MODIFYMENUITEM,hMenuMyShows,tlParam(@mi)); + result:=ord(not odd(msh_on)); +end; + +procedure CreateMenus; +var + mi:TCListMenuItem; + sid:TSKINICONDESC; +begin + FillChar(sid,SizeOf(TSKINICONDESC),0); + sid.cbSize:=SizeOf(TSKINICONDESC); + sid.cx:=16; + sid.cy:=16; + sid.szSection.a:='WATrack'; + + sid.hDefaultIcon :=LoadImage(hInstance,'IDI_MYSHOWS',IMAGE_ICON,16,16,0); + sid.pszName :=IcoMyShows; + sid.szDescription.a:='MyShows'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + + FillChar(mi, sizeof(mi), 0); + mi.cbSize :=sizeof(mi); + mi.szPopupName.a:=PluginShort; + + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,tlParam(IcoMyShows)); + mi.szName.a :='Disable scrobbling'; + mi.pszService :=MS_WAT_MYSHOWS; + mi.popupPosition:=500050000; + hMenuMyShows:=Menu_AddMainMenuItem(@mi); +end; + +// ------------ base interface functions ------------- + +function AddOptionsPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +begin + tmpl:='MYSHOWS'; + proc:=@DlgProcOptions; + name:='MyShows'; + result:=0; +end; + +var + plStatusHook:THANDLE; + +function InitProc(aGetStatus:boolean=false):integer; +begin +// slastinf:=CreateServiceFunction(MS_WAT_MYSHOWSINFO,@SrvMyShowsInfo); + if aGetStatus then + begin + if GetModStatus=0 then + begin + result:=0; + exit; + end; + end + else + begin + SetModStatus(1); + msh_on:=msh_on and not 4; + end; + result:=1; + + LoadOpt; + + slast:=CreateServiceFunction(MS_WAT_MYSHOWS,@SrvMyShows); + if hMenuMyShows=0 then + CreateMenus; + sic:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged); + if (msh_on and 4)=0 then + plStatusHook:=HookEvent(ME_WAT_NEWSTATUS,@NewPlStatus); +end; + +procedure DeInitProc(aSetDisable:boolean); +begin + if aSetDisable then + SetModStatus(0) + else +;// DestroyServiceFunction(slastinf); + + DestroyServiceFunction(slast); + UnhookEvent(plStatusHook); + UnhookEvent(sic); + + if hTimer<>0 then + begin + KillTimer(0,hTimer); + hTimer:=0; + end; + + FreeOpt; + + mFreeMem(session_id); + mFreeMem(np_url); + mFreeMem(sub_url); + + msh_on:=msh_on or 4; + + mFreeMem(cookies); //!! +end; + +var + mmyshows:twModule; + +procedure Init; +begin + mmyshows.Next :=ModuleLink; + mmyshows.Init :=@InitProc; + mmyshows.DeInit :=@DeInitProc; + mmyshows.AddOption :=@AddOptionsPage; + mmyshows.ModuleName:='MyShows.ru'; + ModuleLink :=@mmyshows; + +end; + +begin + Init; +end. diff --git a/plugins/Watrack/myshows/myshows.rc b/plugins/Watrack/myshows/myshows.rc new file mode 100644 index 0000000000..adc05a23b7 --- /dev/null +++ b/plugins/Watrack/myshows/myshows.rc @@ -0,0 +1,41 @@ +#include "i_const.inc" + +LANGUAGE 0,0 + +MYSHOWS DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + LTEXT "Login" , -1, 108, 2, 70, 16, SS_CENTERIMAGE + EDITTEXT IDC_LOGIN , 4, 4, 100, 12, + LTEXT "Password" , -1, 108, 18, 70, 16, SS_CENTERIMAGE + EDITTEXT IDC_PASS , 4, 20, 100, 12, ES_PASSWORD + LTEXT "Attempts" , -1, 40, 34, 64, 16, SS_CENTERIMAGE + EDITTEXT IDC_TRIES , 4, 36, 32, 12, ES_RIGHT | ES_NUMBER +// LTEXT "Timeout, ms", -1, 40, 50, 64, 16, SS_CENTERIMAGE +// EDITTEXT IDC_TIME , 4, 52, 32, 12, ES_RIGHT | ES_NUMBER + + CONTROL "",IDC_SCROBPOS,"msctls_trackbar32", TBS_BOTTOM|TBS_NOTICKS|$100,120,45,94,11 + CTEXT "Scrobble at",-1,120,35,94,11, SS_CENTERIMAGE +/* + PUSHBUTTON "Get Series Info", IDC_INFO_SERIES, 4, 206, 72, 16 + + CONTROL "", IDC_DATA_PIC, "STATIC", SS_BITMAP | WS_BORDER, 220, 2, 80, 80 + + RTEXT "Show", -1 , 0, 86, 76, 16, SS_CENTERIMAGE + EDITTEXT IDC_DATA_SERIES , 80, 87, 220, 14, ES_READONLY | ES_AUTOHSCROLL + RTEXT "Episode",-1 , 0, 102, 76, 16, SS_CENTERIMAGE + EDITTEXT IDC_DATA_EPISODE , 80, 103, 220, 14, ES_READONLY | ES_AUTOHSCROLL + RTEXT "Genres", -1 , 0, 118, 76, 16, SS_CENTERIMAGE + EDITTEXT IDC_DATA_TAGS , 80, 119, 220, 14, ES_READONLY | ES_AUTOHSCROLL + RTEXT "Info" , -1 , 0, 134, 76, 16, SS_CENTERIMAGE + EDITTEXT IDC_DATA_INFO , 80, 135, 220, 75, + ES_MULTILINE | ES_READONLY | ES_AUTOVSCROLL | WS_VSCROLL + + CONTROL "Kinopoisk info page", IDC_KINOPOISK, "Hyperlink", + WS_CHILD | WS_TABSTOP | WS_DISABLED | 0x1, 80, 212, 220, 10 +*/ +} + +IDI_MYSHOWS ICON "myshows.ico" diff --git a/plugins/Watrack/myshows/myshows.res b/plugins/Watrack/myshows/myshows.res new file mode 100644 index 0000000000..1b888d6762 Binary files /dev/null and b/plugins/Watrack/myshows/myshows.res differ diff --git a/plugins/Watrack/player.ini b/plugins/Watrack/player.ini new file mode 100644 index 0000000000..16572c983e --- /dev/null +++ b/plugins/Watrack/player.ini @@ -0,0 +1,283 @@ +;[name] +;text0= for stopped (empty) player? +;class= +;text= +;class1= +;text1= +;file= +;flags= +;url= +;notes= +; +;prefix= +;postfix= + +[ALShow] +class='ALShowShellWindow' +class1='ALShowMainWindow' +url='http://www.altools.net/' +[ALSong] +class='ALSongKernelWindow' +url='http://www.altools.net/' + +[ArezMedia] +text='ArezMedia v8.1' +class1='Media Event Sink Window' +text1='Media Event Sink Window' +file='AREZMEDIA.EXE' +url='http://www.arezsoft.co.uk/' + +[Ashampoo Media Player] +test='Ashampoo Media Player+' +class='AMPMainWindow class' +class1='AMP MainOwnerWindow Class' +url='http://www2.ashampoo.com/webcache/html/1/product_2_0014___USD.htm' + +[AudioPlayer] +class='AudioPlayer' +url='http://audioplayer.sourceforge.net/' + +[Billy] +class='TAppBilly' +url='http://sheepfriends.com/?page=billy' + +[BizzOn] +class='BizzOn v2.x' +flags=8 +url='http://bizzon.nm.ru/' + +[Core Media Player] +class='TApplication' +file='COREPLAYER.EXE' +url='http://www.tcmp.org/' + +[Creative Media Source] +class='CT_MEDIASOURCE' +url='http://www.creative.com/' + +[Crystal Player] +class='CrystalPlayerClass' +class1='CrystalClassOwner' +url='http://crystalplayer.com/' + +[Cyberlink PowerDVD] +class='Class of CyberLink Universal Player' +text='CommandWindow' +url='http://www.cyberlink.com/' + +[Daum PotPlayer] +class='PotPlayer' +notes='"Daum PotPlayer" text for stopped player?' + +[dBpowerAMP] +class='dBpowerAMP Audio Player' +text='dBpowerAMP Audio Player' +class1='dBpowerAMP Core' +text1='dBpowerAMP Core' +url='http://www.dbpoweramp.com/' + +[Evil Player] +class='TApplication' +text='Evil Player' +;title: Evil Player - 00:00 / 00:00 +;class='TForm1' +;file='EVIL_PLAYER.EXE' +url='http://www.hakeem.gigahost.dk/' + +[FLVPlayer] +text='SW3 Player Engine [ Debug Window ]' +url='http://www.martijndevisser.com/' + +;Fucker Player +[FPlayer] +class='TForm1' +class1='TApplication' +file='FPLAYER 3.0.EXE' +url='http://www.kuzbassproduction.narod.ru/' + +[Freebox player] +class='ThunderRT6FormDC' +text='Freebox Player' +class1='ThunderRT6Main' +text1='MP3 Freebox' +url='http://www.freeboxjukebox.com/' + +[J.River Media Center] +class='MJFrame' +class1='J. River Display Window' +url='http://www.jrmediacenter.com/' + +[HKDC] +text='HKDC_HangWnd' +file='HKDC.exe' + +[Helium Music Manager] +class='THeliumMainForm' +url='http://www.helium-music-manager.com/' + +[IPOP GOMPlayer] +class='GomPlayer1.x' +url='http://gomplayer.com/' + +[KMPlayer] +class='TApplication' +file='KMPLAYER.EXE' +flags=8 +url='http://www.kmplayer.com' +Notes='Winamp API used to get more info' + +[MPlayer] +class='MPlayer - The Movie Player' +url='http://www.mplayerhq.hu/' + +[Media Commander Express] +class='TApplication' +file='MCX.EXE' +url='http://skynet.hut1.ru/' + +[Media Library Master] +class='TMainForm' +class1='TApplication' +file='MLMASTER.EXE' +url='http://www.grafmstudio.narod.ru/mlmaster.htm' + +[MoreAmp] +class='wxWindowClassNR' +file='MOREAMP.EXE' +url='http://sourceforge.net/projects/moreamp/' + +[MusicCube One] +class='TfMain' +text='MusicCubeOne' +prefix='MusicCubeOne - ' +url='http://www.rodi.dk/musiccubeone' + +[Musicmatch Jukebox] +class='MMJB:MAINWND' +postfix=' - Musicmatch Jukebox' +url='http://wwwp.musicmatch.com/' + +[MusikCube] +class='musikCubeWindow1.0' +postfix=']' +url='http://www.musikcube.com/' + +[PlayNow] +class='TForm1' +file='Play Now!.exe' +url='http://www.playnow.nightmail.ru/' + +[Pluton] +class='TApplication' +file='PLUTON.EXE' +url='http://pluton.oss.ru/' + +[QCD] +file='QMPLAYER.EXE' +;file='QCDPLAYER.EXE' +text='PlayerCanvas' +flags=8 +url='http://quinnware.com/' + +[Quicktime Player] +class='QuickTimePlayerMain' +url='http://www.quicktime.com/' + +[RadLight] +class='TVideoForm' +class1='TApplication' +file='RadLight.exe' +url='http://radlight.da.ru/' + +[Real Player] +class='GeminiWindowClass' +prefix='RealPlayer: ' +url='http://www.real.com/' + +[SAPS] +class='ThunderRT6Main' +text='SAPS' +file='SAPS.EXE' +url='http://www.troupware.com/' + +[SongBird] +class='SongbirdMessageWindow' +url='http://songbirdnest.com/' + +[Spider Player] +class='TSpiderMainForm' +text='Spider Audio Player' +class1='TApplication' +;text1=%artist% - %title% 'Spider Player 1.80' +file='SPIDER.EXE' +url='http://spider-player.com/' + +[Storm Player Exotic] +class='TMainStormForm' +class1='TApplication' +text1='Storm Player Exotic 2.0' +url='http://splayer.nm.ru/' + +[Suamp] +class='Suamp' +class1='TApplication' ; with title (if scrolling) +file='suamp.exe' +url='http://www.suamp.ro/' + +[TotalMedia Theatre 3] +text='ArcSoft TotalMedia Theatre 3' +class='TotalMedia2FDVDPlayerFrame' + +[Ultra player] +class='UltraPlayerMainWindowClass88667' +url='http://www.ultraplayer.com/' + +[ViPlay] +class='ViPlay3' +url='http://www.urusoft.net/' + +[VUPlayer] +class='VUPlayerClass' +url='http://www.vuplayer.com/' + +[WiFiRadio Player] +class='WasabiIPC_WiFi Radio' +url='http://pspmx.com/wifiradio/' + +[WMP] +class='WMPlayerApp' +class1='Media Player 2' +flags=69632 +url='http://www.microsoft.com/windows/windowsmedia/players.aspx' + +[WinDVD] +class='WinDVDClass' +;text='Player' +url='http://www.intervideo.com/' + +[WxMusik] +class='wxWindowClassNR' +;text='wxMusik 0.4.2' +file='WXMUSIK.EXE' +url='http://musik.berlios.de/' + +[XAMP] +class='TfrmMp3' +class1='TApplication' +text1='XAMP' +;file='MP3.EXE' +url='http://www.darksoftware.narod.ru/' + +[XMPlay] +class='XMPLAY-MAIN' +flags=8 +url='http://www.un4seen.com/' + +;[ZINF] +;url='http://www.zinf.org/' + +[Zoom] +class='TApplication' +file='ZPLAYER.EXE' +postfix=' - Zoom Player' +url='http://www.inmatrix.com/' diff --git a/plugins/Watrack/players/mradio.ico b/plugins/Watrack/players/mradio.ico new file mode 100644 index 0000000000..7993fce57b Binary files /dev/null and b/plugins/Watrack/players/mradio.ico differ diff --git a/plugins/Watrack/players/mradio.rc b/plugins/Watrack/players/mradio.rc new file mode 100644 index 0000000000..ce858cbe82 --- /dev/null +++ b/plugins/Watrack/players/mradio.rc @@ -0,0 +1,3 @@ +LANGUAGE 0,0 + +ICO_MRADIO ICON "mradio.ico" diff --git a/plugins/Watrack/players/mradio.res b/plugins/Watrack/players/mradio.res new file mode 100644 index 0000000000..52d06f147d Binary files /dev/null and b/plugins/Watrack/players/mradio.res differ diff --git a/plugins/Watrack/players/pl_1by1.pas b/plugins/Watrack/players/pl_1by1.pas new file mode 100644 index 0000000000..630b825363 --- /dev/null +++ b/plugins/Watrack/players/pl_1by1.pas @@ -0,0 +1,84 @@ +{1by1 player} +unit pl_1by1; +{$include compilers.inc} + +interface + +implementation +uses windows,common,wrapper,srv_player,wat_api; + +const + ObOClass = '1by1WndClass'; + ObOTitle = '1by1 - The Directory Player'; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindow(ObOClass,NIL); +end; + +{ + need to set 'Elapsed time in title bar' + and 'Show : instead of ' as minute char' +} +function GetElapsedTime(wnd:HWND):integer; +var + s,p:PAnsiChar; +begin + result:=0; + s:=GetDlgText(wnd,true); + if s<>nil then + begin + if (s^>='0') and (s^<='9') then + begin + p:=StrScan(s,' '); + if p<>nil then + p^:=#0; + result:=TimeToInt(s) + end; + mFreeMem(s); + end; +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +begin + result:=0; + if (flags and WAT_OPT_CHANGES)<>0 then + SongInfo.time:=GetElapsedTime(SongInfo.plwnd); +end; + +const + plRec:tPlayerCell=( + Desc :'1by1'; + flags :WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:nil; + GetName :nil; + GetInfo :@GetInfo; + Command :nil; + URL :'http://www.mpesch3.de/'; + Notes :'To get elapsed time, needs to set "Elapsed time in title bar" and '#13#10+ + '"Show : instead of '#39' as minute char" in player settings "Display" tab.' +); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_aimp.pas b/plugins/Watrack/players/pl_aimp.pas new file mode 100644 index 0000000000..17c52bc5b6 --- /dev/null +++ b/plugins/Watrack/players/pl_aimp.pas @@ -0,0 +1,376 @@ +{AIMP player} +unit pl_AIMP; +{$include compilers.inc} + +interface + +implementation +uses windows,messages,common,srv_player,wat_api,winampapi; + +const + WM_AIMP_COMMAND = WM_USER + $75; + WM_AIMP_GET_VERSION = 4; + WM_AIMP_STATUS_GET = 1; + WM_AIMP_STATUS_SET = 2; + WM_AIMP_CALLFUNC = 3; +const + AIMP_STS_Player = 4; + AIMP_STS_VOLUME = 1; + AIMP_STS_POS = 31; +const + AIMP_PLAY = 15; + AIMP_PAUSE = 16; + AIMP_STOP = 17; + AIMP_NEXT = 18; + AIMP_PREV = 19; + +const + AIMP2_RemoteClass:PAnsiChar = 'AIMP2_RemoteInfo'; +const + AIMP2_RemoteFileSize = 2048; + +type + PAIMP2FileInfo = ^TAIMP2FileInfo; + TAIMP2FileInfo = packed record + cbSizeOF :dword; + // + nActive :LONGBOOL; + nBitRate :dword; + nChannels :dword; + nDuration :dword; + nFileSize :Int64; + nRating :dword; + nSampleRate :dword; + nTrackID :dword; + // + nAlbumLen :dword; + nArtistLen :dword; + nDateLen :dword; + nFileNameLen:dword; + nGenreLen :dword; + nTitleLen :dword; + // + sAlbum :dword; // size of pointer for 32 bit system + sArtist :dword; + sDate :dword; + sFileName :dword; + sGenre :dword; + sTitle :dword; + end; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindowA(AIMP2_RemoteClass,AIMP2_RemoteClass); +end; + +function GetVersionText(ver:integer):pWideChar; +begin + if (ver and $F00)<>0 then + begin + mGetMem(result,8*SizeOf(WideChar)); + result[0]:=WideChar((ver div 1000)+ORD('0')); + ver:=ver mod 1000; + result[1]:='.'; + result[2]:=WideChar((ver div 100)+ORD('0')); + ver:=ver mod 100; + result[3]:='.'; + result[4]:=WideChar((ver div 10)+ORD('0')); + result[5]:='.'; + result[6]:=WideChar((ver mod 10)+ORD('0')); + result[7]:=#0; + end + else + result:=nil; +end; + +function GetVersion(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_AIMP_COMMAND,WM_AIMP_GET_VERSION,0); +end; + +function GetStatus(wnd:HWND):integer; cdecl; +begin + result:=SendMessage(wnd,WM_AIMP_COMMAND,WM_AIMP_STATUS_GET,AIMP_STS_Player); +end; + +function GetVolume(wnd:HWND):cardinal; +begin + result:=SendMessage(wnd,WM_AIMP_COMMAND,WM_AIMP_STATUS_GET,AIMP_STS_VOLUME); + result:=(result shl 16)+round((result shl 4)/100); +end; + +procedure SetVolume(wnd:HWND;value:cardinal); +begin + SendMessage(wnd,WM_AIMP_COMMAND,WM_AIMP_STATUS_SET, + (AIMP_STS_VOLUME shl 16)+((value*100) shr 4)); +end; + +function VolDn(wnd:HWND):integer; +var + val:dword; +begin + result:=GetVolume(wnd); + val:=loword(result); + if val>0 then + SetVolume(wnd,val-1); +end; + +function VolUp(wnd:HWND):integer; +var + val:dword; +begin + result:=GetVolume(wnd); + val:=loword(result); + if val<16 then + SetVolume(wnd,val+1); +end; + +function GetFileName(wnd:HWND;flags:integer):pWideChar;cdecl; +var + FFile:THANDLE; + pStr:pointer; + s:integer; + p:PAnsiChar; + pw,pw1:pWideChar; +begin + result:=nil; + s:=AIMP2_RemoteFileSize; + p:=AIMP2_RemoteClass; + FFile:=OpenFileMappingA(FILE_MAP_READ,True,p); + pStr:=MapViewOfFile(FFile,FILE_MAP_READ,0,0,s); + try + if pStr<>nil then + begin + with PAIMP2FileInfo(pStr)^ do + begin + StrDupW(result, + pWideChar(PAnsiChar(pStr)+SizeOf(TAIMP2FileInfo)+ + (nAlbumLen+nArtistLen+nDateLen)*SizeOf(WideChar)), + nFileNameLen); + // Delete rest index (like "filename.cue:3") + pw :=StrRScanW(result,':'); + if pw<>nil then + begin + pw1:=StrScanW (result,':'); + if pw<>pw1 then + pw^:=#0; + end; + end; + end; + finally + UnmapViewOfFile(pStr); + CloseHandle(FFile); + end; +end; + +procedure TranslateRadio(var SongInfo:tSongInfo); +var + pc,pc1:pWideChar; +begin +{ + artist - album - title (radio) +} + with SongInfo do + begin + if (artist=nil) and (title<>nil) then + begin + // Radio title + if (StrEndW(title)-1)^=')' then + begin + pc:=StrRScanW(title,'('); + if (pc<>nil) and (pc>title) and ((pc-1)^=' ') then + begin + if comment=nil then + begin + StrDupW(comment,pc+1); + (StrEndW(comment)-1)^:=#0; + end; + (pc-1)^:=#0; + end; + end; + // artist - title + pc:=StrPosW(title,' - '); + if pc<>nil then + begin + if artist=nil then + begin + pc^:=#0; + inc(pc,3); + StrDupW(artist,title); + end; + // artist - album - title + pc1:=StrPosW(pc,' - '); + if pc1<>nil then + begin + if album=nil then + begin + pc1^:=#0; + StrDupW(album,pc); + pc:=pc1+3; + end; + end; + pc1:=title; + StrDupW(title,pc); + mFreeMem(pc1); + end; + end; + end; +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +var + FFile:THANDLE; + s:integer; + p:PAnsiChar; + pStr:PAIMP2FileInfo; +begin + result:=0; + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if SongInfo.plyver=0 then + begin + SongInfo.plyver:=GetVersion (SongInfo.plwnd); + SongInfo.txtver:=GetVersionText(SongInfo.plyver); + end; + if SongInfo.winampwnd=0 then + SongInfo.winampwnd:=WinampFindWindow(SongInfo.plwnd); + exit; + end; + + if SongInfo.winampwnd<>0 then + WinampGetInfo(int_ptr(@SongInfo),flags); + + if (flags and WAT_OPT_CHANGES)=0 then + begin + s:=AIMP2_RemoteFileSize; + p:=AIMP2_RemoteClass; + FFile:=OpenFileMappingA(FILE_MAP_READ,True,p); + pStr:=MapViewOfFile(FFile,FILE_MAP_READ,0,0,s); + try + if pStr<>nil then + begin + with SongInfo do + begin + with pStr^ do + begin + if channels=0 then channels:=nChannels; + if kbps =0 then kbps :=nBitRate div 1000; + if khz =0 then khz :=nSampleRate div 1000; + if total =0 then total :=nduration; + if fsize =0 then fsize :=nFileSize; + if track =0 then track :=nTrackID; + + with PAIMP2FileInfo(pStr)^ do + begin + if (artist=nil) and (nArtistLen>0) then + begin + StrDupW(artist, + pWideChar(PAnsiChar(pStr)+SizeOf(TAIMP2FileInfo))+ + nAlbumLen,nArtistLen); + end; + if (album=nil) and (nAlbumLen>0) then + begin + StrDupW(album, + pWideChar(PAnsiChar(pStr)+SizeOf(TAIMP2FileInfo)), + nAlbumLen); + end; + if (title=nil) and (nTitleLen>0) then + begin + StrDupW(title, + pWideChar(PAnsiChar(pStr)+SizeOf(TAIMP2FileInfo))+ + nAlbumLen+nArtistLen+nDateLen+nFileNameLen+nGenreLen, + nTitleLen); + end; + if (year=nil) and (nDateLen>0) then + begin + StrDupW(year, + pWideChar(PAnsiChar(pStr)+SizeOf(TAIMP2FileInfo))+ + nAlbumLen+nArtistLen, + nDateLen); + end; + if (genre=nil) and (nGenreLen>0) then + begin + StrDupW(genre, + pWideChar(PAnsiChar(pStr)+SizeOf(TAIMP2FileInfo))+ + nAlbumLen+nArtistLen+nDateLen+nFileNameLen, + nGenreLen); + end; + + if StrPosW(mfile,'://')<>nil then + TranslateRadio(SongInfo); + end; + end; + end; + end; + finally + UnmapViewOfFile(pStr); + CloseHandle(FFile); + end; + end + else // request AIMP changed data: volume + begin + SongInfo.time:=SendMessage(SongInfo.plwnd,WM_AIMP_COMMAND,WM_AIMP_STATUS_GET,AIMP_STS_POS); + SongInfo.volume:=GetVolume(SongInfo.plwnd); + end; +end; + +function Command(wnd:HWND;cmd:integer;value:integer):integer;cdecl; +var + WinampWindow:HWND; +begin + WinampWindow:=WinampFindWindow(wnd); + if WinampWindow<>0 then + result:=WinampCommand(WinampWindow,cmd+(value shl 16)) + else + begin + result:=0; + case cmd of + WAT_CTRL_PREV : SendMessage(wnd,WM_AIMP_COMMAND,WM_AIMP_CALLFUNC,AIMP_PREV); + WAT_CTRL_PLAY : SendMessage(wnd,WM_AIMP_COMMAND,WM_AIMP_CALLFUNC,AIMP_PLAY); + WAT_CTRL_PAUSE: SendMessage(wnd,WM_AIMP_COMMAND,WM_AIMP_CALLFUNC,AIMP_PAUSE); + WAT_CTRL_STOP : SendMessage(wnd,WM_AIMP_COMMAND,WM_AIMP_CALLFUNC,AIMP_STOP); + WAT_CTRL_NEXT : SendMessage(wnd,WM_AIMP_COMMAND,WM_AIMP_CALLFUNC,AIMP_NEXT); + WAT_CTRL_VOLDN: result:=VolDn(wnd); + WAT_CTRL_VOLUP: result:=VolUp(wnd); + WAT_CTRL_SEEK : begin + SendMessage(wnd,WM_AIMP_COMMAND,WM_AIMP_STATUS_SET, + (AIMP_STS_POS shl 16)+value); + end; + end; + end; +end; + +const + plRec:tPlayerCell=( + Desc :'AIMP'; + flags :WAT_OPT_APPCOMMAND or WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:@GetStatus; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :@Command; + URL :'http://www.aimp.ru/'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_apollo.pas b/plugins/Watrack/players/pl_apollo.pas new file mode 100644 index 0000000000..360b23ab89 --- /dev/null +++ b/plugins/Watrack/players/pl_apollo.pas @@ -0,0 +1,263 @@ +{Apollo player} +unit pl_Apollo; +{$include compilers.inc} + +interface + +implementation +uses windows,winampapi,messages,common,srv_player,wat_api; + +const + ApolloClass = 'Apollo - Main Window'; + +const + WM_APOLLO_COMMAND = WM_USER+3; + APOLLO_GETVERSION = 0; + APOLLO_GETSTATUS = 1; + APOLLO_GETPLAYLISTPOSITION = 16; + APOLLO_GETCURRENTTRACKNUMBER = 17; + APOLLO_SETPLAYBACKPOSITION = 18; + APOLLO_GETPLAYBACKPOSITION = 19; + APOLLO_GETPLAYBACKCOUNTDOWN = 33; + APOLLO_GETCURRENTLYPLAYEDFILENAME = 24; + APOLLO_GETCURRENTLYPLAYEDTITLE = 25; + APOLLO_GETPLAYLISTENTRY = 26; + APOLLO_GETPLAYLISTTITLE = 27; +// APOLLO_OPENURL = 4; + APOLLO_OPENFILE = 2; + APOLLO_PREVIOUSTRACK = 10; + APOLLO_STOP = 11; + APOLLO_PLAY = 12; + APOLLO_PAUSE = 13; + APOLLO_NEXTTRACK = 14; + APOLLO_SETVOLUME = 20; + APOLLO_GETVOLUME = 21; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindow(ApolloClass,NIL) +end; + +function GetVersion(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_GETVERSION,0); +end; + +function GetVersionText(ver:integer):PWideChar; +begin + mGetMem(result,5*SizeOf(WideChar)); + IntToStr(result,ver); +end; + +function GetStatus(wnd:HWND):integer; cdecl; +begin + result:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_GETSTATUS,0); + if result>1 then + result:=2; +end; + +function GetFileName(wnd:HWND;flags:integer):pWideChar;cdecl; +var + tmpwnd:hwnd; + ps:array [0..255] of AnsiChar; +begin + if GetStatus(wnd)<>WAT_MES_STOPPED then + begin + tmpwnd:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_GETCURRENTLYPLAYEDFILENAME,0); + ps[0]:=#0; + SendMessageA(tmpwnd,WM_GETTEXT,255,lparam(@ps)); + if ps[0]<>#0 then + begin + mGetMem(result,(StrLen(ps)+1)*SizeOf(WideChar)); + AnsiToWide(ps,result); + exit; + end; + end; + result:=nil; +end; + +function GetWndText(wnd:HWND):pWideChar; +var + tmpwnd:hwnd; + ps:array [0..255] of AnsiChar; +begin + tmpwnd:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_GETCURRENTLYPLAYEDTITLE,0); + SendMessageA(tmpwnd,WM_GETTEXT,255,lparam(@ps)); + mGetMem(result,(StrLen(ps)+1)*SizeOf(WideChar)); + AnsiToWide(ps,result); +end; + +function Play(wnd:HWND;fname:PWideChar=nil):integer; +var + cds:COPYDATASTRUCT; +begin + if (fname<>nil) and (fname^<>#0) then + begin + cds.dwData:=APOLLO_OPENFILE; + WideToAnsi(fname,PAnsiChar(cds.lpData)); + cds.cbData:=StrLen(PAnsiChar(cds.lpData))+1; + SendMessage(wnd,WM_COPYDATA,0,lparam(@cds)); + mFreeMem(cds.lpData); + end; + result:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_PLAY,0); +end; + +function Pause(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_PAUSE,0); +end; + +function Stop(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_STOP,0); +end; + +function Next(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_NEXTTRACK,0); +end; + +function Prev(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_PREVIOUSTRACK,0); +end; + +function GetVolume(wnd:HWND):cardinal; +begin + result:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_GETVOLUME,0); + result:=(result shl 16)+(result shr 12); +end; + +procedure SetVolume(wnd:HWND;value:cardinal); +begin + SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_SETVOLUME,value shl 12); +end; + +function VolDn(wnd:HWND):integer; +var + val:integer; +begin + result:=GetVolume(wnd); + val:=loword(result); + if val>0 then + SetVolume(wnd,val-1); +end; + +function VolUp(wnd:HWND):integer; +var + val:integer; +begin + result:=GetVolume(wnd); + val:=loword(result); + if val<16 then + SetVolume(wnd,val+1); +end; + +function Seek(wnd:HWND;value:integer):integer; +begin + result:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_GETPLAYBACKPOSITION,0); + if value>0 then + SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_SETPLAYBACKPOSITION,value); +end; + +function GetRemoteTitle(wnd:HWND):pWideChar; +var + tmpwnd:hwnd; + ps:array [0..255] of AnsiChar; + num:integer; +begin + num :=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_GETPLAYLISTPOSITION,0); + tmpwnd:=SendMessage(wnd,WM_APOLLO_COMMAND,APOLLO_GETPLAYLISTTITLE ,num); + SendMessageA(tmpwnd,WM_GETTEXT,255,lparam(@ps)); + mGetMem(result,(StrLen(ps)+1)*SizeOf(WideChar)); + AnsiToWide(ps,result); +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +begin + result:=0; + + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if SongInfo.plyver=0 then + begin + SongInfo.plyver:=GetVersion (SongInfo.plwnd); + SongInfo.txtver:=GetVersionText(SongInfo.plyver); + end; + if SongInfo.winampwnd=0 then + SongInfo.winampwnd:=WinampFindWindow(SongInfo.plwnd); + exit; + end; + + if SongInfo.winampwnd<>0 then + result:=WinampGetInfo(int_ptr(@SongInfo),flags); + + if (flags and WAT_OPT_CHANGES)<>0 then + begin + with SongInfo do + begin + wndtext:=GetWndText(plwnd); + volume :=GetVolume (plwnd); + end + end + else + begin + with SongInfo do + begin + if (status<>WAT_MES_STOPPED) and + (mfile<>nil) and (StrPosW(mfile,'://')<>nil) and (album=nil) then + album:=GetRemoteTitle(plwnd); + end; + end; +end; + +function Command(wnd:HWND;cmd:integer;value:int_ptr):integer;cdecl; +begin + case cmd of + WAT_CTRL_PREV : result:=Prev(wnd); + WAT_CTRL_PLAY : result:=Play(wnd,pWideChar(value)); + WAT_CTRL_PAUSE: result:=Pause(wnd); + WAT_CTRL_STOP : result:=Stop(wnd); + WAT_CTRL_NEXT : result:=Next(wnd); + WAT_CTRL_VOLDN: result:=VolDn(wnd); + WAT_CTRL_VOLUP: result:=VolUp(wnd); + WAT_CTRL_SEEK : result:=Seek(wnd,value); + else + result:=0; + end; +end; + +const + plRec:tPlayerCell=( + Desc :'Apollo'; + flags :WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:@GetStatus; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :@Command; + URL :'http://www.iki.fi/hy/apollo/'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_behold.pas b/plugins/Watrack/players/pl_behold.pas new file mode 100644 index 0000000000..977a021034 --- /dev/null +++ b/plugins/Watrack/players/pl_behold.pas @@ -0,0 +1,175 @@ +{BeholderTV} +unit pl_behold; +{$include compilers.inc} + +interface + +implementation + +uses windows,messages,common,wrapper,srv_player,wat_api; + +const + WM_BHCMD = WM_USER+200; + WMBH_CHNLUP = WM_USER+203; // Ïåðåêëþ÷èòü íà ñëåäóþùèé êàíàë + WMBH_CHNLDOWN = WM_USER+204; // Ïåðåêëþ÷èòü íà ïðåäûäóùèé êàíàë + WMBH_VOLUMEUP = WM_USER+210; // Óâåëè÷èòü âûáðàííûé óðîâåíü + WMBH_VOLUMEDOWN = WM_USER+211; // Óìåíüøèòü âûáðàííûé óðîâåíü + WMBH_FREEZE = WM_USER+232; // Òðèããåð ñòîï-êàäðà + WMBH_SETVOLUME = WM_USER+280; // Óñòàíîâèòü óðîâåíü ãðîìêîñòè (LParam = 0..65535) + WMBH_GETVOLUME = WM_USER+281; // Ïîëó÷èòü òåêóùèé óðîâåíü ãðîìêîñòè (èñïîëüçîâàòü SendMessage, Result = 0..65535) + WMBH_GETVERSION = WM_USER+285; // Ïîëó÷èòü íîâåð âåðñèè ÏÎ (èñïîëüçîâàòü SendMessage) + +const + TitleWndClass = 'TApplication'; + EXEName = 'BEHOLDTV.EXE'; + +var + TitleWnd:HWND; + +function enumproc(wnd:HWND; lParam:LPARAM):bool; stdcall; +var + buf:array [0..64] of AnsiChar; +begin + result:=true; + if GetClassNameA(wnd,buf,63)<>0 then + begin + if StrCmp(buf,TitleWndClass)=0 then + begin + TitleWnd:=wnd; + result:=false; + end + end; +end; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindow('TMain','BeholdTV'); + if result<>0 then + EnumThreadWindows(GetWindowThreadProcessId(result,nil),@enumproc,0); +end; + +function GetVersion(wnd:HWND):integer; +begin + result:=DWORD(SendMessage(wnd,WM_BHCMD,WMBH_GETVERSION,0)); + result:=((result shr 16) shl 8)+LoWord(result); +end; + +function GetVersionText(ver:integer):PWideChar; //!! +begin + mGetMem(result,10*SizeOf(WideChar)); + IntToStr(result+1,ver); + result[0]:=result[1]; + result[1]:='.'; +end; + +function GetFileName(wnd:HWND;flags:integer):pWideChar;cdecl; +begin + result:=nil; +end; + +function Pause(wnd:HWND):integer; +begin + result:=0; + PostMessage(wnd,WM_BHCMD,WMBH_FREEZE,0); +end; + +function Next(wnd:HWND):integer; +begin + result:=0; + PostMessage(wnd,WM_BHCMD,WMBH_CHNLUP,0); +end; + +function Prev(wnd:HWND):integer; +begin + result:=0; + PostMessage(wnd,WM_BHCMD,WMBH_CHNLDOWN,0); +end; + +function GetVolume(wnd:HWND):cardinal; +begin + result:=WORD(SendMessage(wnd,WM_BHCMD,WMBH_GETVOLUME,0)); + result:=(result shl 16)+(result shr 12); +end; + +procedure SetVolume(wnd:HWND;value:cardinal); +begin + SendMessage(wnd,WM_BHCMD,WMBH_SETVOLUME,value shl 12); +end; + +function VolDn(wnd:HWND):integer; +begin + result:=WORD(SendMessage(wnd,WM_BHCMD,WMBH_VOLUMEDOWN,0)); +end; + +function VolUp(wnd:HWND):integer; +begin + result:=WORD(SendMessage(wnd,WM_BHCMD,WMBH_VOLUMEUP,0)); +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +begin + result:=0; + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if SongInfo.plyver=0 then + begin + SongInfo.plyver:=GetVersion (SongInfo.plwnd); + SongInfo.txtver:=GetVersionText(SongInfo.plyver); + end; + exit; + end; + + if (flags and WAT_OPT_CHANGES)<>0 then + SongInfo.wndtext:=GetDlgText(TitleWnd); +end; + +function Command(wnd:HWND;cmd:integer;value:integer):integer;cdecl; +begin + case cmd of + WAT_CTRL_PREV : result:=Prev(wnd); +// WAT_CTRL_PLAY : result:=Play(wnd,pWideChar(value)); + WAT_CTRL_PAUSE: result:=Pause(wnd); +// WAT_CTRL_STOP : result:=Stop(wnd); + WAT_CTRL_NEXT : result:=Next(wnd); + WAT_CTRL_VOLDN: result:=VolDn(wnd); + WAT_CTRL_VOLUP: result:=VolUp(wnd); +// WAT_CTRL_SEEK : result:=Seek(wnd,value); + else + result:=0; + end; +end; + +const + plRec:tPlayerCell=( + Desc :'BeholdTV'; + flags :WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:nil; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :@Command; + URL :nil; + Notes :'Still experimental, no tested. Can work not properly'); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_bs.pas b/plugins/Watrack/players/pl_bs.pas new file mode 100644 index 0000000000..7fd2e9c5e5 --- /dev/null +++ b/plugins/Watrack/players/pl_bs.pas @@ -0,0 +1,252 @@ +{BSPlayer player} +unit pl_BS; +{$include compilers.inc} + +interface + +implementation +uses windows,messages,common,srv_player,wat_api; + +const + HWND_MESSAGE = HWND(-3); +const + BSPlayerClass = 'BSPlayer'; +const + WM_BSP_CMD = WM_USER+2; + BSP_GETVERSION = $10000; + BSP_GetMovLen = $10100; + BSP_GetMovPos = $10101; + BSP_GetStatus = $10102; + BSP_Seek = $10103; + +// BSP_LoadPlaylist = $1010C; + BSP_SetVol = $10104; + BSP_GetVol = $10105; + BSP_OpenFile = $10108; + BSP_GetFileName = $1010B; + + BSP_VolUp = 1; + BSP_VolDown = 2; + BSP_Play = 20; + BSP_Pause = 21; + BSP_Stop = 22; + BSP_Prev = 25; + BSP_Next = 28; + +const + bspwnd:HWND = 0; + +function HiddenWindProc(wnd:HWnd; msg:UINT;wParam:WPARAM;lParam:LPARAM):integer; stdcall; +begin + result:=DefWindowProc(wnd,msg,wParam,lParam); +end; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindow(BSPlayerClass,NIL); + if result=0 then + begin + if bspwnd<>0 then + begin + DestroyWindow(bspwnd); + + bspwnd:=0; + end; + end + else if bspwnd=0 then + begin + bspwnd:=CreateWindowExW(0,'STATIC',nil,0,1,1,1,1,HWND_MESSAGE,0,hInstance,nil); + if bspwnd<>0 then + setwindowlongPtrW(bspwnd,GWL_WNDPROC,LONG_PTR(@HiddenWindProc)); + end; +end; + +function GetVersion(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_GETVERSION,0) +end; + +function GetVersionText(ver:integer):pWideChar; +begin + mGetMem(result,11*SizeOf(WideChar)); + IntToHex(result,ver shr 24,2); + result[2]:='.'; + IntToHex(result+3,(ver shr 16) and $FF,2); + result[5]:='.'; + IntToHex(result+6,ver and $FFFF); +end; + +function GetElapsedTime(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_GetMovPos,0) div 1000; +end; + +function GetTotalTime(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_GetMovLen,0) div 1000; +end; + +function GetStatus(wnd:HWND):integer; cdecl; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_GetStatus,0); + if result=1 then result:=2 + else if result=2 then result:=1; + if result>2 then result:=2; +end; + +function GetFileName(wnd:HWND;flags:integer):pWideChar; +var + cds:tcopyDataStruct; + buf:array [0..255] of AnsiChar; + adr:pointer; +begin + adr:=@buf; + cds.dwData:=BSP_GetFileName; + cds.lpData:=@adr; + cds.cbData:=4; + SendMessage(wnd,WM_COPYDATA,bspwnd,lparam(@cds)); + + AnsiToWide(buf,result); +end; + +function Play(wnd:HWND;fname:PWideChar=nil):integer; +var + cds:COPYDATASTRUCT; +begin + if (fname<>nil) and (fname^<>#0) then + begin + cds.dwData:=BSP_OpenFile; + WideToAnsi(fname,PAnsiChar(cds.lpData)); + cds.cbData:=StrLen(PAnsiChar(cds.lpData))+1; + SendMessage(wnd,WM_COPYDATA,0{!!!},lparam(@cds)); + mFreeMem(cds.lpData); + end; + result:=SendMessage(wnd,WM_BSP_CMD,BSP_Play,0); +end; + +function Pause(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_Pause,0); +end; + +function Stop(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_Stop,0); +end; + +function Next(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_Next,0); +end; + +function Prev(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_Prev,0); +end; + +function VolDn(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_VolDown,0); +end; + +function VolUp(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_VolUp,0); +end; + +function GetVolume(wnd:HWND):cardinal; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_GetVol,0); + result:=(result shl 16)+((result shl 4) div 25); +end; + +procedure SetVolume(wnd:HWND;value:cardinal); +begin + SendMessage(wnd,WM_BSP_CMD,BSP_SetVol,(value*25) shr 4); +end; + +function Seek(wnd:HWND;value:integer):integer; +begin + result:=SendMessage(wnd,WM_BSP_CMD,BSP_GetMovPos,0) div 1000; + SendMessage(wnd,WM_BSP_CMD,BSP_Seek,value*1000); +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +begin + result:=0; + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if SongInfo.plyver=0 then + begin + SongInfo.plyver:=GetVersion (SongInfo.plwnd); + SongInfo.txtver:=GetVersionText(SongInfo.plyver); + end; + exit; + end; + + with SongInfo do + begin + if (flags and WAT_OPT_CHANGES)<>0 then + begin + volume:=GetVolume(plwnd); + if status<>WAT_MES_STOPPED then + time:=GetElapsedTime(plwnd); + end + else + begin + if total=0 then + total:=GetTotalTime(plwnd); + end; + end; +end; + +function Command(wnd:HWND;cmd:integer;value:int_ptr):integer;cdecl; +begin + case cmd of + WAT_CTRL_PREV : result:=Prev (wnd); + WAT_CTRL_PLAY : result:=Play (wnd,pWideChar(value)); + WAT_CTRL_PAUSE: result:=Pause(wnd); + WAT_CTRL_STOP : result:=Stop (wnd); + WAT_CTRL_NEXT : result:=Next (wnd); + WAT_CTRL_VOLDN: result:=VolDn(wnd); + WAT_CTRL_VOLUP: result:=VolUp(wnd); + WAT_CTRL_SEEK : result:=Seek (wnd,value); + else + result:=0; + end; +end; + +const + plRec:tPlayerCell=( + Desc :'BSPlayer'; + flags :WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:@GetStatus; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :@Command; + URL :'http://www.bsplayer.org/'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_cowon.pas b/plugins/Watrack/players/pl_cowon.pas new file mode 100644 index 0000000000..0977ea4b20 --- /dev/null +++ b/plugins/Watrack/players/pl_cowon.pas @@ -0,0 +1,392 @@ +{COWON JetAudio player} +unit pl_cowon; +{$include compilers.inc} + +interface + +implementation +uses windows,winampapi,wrapper,messages,common,srv_player,wat_api; + +const + HWND_MESSAGE = HWND(-3); +const + HOSTWND_CLASS = 'TLB_JETAUDIO'; + + CowonClass = 'COWON Jet-Audio MainWnd Class'; + CowonTitle = 'Afx:400000:8:0:0:'; // for example 'Afx:400000:8:0:0:18c300fd' + ControlClass = 'COWON Jet-Audio Remocon Class'; + ControlName = 'Jet-Audio Remote Control'; + PluginClass = 'Streamzap.WMX'; + PluginName = 'Jet-Audio Remote Plugin'; +const + MCI_STRING_OFFSET = 512; + MCI_MODE_NOT_READY = MCI_STRING_OFFSET + 12; + MCI_MODE_STOP = MCI_STRING_OFFSET + 13; + MCI_MODE_PLAY = MCI_STRING_OFFSET + 14; + MCI_MODE_RECORD = MCI_STRING_OFFSET + 15; + MCI_MODE_SEEK = MCI_STRING_OFFSET + 16; + MCI_MODE_PAUSE = MCI_STRING_OFFSET + 17; + MCI_MODE_OPEN = MCI_STRING_OFFSET + 18; + + WM_REMOCON_GETSTATUS = WM_APP+740; + WM_REMOCON_SENDCOMMAND = WM_APP+741; + + JRC_ID_STOP = 5102; + JRC_ID_PLAY = 5104; // Track Number (>=1). Use 0 for normal playback. + JRC_ID_PREV_TRACK = 5107; + JRC_ID_NEXT_TRACK = 5108; + JRC_ID_VOL_DOWN = 5134; + JRC_ID_VOL_UP = 5135; + JRC_ID_SET_VOLUME = 5180; // Volume Value (0 - 32) + JRC_ID_SEEK = 5192; // New position (second) + JRC_ID_RANDOMMODE = 5117; + + GET_STATUS_STATUS = 1; + GET_STATUS_CUR_TRACK = 8; + GET_STATUS_CUR_TIME = 9; + GET_STATUS_MAX_TIME = 10; + GET_STATUS_TRACK_FILENAME = 11; + GET_STATUS_TRACK_TITLE = 12; + GET_STATUS_TRACK_ARTIST = 13; + + GET_STATUS_VOLUME = 127; + + JRC_COPYDATA_ID_ALBUMNAME = $1000; + JRC_COPYDATA_ID_GETVER = $1002; + JRC_COPYDATA_ID_TRACK_FILENAME = $3000; + JRC_COPYDATA_ID_TRACK_TITLE = $3001; + JRC_COPYDATA_ID_TRACK_ARTIST = $3002; + + PLAY_NORMAL = 0; + PLAY_RANDOM = 1; + + GET_STATUS_JETAUDIO_VER1 = 995; + GET_STATUS_JETAUDIO_VER2 = 996; + GET_STATUS_JETAUDIO_VER3 = 997; + +const + titlewnd:HWND = 0; + hostwnd :HWND = 0; + tmpstr :pWideChar=nil; + +function HiddenWindProc(wnd:HWnd; msg:UINT;wParam:WPARAM;lParam:LPARAM):integer; stdcall; +var + cds:PCOPYDATASTRUCT; +begin + case msg of + WM_COPYDATA: begin + cds:=PCOPYDATASTRUCT(lParam); + case cds^.dwData of + JRC_COPYDATA_ID_TRACK_FILENAME, + JRC_COPYDATA_ID_TRACK_TITLE , + JRC_COPYDATA_ID_TRACK_ARTIST : AnsiToWide(cds^.lpData,tmpstr); + end; + result:=1; + exit; + end; + end; + result:=DefWindowProc(wnd,msg,wParam,lParam); +end; + +function Init:integer;cdecl; +begin + hostwnd:=CreateWindowExW(0,'STATIC',nil,0,1,1,1,1,HWND_MESSAGE,0,hInstance,nil); + if hostwnd<>0 then + SetWindowLongPtrW(hostwnd,GWL_WNDPROC,LONG_PTR(@HiddenWindProc)); + result:=hostwnd; +end; + +function DeInit:integer;cdecl; +begin + result:=0; + if hostwnd<>0 then + begin + DestroyWindow(hostwnd); + hostwnd:=0; + end; +end; + +function chwnd(awnd:hwnd;param:pdword):boolean; stdcall; +var + s:array [0..255] of AnsiChar; +begin + result:=true; + if GetClassNameA(awnd,s,255)>0 then + begin + if StrCmp(s,CowonTitle,Length(CowonTitle))=0 then + begin + param^:=awnd; + result:=false; + end; + end; +end; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindow(ControlClass,ControlName); +{ + if result=0 then + result:=FindWindow(PluginClass,PluginName); +} + if (result<>0) {and (result<>wnd)} then + if EnumWindows(@chwnd,int_ptr(@titlewnd)) then + titlewnd:=0; +end; + +function GetWndText:pWideChar; +var + p:pWideChar; +begin + result:=nil; + if titlewnd<>0 then + begin + result:=GetDlgText(titlewnd); + if result<>nil then + begin + if StrScanW(result,'[')<>nil then + begin + p:=StrScanW(result,']'); + if p<>nil then + begin + StrCopyW(result,p+1); + end; + end; + end; + end; +end; + +function GetVersion(wnd:HWND):integer; +begin + result:= SendMessage(wnd,WM_REMOCON_GETSTATUS,0,GET_STATUS_JETAUDIO_VER1); + result:=(result shl 8)+SendMessage(wnd,WM_REMOCON_GETSTATUS,0,GET_STATUS_JETAUDIO_VER2); + result:=(result shl 8)+SendMessage(wnd,WM_REMOCON_GETSTATUS,0,GET_STATUS_JETAUDIO_VER3); +end; + +function GetVersionText(ver:integer):PWideChar; +{var + ver:integer; +begin + ver:=GetVersion; + mGetMem(result,11*SizeOf(WideChar)); + IntToHex(result,ver shr 16,2); + result[2]:='.'; + IntToHex(result+3,(ver shr 8) and $FF,2); + result[5]:='.'; + IntToHex(result+6,ver and $FF); +} +var + s:array [0..31] of WideChar; + i:integer; +begin + i:=StrLenW(IntToStr(s,ver shr 16)); + s[i]:='.'; + i:=integer(StrLenW(IntToStr(pWideChar(@s[i+1]),(ver shr 8) and $FF)))+i+1; + s[i]:='.'; + IntToStr(pWideChar(@s[i+1]),ver and $FF); + StrDupW(result,PWideChar(@s)); +end; + +function GetStatus(wnd:HWND):integer; cdecl; +begin + result:=SendMessage(wnd,WM_REMOCON_GETSTATUS,0,GET_STATUS_STATUS); + case result of + MCI_MODE_STOP : result:=WAT_MES_STOPPED; + MCI_MODE_PAUSE: result:=WAT_MES_PAUSED; + MCI_MODE_PLAY : result:=WAT_MES_PLAYING; + else + result:=WAT_MES_UNKNOWN; + end; +end; + +function GetFileName(wnd:HWND;flags:integer):pWideChar;cdecl; +begin + SendMessage(wnd,WM_REMOCON_GETSTATUS,hostwnd,GET_STATUS_TRACK_FILENAME); + result:=tmpstr; +end; + +function GetArtist(wnd:HWND):pWideChar; +begin + SendMessage(wnd,WM_REMOCON_GETSTATUS,hostwnd,GET_STATUS_TRACK_ARTIST); + result:=tmpstr; +end; + +function GetTitle(wnd:HWND):pWideChar; +begin + SendMessage(wnd,WM_REMOCON_GETSTATUS,hostwnd,GET_STATUS_TRACK_TITLE); + result:=tmpstr; +end; + +function GetTrack(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_GETSTATUS,0,GET_STATUS_CUR_TRACK); +end; + +function GetTotalTime(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_GETSTATUS,0,GET_STATUS_MAX_TIME) div 1000; +end; + +function GetElapsedTime(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_GETSTATUS,0,GET_STATUS_CUR_TIME) div 1000; +end; + +function Play(wnd:HWND;fname:PWideChar=nil):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_SENDCOMMAND,0,JRC_ID_PLAY); +end; + +function Pause(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_SENDCOMMAND,0,JRC_ID_PLAY); +end; + +function Stop(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_SENDCOMMAND,0,JRC_ID_STOP); +end; + +function Next(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_SENDCOMMAND,0,JRC_ID_NEXT_TRACK); +end; + +function Prev(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_SENDCOMMAND,0,JRC_ID_PREV_TRACK); +end; + +function VolDn(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_SENDCOMMAND,0,JRC_ID_VOL_DOWN); +end; + +function VolUp(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_SENDCOMMAND,0,JRC_ID_VOL_UP); +end; + +function GetVolume(wnd:HWND):cardinal; +begin + result:=SendMessage(wnd,WM_REMOCON_GETSTATUS,0,GET_STATUS_VOLUME); + result:=(result shl 16)+(result shr 1); +end; + +procedure SetVolume(wnd:HWND;value:cardinal); +begin + SendMessage(wnd,WM_REMOCON_SENDCOMMAND,0,JRC_ID_SET_VOLUME+(value shl 17)); +end; + +function Seek(wnd:HWND;value:integer):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_SENDCOMMAND,0,JRC_ID_SEEK+(value shl 16)); +end; +{ +function Shuffle(setOn:integer):integer; +begin + result:=SendMessage(wnd,WM_REMOCON_GETSTATUS,0,GETSTATUS_COMPONENT_RANDOMMODE); + SendMessage(wnd,WM_REMOCON_SENDCOMMAND,JRC_ID_RANDOMMODE+(SetOn shl 16)); +end; +} + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +var + p:pWideChar; +begin + result:=0; +// result:=CallService(MS_WAT_WINAMPINFO,integer(@SongInfo),flags); +// result:=WinampGetInfo(integer(@SongInfo),flags); + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if SongInfo.plyver=0 then + begin + SongInfo.plyver:=GetVersion (SongInfo.plwnd); + SongInfo.txtver:=GetVersionText(SongInfo.plyver); + end; + exit; + end; + + with SongInfo do + begin + if (flags and WAT_OPT_CHANGES)<>0 then + begin + wndtext:=GetWndText; + volume :=GetVolume(plwnd); + if status<>WAT_MES_STOPPED then +// if time=0 then + time:=GetElapsedTime(plwnd); + end + else + begin + + if artist=NIL then + begin + artist:=GetArtist(plwnd); + if artist^=#0 then + mFreeMem(artist); + end; + if title =NIL then + begin + title:=GetTitle(plwnd); + p:=ExtractW(mfile,true); + if (title^=#0) or (StrCmpW(title,p)=0) then + mFreeMem(title); + mFreeMem(p); + end; + + if total=0 then + total:=GetTotalTime(plwnd); + end; + end; +end; + +function Command(wnd:HWND;cmd:integer;value:int_ptr):integer;cdecl; +begin + case cmd of + WAT_CTRL_PREV : result:=Prev (wnd); + WAT_CTRL_PLAY : result:=Play (wnd,pWideChar(value)); + WAT_CTRL_PAUSE: result:=Pause(wnd); + WAT_CTRL_STOP : result:=Stop (wnd); + WAT_CTRL_NEXT : result:=Next (wnd); + WAT_CTRL_VOLDN: result:=VolDn(wnd); + WAT_CTRL_VOLUP: result:=VolUp(wnd); + WAT_CTRL_SEEK : result:=Seek (wnd,value); + else + result:=0; + end; +end; + +const + plRec:tPlayerCell=( + Desc :'Cowon JetAudio'; + flags :WAT_OPT_HASURL; + Icon :0; + Init :@Init; + DeInit :@DeInit; + Check :@Check; + GetStatus:@GetStatus; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :@Command; + URL :'http://www.jetaudio.com/'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_foobar.pas b/plugins/Watrack/players/pl_foobar.pas new file mode 100644 index 0000000000..f861db6327 --- /dev/null +++ b/plugins/Watrack/players/pl_foobar.pas @@ -0,0 +1,534 @@ +{Foobar2000 player} +unit pl_Foobar; +{$include compilers.inc} + +interface + +implementation +uses {$IFDEF KOL_MCK}err,{$ENDIF} + windows,common,syswin,wrapper,srv_player,messages,wat_api,winampapi + {$IFDEF DELPHI_7_UP} + ,variants + {$ENDIF} + {$IFDEF KOL_MCK} + ,kolcomobj + {$ELSE} + ,ComObj + {$ENDIF} +; + +const + COMName:PAnsiChar = 'Foobar2000.Application.0.7'; +const + dummywnd = 'uninteresting'; +const + FooExe = 'FOOBAR2000.EXE'; + FooPrefix = 'foobar2000 v'; +const + FooBarClassExt = '{97E27FAA-C0B3-4b8e-A693-ED7881E99FC1}'; + FooBarClassNew = '{DA7CD0DE-1602-45e6-89A1-C2CA151E008E}'; + FooBarClassAdd = '{E7076D1C-A7BF-4f39-B771-BCBE88F2A2A8}'; +(* + class1='{B73733CA-9B0A-4f53-93FA-AC95D4FF2166}'; + text1='Cthulhu fhtagn!'; + + '{53229DFC-A273-45cd-A3A4-161FA9FC6414}'; + '{641C2469-355C-4d6f-9663-E714382DA462}'; +*) +var + WinampWindow:HWND; + +function proc(awnd:hwnd;param:pdword):boolean; stdcall; +var + s:array [0..255] of AnsiChar; +begin + result:=true; + if (awnd<>param^) and (GetClassNameA(awnd,s,255)>0) then + begin + s[Length(FooBarClassNew)]:=#0; + if (StrCmp(s,FooBarClassExt)=0) or + (StrCmp(s,FooBarClassNew)=0) or + (StrCmp(s,FooBarClassAdd)=0) then + begin + GetWindowTextA(awnd,s,255); + if StrCmp(s,dummywnd)<>0 then + param^:=awnd; +// if WinampWindow<>0 then +// result:=false; + end + + else if (WinampWindow=0) and (StrCmp(s,WinampClass)=0) then + begin + WinampWindow:=awnd; + end; + + end; +end; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +var + tmp,EXEName:PAnsiChar; + lwnd:HWND; + ltmp:bool; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + lwnd:=0; + repeat + lwnd:=FindWindowEx(0,lwnd,nil,dummywnd); + if lwnd=0 then + break; + tmp:=Extract(GetEXEByWnd(lwnd,EXEName),true); + mFreeMem(EXEName); + ltmp:=lstrcmpia(tmp,FooExe)=0; + mFreeMem(tmp); + if ltmp then + begin + WinampWindow:=0; + EnumThreadWindows(GetWindowThreadProcessId(lwnd,nil),@proc,int_ptr(@lwnd)); + break; + end; + until false; + result:=lwnd; +end; + +function GetYear(const v:variant):PWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.Playback.FormatTitle('[%year%]')))); + except + result:=nil; + end; +end; + +function GetArtist(const v:variant):PWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.Playback.FormatTitle('[%artist%]')))); + except + result:=nil; + end; +end; + +function GetTitle(const v:variant):PWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.Playback.FormatTitle('[%title%]')))); + except + result:=nil; + end; +end; + +function GetAlbum(const v:variant):PWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.Playback.FormatTitle('[%album%]')))); + except + result:=nil; + end; +end; + +function GetGenre(const v:variant):PWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.Playback.FormatTitle('[%genre%]')))); + except + result:=nil; + end; +end; + +function GetBitrate(const v:variant):integer; +begin + try + result:=v.Playback.FormatTitle('%bitrate%'); + except + result:=0; + end; +end; + +function GetSamplerate(const v:variant):integer; +begin + try + result:=v.Playback.FormatTitle('%samplerate%'); + except + result:=0; + end; +end; + +function GetChannels(const v:variant):integer; +var + s:WideString; +begin + result:=0; + try + s:=v.Playback.FormatTitle('%channels%'); + if StrCmpW(pWideChar(s),'mono')=0 then + result:=1 + else if StrCmpW(pWideChar(s),'Stereo')=0 then + result:=2; + except + end; +end; + +function GetCodec(const v:variant):integer; +var + s:WideString; + i:integer; +begin + result:=0; + try + s:=v.Playback.FormatTitle('%codec%'); + i:=Length(s); + if i>0 then result:=ORD(s[1]); + if i>1 then result:=result+(ORD(s[2]) shl 8); + if i>2 then result:=result+(ORD(s[3]) shl 16); + if i>3 then result:=result+(ORD(s[4]) shl 24); + except + end; +end; + +function SplitVersion(p:pWideChar):integer; +begin + result:=StrToInt(p); + while (p^>='0') and (p^<='9') do inc(p); inc(p); + result:=result*16+StrToInt(p); + while (p^>='0') and (p^<='9') do inc(p); inc(p); + result:=result*16+StrToInt(p); + while (p^>='0') and (p^<='9') do inc(p); + if p^<>#0 then inc(p); + if (p^>='0') and (p^<='9') then + begin + result:=result*16+StrToInt(p); + while (p^>='0') and (p^<='9') do inc(p); + end; + if p^<>#0 then + begin + inc(p); + while (p^<>#0) and (p^<>' ') do inc(p); + if p^=' ' then + begin + inc(p); + result:=result*16+StrToInt(p); + end; + end; +end; + +function GetVersion(const ver:pWideChar):integer; +begin + if (ver=nil) or (ver^=#0) then + result:=0 + else + result:=SplitVersion(ver); +end; + +function GetVersionText(const v:variant):PWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.Name))+length(FooPrefix)); + except + result:=nil; + end; +end; + +function GetTotalTime(const v:variant):integer; +begin + try + result:=v.Playback.Length; + except + result:=0; + end; +end; + +function GetElapsedTime(const v:variant):integer; +begin + try + result:=v.Playback.Position; + except + result:=0; + end; +end; + +function GetStatus(wnd:HWND):integer; cdecl; +var + tmp:boolean; + v:variant; + winampwnd:HWND; +begin + try + result:=WAT_MES_STOPPED; + v:=GetActiveOleObject(COMName); + tmp:=v.Playback.IsPaused; + if tmp then + result:=WAT_MES_PAUSED + else + begin + tmp:=v.Playback.IsPlaying; + if tmp then + result:=WAT_MES_PLAYING; + end; + except + winampwnd:=WinampFindWindow(wnd); + if winampwnd<>0 then + result:=WinampGetStatus(winampwnd) + else + result:=WAT_MES_UNKNOWN; + end; + v:=null; +end; + +function GetWndText(wnd:HWND):pWideChar; +var + i:integer; +begin + result:=GetDlgText(wnd); + if result<>nil then + begin + i:=StrIndexW(result,'[foobar'); + if i<>0 then + begin + dec(i); + repeat + dec(i); + if ord(result[i])>ord(' ') then break; + until i<0; + result[i+1]:=#0;//if at end + end; + end; +end; + +function GetFileName(wnd:HWND;flags:integer):PWideChar;cdecl; +var + v:variant; +begin + try + v:=GetActiveOleObject(COMName); +// v:=CreateOleObject(COMName); + StrDupW(result,PWideChar(WideString(v.Playback.FormatTitle('%path%')))); + except + result:=nil; + end; + v:=Null; +end; + +function Play(const v:variant;fname:PWideChar=nil):integer; +begin + try + result:=v.Playback.Start(false); + except + result:=0; + end; +end; + +function Pause(const v:variant):integer; +begin + try + result:=v.Playback.Pause; + except + result:=0; + end; +end; + +function Stop(const v:variant):integer; +begin + try + result:=v.Playback.Stop; + except + result:=0; + end; +end; + +function Next(const v:variant):integer; +begin + try + result:=v.Playback.Next; + except + result:=0; + end; +end; + +function Prev(const v:variant):integer; +begin + try + result:=v.Playback.Previous; + except + result:=0; + end; +end; + +function GetVolume(const v:variant):cardinal; +begin + try + result:=v.Playback.Settings.Volume+100; + result:=(result shl 16)+round((result shl 4) / 100); + except + result:=0; + end; +end; + +procedure SetVolume(const v:variant;value:cardinal); +begin + try + v.Playback.Settings.Volume:=integer(((loword(value)*100) shr 4)-100); + except + end; +end; + +function VolDn(const v:variant):integer; +var + val:integer; +begin + result:=GetVolume(v); + val:=loword(result); + if val>0 then + SetVolume(v,val-1); +end; + +function VolUp(const v:variant):integer; +var + val:integer; +begin + result:=GetVolume(v); + val:=loword(result); + if val<16 then + SetVolume(v,val+1); +end; + +function Seek(const v:variant;value:integer):integer; +begin + try + result:=v.Playback.Position; + if (value>0) and (v.Playback.CanSeek) and (value0 then + begin + if SongInfo.plyver=0 then + begin + SongInfo.txtver:=GetVersionText(v); + SongInfo.plyver:=GetVersion(txtver); + end; + end + else if (flags and WAT_OPT_CHANGES)<>0 then + begin + volume:=GetVolume(v); + if status<>WAT_MES_STOPPED then + time:=GetElapsedTime(v); + end + else + begin + if kbps =0 then kbps :=GetBitrate(v); + if khz =0 then khz :=GetSamplerate(v); + if channels=0 then channels:=GetChannels(v); + if codec =0 then codec :=GetCodec(v); + if total =0 then total :=GetTotalTime(v); + if year =NIL then year :=GetYear(v); + if artist =NIL then artist :=GetArtist(v); + if title =NIL then title :=GetTitle(v); + if album =NIL then album :=GetAlbum(v); + if genre =NIL then genre :=GetGenre(v); + end; + except + SongInfo.winampwnd:=WinampWindow; + if SongInfo.winampwnd<>0 then + begin + result:=WinampGetInfo(int_ptr(@SongInfo),flags); + end; + end; + v:=Null; + if (flags and WAT_OPT_CHANGES)<>0 then + wndtext:=GetWndText(SongInfo.plwnd); + end; +end; + +function Command(wnd:HWND;cmd:integer;value:int_ptr):integer;cdecl; +//var +// c:integer; +var + v:Variant; +begin + result:=0; + try + v:=GetActiveOleObject(COMName); + case cmd of + WAT_CTRL_PREV : result:=Prev (v); + WAT_CTRL_PLAY : result:=Play (v,pWideChar(value)); + WAT_CTRL_PAUSE: result:=Pause(v); + WAT_CTRL_STOP : result:=Stop (v); + WAT_CTRL_NEXT : result:=Next (v); + WAT_CTRL_VOLDN: result:=VolDn(v); + WAT_CTRL_VOLUP: result:=VolUp(v); + WAT_CTRL_SEEK : result:=Seek (v,value); + end; + except + if WinampWindow<>0 then + result:=WinampCommand(WinampWindow,cmd+(value shl 16)) +{ + else + begin + case cmd of + WAT_CTRL_PREV : c:=ORD('B'); + WAT_CTRL_PLAY : c:=ORD('C'); + WAT_CTRL_PAUSE: c:=ORD('X'); + WAT_CTRL_STOP : c:=ORD('Z'); + WAT_CTRL_NEXT : c:=ORD('V'); + WAT_CTRL_VOLDN: c:=VK_SUBTRACT; + WAT_CTRL_VOLUP: c:=VK_ADD; + else + exit; + end; + PostMessageW(wnd,WM_KEYDOWN,c,1); + end; +} + end; + v:=Null; +end; + +const + plRec:tPlayerCell=( + Desc :'foobar2000'; + flags :WAT_OPT_SINGLEINST or WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:@GetStatus; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :@Command; + URL :'http://www.foobar2000.org/'; + Notes :'For more full info WinampSpam or foo_comserver (more powerful) '#13#10+ + 'components needs to be installed.'); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_itunes.pas b/plugins/Watrack/players/pl_itunes.pas new file mode 100644 index 0000000000..f43e6bac91 --- /dev/null +++ b/plugins/Watrack/players/pl_itunes.pas @@ -0,0 +1,392 @@ +{iTunes player} +unit pl_iTunes; +{$include compilers.inc} + +interface + +implementation +uses windows,common,srv_player,wat_api + {$IFDEF DELPHI_7_UP} + ,variants + {$ENDIF} + {$IFDEF KOL_MCK} + ,kolcomobj + {$ELSE} + ,ComObj + {$ENDIF} +; + +const + iTunesClass = 'iTunes'; + iTunesTitle = 'iTunes'; + COMName = 'iTunes.Application'; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindow(iTunesClass,iTunesTitle); +end; + +function GetFileName(wnd:HWND;flags:integer):PWideChar;cdecl; +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + StrDupW(result,PWideChar(WideString(v.CurrentTrack.Location))); + except + result:=nil; + end; + v:=Null; +end; + +function SplitVersion(p:pWideChar):integer; +begin + result:=StrToInt(p); + while (p^>='0') and (p^<='9') do inc(p); inc(p); + result:=result*16+StrToInt(p); + while (p^>='0') and (p^<='9') do inc(p); inc(p); + result:=(result*16+StrToInt(p))*16; + while (p^>='0') and (p^<='9') do inc(p); inc(p); + result:=result*16+StrToInt(p); +end; + +function GetVersion(const ver:pWideChar):integer; +begin + if (ver<>nil) and (ver^<>#0) then + result:=SplitVersion(ver) + else + result:=0; +end; + +function GetVersionText(const v:variant):PWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.Version))); + except + result:=nil; + end; +end; + +function GetTotalTime(const v:variant):integer; +begin + try + result:=v.CurrentTrack.Duration; + except + result:=0; + end; +end; + +function GetElapsedTime(const v:variant):integer; +begin + try + result:=v.PlayerPosition; + except + result:=0; + end; +end; + +function GetStatus(wnd:HWND):integer; cdecl; +var + tmp:integer; + v:variant; +begin + try + v:=CreateOleObject(COMName); + tmp:=v.PlayerState; + if tmp=1 then + result:=WAT_MES_PLAYING + else + result:=WAT_MES_STOPPED; + except + result:=WAT_MES_UNKNOWN; + end; + v:=Null; +end; + +function GetKbps(const v:variant):integer; +begin + try + result:=v.CurrentTrack.BitRate; + except + result:=0; + end; +end; + +function GetKhz(const v:variant):integer; +begin + try + result:=v.CurrentTrack.SampleRate; + except + result:=0; + end; +end; + +function GetTrack(const v:variant):integer; +begin + try + result:=v.CurrentTrack.TrackNumber; + except + result:=0; + end; +end; + +function GetAlbum(const v:variant):pWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.CurrentTrack.Album))); + except + result:=nil; + end; +end; + +function GetYear(const v:variant):pWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.CurrentTrack.Year))); + except + result:=nil; + end; +end; + +function GetGenre(const v:variant):pWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.CurrentTrack.Genre))); + except + result:=nil; + end; +end; + +function GetArtist(const v:variant):pWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.CurrentTrack.Artist))); + except + result:=nil; + end; +end; + +function GetTitle(const v:variant):pWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.CurrentStreamTitle))); + except + result:=nil; + end; +end; + +function GetComment(const v:variant):pWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.CurrentTrack.Comment))); + except + result:=nil; + end; +end; + +function GetWndText(const v:variant):pWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.Windows.Name))); + except + result:=nil; + end; +end; + +function Play(const v:variant;fname:PWideChar=nil):integer; +begin + try +// v.PlayFile(fname); + v.BackTrack; + result:=v.Play; + except + result:=0; + end; +end; + +function Pause(const v:variant):integer; +begin + try + result:=v.PlayPause; + except + result:=0; + end; +end; + +function Stop(const v:variant):integer; +begin + try + result:=v.Stop; + except + result:=0; + end; +end; + +function Next(const v:variant):integer; +begin + try + result:=v.NextTrack; + except + result:=0; + end; +end; + +function Prev(const v:variant):integer; +begin + try + result:=v.PreviousTrack; + except + result:=0; + end; +end; + +function Seek(const v:variant;value:integer):integer; +begin + try + result:=v.PlayerPosition; + if value>0 then + v.PlayerPosition:=value + else + result:=0; + except + result:=0; + end; +end; + +function GetVolume(const v:variant):cardinal; +begin + try + result:=v.SoundVolume; + result:=(result shl 16)+round((result shl 4)/100); + except + result:=0; + end; +end; + +procedure SetVolume(const v:variant;value:cardinal); +begin + try + v.SoundVolume:=integer((value*100) shr 4); + except + end; +end; + +function VolDn(const v:variant):integer; +var + val:integer; +begin + result:=GetVolume(v); + val:=loword(result); + if val>0 then + SetVolume(v,val-1); +end; + +function VolUp(const v:variant):integer; +var + val:integer; +begin + result:=GetVolume(v); + val:=loword(result); + if val<16 then + SetVolume(v,val+1); +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +var + v:variant; +begin + result:=0; + with SongInfo do + begin + try + v:=CreateOleObject(COMName); + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if plyver=0 then + begin + txtver:=GetVersionText(v); + plyver:=GetVersion(txtver); + end; + end + else if (flags and WAT_OPT_CHANGES)<>0 then + begin + volume:=GetVolume(v); + if status<>WAT_MES_STOPPED then + time:=GetElapsedTime(v); + end + else + begin + if total =0 then total :=GetTotalTime(v); + if track =0 then track :=GetTrack(v); + if year =NIL then year :=GetYear(v); + if genre =NIL then genre :=GetGenre(v); + if artist =NIL then artist :=GetArtist(v); + if album =NIL then album :=GetAlbum(v); + if comment=NIL then comment:=GetComment(v); + if kbps =0 then kbps :=GetKbps(v); + if khz =0 then khz :=GetKhz(v); + end; +// wndtext:=GetWndText(v); + except + end; + v:=Null; +// if title=NIL then title:=GetTitle; // only for streaming audio + end; +end; + +function Command(wnd:HWND;cmd:integer;value:int_ptr):integer;cdecl; +var + v:Variant; +begin + result:=0; + try + v:=CreateOleObject(COMName); + case cmd of + WAT_CTRL_PREV : result:=Prev (v); + WAT_CTRL_PLAY : result:=Play (v,pWideChar(value)); + WAT_CTRL_PAUSE: result:=Pause(v); + WAT_CTRL_STOP : result:=Stop (v); + WAT_CTRL_NEXT : result:=Next (v); + WAT_CTRL_VOLDN: result:=VolDn(v); + WAT_CTRL_VOLUP: result:=VolUp(v); + WAT_CTRL_SEEK : result:=Seek (v,value); + end; + except + end; + v:=Null; +end; + +const + plRec:tPlayerCell=( + Desc :'iTunes'; + flags :WAT_OPT_SINGLEINST or WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:@GetStatus; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :@Command; + URL :'http://www.itunes.com/'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_la.pas b/plugins/Watrack/players/pl_la.pas new file mode 100644 index 0000000000..1945cf6580 --- /dev/null +++ b/plugins/Watrack/players/pl_la.pas @@ -0,0 +1,141 @@ +{LightAlloy player} +unit pl_la; +{$include compilers.inc} + +interface + +implementation +uses windows,messages,common,srv_player,wat_api; + +const + LAClass = 'LightAlloyFront'; +const + WM_LACMD = WM_APP + 2504; + LAC_VERSION = 000; + + LAC_FILE_OPEN = 050; + LAC_PLAYBACK_STOP = 100; + LAC_PLAYBACK_PLAY = 101; + LAC_PLAYBACK_STOP_PLAY = 102; + LAC_PLAYLIST_NEXT = 250; + LAC_PLAYLIST_PREV = 251; + LAC_PLAYLIST_PLAY = 252; + LAC_SOUND_VOLUME_INC = 401; + LAC_SOUND_VOLUME_DEC = 402; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindow(LAClass,NIL); +end; + +function GetVersion(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_LACMD,LAC_VERSION,0) +end; + +function Play(wnd:HWND;fname:PWideChar=nil):integer; +var + cds:COPYDATASTRUCT; +begin + if (fname<>nil) and (fname^<>#0) then + begin + cds.dwData:=LAC_FILE_OPEN; + WideToAnsi(fname,PAnsiChar(cds.lpData)); + cds.cbData:=StrLen(PAnsiChar(cds.lpData))+1; + SendMessage(wnd,WM_COPYDATA,0,lparam(@cds)); + mFreeMem(cds.lpData); + end; + result:=SendMessage(wnd,WM_LACMD,LAC_PLAYLIST_PLAY,0) // LAC_PLAYLIST_PLAY +end; + +function Pause(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_LACMD,LAC_PLAYBACK_STOP_PLAY,0) +end; + +function Stop(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_LACMD,LAC_PLAYBACK_STOP,0) +end; + +function Next(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_LACMD,LAC_PLAYLIST_NEXT,0) +end; + +function Prev(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_LACMD,LAC_PLAYLIST_PREV,0) +end; + +function VolDn(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_LACMD,LAC_SOUND_VOLUME_DEC,0); +end; + +function VolUp(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_LACMD,LAC_SOUND_VOLUME_INC,0); +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +begin + result:=0; + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if SongInfo.plyver=0 then + begin + SongInfo.plyver:=GetVersion(SongInfo.plwnd); + end; + end; +end; + +function Command(wnd:HWND;cmd:integer;value:int_ptr):integer;cdecl; +begin + case cmd of + WAT_CTRL_PREV : result:=Prev (wnd); + WAT_CTRL_PLAY : result:=Play (wnd,pWideChar(value)); + WAT_CTRL_PAUSE: result:=Pause(wnd); + WAT_CTRL_STOP : result:=Stop (wnd); + WAT_CTRL_NEXT : result:=Next (wnd); + WAT_CTRL_VOLDN: result:=VolDn(wnd); + WAT_CTRL_VOLUP: result:=VolUp(wnd); + else + result:=0; + end; +end; + +const + plRec:tPlayerCell=( + Desc :'LightAlloy'; + flags :WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:nil; + GetName :nil; + GetInfo :@GetInfo; + Command :@Command; + URL :'http://www.softella.com/'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_lastfm.pas b/plugins/Watrack/players/pl_lastfm.pas new file mode 100644 index 0000000000..56ed3c7d4b --- /dev/null +++ b/plugins/Watrack/players/pl_lastfm.pas @@ -0,0 +1,129 @@ +{Last.fm Player} +unit pl_LastFM; + +interface + +implementation + +uses windows,common,messages,syswin,srv_player,wat_api; + + +const + LFMName = 'Last.fm Player'; + LFMText = 'Last.fm'; + LFMClass = 'QWidget'; + +const + UserName:pWideChar=nil; + +function Check(wnd:HWND;aflags:integer):HWND;cdecl; +var + tmp,EXEName:PAnsiChar; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindow(LFMClass,nil{LFMName}); + if result<>0 then + begin + tmp:=Extract(GetEXEByWnd(result,EXEName),true); + if lstrcmpia(tmp,'LASTFM.EXE')<>0 then + result:=0; + mFreeMem(tmp); + mFreeMem(EXEName); + if result<>0 then + result:=GetWindow(result,GW_OWNER); + end; + if result=0 then + mFreeMem(UserName); +end; + +function GetWndText(wnd:HWND):pWideChar; +var + ps:array [0..255] of WideChar; + p:pWideChar; +begin + SendMessageW(wnd,WM_GETTEXT,255,lparam(@ps)); + p:=StrPosW(ps,' | '); + if p<>nil then + begin + mFreeMem(UserName); + StrDupW(UserName,p+3); + p^:=#0; + end; + StrDupW(result,ps); +end; + +function GetFileName(wnd:HWND;flags:integer):PWideChar;cdecl; +var + buf:array [0..1023] of WideChar; + p:pWideChar; +begin +// lstrcpyw(buf,'http://'); +buf[0]:=#0; + p:=GetWndText(wnd); + StrCatW(buf,p); + StrCatW(buf,'.mp3'); + StrDupW(result,buf); + mFreeMem(p); +end; + +function GetStatus(wnd:HWND):integer; cdecl; +var + txt:pWideChar; +begin + txt:=GetWndText(wnd); + if StrCmpW(txt,LFMText,Length(LFMText))<>0 then + result:=WAT_MES_PLAYING + else + result:=WAT_MES_STOPPED; + mFreeMem(txt); +end; + +function GetInfo(var SongInfo:tSongInfo;aflags:integer):integer;cdecl; +begin + result:=0; + with SongInfo do + begin + fsize:=1; + if (aflags and WAT_OPT_CHANGES)<>0 then + begin + wndtext:=GetWndText(plwnd); + end + else + begin + end; + end; +end; + +const + plRec:tPlayerCell=( + Desc :'Last.fm'; + flags :WAT_OPT_LAST or WAT_OPT_SINGLEINST or WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:@GetStatus; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :nil; + URL :'http://www.lastfm.com/'; + Notes :'Works by window title analysing only'); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_mmonkey.pas b/plugins/Watrack/players/pl_mmonkey.pas new file mode 100644 index 0000000000..bb826b9851 --- /dev/null +++ b/plugins/Watrack/players/pl_mmonkey.pas @@ -0,0 +1,181 @@ +{MediaMonkey player} +unit pl_mmonkey; +{$include compilers.inc} + +interface + +implementation +uses windows,messages,winampapi,common,srv_player,wat_api + {$IFDEF DELPHI_7_UP} + ,variants + {$ENDIF} + {$IFDEF KOL_MCK} + ,kolcomobj + {$ELSE} + ,ComObj + {$ENDIF} +; + +const + COMName:PAnsiChar = 'SongsDB.SDBApplication'; + +const + WM_WA_IPC = WM_USER; + IPC_GETVERSION = 0; + +{ +const + MMonkeyName = 'MediaMonkey'; +} +function Check(wnd:HWND;flags:integer):HWND;cdecl; +//var +// i:integer; +{ + EXEName:pWideChar; + tmp:pWideChar; +} +// v:Variant; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindow('TFMainWindow','MediaMonkey'); + if result=0 then + result:=FindWindow('TFMainWindow.UnicodeClass','MediaMonkey'); +{ + wnd:=FindWindow(WinAmpClass,NIL); + if wnd<>0 then + begin + if (SendMessage(wnd,WM_WA_IPC,0,IPC_GETVERSION) and $FF0F)<>$990B then + wnd:=result; + end; +} +{ + wnd:=FindWindow(WinAmpClass,NIL); + if wnd<>0 then + begin + i:=SendMessage(wnd,WM_WA_IPC,0,IPC_GETVERSION) and $FF0F; + if i=$990B then + begin + + try +// v:=GetActiveOleObject(COMName); + v:=CreateOleObject(COMName); + if not v.IsRunning then + wnd:=0; + except + end; + v:=Null; + + end + else + wnd:=0; + end; + result:=wnd; +{ + begin + EXEName:=GetEXEByWnd(wnd); + tmp:=Extract(EXEName,true); + mFreeMem(EXEName); + result:=StrCmpW(tmp,MMonkeyName,length(MMonkeyName))=0; + mFreeMem(tmp); + end; +} +end; + +function GetVersion(const v:variant):integer; +begin + try + result:=(v.VersionHi shl 8)+(v.VersionLo shl 4)+v.VersionRelease; + except + result:=0; + end; +end; + +function GetVersionText(const v:variant):PWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.VersionString))); + except + result:=nil; + end; +end; + +function GetFileName(wnd:HWND;flags:integer):pWideChar;cdecl; +var + v:Variant; +begin + try +// SDB:=GetActiveOleObject(COMName); + v:=CreateOleObject(COMName); + StrDupW(result,PWideChar(WideString(v.Player.CurrentSong.Path))); + except + result:=nil; + end; + v:=Null; +end; + +function GetStatus(wnd:HWND):integer; cdecl; +begin + result:=WinampGetStatus(wnd) +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +var + v:variant; +begin + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if SongInfo.plyver=0 then + begin + try + v:=CreateOleObject(COMName); + with SongInfo do + begin + plyver:=GetVersion(v); + txtver:=GetVersionText(v); + end; + except + end; + v:=Null; + end; + end; + result:=WinampGetInfo(int_ptr(@SongInfo),flags); +end; + +function Command(wnd:HWND;cmd:integer;value:integer):integer;cdecl; +begin + result:=WinampCommand(wnd,cmd+(value shl 16)); +end; + +const + plRec:tPlayerCell=( + Desc :'MediaMonkey'; + flags :WAT_OPT_SINGLEINST or WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:@GetStatus; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :@Command; + URL :'http://www.mediamonkey.com/'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_mpc.pas b/plugins/Watrack/players/pl_mpc.pas new file mode 100644 index 0000000000..a2127cea76 --- /dev/null +++ b/plugins/Watrack/players/pl_mpc.pas @@ -0,0 +1,117 @@ +{Media Player Classic} +unit pl_MPC; +{$include compilers.inc} + +interface + +implementation +uses windows,common,wrapper,srv_player,wat_api; + +const + MPCClass98 = 'MediaPlayerClassicA'; + MPCClassXP = 'MediaPlayerClassicW'; + MPCTail = ' - Media Player Classic'; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + result:=FindWindowEx(0,wnd,MPCClassXP,NIL); + if result=0 then + result:=FindWindowEx(0,wnd,MPCClass98,NIL); +end; + +function chwnd(awnd:hwnd;Param:pdword):boolean; stdcall; +var + s:array [0..31] of AnsiChar; + i:integer; +begin + FillChar(s,SizeOf(s),0); + GetWindowTextA(awnd,s,30); + i:=StrIndex(PAnsiChar(@s),' / '); + if i<>0 then + begin + if Param^=0 then + begin + s[i-1]:=#0; + Param^:=TimeToInt(s); + end + else + begin + Param^:=TimeToInt(s+i+2); + end; + result:=false; + end + else + result:=true; +end; + +function GetElapsedTime(wnd:HWND):integer; +begin + result:=0; + if EnumChildWindows(wnd,@chwnd,int_ptr(@result)) then + result:=0; +end; + +function GetTotalTime(wnd:HWND):integer; +begin + result:=1; + if EnumChildWindows(wnd,@chwnd,int_ptr(@result)) then + result:=0; +end; + +function GetWndText(wnd:HWND):pWidechar; +var + p:pWideChar; +begin + result:=GetDlgText(wnd); + if result<>nil then + begin + p:=StrPosW(result,MPCTail); + if p<>nil then + p^:=#0; + end; +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +begin + result:=0; + with SongInfo do + begin + if (flags and WAT_OPT_CHANGES)<>0 then + begin + time :=GetElapsedTime(SongInfo.plwnd); + wndtext:=GetWndText(SongInfo.plwnd); + end + else if total=0 then + total:=GetTotalTime(SongInfo.plwnd); + end; +end; + +const + plRec:tPlayerCell=( + Desc :'MPC'; + flags :WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:nil; + GetName :nil; + GetInfo :@GetInfo; + Command :nil; + URL :'http://gabest.org/'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_mradio.pas b/plugins/Watrack/players/pl_mradio.pas new file mode 100644 index 0000000000..3d97037fbb --- /dev/null +++ b/plugins/Watrack/players/pl_mradio.pas @@ -0,0 +1,345 @@ +{mRadio protocol support} +unit pl_mradio; +{$include compilers.inc} +{$r mradio.res} +interface + +implementation +uses m_api,dbsettings,windows,common,srv_player,wat_api,io; + +const + strUnknown:PwideChar = 'Unknown'; + playername:PAnsiChar = 'mRadio'; +const + CurrentStation:THANDLE=THANDLE(-1); +const + ChangesHook:THANDLE=0; +const + MS_RADIO_COMMAND = 'mRadio/Command'; + MS_RADIO_SETVOL = 'mRadio/SetVol'; + ME_RADIO_STATUS:PAnsiChar = 'mRadio/Status'; +const + MRC_STOP = 0; + MRC_PLAY = 1; + MRC_PAUSE = 2; + MRC_PREV = 3; + MRC_NEXT = 4; + MRC_STATUS = 5; + MRC_SEEK = 6; +const + RD_STATUS_NOSTATION = 0; // no active station found + RD_STATUS_PLAYING = 1; // media is playing + RD_STATUS_PAUSED = 2; // media is paused + RD_STATUS_STOPPED = 3; // media is stopped (only for playlists) + RD_STATUS_CONNECT = 4; // plugin try to connect to the station + RD_STATUS_ABORT = 5; // plugin want to abort while try to connect + // next is for events only + RD_STATUS_POSITION = 107; // position was changed + RD_STATUS_MUTED = 108; // Mute/Unmute command was sent + RD_STATUS_RECORD = 109; // "Record" action called + RD_STATUS_NEWTRACK = 110; // new track/station + RD_STATUS_NEWTAG = 111; // tag data changed + RD_STATUS_NEWSTATION = 112; // new station (contact) + // next command is for users + RD_STATUS_GET = 6; // to get current status +const + prevfile:PWideChar=nil; + +function ClearmRadio:integer; cdecl; +begin + result:=0; + if ChangesHook>0 then + begin + UnhookEvent(ChangesHook); + ChangesHook:=0; + CurrentStation:=THANDLE(-1); + end; + mFreeMem(prevfile); +end; + +function SettingsChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + result:=0; + case wParam of + // clear station + RD_STATUS_NOSTATION: CurrentStation:=THANDLE(-1); + // get new url + RD_STATUS_NEWSTATION: CurrentStation:=lParam; + end; +end; + +function Fill:integer; +var + i:integer; +begin + CurrentStation:=CallService(MS_DB_CONTACT_FINDFIRST,0,0); + while CurrentStation<>0 do + begin + i:=DBReadWord(CurrentStation,playername,'Status',WORD(-1)); + if i=ID_STATUS_ONLINE then + begin + result:=1; + exit; + end; + CurrentStation:=CallService(MS_DB_CONTACT_FINDNEXT,CurrentStation,0); + end; + result:=WAT_RES_NOTFOUND; +end; + +function InitmRadio:integer; +begin + if ChangesHook=0 then + begin + ChangesHook:=HookEvent(ME_RADIO_STATUS,@SettingsChanged); + result:=Fill; + end + else if (CurrentStation<>0) and (CurrentStation<>THANDLE(-1)) then + result:=1 + else + result:=WAT_RES_NOTFOUND; +end; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + if CallProtoService(playername,PS_GETSTATUS,0,0)=ID_STATUS_ONLINE then + begin + result:=InitmRadio + end + else + begin + result:=HWND(WAT_RES_NOTFOUND); + ClearmRadio; + end; +end; + +function GetKbps:integer; +var + pc:PWideChar; +begin + pc:=DBReadUnicode(CurrentStation,playername,'Bitrate','0'); + result:=StrToInt(pc); + mFreeMem(pc); +end; + +function GetFileName(wnd:HWND;flags:integer):pWideChar; cdecl; +begin + result:=DBReadUnicode(0,playername,'ActiveURL',nil) +end; + +function GetGenre:pWideChar; +begin + result:=DBReadUnicode(CurrentStation,playername,'Genre',nil); +end; + +function GetWndText:pWideChar; +begin + result:=DBReadUnicode(CurrentStation,strCList,'StatusMsg',strUnknown); +end; + +function GetTitle:pWideChar; +begin + result:=DBReadUnicode(0,playername,'Title'); + if result=nil then + result:=DBReadUnicode(CurrentStation,strCList,'StatusMsg',strUnknown); +end; + +function GetArtist:pWideChar; +begin + result:=DBReadUnicode(0,playername,'Artist'); + if result=nil then + result:=DBReadUnicode(CurrentStation,strCList,'MyHandle',strUnknown); +end; + +function GetVolume:cardinal; +begin + result:=DBReadByte(0,playername,'Volume',0); + result:=(result shl 16)+round((result shl 4)/100); +end; + +procedure SetVolume(value:cardinal); +begin + CallService(MS_RADIO_SETVOL,(value*100) shr 4,0); +end; + +function VolDn:integer; +var + val:dword; +begin + result:=GetVolume; + val:=loword(result); + if val>0 then + SetVolume(val-1); +end; + +function VolUp:integer; +var + val:dword; +begin + result:=GetVolume; + val:=loword(result); + if val<16 then + SetVolume(val+1); +end; + +function GetCover:pWideChar; +var + ptr:PavatarCacheEntry; +begin + result:=nil; + if ServiceExists(MS_AV_GETAVATARBITMAP)<>0 then + begin + ptr:=PavatarCacheEntry(CallService(MS_AV_GETAVATARBITMAP,CurrentStation,0)); + if ptr<>nil then + AnsiToWide(ptr^.szFilename,result) + end; +end; + +function GetVersionText(ver:dword):pWideChar; +var + s:array [0..31] of WideChar; + p:pWideChar; +begin + p:=@s; + IntToStr(p,ver shr 12); + while p^<>#0 do inc(p); + p^:='.'; + IntToStr(p+1,(ver shr 8) and $F); + while p^<>#0 do inc(p); + p^:='.'; + IntToStr(p+1,(ver shr 4) and $F); + while p^<>#0 do inc(p); + p^:='.'; + IntToStr(p+1,ver and $F); + StrDupW(result,PWideChar(@s)); +end; + +function GetStatus:integer; cdecl; +begin + if CurrentStation<>0 then + begin + result:=WAT_MES_PLAYING; + case CallService(MS_RADIO_COMMAND,MRC_STATUS,RD_STATUS_GET) of + RD_STATUS_PAUSED : result:=WAT_MES_PAUSED; + RD_STATUS_STOPPED: begin + result:=WAT_MES_STOPPED; + mFreeMem(prevfile); + end; + RD_STATUS_NOSTATION, + RD_STATUS_ABORT : result:=WAT_MES_UNKNOWN; + end; + end + else + result:=WAT_MES_STOPPED; +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +var + lfile:pWideChar; + isRemote:bool; + isChanging:bool; +begin + result:=0; + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if SongInfo.plyver=0 then + begin + SongInfo.plyver:=DBReadDWord(0,playername,'version'); + SongInfo.txtver:=GetVersionText(SongInfo.plyver); + end; + end + else if CurrentStation<>0 then + with SongInfo do + begin + if (flags and WAT_OPT_CHANGES)<>0 then + begin + volume:=GetVolume; + mFreeMem(wndtext); + wndtext:=GetWndText; + time:=CallService(MS_RADIO_COMMAND,MRC_SEEK,-1); + end + else + begin + lfile:=GetFileName(plwnd,flags); + isRemote:=StrPosW(lfile,'://')<>nil; + if (prevfile=nil) or isRemote or (StrCmpW(prevfile,lfile)<>0) then + begin + ClearTrackInfo(SongInfo,false); + mfile:=lfile; + mFreeMem(prevfile); + StrDupW(prevfile,mfile); + isChanging:=true; + end + else + begin + isChanging:=false; + mFreeMem(lfile); + end; + + if not isRemote then + begin + if isChanging then + begin + CallService(MS_WAT_GETFILEINFO,0,lparam(@SongInfo)); + fsize:=GetFSize(mfile); + mFreeMem(prevfile); + StrDupW(prevfile,mfile); + end; + end; +//!! + if kbps =0 then kbps :=GetKbps; + if genre =nil then genre :=GetGenre; + if title =nil then title :=GetTitle; + if artist=nil then artist:=GetArtist; + if cover =nil then cover :=GetCover; + end; + end; +end; + +function Command(wnd:HWND;cmd:integer;value:integer):integer;cdecl; +begin + result:=0; + case cmd of + WAT_CTRL_PREV : result:=CallService(MS_RADIO_COMMAND,MRC_PREV,0); + WAT_CTRL_PLAY : result:=CallService(MS_RADIO_COMMAND,MRC_PLAY,0); + WAT_CTRL_PAUSE: result:=CallService(MS_RADIO_COMMAND,MRC_PAUSE,0); + WAT_CTRL_STOP : result:=CallService(MS_RADIO_COMMAND,MRC_STOP,0); + WAT_CTRL_NEXT : result:=CallService(MS_RADIO_COMMAND,MRC_NEXT,0); + WAT_CTRL_VOLDN: result:=VolDn; + WAT_CTRL_VOLUP: result:=VolUp; + WAT_CTRL_SEEK : result:=CallService(MS_RADIO_COMMAND,MRC_SEEK,value); + end; +end; + +const + plRec:tPlayerCell=( + Desc :'mRadio'; + flags :WAT_OPT_PLAYERINFO or WAT_OPT_SINGLEINST or WAT_OPT_HASURL or WAT_OPT_LAST; + Icon :0; + Init :nil; + DeInit :@ClearmRadio; + Check :@Check; + GetStatus:@GetStatus; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :@Command; + URL :'https://code.google.com/p/delphi-miranda-plugins/'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + if plRec.Icon=0 then + plRec.Icon:=LoadImage(hInstance,'ICO_MRADIO',IMAGE_ICON,16,16,0); + + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization + InitLink; +finalization + if plRec.Icon<>0 then DestroyIcon(plRec.Icon); +end. diff --git a/plugins/Watrack/players/pl_vlc.pas b/plugins/Watrack/players/pl_vlc.pas new file mode 100644 index 0000000000..9d3a2ad57d --- /dev/null +++ b/plugins/Watrack/players/pl_vlc.pas @@ -0,0 +1,380 @@ +{Video Lan player} +unit pl_VLC; +{$include compilers.inc} + +interface + +implementation +uses windows,common,srv_player,wat_api,syswin,wrapper + {$IFDEF DELPHI_7_UP} + ,variants + {$ENDIF} + {$IFDEF KOL_MCK} + ,kolcomobj + {$ELSE} + ,ComObj + {$ENDIF} +; + +{ + procedure play; safecall; + procedure pause; safecall; + procedure stop; safecall; + procedure playlistNext; safecall; + procedure playlistPrev; safecall; + property Playing: WordBool read Get_Playing; + property Position: Single read Get_Position write Set_Position; + property Time: SYSINT read Get_Time write Set_Time; + property Length: SYSINT read Get_Length; + (0)1-97(100) + property Volume: SYSINT read Get_Volume write Set_Volume; + property VersionInfo: WideString read Get_VersionInfo; +} + +const +// GuidOld: TGUID = '{E23FE9C6-778E-49D4-B537-38FCDE4887D8}'; + VLCClass = 'wxWindowClassNR'; + VLCName = 'VLC media player'; + COMName = 'VideoLAN.VLCPlugin.1'; // IVLCControl + +// GuidNew: TGUID = '{9BE31822-FDAD-461B-AD51-BE1D1C159921}'; + VLCClassSkin = 'SkinWindowClass'; + VLCClassNew = 'QWidget'; + VLCEXEName = 'VLC.EXE'; + COMNameNew = 'VideoLAN.VLCPlugin2'; // IVLCControl2 + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +var + tmp,EXEName:PAnsiChar; +begin + if wnd<>0 then + begin + result:=0; + exit; + end; + result:=FindWindow(VLCClass,VLCName); + if result=0 then + result:=FindWindow(VLCClassSkin,nil); // VLCName + if result=0 then + result:=FindWindow(VLCClassNew,nil); + if result<>0 then + begin + tmp:=Extract(GetEXEByWnd(result,EXEName),true); + if lstrcmpia(tmp,VLCEXEName)<>0 then + result:=0; + mFreeMem(tmp); + mFreeMem(EXEName); + end; +{ if result<>0 then + begin + tmp:=Extract(GetEXEByWnd(result,EXEName),true); + if lstrcmpia(tmp,'VLC.EXE')<>0 then + result:=0; + mFreeMem(tmp); + mFreeMem(EXEName); + end; +} +end; + +function SplitVersion(p:pWideChar):integer; +begin + result:=StrToInt(p); + while (p^>='0') and (p^<='9') do inc(p); inc(p); + result:=result*16+StrToInt(p); + while (p^>='0') and (p^<='9') do inc(p); inc(p); + result:=(result*16+StrToInt(p))*16; + while (p^>='0') and (p^<='9') do inc(p); inc(p); + result:=result*16+StrToInt(p); +end; + +function GetVersion(const ver:pWideChar):integer; +begin + try + result:=SplitVersion(ver); + except + result:=0; + end; +end; + +function GetVersionText(const v:variant):PWideChar; +begin + try + StrDupW(result,PWideChar(WideString(v.VersionInfo))); + except + result:=nil; + end; +end; + +function GetWndText(wnd:HWND):pWideChar; +var + p:pWideChar; +begin + result:=GetDlgText(wnd); +{ +need to clear " - lalala VLC" at the end +} + if result<>nil then + begin + p:=StrRScanW(result,'-'); + if p<>nil then // found + begin + if (p>result) and ((p-1)^=' ') and ((p+1)^=' ') then + (p-1)^:=#0; + end; + end; +end; + +{ +function GetTotalTime:integer; +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + result:=v.Length; + except + result:=inherited GetTotalTime; + end; + v:=Null; +end; + +function GetElapsedTime:integer; +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + result:=v.Time; + except + result:=inherited GetElapsedTime; + end; + v:=Null; +end; + +function GetStatus:integer; cdecl; +var + v:variant; + tmp:boolean; +begin + try + v:=CreateOleObject(COMName); + tmp:=v.Playing; + if tmp then + result:=WAT_MES_PLAYING + else + result:=WAT_MES_STOPPED; + except + result:=inherited GetStatus; + end; + v:=Null; +end; + +function Play(fname:PWideChar=nil):integer; +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + result:=v.play; + except + result:=inherited Play(fname); + end; + v:=Null; +end; + +function Pause:integer; +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + result:=v.pause; + except + result:=inherited Pause; + end; + v:=Null; +end; + +function Stop:integer; +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + result:=v.stop; + except + result:=inherited Stop; + end; + v:=Null; +end; + +function Next:integer; +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + result:=v.playlistNext; + except + result:=inherited Next; + end; + v:=Null; +end; + +function Prev:integer; +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + result:=v.playlistPrev; + except + result:=inherited Prev; + end; + v:=Null; +end; + +function Seek(value:integer):integer; +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + result:=v.Position; + if value>0 then + v.Position:=value + else + result:=0; + except + result:=inherited Seek(value); + end; + v:=Null; +end; + +function GetVolume:cardinal; +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + result:=v.Volume; + result:=(result shl 16)+((result shl 4) div 100); + except + result:=0; + end; + v:=Null; +end; + +procedure SetVolume(value:cardinal); +var + v:variant; +begin + try + v:=CreateOleObject(COMName); + v.Volume:=(value*100) shr 4; + end; + except + result:=inherited SetVolume(value); + end; + v:=Null; +end; + +function VolDn:integer; +var + val:integer; +begin + result:=GetVolume; + val:=loword(result); + if val>0 then + SetVolume(val-1); +end; + +function VolUp:integer; +var + val:integer; +begin + result:=GetVolume; + val:=loword(result); + if val<16 then + SetVolume(val+1); +end; + +} +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +var + v:variant; +begin + result:=0; + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if SongInfo.plyver=0 then + begin + try + try + v:=CreateOleObject(COMName); + except + try + v:=CreateOleObject(COMNameNew); + except + v:=Null; + end; + end; + if v<>Null then + with SongInfo do + begin + txtver:=GetVersionText(v); + plyver:=GetVersion(txtver); + end; + except + end; + v:=Null; + if (flags and WAT_OPT_CHANGES)<>0 then + SongInfo.wndtext:=GetWndText(SongInfo.plwnd); + end; + end; +end; +{ +function Command(wnd:HWND;cmd:integer;value:integer):integer;cdecl; +begin + result:=0; + case cmd of + WAT_CTRL_PREV : result:=Prev; + WAT_CTRL_PLAY : result:=Play(pWideChar(value)); + WAT_CTRL_PAUSE: result:=Pause; + WAT_CTRL_STOP : result:=Stop; + WAT_CTRL_NEXT : result:=Next; + WAT_CTRL_VOLDN: result:=VolDn; + WAT_CTRL_VOLUP: result:=VolUp; + WAT_CTRL_SEEK : result:=Seek(value); + end; +end; +} +const + plRec:tPlayerCell=( + Desc :'VideoLAN player'; + flags :WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:nil; + GetName :nil; + GetInfo :@GetInfo; + Command :nil; + URL :'http://www.videolan.org/'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_winamp.pas b/plugins/Watrack/players/pl_winamp.pas new file mode 100644 index 0000000000..254475e09a --- /dev/null +++ b/plugins/Watrack/players/pl_winamp.pas @@ -0,0 +1,170 @@ +{Winamp-like - base class} +unit pl_WinAmp; +{$include compilers.inc} + +interface + +implementation + +uses winampapi,windows,common,messages,syswin,srv_player,wat_api; + +{ +#define IPC_GETPLAYLISTTITLE 212 +/* (requires Winamp 2.04+, only usable from plug-ins (not external apps)) +** char *name=SendMessage(hwnd_winamp,WM_WA_IPC,index,IPC_GETPLAYLISTTITLE); +** +** IPC_GETPLAYLISTTITLE gets the title of the playlist entry [index]. +** returns a pointer to it. returns NULL on error. +*/ +} +// class = BaseWindow_RootWnd +// title = Main Window + +// ---------- check player ------------ + +function Check(wnd:HWND;aflags:integer):HWND;cdecl; +var + tmp,EXEName:PAnsiChar; +begin + result:=FindWindowEx(0,wnd,WinampClass,NIL); + if result<>0 then + begin + tmp:=Extract(GetEXEByWnd(result,EXEName),true); + if lstrcmpia(tmp,'WINAMP.EXE')<>0 then + result:=0; + mFreeMem(tmp); + mFreeMem(EXEName); + end; +end; + +function WAnyCheck(wnd:HWND;aflags:integer):HWND;cdecl; +begin + result:=FindWindowEx(0,wnd,WinampClass,NIL); +end; + +// ----------- Get info ------------ + +function GetStatus(wnd:HWND):integer; cdecl; +begin + result:=WinampGetStatus(wnd) +end; + +function GetWidth(wnd:HWND):integer; +begin + result:=LOWORD(SendMessage(wnd,WM_WA_IPC,3,IPC_GETINFO)); +end; + +function GetHeight(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_WA_IPC,3,IPC_GETINFO) shr 16; +end; + +function GetInfo(var SongInfo:tSongInfo;aflags:integer):integer;cdecl; +begin + SongInfo.winampwnd:=SongInfo.plwnd; + result:=WinampGetInfo(int_ptr(@SongInfo),aflags); + with SongInfo do + begin + if (aflags and WAT_OPT_CHANGES)<>0 then + wndtext:=WinampGetWindowText(winampwnd) + else + begin +{ + if ((loword(plyver) shr 12)>=5) and + (SendMessage(wnd,WM_WA_IPC,0,IPC_IS_PLAYING_VIDEO)>1) then + begin + if width =0 then width :=GetWidth(wnd); + if height=0 then Height:=GetHeight(wnd); + end; +} + end; + end; +end; + +// ------- Commands ---------- + +function Command(wnd:HWND;cmd:integer;value:integer):integer;cdecl; +begin + result:=WinampCommand(wnd,cmd+(value shl 16)); +end; + +// ------- In-process code ------- + +function GetFileName(wnd:HWND;flags:integer):pWideChar;cdecl; +var + fpos,fname:int_ptr; + pid:dword; + op:THANDLE; + buf:array [0..1023] of AnsiChar; + tmp:{$IFDEF FPC}LongWord{$ELSE}ulong_ptr{$ENDIF}; +begin + result:=nil; + if (flags and WAT_OPT_IMPLANTANT)<>0 then + begin + if SendMessage(wnd,WM_WA_IPC,0,IPC_ISPLAYING)<>WAT_MES_STOPPED then + begin + fpos :=SendMessage(wnd,WM_USER,0 ,IPC_GETLISTPOS); + fname:=SendMessage(wnd,WM_USER,fpos,IPC_GETPLAYLISTFILE); + GetWindowThreadProcessId(wnd,@pid); + op:=OpenProcess(PROCESS_VM_READ,false,pid); + if op<>0 then + begin + ReadProcessMemory(op,PByte(fname),@buf,SizeOf(buf),tmp); + CloseHandle(op); + if tmp>0 then + AnsiToWide(buf,result); + end; + end; + end; +end; + +const + plRec:tPlayerCell=( + Desc :'Winamp'; + flags :WAT_OPT_ONLYONE or WAT_OPT_WINAMPAPI or WAT_OPT_HASURL; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:@GetStatus; + GetName :@GetFileName; + GetInfo :@GetInfo; + Command :@Command; + URL :'http://www.winamp.com/'; + Notes :nil); + +const + plRecClone:tPlayerCell=( + Desc :'Winamp Clone'; + flags :WAT_OPT_ONLYONE or WAT_OPT_WINAMPAPI or WAT_OPT_LAST; + Icon :0; + Init :nil; + DeInit :nil; + Check :@WAnyCheck; + GetStatus:@GetStatus; + GetName :nil; + GetInfo :@WinampGetInfo; + Command :@Command; + URL :nil; + Notes :'All "unknown" players using Winamp API'); + +var + LocalPlayerLink, + LocalPlayerLinkC:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; + + LocalPlayerLinkC.Next:=PlayerLink; + LocalPlayerLinkC.This:=@plRecClone; + PlayerLink :=@LocalPlayerLinkC; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRecClone)); + InitLink; +end. diff --git a/plugins/Watrack/players/pl_wmp.pas b/plugins/Watrack/players/pl_wmp.pas new file mode 100644 index 0000000000..971cb28ac6 --- /dev/null +++ b/plugins/Watrack/players/pl_wmp.pas @@ -0,0 +1,128 @@ +{Windows Media Player} +unit pl_WMP; +{$include compilers.inc} + +interface + +implementation +uses windows,common,messages,srv_player,wat_api + {$IFDEF DELPHI_7_UP} + ,variants + {$ENDIF} + {$IFDEF KOL_MCK} + ,kolcomobj + {$ELSE} + ,ComObj + {$ENDIF} +; + +const + WMPOld:boolean=false; + +const +// CLASS_MP :TGUID = '{22D6F312-B0F6-11D0-94AB-0080C74C7E95}'; +// CLASS_WMP:TGUID = '{6BF52A52-394A-11D3-B153-00C04F79FAA6}'; CLASS_WindowsMediaPlayer + MPCOMName = 'MediaPlayer.MediaPlayer.1'; + WMPCOMName = 'WMPlayer.OCX.7'; +const + MPClass = 'Media Player 2'; + WMPClass = 'WMPlayerApp'; + +function Check(wnd:HWND;flags:integer):HWND;cdecl; +begin + result:=FindWindowEx(0,wnd,MPClass,NIL); + if result=0 then + begin + result:=FindWindowEx(0,wnd,WMPClass,NIL); //? + WMPOld:=false; + end + else + WMPOld:=true; +end; + +{ Version detect + fHasWMP64 = (WMP64.FileName="") ' WMP64 was create above via OBJECT tag else this returns False. + fHasWMP7 = (WMP7.URL = "") ' WMP7 or later was create above via OBJECT tag else this returns False. +} + +const + MPVersion:PWideChar = '6.4'; + +function GetVersionText(flags:integer):PWideChar; +var + v:variant; +begin + if WMPOld then + StrDupW(result,MPVersion) + else + begin + try + v:=CreateOleObject(WMPCOMName); + StrDupW(result,pWideChar(Widestring(v.versionInfo))); + except + result:=nil; + end; +// VarClear(v); + v:=Null; + end; +end; + +function GetInfo(var SongInfo:tSongInfo;flags:integer):integer;cdecl; +begin + result:=0; + if (flags and WAT_OPT_PLAYERDATA)<>0 then + begin + if SongInfo.txtver=nil then + SongInfo.txtver:=GetVersionText(flags); + end; +end; + +{ +function Command(wnd:HWND;cmd:integer;value:integer):integer;cdecl; +var + c:integer; +begin + result:=0; + case cmd of +// WAT_CTRL_PREV : c:=VK_B; +// WAT_CTRL_PLAY : c:=VK_C; +// WAT_CTRL_PAUSE: c:=VK_X; +// WAT_CTRL_STOP : c:=VK_Z; +// WAT_CTRL_NEXT : c:=VK_V; + WAT_CTRL_VOLDN: c:=VK_F9; + WAT_CTRL_VOLUP: c:=VK_F10; + else + exit; + end; + PostMessageW(wnd,WM_KEYDOWN,c,1); +end; +} +const + plRec:tPlayerCell=( + Desc :'WMP'; + flags :WAT_OPT_APPCOMMAND or WAT_OPT_SINGLEINST; + Icon :0; + Init :nil; + DeInit :nil; + Check :@Check; + GetStatus:nil; + GetName :nil; + GetInfo :@GetInfo; + Command :nil; + URL :'http://www.microsoft.com/windows/windowsmedia/players.aspx'; + Notes :nil); + +var + LocalPlayerLink:twPlayer; + +procedure InitLink; +begin + LocalPlayerLink.Next:=PlayerLink; + LocalPlayerLink.This:=@plRec; + PlayerLink :=@LocalPlayerLink; +end; + +initialization +// ServicePlayer(WAT_ACT_REGISTER,dword(@plRec)); + InitLink; +end. diff --git a/plugins/Watrack/plugins/watrack_mpd/Makefile b/plugins/Watrack/plugins/watrack_mpd/Makefile new file mode 100644 index 0000000000..02c89bd6d3 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/Makefile @@ -0,0 +1,12 @@ +all: + i686-pc-mingw32-gcc -c -DBUILD_DLL -D UNICODE -D _UNICODE *.c -I../../include -I/usr/i686-pc-mingw32/usr/include -I. -w -mwin32 -mwindows -mdll -march=i686 -msse -O2 -pipe + i686-pc-mingw32-windres -i watrack_mpd.rc -o resources.o + i686-pc-mingw32-gcc -shared -o watrack_mpd.dll *.o -Wl,-O1,-s + upx -9 watrack_mpd.dll + +clean: + rm *.o + +clean-all: + rm *.o *.dll + diff --git a/plugins/Watrack/plugins/watrack_mpd/res/watrack_mpd.rc b/plugins/Watrack/plugins/watrack_mpd/res/watrack_mpd.rc new file mode 100644 index 0000000000..17aaad10e4 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/res/watrack_mpd.rc @@ -0,0 +1,112 @@ +// Microsoft Visual C++ generated resource script. +// +#include "src/resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Russian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS) +#ifdef _WIN32 +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT +#pragma code_page(1251) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Russian resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT_WA_MPD DIALOGEX 0, 0, 268, 214 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +FONT 8, "MS Shell Dlg", 400, 0, 0x0 +BEGIN + EDITTEXT IDC_SERVER,71,18,72,14,ES_AUTOHSCROLL + EDITTEXT IDC_PORT,72,38,72,14,ES_AUTOHSCROLL + EDITTEXT IDC_PASSWORD,71,58,73,14,ES_PASSWORD | ES_AUTOHSCROLL + LTEXT "MPD Host",IDC_STATIC,7,20,32,8 + LTEXT "Port",IDC_STATIC,7,42,14,8 + LTEXT "Password",IDC_STATIC,7,63,32,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPT_WA_MPD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 261 + TOPMARGIN, 7 + BOTTOMMARGIN, 207 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/plugins/Watrack/plugins/watrack_mpd/src/commonheaders.h b/plugins/Watrack/plugins/watrack_mpd/src/commonheaders.h new file mode 100644 index 0000000000..85eb73a335 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/commonheaders.h @@ -0,0 +1,43 @@ +// Copyright © 2008 sss, chaos.persei +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public 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 COMMONHEADERS_H +#define COMMONHEADERS_H +#include +#include +#include +#include + + +#define MIRANDA_VER 0x0800 +#include +#include +//#include +//#include +#include +//#include +//#include +//#include +#include +#include + +#include "resource.h" + +#include "constants.h" +#include "globals.h" +#include "main.h" +#include "m_music.h" +#include "utilities.h" +#endif diff --git a/plugins/Watrack/plugins/watrack_mpd/src/constants.h b/plugins/Watrack/plugins/watrack_mpd/src/constants.h new file mode 100644 index 0000000000..2ac58a4d43 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/constants.h @@ -0,0 +1,4 @@ +#ifndef CONSTANTS_H +#define CONSTANTS_H +#define szModuleName "Watrack_MPD" +#endif diff --git a/plugins/Watrack/plugins/watrack_mpd/src/globals.h b/plugins/Watrack/plugins/watrack_mpd/src/globals.h new file mode 100644 index 0000000000..edc5bd10c3 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/globals.h @@ -0,0 +1,11 @@ +#ifndef GLOBALS_H +#define GLOBALS_H +HANDLE ghNetlibUser; +HANDLE ghConnection; +HANDLE ghPacketReciever; +BOOL bWatrackService; +TCHAR *gbHost, *gbPassword; +WORD gbPort; +BOOL Connected; +int gbState; +#endif diff --git a/plugins/Watrack/plugins/watrack_mpd/src/init.c b/plugins/Watrack/plugins/watrack_mpd/src/init.c new file mode 100644 index 0000000000..4d4f9eba29 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/init.c @@ -0,0 +1,112 @@ +// Copyright © 2009-2010 sss +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public 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 "commonheaders.h" + + +#define PLUGIN_NAME "Watrack_MPD" + +HINSTANCE hInst; +BOOL bWatrackService = FALSE; +int hLangpack = 0; +static int OnModulesLoaded(WPARAM wParam,LPARAM lParam); +extern char *date(); +extern int WaMpdOptInit(WPARAM wParam,LPARAM lParam); + + +PLUGININFOEX pluginInfo={ + sizeof(PLUGININFOEX), + 0, + PLUGIN_MAKE_VERSION(0,0,0,4), + "Music Player Daemon support for watrack", + "sss, others..", + "sss123next@list.ru", + "© 2009 sss, others...", + "http://sss.chaoslab.ru:81/tracker/mim_plugs/", + 1, //unicode + { 0x692e87d0, 0x6c71, 0x4cdc, { 0x9e, 0x36, 0x2b, 0x2d, 0x69, 0xfb, 0xdc, 0x4c } } + +}; + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + hInst=hinstDLL; + return TRUE; +} + +__declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + { + static char plugname[52]; + strcpy(plugname, PLUGIN_NAME" ["); + strcat(plugname, date()); + strcat(plugname, " "); + strcat(plugname, __TIME__); + strcat(plugname, "]"); + pluginInfo.shortName = plugname; + } + return &pluginInfo; +} + +static const MUUID interfaces[] = {MIID_SERVICEMODE, MIID_LAST}; +__declspec(dllexport) const MUUID* MirandaPluginInterfaces(void) +{ + return interfaces; +} + +int __declspec(dllexport) Load() +{ + mir_getLP(&pluginInfo); + HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + return 0; +} + +void InitVars() +{ + gbPort = DBGetContactSettingWord(NULL, szModuleName, "Port", 6600); + gbPassword = (TCHAR*)malloc(64*sizeof(TCHAR)); + gbHost = (TCHAR*)malloc(128*sizeof(TCHAR)); + gbHost = UniGetContactSettingUtf(NULL, szModuleName, "Server", _T("127.0.0.1")); + gbPassword = UniGetContactSettingUtf(NULL, szModuleName, "Password", _T("")); +} + + +extern void RegisterPlayer(); +static int OnModulesLoaded(WPARAM wParam,LPARAM lParam) +{ + HANDLE hHookOptionInit; + NETLIBUSER nlu = {0}; + nlu.cbSize = sizeof(nlu); + nlu.flags = (NUF_OUTGOING | NUF_HTTPCONNS); + nlu.szDescriptiveName = "Watrack MPD connection"; + nlu.szSettingsModule = PLUGIN_NAME; + ghNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu); + InitVars(); + hHookOptionInit = HookEvent(ME_OPT_INITIALISE, WaMpdOptInit); + if (ServiceExists("WATrack/Player")) + bWatrackService = TRUE; + RegisterPlayer(); + + return 0; +} + + +int __declspec(dllexport) Unload(void) +{ + free(gbHost); + free(gbPassword); + return 0; +} diff --git a/plugins/Watrack/plugins/watrack_mpd/src/m_music.h b/plugins/Watrack/plugins/watrack_mpd/src/m_music.h new file mode 100644 index 0000000000..4b33881f06 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/m_music.h @@ -0,0 +1,355 @@ +#ifndef M_MUSIC +#define M_MUSIC + +#define MIID_WATRACK {0xfc6c81f4, 0x837e, 0x4430, {0x96, 0x01, 0xa0, 0xaa, 0x43, 0x17, 0x7a, 0xe3}} + +typedef struct tSongInfoA { + char *artist; + char *title; + char *album; + char *genre; + char *comment; + char *year; + char *mfile; // media file + int kbps; + int khz; + int channels; + int track; + int total; // music length + int time; // elapsed time + char *wndtext; // window title + char *player; // player name + int plyver; // player version + HANDLE icon; // player icon + int fsize; // media file size + int vbr; + int status; // player status: 0 - stopped; 1 - playing; 2 - paused + HWND plwnd; // player window + // video part + int codec; + int width; + int height; + int fps; + __int64 date; + char *txtver; + char *lyric; + char *cover; + int volume; + char *url; +} SONGINFOA, *LPSONGINFOA; + +typedef struct tSongInfo { + wchar_t *artist; + wchar_t *title; + wchar_t *album; + wchar_t *genre; + wchar_t *comment; + wchar_t *year; + wchar_t *mfile; // media file + int kbps; + int khz; + int channels; + int track; + int total; // music length + int time; // elapsed time + wchar_t *wndtext; // window title + wchar_t *player; // player name + int plyver; // player version + HANDLE icon; // player icon + int fsize; // media file size + int vbr; + int status; // player status: 0 - stopped; 1 - playing; 2 - paused + HWND plwnd; // player window + // video part + int codec; + int width; + int height; + int fps; + __int64 date; + wchar_t *txtver; + // not implemented yet + wchar_t *lyric; + wchar_t *cover; + int volume; + wchar_t *url; +} SONGINFO, *LPSONGINFO; + +#if defined(_UNICODE) + #define WAT_INF_TCHAR WAT_INF_UNICODE + #define SongInfoT tSongInfo +#else + #define WAT_INF_TCHAR WAT_INF_ANSI + #define SongInfoT tSongInfoA +#endif + + // result codes +#define WAT_RES_UNKNOWN -2 +#define WAT_RES_NOTFOUND -1 +#define WAT_RES_ERROR WAT_RES_NOTFOUND +#define WAT_RES_OK 0 +#define WAT_RES_ENABLED WAT_RES_OK +#define WAT_RES_DISABLED 1 + // internal +#define WAT_RES_NEWFILE 3 + +#define WAT_PLS_NORMAL WAT_RES_OK +#define WAT_PLS_NOMUSIC WAT_RES_DISABLED +#define WAT_PLS_NOTFOUND WAT_RES_NOTFOUND + +#define WAT_INF_UNICODE 0 +#define WAT_INF_ANSI 1 +#define WAT_INF_UTF8 2 +#define WAT_INF_CHANGES 0x100 + +/* + wParam : WAT_INF_* constant + lParam : pointer to LPSONGINGO (Unicode) or LPSONGINFOA (ANSI/UTF8) + Affects: Fill structure by currently played music info + returns: WAT_PLS_* constant + note: pointer will be point to global SONGINFO structure of plugin + warning: Non-Unicode data filled only by request + if lParam=0 only internal SongInfo structure will be filled + Example: + LPSONGINFO p; + PluginLink->CallService(MS_WAT_GETMUSICINFO,0,(DWORD)&p); +*/ + +#define MS_WAT_GETMUSICINFO "WATrack/GetMusicInfo" + +/* + wParam:0 + lParam : pointer to pSongInfo (Unicode) + Affects: Fill structure by info from file named in SongInfo.mfile + returns: 0, if success + note: fields, which values can't be obtained, leaves old values. + you must free given strings by miranda mmi.free +*/ +#define MS_WAT_GETFILEINFO "WATrack/GetFileInfo" + +/* + wParam: encoding (WAT_INF_* consts, 0 = WAT_INF_UNICODE) + lParam: codepage (0 = ANSI) + Returns Global unicode SongInfo pointer or tranlated to Ansi/UTF8 structure +*/ +#define MS_WAT_RETURNGLOBAL "WATrack/GetMainStructure" + +#define WAT_CTRL_PREV 1 +#define WAT_CTRL_PLAY 2 +#define WAT_CTRL_PAUSE 3 +#define WAT_CTRL_STOP 4 +#define WAT_CTRL_NEXT 5 +#define WAT_CTRL_VOLDN 6 +#define WAT_CTRL_VOLUP 7 +#define WAT_CTRL_SEEK 8 // lParam is new position (sec) +/* + wParam: button code (WAT_CTRL_* const) + lParam: 0, or value (see WAT_CTRL_* const comments) + Affects: emulate player button pressing + returns: 0 if unsuccesful +*/ +#define MS_WAT_PRESSBUTTON "WATrack/PressButton" + +/* + Get user's Music Info +*/ +#define MS_WAT_GETCONTACTINFO = "WATrack/GetContactInfo" + +// ------------ Plugin/player status ------------ + +/* + wParam: 1 - switch off plugin + 0 - switch on plugin + -1 - switch plugin status + 2 - get plugin version + other - get plugin status + lParam: 0 + Affects: Switch plugin status to enabled or disabled + returns: version, old plugin status, 0, if was enabled +*/ + +#define MS_WAT_PLUGINSTATUS "WATrack/PluginStatus" + +#define ME_WAT_MODULELOADED "WATrack/ModuleLoaded" + +#define WAT_EVENT_PLAYERSTATUS 1 // 0-normal; 1-no music (possibly stopped); 2-not found +#define WAT_EVENT_NEWTRACK 2 +#define WAT_EVENT_PLUGINSTATUS 3 // 0-enabled; 1-dis.temporary; 2-dis.permanent +#define WAT_EVENT_NEWPLAYER 4 // +#define WAT_EVENT_NEWTEMPLATE 5 // TM_* constant + +/* + Plugin or player status changed: + wParam: type of event (see above) + lParam: value +*/ +#define ME_WAT_NEWSTATUS "WATrack/NewStatus" + +// ---------- Popup module ------------ + +/* + wParam: not used + lParam: not used + Affects: Show popup or Info window with current music information + note: Only Info window will be showed if Popup plugin disabled +*/ + +#define MS_WAT_SHOWMUSICINFO "WATrack/ShowMusicInfo" + +// --------- Statistic (report) module ------------- + +/* + wParam: pointer to log file name or NULL + lParam: pointer to report file name or NULL + Affects: Create report from log and run it (if option is set) + returns: 0 if unsuccesful + note: if wParam or lParam is a NULL then file names from options are used +*/ +#define MS_WAT_MAKEREPORT "WATrack/MakeReport" + +/* + wParam, lParam - not used + Affects: pack statistic file +*/ +#define MS_WAT_PACKLOG = "WATrack/PackLog" + +/* + wParam: not used + lParam: pointer to SongInfo +*/ +#define MS_WAT_ADDTOLOG = "WATrack/AddToLog" + +// ----------- Formats and players ----------- + +// media file status + +#define WAT_MES_STOPPED 0 +#define WAT_MES_PLAYING 1 +#define WAT_MES_PAUSED 2 +#define WAT_MES_UNKNOWN -1 + +#define WAT_ACT_REGISTER 1 +#define WAT_ACT_UNREGISTER 2 +#define WAT_ACT_DISABLE 3 +#define WAT_ACT_ENABLE 4 +#define WAT_ACT_GETSTATUS 5 // not found/enabled/disabled +#define WAT_ACT_SETACTIVE 6 +#define WAT_ACT_REPLACE 0x10000 // can be combined with WAT_REGISTERFORMAT + + // flags +#define WAT_OPT_DISABLED 0x00000001 // format registered but disabled +#define WAT_OPT_ONLYONE 0x00000002 // format can't be overwriten +#define WAT_OPT_PLAYERINFO 0x00000004 // song info from player +#define WAT_OPT_WINAMPAPI 0x00000008 // Winamp API support +#define WAT_OPT_CHECKTIME 0x00000010 // check file time for changes +#define WAT_OPT_VIDEO 0x00000020 // only for format registering used +#define WAT_OPT_LAST 0x00000040 // (internal) +#define WAT_OPT_FIRST 0x00000080 // (internal) +#define WAT_OPT_TEMPLATE 0x00000100 // (internal) +#define WAT_OPT_IMPLANTANT 0x00000200 // use process implantation +#define WAT_OPT_HASURL 0x00000400 // (player registration) URL field present +#define WAT_OPT_CHANGES 0x00000800 // obtain only chaged values + // (volume, status, window text, elapsed time) +#define WAT_OPT_APPCOMMAND 0x00001000 // Special (multimedia) key support +#define WAT_OPT_CHECKALL 0x00002000 // Check all players +#define WAT_OPT_KEEPOLD 0x00004000 // Keep Old opened file +#define WAT_OPT_MULTITHREAD 0x00008000 // Use multithread scan +#define WAT_OPT_SINGLEINST 0x00010000 // Single player instance + + +typedef BOOL (__cdecl *LPREADFORMATPROC)(LPSONGINFO Info); + +typedef struct tMusicFormat { + LPREADFORMATPROC proc; + char ext[8]; + int flags; +} MUSICFORMAT, *LPMUSICFORMAT; + +/* + wParam: action + lParam: pointer to MUSICFORMAT if wParam = WAT_ACT_REGISTER, + else - pointer to extension string (ANSI) + returns: see result codes +*/ + +#define MS_WAT_FORMAT "WATrack/Format" + +/* + wParam - pointer to SONGINFO structure (plwind field must be initialized) + lParam - flags +*/ + +#define MS_WAT_WINAMPINFO "WATrack/WinampInfo" + +/* + wParam: window + lParam: LoWord - command; HiWord - value +*/ + +#define MS_WAT_WINAMPCOMMAND "WATrack/WinampCommand" + +int tInitProc(); +int tDeInitProc(); +int tStatusProc(); + +typedef int (__cdecl *LPINITPROC)(); +typedef int (__cdecl *LPDEINITPROC)(); +typedef int (__cdecl *LPSTATUSPROC)(HWND wnd); +typedef wchar_t (__cdecl *LPNAMEPROC)(HWND wnd, int flags); +typedef HWND (__cdecl *LPCHECKPROC)(HWND wnd, int flags); +typedef int (__cdecl *LPGETSTATUSPROC) (HWND wnd); +typedef int (__cdecl *LPINFOPROC)(LPSONGINFO Info, int flags); +typedef int (__cdecl *LPCOMMANDPROC)(HWND wnd, int command, int value); + +typedef struct tPlayerCell { + char *Desc; + int flags; + HICON Icon; // can be 0. for registration only + LPINITPROC Init; + LPDEINITPROC DeInit; + LPCHECKPROC Check; // check player + LPGETSTATUSPROC GetStatus; + LPNAMEPROC GetName; // can be NULL. get media filename + LPINFOPROC GetInfo; // can be NULL. get info from player + LPCOMMANDPROC Command; // can be NULL. send command to player + char *URL; // only if WAT_OPT_HASURL flag present + wchar_t *Notes; +} PLAYERCELL, *LPPLAYERCELL; + +/* + wParam: action + lParam: pointer to PLAYERCELL if wParam = WAT_ACT_REGISTER, + else - pointer to player description string (ANSI) + returns: player window handle or value>0 if found + note: If you use GetName or GetInfo field, please, do not return empty + filename even when mediafile is remote! +*/ + +#define MS_WAT_PLAYER "WATrack/Player" + +// --------- Templates ---------- + +/* + wParam: not used + lParam: Unicode template + returns: New Unicode (replaced) string +*/ +#define MS_WAT_REPLACETEXT "WATrack/ReplaceText" + +/* + event types for History + Blob structure for EVENTTYPE_WAT_ANSWER: + Uniciode artist#0title#0album#0answer +*/ +#define EVENTTYPE_WAT_REQUEST 9601 +#define EVENTTYPE_WAT_ANSWER 9602 +#define EVENTTYPE_WAT_ERROR 9603 +#define EVENTTYPE_WAT_MESSAGE 9604 + +/* + wParam: 0 or parent window + lParam: 0 + note: Shows Macro help window with edit aliases ability +*/ +#define MS_WAT_MACROHELP "WATrack/MacroHelp" + +#endif diff --git a/plugins/Watrack/plugins/watrack_mpd/src/main.c b/plugins/Watrack/plugins/watrack_mpd/src/main.c new file mode 100644 index 0000000000..17a8c29d64 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/main.c @@ -0,0 +1,433 @@ +// Copyright © 2008 sss, chaos.persei +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public 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 "commonheaders.h" + + +//maybe add mutex ? +void Start(void *param); +int Parser(); + +LPINITPROC Init() +{ + mir_forkthread(&Start, 0); + return 0; +} +void Stop(); +LPDEINITPROC DeInit() +{ + Stop(); + return 0; +} +LPCHECKPROC CheckPlayer(HWND wnd, int flags) +{ + if(!ghConnection) + { + mir_forkthread(&Start, 0); + return 0; + } + if(Parser()) + return (LPCHECKPROC)WAT_MES_STOPPED; + if(Connected) + return (LPCHECKPROC)WAT_MES_PLAYING; + return 0; +} +LPGETSTATUSPROC GetStatus() +{ + if(!ghConnection) + { + mir_forkthread(&Start, 0); + return 0; + } + if(Parser()) + return (LPGETSTATUSPROC)-1; + return (LPGETSTATUSPROC)(gbState); +} +LPNAMEPROC GetFileName(HWND wnd, int flags) +{ + if(!ghConnection) + { + mir_forkthread(&Start, 0); + return 0; + } + return 0; +} +SONGINFO SongInfo = {0}; + +LPINFOPROC GetPlayerInfo(LPSONGINFO info, int flags) +{ + if(!ghConnection) + { + mir_forkthread(&Start, 0); + return 0; + } + if(Parser()) + return (LPINFOPROC)-1; +/* + + info->channels = SongInfo.channels; + info->codec = SongInfo.codec; + info->comment = SongInfo.comment; + info->cover = SongInfo.cover; + info->date = SongInfo.date; + info->fps = SongInfo.fps; + info->fsize = SongInfo.fsize; + + info->icon = SongInfo.icon; + info->kbps = SongInfo.kbps; + info->khz = SongInfo.khz; + info->lyric = SongInfo.lyric; + info->mfile = SongInfo.mfile; + info->player = SongInfo.player; + info->plyver = SongInfo.plyver; + info->status = SongInfo.status; + info->time = SongInfo.time; + info->title = SongInfo.title; + info->total = SongInfo.total; + info->track = SongInfo.track;*/ + info->total = SongInfo.total; + info->time = SongInfo.time; + info->mfile = SongInfo.mfile; + info->txtver = SongInfo.txtver; + info->title = SongInfo.title; + info->artist = SongInfo.artist; + info->genre = SongInfo.genre; + info->album = SongInfo.album; + info->year = SongInfo.year; + info->kbps = SongInfo.kbps; + info->track = SongInfo.track; + info->khz = SongInfo.khz; + info->volume = SongInfo.volume; +/* info->url = SongInfo.url; //?? + info->vbr = SongInfo.vbr; + info->volume = SongInfo.volume; + */ + return 0; +} +LPCOMMANDPROC SendCommand(HWND wnd, int command, int value) +{ + switch (command) + { + case WAT_CTRL_PREV: + Netlib_Send(ghConnection, "previous\n", strlen("previous\n"), 0); + break; + case WAT_CTRL_PLAY: //add resuming support + if(gbState != WAT_MES_PAUSED) + Netlib_Send(ghConnection, "play\n", strlen("play\n"), 0); + else + Netlib_Send(ghConnection, "pause 0\n", strlen("pause 0\n"), 0); + break; + case WAT_CTRL_PAUSE: + Netlib_Send(ghConnection, "pause 1\n", strlen("pause 1\n"), 0); + break; + case WAT_CTRL_STOP: + Netlib_Send(ghConnection, "stop\n", strlen("stop\n"), 0); + break; + case WAT_CTRL_NEXT: + Netlib_Send(ghConnection, "next\n", strlen("next\n"), 0); + break; + case WAT_CTRL_VOLDN: + break; + case WAT_CTRL_VOLUP: + break; + case WAT_CTRL_SEEK: + break; + default: + break; + } + return 0; +} + + +void RegisterPlayer() +{ + if(!bWatrackService) + return; + { + PLAYERCELL player = {0}; + player.Desc = "Music Player Daemon"; + player.Check = (LPCHECKPROC)CheckPlayer; + player.Init = (LPINITPROC)Init; + player.DeInit = (LPDEINITPROC)DeInit; + player.GetStatus = (LPGETSTATUSPROC)GetStatus; + player.Command = (LPCOMMANDPROC)SendCommand; + player.flags = (WAT_OPT_HASURL|WAT_OPT_SINGLEINST|WAT_OPT_PLAYERINFO); + player.GetName = (LPNAMEPROC)GetFileName; + player.GetInfo = (LPINFOPROC)GetPlayerInfo; +// player.Icon = //TODO:implement icon support + player.Notes = _T("mpd is a nice music player for *nix which have not any gui, just daemon.\nuses very small amount of ram, cpu."); + player.URL = "http://www.musicpd.org"; + CallService(MS_WAT_PLAYER, (WPARAM)WAT_ACT_REGISTER, (LPARAM)&player); + } +} +void ReStart(void *data); +int Parser() +{ + static NETLIBPACKETRECVER nlpr = {0}; + char *ptr; + char tmp[256]; + int i; + char *buf; + static char ver[16]; + nlpr.cbSize = sizeof(nlpr); + nlpr.dwTimeout = 5; + if(!ghConnection) + { + mir_forkthread(&Start, 0); + } + if(ghConnection) + { + int recvResult; +/* do + { + recvResult = CallService(MS_NETLIB_GETMOREPACKETS,(WPARAM)ghPacketReciever, (LPARAM)&nlpr); + if(recvResult == SOCKET_ERROR) + { + ReStart(); + return 1; + } + } + while(recvResult > 0);*/ + if(!Connected) + { + char tmp[128]; + char *tmp2 = mir_t2a(gbPassword); + recvResult = CallService(MS_NETLIB_GETMOREPACKETS,(WPARAM)ghPacketReciever, (LPARAM)&nlpr); + if(recvResult == SOCKET_ERROR) + { + mir_forkthread(&ReStart, 0); +// ReStart(); + return 1; + } + if(strlen(tmp2) > 2) + { + strcpy(tmp, "password "); + strcat(tmp, tmp2); + strcat(tmp, "\n"); + Netlib_Send(ghConnection, tmp, strlen(tmp), 0); + recvResult = CallService(MS_NETLIB_GETMOREPACKETS,(WPARAM)ghPacketReciever, (LPARAM)&nlpr); + if(recvResult == SOCKET_ERROR) + { + mir_forkthread(&ReStart, 0); + return 1; + } + } + mir_free(tmp2); + } + Netlib_Send(ghConnection, "status\n", strlen("status\n"), 0); + recvResult = CallService(MS_NETLIB_GETMOREPACKETS,(WPARAM)ghPacketReciever, (LPARAM)&nlpr); + if(recvResult == SOCKET_ERROR) + { + mir_forkthread(&ReStart, 0); + return 1; + } + Netlib_Send(ghConnection, "currentsong\n", strlen("currentsong\n"), 0); + recvResult = CallService(MS_NETLIB_GETMOREPACKETS,(WPARAM)ghPacketReciever, (LPARAM)&nlpr); + if(recvResult == SOCKET_ERROR) + { + mir_forkthread(&ReStart, 0); + return 1; + } + nlpr.bytesUsed = nlpr.bytesAvailable; + } + buf = nlpr.buffer; + if(ptr = strstr(buf, "MPD")) + { + Connected = TRUE; + ptr = &ptr[4]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + strcpy(ver, tmp); + SongInfo.txtver = (TCHAR*)mir_utf8decodeW(tmp); + } + else + SongInfo.txtver = (TCHAR*)mir_utf8decodeW(ver); + if(ptr = strstr(buf, "file:")) + { + ptr = &ptr[6]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.mfile = (TCHAR*)mir_utf8decodeW(tmp); + } + else + SongInfo.mfile = _T(""); + if(ptr = strstr(buf, "Time:")) + { + ptr = &ptr[6]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.total = atoi(tmp); + } + else if(!SongInfo.total) + SongInfo.total = 0; + if(ptr = strstr(buf, "time:")) + { + ptr = &ptr[6]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.time = atoi(tmp); + } + else if(!SongInfo.time) + SongInfo.time = 0; + if(ptr = strstr(buf, "Title:")) + { + ptr = &ptr[7]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.title = (TCHAR*)mir_utf8decodeW(tmp); + } + else + SongInfo.title = _T("Unknown track"); + if(ptr = strstr(buf, "Artist:")) + { + ptr = &ptr[8]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.artist = (TCHAR*)mir_utf8decodeW(tmp); + } + else + SongInfo.artist = _T("Unknown artist"); + if(ptr = strstr(buf, "Genre:")) + { + ptr = &ptr[7]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.genre = (TCHAR*)mir_utf8decodeW(tmp); + } + else + SongInfo.genre = _T("Unknown genre"); + if(ptr = strstr(buf, "Album:")) + { + ptr = &ptr[7]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.album = (TCHAR*)mir_utf8decodeW(tmp); + } + else + SongInfo.album = _T("Unknown album"); + if(ptr = strstr(buf, "Date:")) + { + ptr = &ptr[6]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.year = (TCHAR*)mir_utf8decodeW(tmp); + } + else + SongInfo.year = _T("Unknown year"); + if(ptr = strstr(buf, "volume:")) + { + ptr = &ptr[8]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.volume = atoi(tmp); + } + else if(!SongInfo.volume) + SongInfo.volume = 0; + if(ptr = strstr(buf, "audio:")) + { + ptr = &ptr[7]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.khz = atoi(tmp); + } + else if(!SongInfo.khz) + SongInfo.khz = 0; + if(ptr = strstr(buf, "bitrate:")) + { + ptr = &ptr[9]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.kbps = atoi(tmp); + } + else if(!SongInfo.kbps) + SongInfo.kbps = 0; + + if(ptr = strstr(buf, "Track:")) + { + ptr = &ptr[7]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + SongInfo.track = atoi(tmp); + } + else if(!SongInfo.track) + SongInfo.track = 0; + if(ptr = strstr(buf, "state:")) + { + ptr = &ptr[7]; + for(i = 0; ((ptr[i] != '\n') && (ptr[i] != '\0')); i++) + tmp[i] = ptr[i]; + tmp[i] = '\0'; + if(strstr(tmp, "play")) + gbState = WAT_MES_PLAYING; + if(strstr(tmp, "pause")) + gbState = WAT_MES_PAUSED; + if(strstr(tmp, "stop")) + gbState = WAT_MES_STOPPED; + } + else if(!gbState) + gbState = WAT_MES_UNKNOWN; + return 0; +} + + +void Start(void* param) +{ + NETLIBOPENCONNECTION nloc = {0}; + char *tmp = (char*)mir_u2a(gbHost); + nloc.cbSize = sizeof(nloc); + nloc.szHost = tmp; + nloc.timeout = 5; + nloc.wPort = gbPort; + Connected = FALSE; + ghConnection = NetLib_CreateConnection(ghNetlibUser, &nloc); + if(ghConnection) + ghPacketReciever = (HANDLE)CallService(MS_NETLIB_CREATEPACKETRECVER,(WPARAM)ghConnection,2048); +} +void Stop() +{ + if(ghPacketReciever) + Netlib_CloseHandle(ghPacketReciever); + if(ghConnection) + Netlib_CloseHandle(ghConnection); + if(ghNetlibUser && (ghNetlibUser != INVALID_HANDLE_VALUE)) + CallService(MS_NETLIB_SHUTDOWN,(WPARAM)ghNetlibUser,0); +} +void ReStart(void *param) +{ + if(ghPacketReciever) + Netlib_CloseHandle(ghPacketReciever); + if(ghConnection) + Netlib_CloseHandle(ghConnection); + Sleep(500); + mir_forkthread(&Start, 0); +} + diff --git a/plugins/Watrack/plugins/watrack_mpd/src/main.h b/plugins/Watrack/plugins/watrack_mpd/src/main.h new file mode 100644 index 0000000000..4dcd949c11 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/main.h @@ -0,0 +1,24 @@ +// Copyright © 2008 sss, chaos.persei +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public 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 MAIN_H +#define MAIN_H + +//TCHAR* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, TCHAR* szDef); +//const TCHAR *stristr( const TCHAR *str, const TCHAR *substr); + +#endif + + diff --git a/plugins/Watrack/plugins/watrack_mpd/src/options.c b/plugins/Watrack/plugins/watrack_mpd/src/options.c new file mode 100644 index 0000000000..ef607d78ed --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/options.c @@ -0,0 +1,91 @@ +// Copyright © 2008 sss, chaos.persei +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public 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 "commonheaders.h" +#include + +HINSTANCE hInst; +static INT_PTR CALLBACK DlgProcWaMpdOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +int WaMpdOptInit(WPARAM wParam,LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_WA_MPD); + odp.ptszTitle = LPGENT("Winamp Track"); + odp.ptszGroup = LPGENT("Plugins"); + odp.ptszTab = LPGENT("Watrack MPD"); + odp.flags=ODPF_BOLDGROUPS|ODPF_TCHAR; + odp.pfnDlgProc = DlgProcWaMpdOpts; + Options_AddPage(wParam, &odp); + return 0; +} + + +static INT_PTR CALLBACK DlgProcWaMpdOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch (msg) + { + case WM_INITDIALOG: + { + TranslateDialogDefault(hwndDlg); + SetDlgItemInt(hwndDlg, IDC_PORT, DBGetContactSettingWord(NULL, szModuleName, "Port", 6600), FALSE); + SetDlgItemText(hwndDlg, IDC_SERVER, UniGetContactSettingUtf(NULL, szModuleName, "Server", _T("127.0.0.1"))); + SetDlgItemText(hwndDlg, IDC_PASSWORD, UniGetContactSettingUtf(NULL, szModuleName, "Password", _T(""))); + return TRUE; + } + + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + + } + + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + + case WM_NOTIFY: + { + switch (((LPNMHDR)lParam)->code) + { + + case PSN_APPLY: + { + TCHAR szText[128]; + DBWriteContactSettingWord(NULL, szModuleName, "Port", (WORD)GetDlgItemInt(hwndDlg, IDC_PORT, NULL, FALSE)); + gbPort = (WORD)GetDlgItemInt(hwndDlg, IDC_PORT, NULL, FALSE); + GetDlgItemText(hwndDlg, IDC_SERVER, szText, sizeof(szText)); + DBWriteContactSettingTString(NULL, szModuleName, "Server", szText); + _tcscpy(gbHost, szText); + GetDlgItemText(hwndDlg, IDC_PASSWORD, szText, sizeof(szText)); + DBWriteContactSettingTString(NULL, szModuleName, "Password", szText); + _tcscpy(gbPassword, szText); + return TRUE; + } + } + } + break; + } + + return FALSE; +} + + + diff --git a/plugins/Watrack/plugins/watrack_mpd/src/resource.h b/plugins/Watrack/plugins/watrack_mpd/src/resource.h new file mode 100644 index 0000000000..15f3d472f1 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/resource.h @@ -0,0 +1,32 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by watrack_mpd.rc +// +#define IDD_OPT_DOS 104 +#define IDD_OPT_WA_MPD 104 +#define IDC_FOR_ONLINE 1003 +#define IDC_MSG_NUMBER 1004 +#define IDC_MSG_TEXT 1005 +#define IDC_MSG_RATE 1006 +#define IDC_ENABLE_CUSTOM_MESSAGE 1007 +#define IDC_FOR_ONLINE2 1008 +#define IDC_CLIENT_BASED 1008 +#define IDC_MESSAGE_SIZE 1009 +#define IDC_MSG_SIZE 1009 +#define IDC_MSG_SIZE2 1010 +#define IDC_CHAR_COUNT 1010 +#define IDC_SERVER 1011 +#define IDC_PORT 1012 +#define IDC_EDIT3 1013 +#define IDC_PASSWORD 1013 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1016 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/Watrack/plugins/watrack_mpd/src/utilities.c b/plugins/Watrack/plugins/watrack_mpd/src/utilities.c new file mode 100644 index 0000000000..444a6d210d --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/utilities.c @@ -0,0 +1,126 @@ +// Copyright © 2008 sss, chaos.persei +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public 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 "commonheaders.h" + +/*HANDLE CreateThreadEx(pThreadFuncEx AFunc, void* arg, DWORD* pThreadID) +{ + FORK_THREADEX_PARAMS params; + DWORD dwThreadId; + HANDLE hThread; + + params.pFunc = AFunc; + params.arg = arg; + params.iStackSize = 0; + params.threadID = &dwThreadId; + hThread = (HANDLE)CallService(MS_SYSTEM_FORK_THREAD_EX, 0, (LPARAM)¶ms); + if (pThreadID) + *pThreadID = dwThreadId; + + return hThread; +}*/ + +TCHAR* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, TCHAR* szDef) +{ + DBVARIANT dbv = {DBVT_DELETED}; + TCHAR* szRes; + if (DBGetContactSettingTString(hContact, szModule, szSetting, &dbv)) + return _tcsdup(szDef); + if(dbv.pszVal) + szRes = _tcsdup(dbv.ptszVal); + DBFreeVariant(&dbv); + return szRes; +} + +// case-insensitive _tcsstr +/*#define NEWTSTR_ALLOCA(A) (A==NULL)?NULL:_tcscpy((TCHAR*)alloca(sizeof(TCHAR)*(_tcslen(A)+1)),A) +const TCHAR *stristr( const TCHAR *str, const TCHAR *substr) +{ + TCHAR *p; + TCHAR *str_up = NEWTSTR_ALLOCA(str); + TCHAR *substr_up = NEWTSTR_ALLOCA(substr); + + CharUpperBuff(str_up, lstrlen(str_up)); + CharUpperBuff(substr_up, lstrlen(substr_up)); + + p = _tcsstr(str_up, substr_up); + return p ? (str + (p - str_up)) : NULL; +}*/ + +char *date() +{ + static char d[11]; + char *tmp = __DATE__, m[4], mn[3] = "01"; + m[0]=tmp[0]; + m[1]=tmp[1]; + m[2]=tmp[2]; + if(strstr(m,"Jan")) + strcpy(mn,"01"); + else if(strstr(m,"Feb")) + strcpy(mn,"02"); + else if(strstr(m,"Mar")) + strcpy(mn,"03"); + else if(strstr(m,"Apr")) + strcpy(mn,"04"); + else if(strstr(m,"May")) + strcpy(mn,"05"); + else if(strstr(m,"Jun")) + strcpy(mn,"06"); + else if(strstr(m,"Jul")) + strcpy(mn,"07"); + else if(strstr(m,"Aug")) + strcpy(mn,"08"); + else if(strstr(m,"Sep")) + strcpy(mn,"09"); + else if(strstr(m,"Oct")) + strcpy(mn,"10"); + else if(strstr(m,"Nov")) + strcpy(mn,"11"); + else if(strstr(m,"Dec")) + strcpy(mn,"12"); + d[0]=tmp[7]; + d[1]=tmp[8]; + d[2]=tmp[9]; + d[3]=tmp[10]; + d[4]='.'; + d[5]=mn[0]; + d[6]=mn[1]; + d[7]='.'; + if (tmp[4] == ' ') + d[8] = '0'; + else + d[8]=tmp[4]; + d[9]=tmp[5]; + return d; +} +HANDLE NetLib_CreateConnection(HANDLE hUser, NETLIBOPENCONNECTION* nloc) //from icq ) +{ + HANDLE hConnection; + + nloc->cbSize = sizeof(NETLIBOPENCONNECTION); + nloc->flags |= NLOCF_V2; + + hConnection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hUser, (LPARAM)nloc); + if (!hConnection && (GetLastError() == 87)) + { // this ensures, an old Miranda will be able to connect also + nloc->cbSize = NETLIBOPENCONNECTION_V1_SIZE; + hConnection = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hConnection, (LPARAM)nloc); + } + return hConnection; +} + + diff --git a/plugins/Watrack/plugins/watrack_mpd/src/utilities.h b/plugins/Watrack/plugins/watrack_mpd/src/utilities.h new file mode 100644 index 0000000000..8cef30fb25 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/src/utilities.h @@ -0,0 +1,6 @@ +#ifndef UTILITIES_H +#define UTILITIES_H +HANDLE NetLib_CreateConnection(HANDLE hUser, NETLIBOPENCONNECTION* nloc); +HANDLE CreateThreadEx(pThreadFuncEx AFunc, void* arg, DWORD* pThreadID); +TCHAR* __stdcall UniGetContactSettingUtf(HANDLE hContact, const char *szModule,const char* szSetting, TCHAR* szDef); +#endif diff --git a/plugins/Watrack/plugins/watrack_mpd/watrack_mpd.vcxproj b/plugins/Watrack/plugins/watrack_mpd/watrack_mpd.vcxproj new file mode 100644 index 0000000000..8f8de22140 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/watrack_mpd.vcxproj @@ -0,0 +1,299 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + {F29D0C8D-141A-43CF-86B2-34A04653F8D4} + watrack_mpd + + + + DynamicLibrary + false + Unicode + + + DynamicLibrary + false + Unicode + + + DynamicLibrary + false + Unicode + + + DynamicLibrary + false + Unicode + + + Unicode + DynamicLibrary + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\Plugins\ + $(SolutionDir)$(Configuration)\ + $(SolutionDir)$(Configuration)\Obj\$(ProjectName)\ + $(Configuration)\ + false + false + .\Debug\ + .\Debug\ + .\Debug\ + .\Debug\ + true + true + AllRules.ruleset + AllRules.ruleset + + + + + AllRules.ruleset + AllRules.ruleset + + + + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Release Unicode/testplug.tlb + + + + + Full + OnlyExplicitInline + Size + true + true + ..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;FULL_BUILD;%(PreprocessorDefinitions);_UNICODE;UNICODE + true + MultiThreadedDLL + true + StreamingSIMDExtensions + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + true + true + true + true + UseLinkTimeCodeGeneration + false + + + .\Release Unicode/testplug.lib + MachineX86 + $(SolutionDir)\lib + + + true + .\Release Unicode/testplug.bsc + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + .\Release Unicode/testplug.tlb + + + + + Full + OnlyExplicitInline + Size + true + true + ..\..\include;..\..\plugins\ExternalAPI;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;FULL_BUILD;%(PreprocessorDefinitions) + true + MultiThreadedDLL + true + StreamingSIMDExtensions + Precise + .\Release Unicode/testplug.pch + .\Release Unicode/ + .\Release Unicode/ + .\Release Unicode/ + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x0809 + + + true + true + true + true + UseLinkTimeCodeGeneration + false + + + .\Release Unicode/testplug.lib + $(SolutionDir)\lib + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);mir_core64.lib;Miranda64.lib + + + true + .\Release Unicode/testplug.bsc + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + .\Debug/testplug.tlb + + + + + Disabled + X:\install\git\miranda\miranda-im\miranda\include;../../include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;TESTPLUG_EXPORTS;_CRT_SECURE_NO_WARNINGS;FULL_BUILD;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebug + .\Debug/testplug.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + EditAndContinue + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + true + true + false + + + .\Debug/testplug.lib + MachineX86 + + + true + .\Debug/testplug.bsc + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + .\Debug/testplug.tlb + + + + + Disabled + X:\install\git\miranda\miranda-im\miranda\include;../../include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;TESTPLUG_EXPORTS;_CRT_SECURE_NO_WARNINGS;FULL_BUILD;%(PreprocessorDefinitions) + EnableFastChecks + MultiThreadedDebug + .\Debug/testplug.pch + .\Debug/ + .\Debug/ + .\Debug/ + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x0809 + + + true + true + false + + + .\Debug/testplug.lib + + + true + .\Debug/testplug.bsc + + + + + + \ No newline at end of file diff --git a/plugins/Watrack/plugins/watrack_mpd/watrack_mpd.vcxproj.filters b/plugins/Watrack/plugins/watrack_mpd/watrack_mpd.vcxproj.filters new file mode 100644 index 0000000000..67721aee48 --- /dev/null +++ b/plugins/Watrack/plugins/watrack_mpd/watrack_mpd.vcxproj.filters @@ -0,0 +1,56 @@ + + + + + {2c37ce60-87c1-44a6-85ff-147b48dd84f4} + + + {1d016f21-3dfc-4617-a16d-2543db03d939} + + + {67db7959-3d43-439b-ae9b-8223911c651d} + + + + + Sources + + + Sources + + + Sources + + + Sources + + + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + Headers + + + + + Resources + + + \ No newline at end of file diff --git a/plugins/Watrack/popup/pop_dlg.inc b/plugins/Watrack/popup/pop_dlg.inc new file mode 100644 index 0000000000..129b538780 --- /dev/null +++ b/plugins/Watrack/popup/pop_dlg.inc @@ -0,0 +1,179 @@ +{PopUp Option Dialog} + +// PopUp options +const + DLGPOPUP = 'POPUP'; + +function DlgPopUpOpt(Dialog:HWnd;hMessage:Uint;wParam:WPARAM;lParam:LPARAM):LRESULT; stdcall; +const + dlginit:boolean=false; +var + tmp:longbool; + ppd:PPOPUPDATAW; + fore,back:HWND; +begin + result:=0; + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + dlginit:=false; + + SetDlgItemTextW(Dialog,IDC_POPUP_TITLE,PopTitle); + SetDlgItemTextW(Dialog,IDC_POPUP_TEXT ,PopText); + + CheckDlgButton(Dialog,IDC_SHOWFILE ,PopUpFile); + CheckDlgButton(Dialog,IDC_REQUEST ,PopRequest); + + CheckDlgButton(Dialog,IDC_ACTLEFTCLOSE ,ord(LoByte(PopUpAction)=0)); + CheckDlgButton(Dialog,IDC_ACTLEFTINFO ,ord(LoByte(PopUpAction)=1)); + CheckDlgButton(Dialog,IDC_ACTLEFTPLAYER ,ord(LoByte(PopUpAction)=2)); + CheckDlgButton(Dialog,IDC_ACTLEFTNEXT ,ord(LoByte(PopUpAction)=3)); + CheckDlgButton(Dialog,IDC_ACTRIGHTCLOSE ,ord(HiByte(PopUpAction)=0)); + CheckDlgButton(Dialog,IDC_ACTRIGHTINFO ,ord(HiByte(PopUpAction)=1)); + CheckDlgButton(Dialog,IDC_ACTRIGHTPLAYER,ord(HiByte(PopUpAction)=2)); + CheckDlgButton(Dialog,IDC_ACTRIGHTNEXT ,ord(HiByte(PopUpAction)=3)); + + CheckDlgButton(Dialog,IDC_USEBUTTONS,PopUpButtons); + + SetDlgItemInt (Dialog,IDC_DELAY,PopUpPause,false); + + if PopUpDelay<0 then + CheckDlgButton(Dialog,IDC_DELAYPERM,BST_CHECKED) + else if PopUpDelay=0 then + CheckDlgButton(Dialog,IDC_DELAYDEF,BST_CHECKED) + else + CheckDlgButton(Dialog,IDC_DELAYCUST,BST_CHECKED); + if PopUpDelay<=0 then + EnableWindow(GetDlgItem(Dialog,IDC_DELAY),false); + + SendDlgItemMessage(Dialog,IDC_MACRO_HELP,BM_SETIMAGE,IMAGE_ICON, + CallService(MS_SKIN_LOADICON,SKINICON_OTHER_HELP,0)); + + fore:=GetDlgItem(Dialog,IDC_FORE); + back:=GetDlgItem(Dialog,IDC_BACK); + SendMessage(fore,CPM_SETCOLOUR,0,PopUpFore); + SendMessage(fore,CPM_SETDEFAULTCOLOUR,0,GetSysColor(COLOR_BTNTEXT)); + SendMessage(back,CPM_SETCOLOUR,0,PopUpBack); + SendMessage(back,CPM_SETDEFAULTCOLOUR,0,GetSysColor(COLOR_BTNFACE)); + SetDlgItemInt(Dialog,IDC_FORE,PopUpFore,false); + SetDlgItemInt(Dialog,IDC_BACK,PopUpBack,false); + if PopUpColor<2 then + begin + EnableWindow(fore,false); + EnableWindow(back,false); + end; + case PopUpColor of + 0: CheckDlgButton(Dialog,IDC_COLORDEF ,BST_CHECKED); + 1: CheckDlgButton(Dialog,IDC_COLORWIN ,BST_CHECKED); + 2: CheckDlgButton(Dialog,IDC_COLORCUST,BST_CHECKED); + end; + dlginit:=true; + end; + + WM_COMMAND: begin + if (wParam shr 16)=BN_CLICKED then + begin + fore:=GetDlgItem(Dialog,IDC_FORE); + back:=GetDlgItem(Dialog,IDC_BACK); + case LoWord(wParam) of + IDC_MACRO_HELP: CallService(MS_WAT_MACROHELP,Dialog,0); + IDC_TEST: begin + mGetMem(ppd,SizeOf(TPOPUPDATAW)); + FillChar(ppd^,SizeOf(ppd^),0); + ppd^.lchIcon:=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + StrCopyW(ppd^.lpwzContactName,TranslateW('popup test')); + StrCopyW(ppd^.lpwzText,TranslateW('second line')); + if IsDlgButtonChecked(Dialog,IDC_COLORDEF)=BST_CHECKED then + begin + ppd^.colorBack:=0; + ppd^.colorText:=0; + end + else if IsDlgButtonChecked(Dialog,IDC_COLORWIN)=BST_CHECKED then + begin + ppd^.colorBack:=GetSysColor(COLOR_BTNFACE); + ppd^.colorText:=GetSysColor(COLOR_BTNTEXT); + end + else + begin + ppd^.colorBack:=SendMessage(back,CPM_GETCOLOUR,0,0); + ppd^.colorText:=SendMessage(fore,CPM_GETCOLOUR,0,0); + end; + CallService(MS_POPUP_ADDPOPUPW,twparam(ppd),0); + mFreeMem(ppd); + end; + IDC_DELAYCUST: + EnableWindow(GetDlgItem(Dialog,IDC_DELAY),true); + IDC_DELAYDEF,IDC_DELAYPERM: + EnableWindow(GetDlgItem(Dialog,IDC_DELAY),false); + IDC_COLORCUST: begin + EnableWindow(fore,true); + EnableWindow(back,true); + end; + IDC_COLORDEF,IDC_COLORWIN: begin + EnableWindow(fore,false); + EnableWindow(back,false); + end; + end; + end; + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + result:=0; + end; + + WM_NOTIFY: begin + if dlginit then + begin + if integer(PNMHdr(lParam)^.code)=PSN_APPLY then + begin + + mFreeMem(PopTitle); + mFreeMem(PopText); + PopTitle:=GetDlgText(Dialog,IDC_POPUP_TITLE); + PopText :=GetDlgText(Dialog,IDC_POPUP_TEXT); + + PopUpButtons:=IsDlgButtonChecked(Dialog,IDC_USEBUTTONS); + + PopUpFile :=IsDlgButtonChecked(Dialog,IDC_SHOWFILE); + PopRequest:=IsDlgButtonChecked(Dialog,IDC_REQUEST); +//color + if IsDlgButtonChecked(Dialog,IDC_COLORDEF)=BST_CHECKED then + PopUpColor:=0 + else if IsDlgButtonChecked(Dialog,IDC_COLORWIN)=BST_CHECKED then + PopUpColor:=1 + else + begin + PopUpColor:=2; + PopUpFore:=SendDlgItemMessage(Dialog,IDC_FORE,CPM_GETCOLOUR,0,0); + PopUpBack:=SendDlgItemMessage(Dialog,IDC_BACK,CPM_GETCOLOUR,0,0); + end; +//pause + if IsDlgButtonChecked(Dialog,IDC_DELAYDEF)=BST_CHECKED then + PopUpDelay:=0 + else if IsDlgButtonChecked(Dialog,IDC_DELAYPERM)=BST_CHECKED then + PopUpDelay:=-1 + else + begin + PopUpDelay:=1; + PopUpPause:=GetDlgItemInt(Dialog,IDC_DELAY,tmp,false); + end; +//action + if IsDlgButtonChecked(Dialog,IDC_ACTLEFTINFO)=BST_CHECKED then + PopUpAction:=1 + else if IsDlgButtonChecked(Dialog,IDC_ACTLEFTPLAYER)=BST_CHECKED then + PopUpAction:=2 + else if IsDlgButtonChecked(Dialog,IDC_ACTLEFTNEXT)=BST_CHECKED then + PopUpAction:=3 + else + PopUpAction:=0; + if IsDlgButtonChecked(Dialog,IDC_ACTRIGHTINFO)=BST_CHECKED then + inc(PopUpAction,$100) + else if IsDlgButtonChecked(Dialog,IDC_ACTRIGHTPLAYER)=BST_CHECKED then + inc(PopUpAction,$200) + else if IsDlgButtonChecked(Dialog,IDC_ACTRIGHTNEXT)=BST_CHECKED then + inc(PopUpAction,$300); + + savepopup; + end; + end; + end; + end; +end; diff --git a/plugins/Watrack/popup/pop_opt.inc b/plugins/Watrack/popup/pop_opt.inc new file mode 100644 index 0000000000..591063923e --- /dev/null +++ b/plugins/Watrack/popup/pop_opt.inc @@ -0,0 +1,81 @@ +{Popup options saving-loading} + +const + defPopupTitle = 'Now listening to'; + defPopupText = '%artist% - %title%'; + defAltPopupTitle = 'Now ?ifgreater(%width%,0,watching,listening to)'; + defAltPopupText = '%artist% - %title%'#13#10'?iflonger(%album%,0, (from "%album%"),)'; +const + opt_ModStatus :PAnsiChar = 'module/popups'; + + opt_PopUpFile :PAnsiChar = 'popup/file'; + opt_PopUpAction :PAnsiChar = 'popup/action'; + opt_PopUpFore :PAnsiChar = 'popup/fore'; + opt_PopUpBack :PAnsiChar = 'popup/back'; + opt_PopUpPause :PAnsiChar = 'popup/time'; + opt_PopUpDelay :PAnsiChar = 'popup/delay'; + opt_PopUpColor :PAnsiChar = 'popup/color'; + opt_ByRequest :PAnsiChar = 'popup/byrequest'; + opt_PopTitle :PAnsiChar = 'popup/poptitle'; + opt_PopText :PAnsiChar = 'popup/poptext'; + opt_PopUpButtons:PAnsiChar = 'popup/usebuttons'; + + spref = 'strings/'; + +function GetModStatus:integer; +begin + result:=DBReadByte(0,PluginShort,opt_ModStatus,1); +end; + +procedure SetModStatus(stat:integer); +begin + DBWriteByte(0,PluginShort,opt_ModStatus,stat); +end; + +procedure loadpopup; +var + def1,def2:pWideChar; +begin + PopUpButtons:=DBReadByte (0,PluginShort,opt_PopUpButtons,BST_CHECKED); + PopUpFile :=DBReadByte (0,PluginShort,opt_PopUpFile ,BST_CHECKED); + PopUpPause :=DBReadByte (0,PluginShort,opt_PopUpPause ,0); + PopUpDelay :=DBReadByte (0,PluginShort,opt_PopUpDelay ,0); + PopUpAction :=DBReadWord (0,PluginShort,opt_PopUpAction ,0); + PopUpColor :=DBReadByte (0,PluginShort,opt_PopUpColor ,0); + PopUpFore :=DBReadDWord(0,PluginShort,opt_PopUpFore ,GetSysColor(COLOR_BTNTEXT)); + PopUpBack :=DBReadDWord(0,PluginShort,opt_PopUpBack ,GetSysColor(COLOR_BTNFACE)); + PopRequest :=DBReadByte (0,PluginShort,opt_ByRequest ,BST_UNCHECKED); + if isVarsInstalled then + begin + def1:=defAltPopupTitle; + def2:=defAltPopupText; + end + else + begin + def1:=defPopupTitle; + def2:=defPopupText; + end; + PopTitle:=DBReadUnicode(0,PluginShort,opt_PopTitle,def1); + PopText :=DBReadUnicode(0,PluginShort,opt_PopText ,def2); +end; + +procedure savepopup; +begin + DBWriteByte (0,PluginShort,opt_PopUpButtons,PopUpButtons); + DBWriteByte (0,PluginShort,opt_PopUpFile ,PopUpFile); + DBWriteByte (0,PluginShort,opt_PopUpPause ,PopUpPause); + DBWriteByte (0,PluginShort,opt_PopUpDelay ,PopUpDelay); + DBWriteWord (0,PluginShort,opt_PopUpAction ,PopUpAction); + DBWriteByte (0,PluginShort,opt_PopUpColor ,PopUpColor); + DBWriteDWord (0,PluginShort,opt_PopUpFore ,PopUpFore); + DBWriteDWord (0,PluginShort,opt_PopUpBack ,PopUpBack); + DBWriteByte (0,PluginShort,opt_ByRequest ,PopRequest); + DBWriteUnicode(0,PluginShort,opt_PopTitle,PopTitle); + DBWriteUnicode(0,PluginShort,opt_PopText ,PopText); +end; + +procedure freepopup; +begin + mFreeMem(PopTitle); + mFreeMem(PopText); +end; diff --git a/plugins/Watrack/popup/pop_rc.inc b/plugins/Watrack/popup/pop_rc.inc new file mode 100644 index 0000000000..4e8298d209 --- /dev/null +++ b/plugins/Watrack/popup/pop_rc.inc @@ -0,0 +1,34 @@ +{POPUP DLG} +const + IDC_DELAY = 1026; + IDC_DELAYDEF = 1027; + IDC_DELAYCUST = 1028; + IDC_DELAYPERM = 1029; + IDC_COLORDEF = 1030; + IDC_BACK = 1031; + IDC_FORE = 1032; + IDC_COLORWIN = 1033; + IDC_COLORCUST = 1034; + IDC_SHOWFILE = 1035; + IDC_TEST = 1036; + IDC_ACTLEFTCLOSE = 1040; + IDC_ACTLEFTINFO = 1041; + IDC_ACTRIGHTCLOSE = 1042; + IDC_ACTRIGHTINFO = 1043; + IDC_ONKEY = 1044; + IDC_KEYEMPTY = 1050; + IDC_KEYCUSTOM = 1051; + IDC_KEYMSG = 1052; + IDC_KEYNOMSG = 1055; + IDC_ACTLEFTPLAYER = 1056; + IDC_ACTRIGHTPLAYER = 1057; + IDC_ACTLEFTNEXT = 1058; + IDC_ACTRIGHTNEXT = 1059; + IDC_REQUEST = 1060; + IDC_STAT_HKBOX = 1061; + IDC_POPUP_TITLE = 1062; + IDC_POPUP_TEXT = 1063; + IDC_MACRO_HELP = 1064; + IDC_USEBUTTONS = 1065; + + BTN_INFO = 9; diff --git a/plugins/Watrack/popup/pop_vars.inc b/plugins/Watrack/popup/pop_vars.inc new file mode 100644 index 0000000000..4a845aaadc --- /dev/null +++ b/plugins/Watrack/popup/pop_vars.inc @@ -0,0 +1,27 @@ +{popup variables} +const + ActionList:PPOPUPACTION=nil; +var + PopTitle, + PopText:pWideChar; + PopRequest, + PopUpFile:dword; + PopUpColor:dword; + PopUpFore, + PopUpBack:cardinal; + PopUpPause:cardinal; + PopUpDelay:integer; + PopUpAction:cardinal; + PopUpButtons:cardinal; + + DisablePlugin:integer; + IsPopup2Present:boolean; + IsFreeImagePresent:boolean; +var + hMenuInfo :THANDLE; + ssmi,sic, + plStatusHook:THANDLE; + PopupPresent:Bool; + onttbhook, + opthook:THANDLE; + ttbInfo:THANDLE; \ No newline at end of file diff --git a/plugins/Watrack/popup/popup.rc b/plugins/Watrack/popup/popup.rc new file mode 100644 index 0000000000..ae05c73860 --- /dev/null +++ b/plugins/Watrack/popup/popup.rc @@ -0,0 +1,55 @@ +#include "pop_rc.inc" + +LANGUAGE 0,0 + +POPUP DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 400, 0 +{ + AUTOCHECKBOX "Show by request only", IDC_REQUEST, 156, 0, 144, 18, BS_MULTILINE + + GROUPBOX "Colors", -1, 4, 18, 144, 74 + CTEXT "Background", -1, 24, 64, 50, 8 + CTEXT "Text" , -1, 84, 64, 50, 8 + AUTORADIOBUTTON "Default colors", IDC_COLORDEF , 12, 28, 88, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "Windows colors", IDC_COLORWIN , 12, 40, 88, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "Custom colors" , IDC_COLORCUST, 12, 52, 88, 10, NOT WS_TABSTOP + CONTROL "", IDC_BACK, "ColourPicker", WS_TABSTOP, 24, 75, 50, 14 + CONTROL "", IDC_FORE, "ColourPicker", WS_TABSTOP, 84, 75, 50, 14 + + GROUPBOX "Actions", -1, 156, 18, 144, 74 + RTEXT "Close" , -1, 162, 40, 50, 10 + RTEXT "Info" , -1, 162, 53, 50, 10 + RTEXT "Show player", -1, 162, 66, 50, 10 + RTEXT "Next track" , -1, 162, 79, 50, 10 + + CTEXT "Left click", -1, 208, 26, 40, 16 + AUTORADIOBUTTON "", IDC_ACTLEFTCLOSE , 224, 40, 10, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "", IDC_ACTLEFTINFO , 224, 53, 10, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "", IDC_ACTLEFTPLAYER, 224, 66, 10, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "", IDC_ACTLEFTNEXT , 224, 79, 10, 10, NOT WS_TABSTOP + CTEXT "Right click", -1, 248, 26, 40, 16 + AUTORADIOBUTTON "", IDC_ACTRIGHTCLOSE , 262, 40, 10, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "", IDC_ACTRIGHTINFO , 262, 53, 10, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "", IDC_ACTRIGHTPLAYER, 262, 66, 10, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "", IDC_ACTRIGHTNEXT , 262, 79, 10, 10, NOT WS_TABSTOP + + GROUPBOX "Delay", -1, 4, 96, 144, 48 + EDITTEXT IDC_DELAY, 86, 117, 36, 12, ES_AUTOHSCROLL | ES_NUMBER + LTEXT "sec", -1, 126, 118, 12, 8 + AUTORADIOBUTTON "Default" , IDC_DELAYDEF , 12, 106, 128, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "Custom" , IDC_DELAYCUST, 12, 118, 72, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "Permanent", IDC_DELAYPERM, 12, 130, 128, 10, NOT WS_TABSTOP + + AUTOCHECKBOX "Show file name in info" , IDC_SHOWFILE , 156, 94 , 144, 17, BS_MULTILINE + AUTOCHECKBOX "Use popup action buttons", IDC_USEBUTTONS, 156, 111, 144, 17, BS_MULTILINE + PUSHBUTTON "Test", IDC_TEST, 156, 128, 48, 16 + + CONTROL "M", IDC_MACRO_HELP ,"MButtonClass",WS_TABSTOP,278,138,16,16,$18000000 + CTEXT "Popup Title / Text", -1, 6, 146, 270, 10 + EDITTEXT IDC_POPUP_TITLE, 6, 156, 290, 14, ES_AUTOHSCROLL + EDITTEXT IDC_POPUP_TEXT , 6, 174, 290, 48, ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN +} + +BTN_INFO ICON "wat_info.ico" diff --git a/plugins/Watrack/popup/popup.res b/plugins/Watrack/popup/popup.res new file mode 100644 index 0000000000..707791399b Binary files /dev/null and b/plugins/Watrack/popup/popup.res differ diff --git a/plugins/Watrack/popup/popups.pas b/plugins/Watrack/popup/popups.pas new file mode 100644 index 0000000000..381d33dab3 --- /dev/null +++ b/plugins/Watrack/popup/popups.pas @@ -0,0 +1,542 @@ +{PopUp support} +unit Popups; +{$include compilers.inc} +interface +{$Resource popup.res} +implementation + +uses windows,messages,commctrl, + wat_api,waticons,global, + wrapper,common,m_api,dbsettings,mirutils; + +const + MenuInfoPos = 500050002; + PluginName = 'Winamp Track'; +const + IcoBtnInfo:PAnsiChar='WATrack_Info'; +const + HKN_POPUP:PAnsiChar = 'WAT_Popup'; + +{$include pop_rc.inc} +{$include pop_vars.inc} +{$include pop_opt.inc} + +const + MainTmpl = 'artist: %ls'#13#10'title: "%ls"'#13#10'album: "%ls"'#13#10+ + 'genre: %ls'#13#10'comment: %ls'#13#10'year: %ls'#13#10'track: %lu'#13#10+ + 'bitrate: %lukbps %ls'#13#10'samplerate: %luKHz'#13#10+ + 'channels: %lu'#13#10'length: %ls'#13#10'player: "%ls" v.%ls'; + AddTmpl = #13#10'file: "%ls"'#13#10'size: %lu bytes'; + +procedure ShowMusicInfo(si:pSongInfo); +var + Tmpl:array [0..255] of WideChar; + buf:pWideChar; + lvars:array [0..15] of uint_ptr; + s:array [0..31] of WideChar; + p:PWideChar; +begin + mGetMem(buf,16384); + with si^ do + begin + lvars[0]:=uint_ptr(artist); + lvars[1]:=uint_ptr(title); + lvars[2]:=uint_ptr(album); + lvars[3]:=uint_ptr(genre); + lvars[4]:=uint_ptr(comment); + lvars[5]:=uint_ptr(year); + lvars[6]:=track; + lvars[7]:=kbps; + if vbr>0 then + p:='VBR' + else + p:='CBR'; + lvars[8]:=uint_ptr(p); + lvars[9]:=khz; + lvars[10]:=channels; + lvars[11]:=uint_ptr(IntToTime(s,total)); + lvars[12]:=uint_ptr(player); + lvars[13]:=uint_ptr(txtver); + end; + StrCopyW(Tmpl,TranslateW(MainTmpl)); + if PopUpFile=BST_CHECKED then + begin + lvars[14]:=uint_ptr(si^.mfile); + lvars[15]:=si^.fsize; + StrCatW(Tmpl,TranslateW(AddTmpl)); + end; + + wvsprintfw(buf,Tmpl,@lvars); + MessageBoxW(0,buf,PluginName,MB_OK); + mFreeMem(buf); +end; + +function DumbPopupDlgProc(Wnd:hwnd;msg:uint;wParam:integer;lParam:longint):integer;stdcall; +var + si:pSongInfo; + h:HBITMAP; +begin + case msg of + WM_COMMAND,WM_CONTEXTMENU: begin + if msg=WM_CONTEXTMENU then + wParam:=HiByte(PopUpAction) + else + wParam:=LoByte(PopUpAction); + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,0,0)); + case wParam of + 1: ShowMusicInfo(si); + 2: ShowWindow(si^.plwnd,SW_RESTORE); + 3: CallServiceSync(MS_WAT_PRESSBUTTON,WAT_CTRL_NEXT,0); + end; + SendMessage(Wnd,UM_DESTROYPOPUP,0,0); + result:=1; + end; + UM_POPUPACTION: begin +// if wParam<>0 then + result:=CallServiceSync(MS_WAT_PRESSBUTTON,lParam,0); + end; + UM_FREEPLUGINDATA: begin + h:=0; + h:=CallService(MS_POPUP_GETPLUGINDATA,Wnd,h); + if h<>0 then + DeleteObject(h); + result:=0; + end; + else + result:=DefWindowProc(Wnd,msg,wParam,lParam); + end; +end; + +function MakeAction(var anAct:TPOPUPACTION;action:integer):PPOPUPACTION; +begin + result:=@anAct; + anAct.cbSize :=SizeOf(TPOPUPACTION); + anAct.lchIcon:=GetIcon(action); + anAct.flags :=PAF_ENABLED; + anAct.wParam :=1; + anAct.lParam :=action; + StrCopy(StrCopyE(anAct.lpzTitle,'Watrack/'),GetIconDescr(action)); +end; + +function MakeActions:PPOPUPACTION; +type + anacts = array [0..6] of TPOPUPACTION; +var + actions:^anacts; +begin + if PopUpButtons<>BST_UNCHECKED then + begin + mGetMem(actions,SizeOf(anacts)); + result:=PPOPUPACTION(actions); + FillChar(actions^,SizeOf(actions^),0); + MakeAction(actions[0],WAT_CTRL_PREV); + MakeAction(actions[1],WAT_CTRL_PLAY); + MakeAction(actions[2],WAT_CTRL_PAUSE); + MakeAction(actions[3],WAT_CTRL_STOP); + MakeAction(actions[4],WAT_CTRL_NEXT); + MakeAction(actions[5],WAT_CTRL_VOLDN); + MakeAction(actions[6],WAT_CTRL_VOLUP); + end + else + result:=nil; +end; + +procedure ThShowPopup(si:pSongInfo); cdecl; +var + ppdu:PPOPUPDATAW; + title,descr:pWideChar; + flag:dword; + ppd2:PPOPUPDATA2; + Icon:HICON; + sec:integer; + cb,ct:TCOLORREF; + line:boolean; + tmp:pAnsiChar; +begin + line:=CallService(MS_POPUP_ISSECONDLINESHOWN,0,0)<>0; + + descr:=PWideChar(CallService(MS_WAT_REPLACETEXT,0,lparam(PopText))); + if line then + title:=PWideChar(CallService(MS_WAT_REPLACETEXT,0,lparam(PopTitle))) + else + title:=nil; + + if (descr<>nil) or (title<>nil) then + begin + if si^.icon<>0 then + Icon:=si^.icon + else + Icon:=LoadSkinnedIcon(SKINICON_OTHER_MIRANDA); + if PopUpDelay<0 then + sec:=-1 + else if PopUpDelay>0 then + sec:=PopUpPause + else + sec:=0; + case PopUpColor of + 0: begin + cb:=0; + ct:=0; + end; + 1: begin + cb:=GetSysColor(COLOR_BTNFACE); + ct:=GetSysColor(COLOR_BTNTEXT); + end; + 2: begin + cb:=PopUpBack; + ct:=PopUpFore; + end; + else + cb:=0; + ct:=0; + end; + + if IsPopup2Present then + begin + mGetMem (ppd2 ,SizeOf(TPOPUPDATA2)); + FillChar(ppd2^,SizeOf(TPOPUPDATA2),0); + with ppd2^ do + begin + cbSize :=SizeOf(TPOPUPDATA2); + flags :=PU2_UNICODE; + lchIcon :=Icon; + colorBack :=cb; + colorText :=ct; + PluginWindowProc:=@DumbPopupDlgProc; + + if line then + begin + pzTitle.w:=title; + pzText .w:=descr; + end + else + pzTitle.w:=descr; + + if ActionList=nil then + flag:=0 + else + begin + flag :=APF_NEWDATA; + actionCount:=7; + lpActions :=ActionList; + end; + + if si.cover<>nil then + begin + if IsFreeImagePresent then + hbmAvatar:=CallService(MS_IMG_LOAD,wparam(si.cover),IMGL_WCHAR) + else + hbmAvatar:=0; + if hbmAvatar=0 then + begin + WideToAnsi(si.cover,tmp); + hbmAvatar:=CallService(MS_UTILS_LOADBITMAP,0,lparam(tmp)); + mFreeMem(tmp); + end; + end; + PluginData:=pointer(hbmAvatar); + end; + CallService(MS_POPUP_ADDPOPUP2,wparam(ppd2),flag); + mFreeMem(ppd2); + end + else + begin + mGetMem (ppdu ,SizeOf(TPOPUPDATAW)); + FillChar(ppdu^,SizeOf(TPOPUPDATAW),0); + with ppdu^ do + begin + if line then + begin + if title<>nil then + StrCopyW(lpwzContactName,title,MAX_CONTACTNAME-1) + else + lpwzContactName[0]:=' '; + if descr<>nil then + StrCopyW(lpwzText,descr,MAX_SECONDLINE-1) + else + lpwzText[0]:=' '; + end + else + begin + StrCopyW(ppdu^.lpwzContactName,title,MAX_CONTACTNAME-1); + lpwzText[0]:=' '; + end; + + lchIcon :=Icon; + PluginWindowProc:=@DumbPopupDlgProc; + iSeconds :=sec; + colorBack :=cb; + colorText :=ct; + + // if ServiceExists(MS_POPUP_REGISTERACTIONS)=0 then + if ActionList=nil then + flag:=0 + else + begin + flag :=APF_NEWDATA; + icbSize :=SizeOf(TPOPUPDATAW); + actionCount:=7; + lpActions :=ActionList; + end; + end; + CallService(MS_POPUP_ADDPOPUPW,wparam(ppdu),flag); + mFreeMem(ppdu); + end; + mFreeMem(title); + mFreeMem(descr); + end; +end; + +procedure ShowPopUp(si:pSongInfo); +begin + CloseHandle(mir_forkthread(@ThShowPopup,si)); +end; + +// --------------- Services and Hooks ---------------- + +function OpenPopUp(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + si:pSongInfo; +begin + result:=0; + if DisablePlugin<>dsEnabled then + exit; + if CallService(MS_WAT_GETMUSICINFO,0,tlparam(@si))=WAT_PLS_NORMAL then + begin + if PopupPresent then + ShowPopUp(si) + else + ShowMusicInfo(si); + end; +end; + +procedure regpophotkey; +var + hkrec:HOTKEYDESC; +begin + if DisablePlugin=dsPermanent then + exit; + FillChar(hkrec,SizeOf(hkrec),0); + with hkrec do + begin + cbSize :=HOTKEYDESC_SIZE_V1; + pszName :=HKN_POPUP; + pszDescription.a:='WATrack popup hotkey'; + pszSection.a :=PluginName; + pszService :=MS_WAT_SHOWMUSICINFO; + DefHotKey:=((HOTKEYF_ALT or HOTKEYF_CONTROL) shl 8) or VK_F7 or HKF_MIRANDA_LOCAL; + end; + CallService(MS_HOTKEY_REGISTER,0,lparam(@hkrec)); +end; + +{$include pop_dlg.inc} + +function NewPlStatus(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; + flag:integer; +begin + result:=0; + case wParam of + WAT_EVENT_NEWTRACK: begin + if PopupPresent and (PopRequest=BST_UNCHECKED) then + ShowPopUp(pSongInfo(lParam)); + end; + WAT_EVENT_PLUGINSTATUS: begin + DisablePlugin:=lParam; + case lParam of + dsEnabled: begin + flag:=0; + end; + dsPermanent: begin + flag:=CMIF_GRAYED; + end; + else // like 1 + exit + end; + FillChar(mi,sizeof(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_FLAGS+flag; + CallService(MS_CLIST_MODIFYMENUITEM,hMenuInfo,tlparam(@mi)); + end; + end; +end; + +function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; +begin + result:=0; + FillChar(mi,SizeOf(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_ICON; + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnInfo)); + CallService(MS_CLIST_MODIFYMENUITEM,hMenuInfo,tlparam(@mi)); + if ActionList<>nil then + begin + mFreeMem(ActionList); + ActionList:=MakeActions; + CallService(MS_POPUP_REGISTERACTIONS,twparam(ActionList),7); + end; +end; + +function OnOptInitialise(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + odp:TOPTIONSDIALOGPAGE; +begin + FillChar(odp,SizeOf(odp),0); + odp.cbSize :=OPTIONPAGE_OLD_SIZE2; //for 0.5 compatibility + odp.flags :=ODPF_BOLDGROUPS; + odp.Position :=900003000; + odp.hInstance :=hInstance; + odp.szTitle.a :=PluginName; + + odp.szGroup.a :='PopUps'; + odp.pszTemplate:=DLGPOPUP; + odp.pfnDlgProc :=@DlgPopUpOpt; + CallService(MS_OPT_ADDPAGE,wParam,tlparam(@odp)); + result:=0; +end; + +function OnTTBLoaded(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + ttb:TTBButton; +begin + result:=0; + if onttbhook<>0 then + UnhookEvent(onttbhook); + // get info button + FillChar(ttb,SizeOf(ttb),0); + ttb.cbSize :=SizeOf(ttb); + ttb.dwFlags :=TTBBF_VISIBLE{ or TTBBF_SHOWTOOLTIP}; + ttb.hIconUp :=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnInfo)); + ttb.hIconDn :=ttb.hIconUp; + ttb.pszService:=MS_WAT_SHOWMUSICINFO; + ttb.name :='Music Info'; + ttbInfo:=TopToolbar_AddButton(@ttb); + if ttbInfo=THANDLE(-1) then + ttbInfo:=0; +end; + +// ------------ base interface functions ------------- + +function InitProc(aGetStatus:boolean=false):integer; +var + mi:TCListMenuItem; + sid:TSKINICONDESC; +begin + if aGetStatus then + begin + if GetModStatus=0 then + begin + result:=0; + exit; + end; + end + else + SetModStatus(1); + result:=1; + + ssmi:=CreateServiceFunction(MS_WAT_SHOWMUSICINFO,@OpenPopUp); + + FillChar(sid,SizeOf(TSKINICONDESC),0); + sid.cbSize:=SizeOf(TSKINICONDESC); + sid.cx:=16; + sid.cy:=16; + sid.szSection.a:='WATrack'; + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(BTN_INFO),IMAGE_ICON,16,16,0); + sid.pszName :=IcoBtnInfo; + sid.szDescription.a:='Music Info'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + sic:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged); + + FillChar(mi,SizeOf(mi),0); + mi.cbSize :=SizeOf(mi); + mi.szPopupName.a:=PluginShort; + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(IcoBtnInfo)); + mi.szName.a :='Music Info'; + mi.pszService :=MS_WAT_SHOWMUSICINFO; + mi.popupPosition:=MenuInfoPos; + hMenuInfo :=Menu_AddMainMenuItem(@mi); + + if ServiceExists(MS_POPUP_ADDPOPUPW)<>0 then + begin + IsFreeImagePresent:=ServiceExists(MS_IMG_LOAD )<>0; + IsPopup2Present :=ServiceExists(MS_POPUP_ADDPOPUP2)<>0; + PopupPresent:=true; + opthook:=HookEvent(ME_OPT_INITIALISE,@OnOptInitialise); + loadpopup; + regpophotkey; + + ActionList:=nil; + if ServiceExists(MS_POPUP_REGISTERACTIONS)<>0 then + begin + if RegisterButtonIcons then + begin + ActionList:=MakeActions; + if ActionList<>nil then + CallService(MS_POPUP_REGISTERACTIONS,wparam(ActionList),7); + end; + end; + end + else + begin + PopupPresent:=false; + end; + + plStatusHook:=HookEvent(ME_WAT_NEWSTATUS,@NewPlStatus); + + if ServiceExists(MS_TTB_ADDBUTTON)>0 then + begin + onttbhook:=0; + OnTTBLoaded(0,0); + if ttbInfo=0 then + onttbhook:=HookEvent(ME_TTB_MODULELOADED,@OnTTBLoaded); + end + else + ttbInfo:=0; +end; + +procedure DeInitProc(aSetDisable:boolean); +begin + if aSetDisable then + SetModStatus(0); + + CallService(MS_CLIST_REMOVEMAINMENUITEM,hMenuInfo,0); + UnhookEvent(plStatusHook); + DestroyServiceFunction(ssmi); + UnhookEvent(sic); + + freepopup; + + if ttbInfo<>0 then + begin + if ServiceExists(MS_TTB_REMOVEBUTTON)>0 then + CallService(MS_TTB_REMOVEBUTTON,WPARAM(ttbInfo),0); + ttbInfo:=0; + end; + + if PopupPresent then + begin + UnhookEvent(opthook); + mFreeMem(ActionList); + end; +end; + +var + Popup:twModule; + +procedure Init; +begin + Popup.Next :=ModuleLink; + Popup.Init :=@InitProc; + Popup.DeInit :=@DeInitProc; + Popup.AddOption :=nil; + Popup.ModuleName:='PopUps'; + ModuleLink :=@Popup; +end; + +begin + Init; +end. diff --git a/plugins/Watrack/popup/wat_info.ico b/plugins/Watrack/popup/wat_info.ico new file mode 100644 index 0000000000..70d54c8bac Binary files /dev/null and b/plugins/Watrack/popup/wat_info.ico differ diff --git a/plugins/Watrack/proto/i_proto_dlg.inc b/plugins/Watrack/proto/i_proto_dlg.inc new file mode 100644 index 0000000000..3c467c79ac --- /dev/null +++ b/plugins/Watrack/proto/i_proto_dlg.inc @@ -0,0 +1,144 @@ +{Misc} + +procedure SetAllContactStat(hwndList:HWND); +var + hContact,hItem:THANDLE; +begin + hContact:=CallService(MS_DB_CONTACT_FINDFIRST,0,0); + while hContact<>0 do + begin + hItem:=SendMessage(hwndList,CLM_FINDCONTACT,hContact,0); + if hItem<>0 then + begin + SendMessage(hwndList,CLM_SETCHECKMARK,hItem, + DBReadByte(hContact,strCList,ShareOptText,0)); + end; + hContact:=CallService(MS_DB_CONTACT_FINDNEXT,hContact,0); + end; +end; + +procedure SaveAllContactStat(hwndList:HWND); +var + hContact,hItem:THANDLE; +begin + hContact:=CallService(MS_DB_CONTACT_FINDFIRST,0,0); + while hContact<>0 do + begin + hItem:=SendMessage(hwndList,CLM_FINDCONTACT,hContact,0); + if hItem<>0 then + begin + if SendMessage(hwndList,CLM_GETCHECKMARK,hItem,0)<>0 then + DBWriteByte(hContact,strCList,ShareOptText,1) + else + DBDeleteSetting(hContact,strCList,ShareOptText); + end; + hContact:=CallService(MS_DB_CONTACT_FINDNEXT,hContact,0); + end; +end; + +procedure ResetListOptions(hwndList:HWND); +var + i:integer; +begin + SendMessage(hwndList,CLM_SETBKBITMAP ,0,0); + SendMessage(hwndList,CLM_SETBKCOLOR ,GetSysColor(COLOR_WINDOW),0); + SendMessage(hwndList,CLM_SETGREYOUTFLAGS,0,0); + SendMessage(hwndList,CLM_SETLEFTMARGIN ,2,0); + SendMessage(hwndList,CLM_SETINDENT ,10,0); + for i:=0 to FONTID_MAX do + SendMessage(hwndList,CLM_SETTEXTCOLOR,i,GetSysColor(COLOR_WINDOWTEXT)); + SetWindowLongPtr(hwndList,GWL_STYLE,GetWindowLongPtr(hwndList,GWL_STYLE) or CLS_SHOWHIDDEN); +end; + +procedure SetHistMask(Dlg:HWND); +begin + CheckDlgButton(Dlg,IDC_IN_REQUEST ,ORD((HistMask and hmInRequest )<>0)); + CheckDlgButton(Dlg,IDC_OUT_REQUEST,ORD((HistMask and hmOutRequest)<>0)); + CheckDlgButton(Dlg,IDC_IN_INFO ,ORD((HistMask and hmInInfo )<>0)); + CheckDlgButton(Dlg,IDC_OUT_INFO ,ORD((HistMask and hmOutInfo )<>0)); + CheckDlgButton(Dlg,IDC_IN_ERROR ,ORD((HistMask and hmInError )<>0)); + CheckDlgButton(Dlg,IDC_OUT_ERROR ,ORD((HistMask and hmOutError )<>0)); + CheckDlgButton(Dlg,IDC_IREQUEST ,ORD((HistMask and hmIRequest )<>0)); + CheckDlgButton(Dlg,IDC_ISEND ,ORD((HistMask and hmISend )<>0)); +end; + +procedure SaveHistMask(Dlg:HWND); +begin + HistMask:=0; + if IsDlgButtonChecked(Dlg,IDC_IN_REQUEST )<>BST_UNCHECKED then HistMask:=HistMask or hmInRequest; + if IsDlgButtonChecked(Dlg,IDC_OUT_REQUEST)<>BST_UNCHECKED then HistMask:=HistMask or hmOutRequest; + if IsDlgButtonChecked(Dlg,IDC_IN_INFO )<>BST_UNCHECKED then HistMask:=HistMask or hmInInfo; + if IsDlgButtonChecked(Dlg,IDC_OUT_INFO )<>BST_UNCHECKED then HistMask:=HistMask or hmOutInfo; + if IsDlgButtonChecked(Dlg,IDC_IN_ERROR )<>BST_UNCHECKED then HistMask:=HistMask or hmInError; + if IsDlgButtonChecked(Dlg,IDC_OUT_ERROR )<>BST_UNCHECKED then HistMask:=HistMask or hmOutError; + if IsDlgButtonChecked(Dlg,IDC_IREQUEST )<>BST_UNCHECKED then HistMask:=HistMask or hmIRequest; + if IsDlgButtonChecked(Dlg,IDC_ISEND )<>BST_UNCHECKED then HistMask:=HistMask or hmISend; +end; + +function DlgProcOptions(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +const + Changed:integer=0; +// hItemAll:THANDLE=0; +var +// cii:TCLCINFOITEM; + hList:HWND; +begin + result:=0; + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + Changed:=DLGED_INIT; + + hList:=GetDlgItem(Dialog,IDC_SHARE); + ResetListOptions(hList); + SendMessage(hList,CLM_SETUSEGROUPS ,1,0); + SendMessage(hList,CLM_SETHIDEEMPTYGROUPS,1,0); + +// SendMessage(hList,CLM_SETEXTRACOLUMNS,2,0); +{ + FillChar(cii,SizeOf(cii),0); + cii.cbSize :=SizeOf(cii); + cii.flags :=CLCIIF_GROUPFONT or CLCIIF_CHECKBOX; + cii.pszText.w:=TranslateW('** All contacts **'); + hItemAll:=SendMessage(hList,CLM_ADDINFOITEM,0,dword(@cii)); +} + SetAllContactStat(hList); + SetHistMask(Dialog); + + SetDlgItemTextW(Dialog,IDC_PROTO_TEXT,ProtoText); + + Changed:=0; + end; + + WM_COMMAND: begin + if Changed<>DLGED_INIT then + begin + case wParam shr 16 of + BN_CLICKED,EN_CHANGE: SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + end; + + WM_NOTIFY: begin + if Changed<>DLGED_INIT then + begin + if PNMHDR(lParam)^.idFrom=IDC_SHARE then + if integer(PNMHdr(lParam)^.code)=CLN_CHECKCHANGED then + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + + if integer(PNMHdr(lParam)^.code)=PSN_APPLY then + begin + mFreeMem(ProtoText); + ProtoText:=GetDlgText(Dialog,IDC_PROTO_TEXT); + + SaveAllContactStat(GetDlgItem(Dialog,IDC_SHARE)); + SaveHistMask(Dialog); + + WriteOptions; + end; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/proto/i_proto_opt.inc b/plugins/Watrack/proto/i_proto_opt.inc new file mode 100644 index 0000000000..c1e2cbf36d --- /dev/null +++ b/plugins/Watrack/proto/i_proto_opt.inc @@ -0,0 +1,35 @@ +{} +const + defProtoText = '%artist% - %title%'; +const + opt_ModStatus:PAnsiChar = 'module/protocol'; + + opt_histmask :PAnsiChar = 'historymask'; + opt_prototext:PAnsiChar = 'prototext'; + +function GetModStatus:integer; +begin + result:=DBReadByte(0,PluginShort,opt_ModStatus,1); +end; + +procedure SetModStatus(stat:integer); +begin + DBWriteByte(0,PluginShort,opt_ModStatus,stat); +end; + +procedure ReadOptions; +begin + HistMask :=DBReadWord (0,PluginShort,opt_histmask,0); + ProtoText:=DBReadUnicode(0,PluginShort,opt_prototext,defProtoText); +end; + +procedure WriteOptions; +begin + DBWriteWord (0,PluginShort,opt_histmask ,HistMask); + DBWriteUnicode(0,PluginShort,opt_prototext,ProtoText); +end; + +procedure FreeOptions; +begin + mFreeMem(ProtoText); +end; diff --git a/plugins/Watrack/proto/i_proto_rc.inc b/plugins/Watrack/proto/i_proto_rc.inc new file mode 100644 index 0000000000..f2d56ad329 --- /dev/null +++ b/plugins/Watrack/proto/i_proto_rc.inc @@ -0,0 +1,17 @@ +const + IDC_EXPORT = 1031; + IDC_SHARE = 1033; + IDC_IN_REQUEST = 1034; + IDC_OUT_REQUEST = 1035; + IDC_IN_INFO = 1036; + IDC_OUT_INFO = 1037; + IDC_IN_ERROR = 1038; + IDC_OUT_ERROR = 1039; + IDC_IREQUEST = 1040; + IDC_ISEND = 1041; + IDC_STAT_EXPORT = 1042; + IDC_STAT_TEXP = 1043; + IDC_STAT_LINE = 1044; + IDC_PROTO_TEXT = 1045; + +BTN_CONTEXT = 130; diff --git a/plugins/Watrack/proto/proto.pas b/plugins/Watrack/proto/proto.pas new file mode 100644 index 0000000000..254a02bac6 --- /dev/null +++ b/plugins/Watrack/proto/proto.pas @@ -0,0 +1,564 @@ +{Statistic} +unit proto; +{$include compilers.inc} +interface +{$Resource proto.res} +implementation + +uses + windows,messages,commctrl, + common,m_api,mirutils,dbsettings,wrapper, + global,wat_api; + +{$include i_proto_rc.inc} + +const + ShareOptText = 'ShareMusic'; +const + IcoBtnContext:PAnsiChar='WATrack_Context'; +const + MenuUserInfoPos = 500050000; + +const + wpRequest = 'WAT###0_'; + wpAnswer = 'WAT###1_'; + wpError = 'WAT###2_'; + wpMessage = 'WAT###3_'; + wpRequestNew = 'ASKWAT'; + +const + SendRequestText:PAnsiChar = + 'WATrack internal info - sorry!'; +{ + 'If you see this message, probably you have no "WATrack" plugin installed or uses old '+ + 'version. See http://miranda-im.org/download/details.php?action=viewfile&id=2345 or '+ + 'http://awkward.miranda.im/ (beta versions) for more information and download.'; +} +const + hmInRequest = $0001; + hmOutRequest = $0002; + hmInInfo = $0004; + hmOutInfo = $0008; + hmInError = $0010; + hmOutError = $0020; + hmIRequest = $0040; + hmISend = $0080; + +var + hSRM, + hGCI, + icchangedhook, + hAddUserHook, + hContactMenuItem, + contexthook:THANDLE; + ProtoText:pWideChar; + HistMask:cardinal; + +{$include i_proto_opt.inc} +{$include i_proto_dlg.inc} + +procedure AddEvent(hContact:THANDLE;atype,flag:integer;data:pointer;size:integer;time:dword=0); +var + dbeo:TDBEVENTINFO; +begin + FillChar(dbeo,SizeOf(dbeo),0); + with dbeo do + begin + cbSize :=SizeOf(dbeo); + eventType:=atype; + szModule :=PluginShort; + if data=nil then + begin + PAnsiChar(data):=''; + size:=1; + end; + pBlob :=data; + cbBlob :=size; + flags :=flag; + if time<>0 then + Timestamp:=time + else + Timestamp:=GetCurrentTime; + end; + CallService(MS_DB_EVENT_ADD,hContact,lparam(@dbeo)); +end; + +{SEND-time text translation} +(* +const + BufSize = 16384; + +function FormatToBBW(src:PWideChar):PWideChar; +var + buf:array [0..32] of WideChar; + p:PWideChar; + i,j:integer; +begin + result:=src; + StrReplaceW(src,'{b}' ,'[b]'); + StrReplaceW(src,'{/b}' ,'[/b]'); + StrReplaceW(src,'{u}' ,'[u]'); + StrReplaceW(src,'{/u}' ,'[/u]'); + StrReplaceW(src,'{i}' ,'[i]'); + StrReplaceW(src,'{/i}' ,'[/i]'); + StrReplaceW(src,'{/cf}','[/color]'); + StrReplaceW(src,'{/bg}',''); + StrCopyW(buf,'[color='); + repeat + i:=StrPosW(src,'{cf'); + if i=0 then break; + j:=i; + dec(i); + while (src[j]<>#0) and (src[j]<>'}') do inc(j); + if src[j]='}' then inc(j); + case StrToInt(src+i+3) of + 4,10: p:='green]'; + 5,6: p:='red]'; + 7,14: p:='magenta]'; + 3,11, + 12,13: p:='blue]'; + 8,9: p:='yellow]'; + 2,15: p:='black]'; + else + {1,16:} p:='white]'; + end; + StrCopyW(buf+7,p); + StrCopyW(src+i,src+j); + StrInsertW(buf,src,i); + until false; + repeat + i:=StrIndex(src,'{bg'); + if i=0 then break; + j:=i; + dec(i); + while (src[j]<>#0) and (src[j]<>'}') do inc(j); + if src[j]='}' then inc(j); + StrCopyW(src+i,src+j); + until false; +end; + +function SendMessageProcW(wParam:WPARAM; lParam:LPARAM):integer; cdecl; +var + ccs:PCCSDATA; + uns,s,ss:pWideChar; + p:PAnsiChar; + present:boolean; + i:integer; +begin + if DisablePlugin<>dsPermanent then + begin + ccs:=PCCSDATA(lParam); + if ccs^.wParam=0 then + present:=StrPos('%music%',PAnsiChar(ccs^.lParam))<>nil + else // not needed? + begin + uns:=PWideChar(ccs^.lParam+StrLen(PAnsiChar(ccs^.lParam))+1); + present:=StrPos(uns,'%music%')<>nil; + end; + + if present then + begin + if CallService(MS_WAT_GETMUSICINFO,0,0)=WAT_PLS_NOTFOUND then + s:=nil + else + begin + if SimpleMode<>BST_UNCHECKED then + i:=0 + else + i:=CallService(MS_PROTO_GETCONTACTBASEPROTO,ccs^.hContact,0); + s:=GetMacros(TM_MESSAGE,i); + end; + // if s<>nil then // for empty strings + begin + mGetMem(ss,BufSize*SizeOf(pWideChar)); + FillChar(ss^,BufSize*SizeOf(pWideChar),0); + if ccs^.wParam=0 then + AnsiToWide(PAnsiChar(ccs^.lParam),uns,UserCP); + StrCopyW(ss,uns); + if ccs^.wParam=0 then + mFreeMem(uns); + StrReplaceW(ss,'%music%',s); + mFreeMem(s); + if StrPos(ss,'{')<>nil then + FormatToBBW(ss); + s:=PWideChar(ccs^.lParam); + WideToAnsi(ss,p,UserCP); + if ccs^.wParam=0 then + begin + ccs^.lParam:=dword(p); + end + else + begin + move(PAnsiChar(ss)^,(PAnsiChar(ss)+StrLen(p)+1)^, + (StrLenW(ss)+1)*SizeOf(WideChar)); + StrCopy(PAnsiChar(ss),p); + ccs^.lParam:=dword(ss); + end; + result:=CallService(MS_PROTO_CHAINSEND,wParam,lParam); + mFreeMem(p); + ccs^.lParam:=dword(s); + mFreeMem(ss); + exit; + end; + end; + end; + result:=CallService(MS_PROTO_CHAINSEND,wParam,lParam); +end; +*) + +function ReceiveMessageProcW(wParam:WPARAM; lParam:LPARAM):integer; cdecl; +const + bufsize = 4096*SizeOf(WideChar); +var + ccs:PCCSDATA; + s:pWideChar; + buf:PWideChar; + base64:TNETLIBBASE64; +// pos_artist,pos_title,pos_album:PwideChar; + pos_template:pWideChar; + curpos:pWideChar; + encbuf:pWideChar; + i:integer; + textpos:PWideChar; + pc:PAnsiChar; + isNewRequest:bool; + si:pSongInfo; +begin + ccs:=PCCSDATA(lParam); + result:=0; + mGetMem(buf,bufsize); + + isNewRequest:=StrCmp(PPROTORECVEVENT(ccs^.lParam)^.szMessage.a, + wpRequestNew,Length(wpRequestNew))=0; + + if isNewRequest or + (StrCmp(PPROTORECVEVENT(ccs^.lParam)^.szMessage.a, + wpRequest,Length(wpRequest))=0) then + begin + StrCopy(PAnsiChar(buf),PAnsiChar(CallService(MS_PROTO_GETCONTACTBASEPROTO,ccs^.hContact,0))); + i:=DBReadWord(ccs^.hContact,PAnsiChar(buf),'ApparentMode'); + StrCat(PAnsiChar(buf),PS_GETSTATUS); + if (i=ID_STATUS_OFFLINE) or + ((i=0) and (CallService(PAnsiChar(buf),0,0)=ID_STATUS_INVISIBLE)) then + begin + result:=CallService(MS_PROTO_CHAINRECV,wParam,lParam); + end + else if DBReadByte(ccs^.hContact,strCList,ShareOptText,0)<>0 then +// or (NotListedAllow and (DBReadByte(ccs^.hContact,strCList,'NotOnList',0)) + begin + if (HistMask and hmInRequest)<>0 then + AddEvent(ccs^.hContact,EVENTTYPE_WAT_REQUEST,DBEF_READ,nil,0, + PPROTORECVEVENT(ccs^.lParam)^.Timestamp); + if GetContactStatus(ccs^.hContact)<>ID_STATUS_OFFLINE then + begin +//!! Request Answer + curpos:=nil; + if DisablePlugin<>dsPermanent then + begin + if CallService(MS_WAT_GETMUSICINFO,0,0)=WAT_PLS_NOTFOUND then + begin + s:=#0#0#0'No player found at this time'; + textpos:=s+3; + end + else + begin + if not isNewRequest then + begin + FillChar(buf^,bufsize,0); + si:=pSongInfo(CallService(MS_WAT_RETURNGLOBAL,0,0)); + StrCopyW(buf ,si^.artist); curpos:=StrEndW(buf)+1; + StrCopyW(curpos,si^.title); curpos:=StrEndW(curpos)+1; + StrCopyW(curpos,si^.album); curpos:=StrEndW(curpos)+1; + end + else + curpos:=buf; +//!! check to DisableTemporary + + s:=PWideChar(CallService(MS_WAT_REPLACETEXT,0,tlparam(ProtoText))); + textpos:=StrCopyW(curpos,s); + mFreeMem(s); + curpos:=StrEndW(curpos)+1; + end; + end + else + begin + s:=#0#0#0'Sorry, but i don''t use WATrack right now!'; + textpos:=s+3; + end; +// encode + if not isNewRequest then + begin + if curpos<>nil then + begin + base64.pbDecoded:=PByte(buf); + base64.cbDecoded:=PAnsiChar(curpos)-PAnsiChar(buf); + end + else + begin + base64.pbDecoded:=PByte(s); + base64.cbDecoded:=(StrLenW(textpos)+3+1)*SizeOf(PWideChar); + end; + base64.cchEncoded:=Netlib_GetBase64EncodedBufferSize(base64.cbDecoded); + mGetMem(encbuf,base64.cchEncoded+1+Length(wpAnswer)); + base64.pszEncoded:=PAnsiChar(encbuf)+Length(wpAnswer); + StrCopy(PAnsiChar(encbuf),wpAnswer); + CallService(MS_NETLIB_BASE64ENCODE,0,tlparam(@base64)); + if (HistMask and hmOutInfo)<>0 then + AddEvent(ccs^.hContact,EVENTTYPE_WAT_ANSWER,DBEF_SENT, + base64.pbDecoded,base64.cbDecoded); + CallContactService(ccs^.hContact,PSS_MESSAGE,0,tlparam(encbuf)); + end + else + begin + i:=WideToCombo(textpos,encbuf,UserCP); + if (HistMask and hmOutInfo)<>0 then + AddEvent(ccs^.hContact,EVENTTYPE_WAT_MESSAGE,DBEF_SENT,encbuf,i); +// if CallContactService(ccs^.hContact,PSS_MESSAGEW,PREF_UNICODE,dword(encbuf))= +// ACKRESULT_FAILED then + CallContactService(ccs^.hContact,PSS_MESSAGE,PREF_UNICODE,tlparam(encbuf)); + end; + mFreeMem(encbuf); + end; + end + else + begin + if (HistMask and hmIRequest)<>0 then + AddEvent(ccs^.hContact,EVENTTYPE_WAT_REQUEST,DBEF_READ,nil,0, + PPROTORECVEVENT(ccs^.lParam)^.Timestamp); + if (HistMask and hmISend)<>0 then + begin +//!! Request Error Answer + if isNewRequest then + pc:=PAnsiChar(buf) + else + begin + StrCopy(PAnsiChar(buf),wpError); + pc:=PAnsiChar(buf)+Length(wpError); + end; + StrCopy(pc,'Sorry, but you have no permission to obtain this info!'); + CallContactService(ccs^.hContact,PSS_MESSAGE,0,tlparam(buf)); + if (HistMask and hmOutError)<>0 then + begin + AddEvent(ccs^.hContact,EVENTTYPE_WAT_ERROR,DBEF_SENT,nil,0, + PPROTORECVEVENT(ccs^.lParam)^.Timestamp); + end; + end; + end; + end + else if StrCmp(PPROTORECVEVENT(ccs^.lParam)^.szMessage.a,wpAnswer,Length(wpAnswer))=0 then + begin +// decode + base64.pszEncoded:=PPROTORECVEVENT(ccs^.lParam)^.szMessage.a+Length(wpAnswer); + base64.cchEncoded:=StrLen(base64.pszEncoded); + base64.cbDecoded :=Netlib_GetBase64DecodedBufferSize(base64.cchEncoded); + mGetMem(base64.pbDecoded,base64.cbDecoded); + + CallService(MS_NETLIB_BASE64DECODE,0,tlparam(@base64)); + + curpos:=pWideChar(base64.pbDecoded); // pos_artist:=curpos; + while curpos^<>#0 do inc(curpos); inc(curpos); // pos_title :=curpos; + while curpos^<>#0 do inc(curpos); inc(curpos); // pos_album :=curpos; + while curpos^<>#0 do inc(curpos); inc(curpos); + pos_template:=curpos; + + if (HistMask and hmInInfo)<>0 then + AddEvent(ccs^.hContact,EVENTTYPE_WAT_ANSWER,DBEF_READ, + base64.pbDecoded,base64.cbDecoded, + PPROTORECVEVENT(ccs^.lParam)^.Timestamp); +// Action + + StrCopyW(buf,TranslateW('Music Info from ')); + StrCatW (buf,PWideChar(CallService(MS_CLIST_GETCONTACTDISPLAYNAME,ccs^.hContact,GCDNF_UNICODE))); + + MessageBoxW(0,TranslateW(pos_template),buf,MB_ICONINFORMATION); + + mFreeMem(base64.pbDecoded); + end + else if StrCmp(PPROTORECVEVENT(ccs^.lParam)^.szMessage.a,wpError,Length(wpError))=0 then + begin + if (HistMask and hmInError)<>0 then + AddEvent(ccs^.hContact,EVENTTYPE_WAT_ERROR,DBEF_READ,nil,0, + PPROTORECVEVENT(ccs^.lParam)^.Timestamp); +{ + AnsiToWide(PAnsiChar(CallService(MS_CLIST_GETCONTACTDISPLAYNAME,ccs^.hContact,0)),s); + StrCopyW(buf,s); + StrCatW (buf,TranslateW(' answer you')); + mFreeMem(s); +} + MessageBoxA(0,Translate(PPROTORECVEVENT(ccs^.lParam)^.szMessage.a+Length(wpError)), + Translate('You Get Error'),MB_ICONERROR); + end + else + result:=CallService(MS_PROTO_CHAINRECV,wParam,lParam); + mFreeMem(buf); +end; + +function SendRequest(hContact:WPARAM;lParam:LPARAM):integer; cdecl; +var + buf:array [0..2047] of AnsiChar; +begin + result:=0; + StrCopy(buf,wpRequest); + StrCopy(buf+Length(wpRequest),SendRequestText); + CallContactService(hContact,PSS_MESSAGE,0,tlparam(@buf)); + if (HistMask and hmOutRequest)<>0 then + AddEvent(hContact,EVENTTYPE_WAT_REQUEST,DBEF_SENT,nil,0); +end; + +procedure RegisterContacts; +var + hContact:integer; +begin + hContact:=CallService(MS_DB_CONTACT_FINDFIRST,0,0); + while hContact<>0 do + begin + if not IsChat(hContact) then + CallService(MS_PROTO_ADDTOCONTACT,hContact,lparam(PluginShort)); + hContact:=CallService(MS_DB_CONTACT_FINDNEXT,hContact,0); + end; +end; + +function HookAddUser(hContact:WPARAM;lParam:LPARAM):integer; cdecl; +begin + result:=0; + if not IsChat(hContact) then + CallService(MS_PROTO_ADDTOCONTACT,hContact,tlparam(PluginShort)); +end; + +function OnContactMenu(hContact:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; +begin + FillChar(mi,SizeOf(mi),0); + mi.cbSize:=sizeof(mi); + if IsMirandaUser(hContact)<=0 then + mi.flags:=CMIF_NOTOFFLINE or CMIF_NOTOFFLIST or CMIM_FLAGS or CMIF_HIDDEN + else + mi.flags:=CMIF_NOTOFFLINE or CMIF_NOTOFFLIST or CMIM_FLAGS; + CallService(MS_CLIST_MODIFYMENUITEM,hContactMenuItem,tlparam(@mi)); + result:=0; +end; + +procedure SetProtocol; +var + desc:TPROTOCOLDESCRIPTOR; +begin + desc.cbSize:=PROTOCOLDESCRIPTOR_V3_SIZE;//SizeOf(desc); + desc.szName:=PluginShort; + desc._type :=PROTOTYPE_TRANSLATION; + + CallService(MS_PROTO_REGISTERMODULE,0,lparam(@desc)); +// CreateProtoServiceFunction(PluginShort,PSS_MESSAGE ,@SendMessageProcW); +// CreateProtoServiceFunction(PluginShort,PSS_MESSAGEW,@SendMessageProcW); + hSRM:=CreateProtoServiceFunction(PluginShort,PSR_MESSAGE ,@ReceiveMessageProcW); +// CreateProtoServiceFunction(PluginShort,PSR_MESSAGEW,@ReceiveMessageProcW); +end; + +function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; +begin + result:=0; + FillChar(mi,SizeOf(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_ICON; + + mi.hIcon:=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnContext)); + CallService(MS_CLIST_MODIFYMENUITEM,hContactMenuItem,tlparam(@mi)); +end; + +procedure RegisterIcons; +var + sid:TSKINICONDESC; +begin + FillChar(sid,SizeOf(TSKINICONDESC),0); + sid.cbSize:=SizeOf(TSKINICONDESC); + sid.cx:=16; + sid.cy:=16; + sid.szSection.a:=PluginShort; + + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(BTN_CONTEXT),IMAGE_ICON,16,16,0); + sid.pszName :=IcoBtnContext; + sid.szDescription.a:='Context Menu'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); +//!! + icchangedhook:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged); +end; + +// ------------ base interface functions ------------- + +function InitProc(aGetStatus:boolean=false):integer; +var + mi:TCListMenuItem; +begin + if aGetStatus then + begin + if GetModStatus=0 then + begin + result:=0; + exit; + end; + end + else + SetModStatus(1); + result:=1; + + ReadOptions; + RegisterIcons; + + FillChar(mi, sizeof(mi), 0); + mi.cbSize :=sizeof(mi); + mi.szPopupName.a:=PluginShort; + mi.flags :=CMIF_NOTOFFLINE or CMIF_NOTOFFLIST; +// mi.popupPosition:=MenuUserInfoPos; + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,lparam(IcoBtnContext)); + mi.szName.a :='Get user''s Music Info'; + mi.pszService :=MS_WAT_GETCONTACTINFO; + hContactMenuItem:=Menu_AddContactMenuItem(@mi); + + SetProtocol; + RegisterContacts; + hGCI:=CreateServiceFunction(MS_WAT_GETCONTACTINFO,@SendRequest); + contexthook :=HookEvent(ME_CLIST_PREBUILDCONTACTMENU,@OnContactMenu); + hAddUserHook:=HookEvent(ME_DB_CONTACT_ADDED ,@HookAddUser); +end; + +procedure DeInitProc(aSetDisable:boolean); +begin + if aSetDisable then + SetModStatus(0); + + UnhookEvent(hAddUserHook); + UnhookEvent(contexthook); + UnhookEvent(icchangedhook); + + DestroyServiceFunction(hSRM); + DestroyServiceFunction(hGCI); + mFreeMem(ProtoText); +end; + +function AddOptionsPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +begin + tmpl:='MISC'; + proc:=@DlgProcOptions; + name:='Misc'; + result:=0; +end; + +var + vproto:twModule; + +procedure Init; +begin + vproto.Next :=ModuleLink; + vproto.Init :=@InitProc; + vproto.DeInit :=@DeInitProc; + vproto.AddOption :=@AddOptionsPage; + vproto.ModuleName:='Protocol'; + ModuleLink :=@vproto; +end; + +begin + Init; +end. diff --git a/plugins/Watrack/proto/proto.rc b/plugins/Watrack/proto/proto.rc new file mode 100644 index 0000000000..dcf5be2faa --- /dev/null +++ b/plugins/Watrack/proto/proto.rc @@ -0,0 +1,36 @@ +#include "i_proto_rc.inc" + +LANGUAGE 0,0 + +MISC DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + CONTROL "",IDC_SHARE, "CListControl", WS_TABSTOP | 0x3CA, 4, 4, 144, 180, WS_EX_CLIENTEDGE + + CTEXT "Save events in database",-1, 154, 4, 144, 12, SS_CENTERIMAGE + LTEXT "Input" ,-1, 154, 16, 70, 12, SS_CENTERIMAGE + RTEXT "Output" ,-1, 226, 16, 70, 12, SS_CENTERIMAGE + + CTEXT "Music Info Request",-1, 170, 30, 112, 14, SS_CENTERIMAGE + AUTOCHECKBOX "", IDC_IN_REQUEST , 154, 30, 14, 14, BS_VCENTER | BS_NOTIFY + AUTOCHECKBOX "", IDC_OUT_REQUEST , 284, 30, 14, 14, BS_VCENTER | BS_NOTIFY | BS_RIGHT | BS_LEFTTEXT + + CTEXT "Music Info" ,-1, 170, 44, 112, 14, SS_CENTERIMAGE + AUTOCHECKBOX "", IDC_IN_INFO , 154, 44, 14, 14, BS_VCENTER | BS_NOTIFY + AUTOCHECKBOX "", IDC_OUT_INFO , 284, 44, 14, 14, BS_VCENTER | BS_NOTIFY | BS_RIGHT | BS_LEFTTEXT + + CTEXT "Request Error" ,-1, 170, 58, 112, 14, SS_CENTERIMAGE + AUTOCHECKBOX "", IDC_IN_ERROR , 154, 58, 14, 14, BS_VCENTER | BS_NOTIFY + AUTOCHECKBOX "", IDC_OUT_ERROR , 284, 58, 14, 14, BS_VCENTER | BS_NOTIFY | BS_RIGHT | BS_LEFTTEXT + + AUTOCHECKBOX "Save ignored requests" , IDC_IREQUEST, 154, 76, 144, 14, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Answer to ignored requests", IDC_ISEND , 154, 90, 144, 14, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + + RTEXT "User music info text", -1, 154, 154, 142, 10 + RTEXT "(%artist%, %title%, %album% and %year% macros can be used only)", -1, 154, 164, 142, 22 + EDITTEXT IDC_PROTO_TEXT, 4, 186, 296, 36, ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN +} + +BTN_CONTEXT ICON "wat_context.ico" diff --git a/plugins/Watrack/proto/proto.res b/plugins/Watrack/proto/proto.res new file mode 100644 index 0000000000..7899ef50cc Binary files /dev/null and b/plugins/Watrack/proto/proto.res differ diff --git a/plugins/Watrack/proto/wat_context.ico b/plugins/Watrack/proto/wat_context.ico new file mode 100644 index 0000000000..37d8413c66 Binary files /dev/null and b/plugins/Watrack/proto/wat_context.ico differ diff --git a/plugins/Watrack/res/i_const.inc b/plugins/Watrack/res/i_const.inc new file mode 100644 index 0000000000..b1cafde523 --- /dev/null +++ b/plugins/Watrack/res/i_const.inc @@ -0,0 +1,27 @@ +const + IDC_FIRST = 1025; + +{DLG 1 - base} +const + IDC_CODEPAGE = 1025; + IDC_TIMER = 1026; + IDC_CHECKTIME = 1027; + IDC_IMPLANTANT = 1028; + IDC_MTHCHECK = 1029; + IDC_KEEPOLD = 1030; + IDC_STAT_TIMER = 1031; + IDC_COVERFN = 1032; + IDC_PLAYERLIST = 1033; + IDC_FORMATLIST = 1034; + IDC_CHK_PLAYER = 1035; + IDC_CHK_FORMAT = 1036; + IDC_APPCOMMAND = 1037; + IDC_CHECKALL = 1038; + IDC_TIMEOUT = 1039; + +{DLG 0 - modules} + IDC_MODULEGROUP = 1025; + +{Icons - same as in waticons.inc} +IDI_PLUGIN_ENABLE = 100; +IDI_PLUGIN_DISABLE = 101; diff --git a/plugins/Watrack/res/wat_disable.ico b/plugins/Watrack/res/wat_disable.ico new file mode 100644 index 0000000000..390f0852a2 Binary files /dev/null and b/plugins/Watrack/res/wat_disable.ico differ diff --git a/plugins/Watrack/res/wat_enable.ico b/plugins/Watrack/res/wat_enable.ico new file mode 100644 index 0000000000..0e20d3a616 Binary files /dev/null and b/plugins/Watrack/res/wat_enable.ico differ diff --git a/plugins/Watrack/res/watrack.rc b/plugins/Watrack/res/watrack.rc new file mode 100644 index 0000000000..2d3e6585d2 --- /dev/null +++ b/plugins/Watrack/res/watrack.rc @@ -0,0 +1,104 @@ +#include "i_const.inc" + +LANGUAGE 0,0 + +BASIC DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + CTEXT "Unicode to Ansi translation codepage:", -1, 192, 2, 108, 20 + COMBOBOX IDC_CODEPAGE, 192, 22, 108, 56, CBS_DROPDOWNLIST | WS_VSCROLL | NOT WS_TABSTOP + CTEXT "Refresh time, sec", IDC_STAT_TIMER, 226, 36, 76, 16, SS_CENTERIMAGE + EDITTEXT IDC_TIMER, 192, 38, 32, 12, ES_RIGHT | ES_NUMBER + AUTOCHECKBOX "Check file time" , IDC_CHECKTIME , 192, 52, 108, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Keep old file" , IDC_KEEPOLD , 192, 68, 108, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Emulate Multimedia keys" , IDC_APPCOMMAND, 192, 84, 108, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Use process implantation" , IDC_IMPLANTANT, 192, 100, 108, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Check all players" , IDC_CHECKALL , 192, 116, 108, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + AUTOCHECKBOX "Other thread handle check" , IDC_MTHCHECK , 192, 132, 108, 16, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + + EDITTEXT IDC_TIMEOUT , 192, 149, 20, 12, ES_RIGHT | ES_NUMBER + LTEXT "Timeout, ms", -1, 214, 148, 86, 14, SS_CENTERIMAGE + + CONTROL "", IDC_PLAYERLIST, "SysListView32", + WS_BORDER | WS_TABSTOP | LVS_NOCOLUMNHEADER | LVS_SHOWSELALWAYS | LVS_SINGLESEL | LVS_REPORT, + 2, 18, 120, 190, WS_EX_CONTROLPARENT + CONTROL "", IDC_FORMATLIST, "SysListView32", + WS_BORDER | WS_TABSTOP | LVS_NOCOLUMNHEADER | LVS_SHOWSELALWAYS | LVS_SINGLESEL | LVS_REPORT, + 125, 18, 60, 190, WS_EX_CONTROLPARENT + CTEXT "Formats", -1, 125, 4, 64, 12 + CTEXT "Players list\n(F1 for note)", -1, 2, 0, 120, 18 + CTEXT "Check", -1, 2, 210, 72, 12, SS_CENTERIMAGE + PUSHBUTTON "None", IDC_CHK_PLAYER, 74, 210, 48, 12 + PUSHBUTTON "None", IDC_CHK_FORMAT, 125, 210, 60, 12 + + CTEXT "Cover filenames", -1, 192, 164, 108, 10 + EDITTEXT IDC_COVERFN, 192, 174, 108, 48, ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN +} + +COLOR DIALOGEX 0, 0, 96, 116, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_VISIBLE | WS_CAPTION +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "Color codes" +FONT 8, "MS Shell Dlg", 0, 0 +{ + DEFPUSHBUTTON "OK", IDOK, 35, 98, 26, 16, NOT WS_TABSTOP + RTEXT "1", -1, 4, 6, 10, 10 + RTEXT "2", -1, 4, 17, 10, 10 + RTEXT "3", -1, 4, 28, 10, 10 + RTEXT "4", -1, 4, 39, 10, 10 + RTEXT "5", -1, 4, 50, 10, 10 + RTEXT "6", -1, 4, 61, 10, 10 + RTEXT "7", -1, 4, 72, 10, 10 + RTEXT "8", -1, 4, 83, 10, 10 + RTEXT "9", -1, 46, 6, 10, 10 + RTEXT "10", -1, 46, 17, 10, 10 + RTEXT "11", -1, 46, 28, 10, 10 + RTEXT "12", -1, 46, 39, 10, 10 + RTEXT "13", -1, 46, 50, 10, 10 + RTEXT "14", -1, 46, 61, 10, 10 + RTEXT "15", -1, 46, 72, 10, 10 + RTEXT "16", -1, 46, 83, 10, 10 +} + +IDI_PLUGIN_ENABLE ICON "wat_enable.ico" +IDI_PLUGIN_DISABLE ICON "wat_disable.ico" + +PARTS DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + GROUPBOX "Switch ON these modules", IDC_MODULEGROUP, 2, 2, 188, 218, WS_TABSTOP +} + +LANGUAGE 0,0 +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,6,12 + PRODUCTVERSION 0,0,6,12 + FILEFLAGSMASK $3F + FILEOS 4 + FILETYPE 2 + FILESUBTYPE 0 +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "CompanyName","" + VALUE "Comments", "Plugin to get, insert to messages and show currently played song info" + VALUE "FileDescription", "WATrack plugin for Miranda NG" + VALUE "FileVersion", "0, 0, 6, 12 "0 + VALUE "InternalName", "WATrack" + VALUE "OriginalFilename", "watrack.dll" + VALUE "ProductName", " WATrack Dynamic Link Library (DLL)" + VALUE "ProductVersion", "0, 0, 6, 12 "0 + VALUE "SpecialBuild", "17.11.2009 "0 + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation",0,1200 + END +END diff --git a/plugins/Watrack/res/watrack.res b/plugins/Watrack/res/watrack.res new file mode 100644 index 0000000000..3c2d4932df Binary files /dev/null and b/plugins/Watrack/res/watrack.res differ diff --git a/plugins/Watrack/srv_format.pas b/plugins/Watrack/srv_format.pas new file mode 100644 index 0000000000..aa892bb7da --- /dev/null +++ b/plugins/Watrack/srv_format.pas @@ -0,0 +1,394 @@ +{format service} +unit srv_format; + +interface + +uses windows,wat_api; + +procedure DefFillFormatList (hwndList:hwnd); +procedure DefCheckFormatList(hwndList:hwnd); +function ProcessFormatLink:integer; + +function GetFileFormatInfo(var dst:tSongInfo):integer; +function CheckExt(fname:pWideChar):integer; + +function DeleteKnownExt(src:pWideChar):pWideChar; +function KnownFileType(fname:PWideChar):boolean; +function isContainer(fname:PWideChar):boolean; + +function ServiceFormat(wParam:WPARAM;lParam:LPARAM):integer;cdecl; +procedure RegisterFormat(ext:PAnsiChar;proc:tReadFormatProc;flags:dword=0); +procedure ClearFormats; + +type + MusEnumProc = function(param:PAnsiChar;lParam:LPARAM):bool;stdcall; + +function EnumFormats(param:MusEnumProc;lParam:LPARAM):bool; + +type + pwFormat = ^twFormat; + twFormat = record + This:tMusicFormat; + Next:pwFormat; + end; + +const + FormatLink:pwFormat=nil; + +implementation + +uses + CommCtrl,common; +type + pFmtArray = ^tFmtArray; + tFmtArray = array [0..10] of tMusicFormat; + +const + StartSize = 32; + Step = 8; + +const + fmtLink:pFmtArray=nil; + FmtNum:integer=0; + FmtMax:integer=0; + +function ProcessFormatLink:integer; +var + ptr:pwFormat; +begin + result:=0; + ptr:=FormatLink; + while ptr<>nil do + begin + RegisterFormat(@ptr.This.ext,ptr.This.proc,ptr.This.flags); + inc(result); + ptr:=ptr^.Next; + end; +end; + +function EnumFormats(param:MusEnumProc;lParam:LPARAM):bool; +var + tmp:pFmtArray; + i,j:integer; + s:array [0..8] of AnsiChar; +begin + if (FmtNum>0) and (@param<>nil) then + begin + GetMem(tmp,FmtNum*SizeOf(tMusicFormat)); + move(fmtLink^,tmp^,FmtNum*SizeOf(tMusicFormat)); + i:=0; + j:=FmtNum; + s[8]:=#0; + repeat + move(tmp^[i].ext,s,8); + if not param(s,lParam) then break; + inc(i); + until i=j; + FreeMem(tmp); + result:=true; + end + else + result:=false; +end; + +function FindFormat(ext:PAnsiChar):integer; +var + i:integer; + ss:array [0..7] of AnsiChar; +begin + i:=0; + int64(ss):=0; + StrCopy(ss,ext,7); + while i=0 then + begin + if (p^.flags and WAT_OPT_DISABLED)=0 then + ListView_SetCheckState(hwndList,newItem,TRUE); + end; + inc(i); + end; + ListView_SetColumnWidth(hwndList,0,LVSCW_AUTOSIZE); +end; + +procedure DefCheckFormatList(hwndList:hwnd); +var + i,j,k:integer; + item:LV_ITEMA; + szTemp:array [0..109] of AnsiChar; + p:pMusicFormat; +begin + FillChar(item,SizeOf(item),0); + item.mask:=LVIF_TEXT; + item.pszText:=@szTemp; + item.cchTextMax:=100; + k:=ListView_GetItemCount(hwndList)-1; + for i:=0 to k do + begin + item.iItem:=i; + SendMessageA(hwndList,LVM_GETITEMA,0,LPARAM(@item)); + j:=FindFormat(item.pszText); + if j<>WAT_RES_NOTFOUND then // always? + begin + p:=@fmtLink^[j]; + if ListView_GetCheckState(hwndList,i)=0 then + p^.flags:=p^.flags or WAT_OPT_DISABLED + else + p^.flags:=p^.flags and not WAT_OPT_DISABLED; + end; + end; +end; + +function DeleteKnownExt(src:pWideChar):pWideChar; +var + s :array [0..7] of WideChar; + ss:array [0..7] of AnsiChar; + i,j:integer; +begin + GetExt(src,s); + if s[0]<>#0 then + begin + int64(ss):=0; + i:=0; + while (s[i]<>#0) and (i<8) do + begin + ss[i]:=AnsiChar(s[i]); + inc(i); + end; + j:=0; + while j#0 then + begin + i:=0; + while (s[i]<>#0) and (i<8) do + begin + ss[i]:=AnsiChar(s[i]); + inc(i); + end; + i:=0; + while i0; + end + else + result:=false; +end; + +function GetFileFormatInfo(var dst:tSongInfo):integer; +begin + result:=CheckExt(dst.mfile); + if result=WAT_RES_OK then + begin + fmtLink^[0].proc(dst); + end; +end; + +function CheckExt(fname:pWideChar):integer; +var + i:integer; + tmp:tMusicFormat; + ls:array [0..7] of WideChar; + ss:array [0..7] of AnsiChar; +begin + GetExt(fname,ls); + i:=0; + int64(ss):=0; + while (ls[i]<>#0) and (i<8) do + begin + ss[i]:=AnsiChar(ls[i]); + inc(i); + end; + i:=0; + while i0 then + begin + tmp:=fmtLink^[i]; + move(fmtLink^[0],fmtLink^[1],SizeOf(tMusicFormat)*i); + fmtLink^[0]:=tmp; + end; + result:=WAT_RES_OK; + exit; + end + else + break; + end; + inc(i); + end; + result:=WAT_RES_NOTFOUND; +end; + +function ServiceFormat(wParam:WPARAM;lParam:LPARAM):integer;cdecl; +var + p:integer; + nl:pFmtArray; +begin + result:=WAT_RES_NOTFOUND; + if LoWord(wParam)<>WAT_ACT_REGISTER then + p:=FindFormat(PAnsiChar(lParam)) + else + p:=0; + case LoWord(wParam) of + WAT_ACT_REGISTER: begin + if @pMusicFormat(lParam)^.proc=nil then + exit; + p:=FindFormat(pMusicFormat(lParam)^.ext); + if (p=WAT_RES_NOTFOUND) or ((wParam and WAT_ACT_REPLACE)<>0) then + begin + if (p<>WAT_RES_NOTFOUND) and ((fmtLink^[p].flags and WAT_OPT_ONLYONE)<>0) then + exit; + if FmtNum=FmtMax then // expand array when append + begin + if FmtMax=0 then + FmtMax:=StartSize + else + inc(FmtMax,Step); + GetMem(nl,FmtMax*SizeOf(tMusicFormat)); + if fmtLink<>nil then + begin + move(fmtLink^,nl^,FmtNum*SizeOf(tMusicFormat)); + FreeMem(fmtLink); + end; + fmtLink:=nl; + end; + if p=WAT_RES_NOTFOUND then + begin + p:=FmtNum; + result:=WAT_RES_OK; + inc(FmtNum); + end + else + result:=int_ptr(@fmtLink^[p].proc); + move(pMusicFormat(lParam)^,fmtLink^[p],SizeOf(tMusicFormat));// fill + end; + end; + WAT_ACT_UNREGISTER: begin + if p<>WAT_RES_NOTFOUND then + begin + dec(FmtNum); + if pWAT_RES_NOTFOUND then + begin + fmtLink^[p].flags:=fmtLink^[p].flags or WAT_OPT_DISABLED; + result:=WAT_RES_DISABLED + end; + end; + WAT_ACT_ENABLE: begin + if p<>WAT_RES_NOTFOUND then + begin + fmtLink^[p].flags:=fmtLink^[p].flags and not WAT_OPT_DISABLED; + result:=WAT_RES_ENABLED + end; + end; + WAT_ACT_GETSTATUS: begin + if p<>WAT_RES_NOTFOUND then + begin + if (fmtLink^[p].flags and WAT_OPT_DISABLED)<>0 then + result:=WAT_RES_DISABLED + else + result:=WAT_RES_ENABLED; + end; + end; + end; +end; + +procedure RegisterFormat(ext:PAnsiChar;proc:tReadFormatProc;flags:dword=0); +var + tmp:tMusicFormat; +begin + FillChar(tmp,SizeOf(tMusicFormat),0); + StrCopy (tmp.ext,ext,7); + tmp.proc:=proc; + tmp.flags:=flags; + ServiceFormat(WAT_ACT_REGISTER,LPARAM(@tmp)); +end; + +procedure ClearFormats; +begin + if FmtNum>0 then + FreeMem(fmtLink); +end; + +end. diff --git a/plugins/Watrack/srv_player.pas b/plugins/Watrack/srv_player.pas new file mode 100644 index 0000000000..60fd6534f4 --- /dev/null +++ b/plugins/Watrack/srv_player.pas @@ -0,0 +1,1220 @@ +{player service} +unit srv_player; + +interface + +uses windows,common,wat_api; + +function GetPlayerNote(name:PAnsiChar):pWideChar; + +function SetPlayerIcons(fname:pAnsiChar):integer; + +function LoadFromFile(fname:PAnsiChar):integer; +function ProcessPlayerLink:integer; + +function ServicePlayer(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +function SendCommand (wParam:WPARAM;lParam:LPARAM;flags:integer):int_ptr; + +procedure ClearPlayers; + +// options procedures +procedure DefFillPlayerList (hwndList:hwnd); +procedure DefCheckPlayerList(hwndList:hwnd); + +type + MusEnumProc = function(param:PAnsiChar;lParam:LPARAM):bool;stdcall; + +function EnumPlayers(param:MusEnumProc;lParam:LPARAM):bool; + +// "Get info" procedures +function CheckPlayers (var dst:tSongInfo;flags:cardinal):integer; +function CheckFile (var dst:tSongInfo;flags:cardinal;timeout:cardinal):integer; +function GetChangingInfo(var dst:tSongInfo;flags:cardinal):integer; +function GetInfo (var dst:tSongInfo;flags:cardinal):integer; + +// support procedures +procedure ClearSongInfoData(var dst:tSongInfo;withFree:bool); +procedure ClearPlayerInfo (var dst:tSongInfo;withFree:bool); +procedure ClearFileInfo (var dst:tSongInfo;withFree:bool); +procedure ClearChangingInfo(var dst:tSongInfo;withFree:bool); +procedure ClearTrackInfo (var dst:tSongInfo;withFree:bool); + +procedure CopyPlayerInfo (const src:tSongInfo;var dst:tSongInfo); +procedure CopyFileInfo (const src:tSongInfo;var dst:tSongInfo); +procedure CopyChangingInfo(const src:tSongInfo;var dst:tSongInfo); +procedure CopyTrackInfo (const src:tSongInfo;var dst:tSongInfo); + +type + pwPlayer = ^twPlayer; + twPlayer = record + This:pPlayerCell; + Next:pwPlayer; + end; + +const + PlayerLink:pwPlayer=nil; + +implementation + +uses + shellapi,CommCtrl + ,appcmdapi,io,syswin,wrapper,srv_format,winampapi,msninfo,memini; + +type + pPlyArray = ^tPlyArray; + tPlyArray = array [0..10] of tPlayerCell; + +type + pTmplCell = ^tTmplCell; + tTmplCell = record + p_class, + p_text :PAnsiChar; + p_class1, + p_text1 :PAnsiChar; + p_file :PAnsiChar; + p_prefix :pWideChar; + p_postfix:pWideChar; + end; + +const + StartSize = 32; + Step = 8; + buflen = 2048; + +const + plyLink:pPlyArray=nil; + PlyNum:integer=0; + PlyMax:integer=0; + +function ProcessPlayerLink:integer; +var + ptr:pwPlayer; +begin + ptr:=PlayerLink; + result:=0; + while ptr<>nil do + begin + ServicePlayer(WAT_ACT_REGISTER,lparam(ptr.This)); + ptr:=ptr^.Next; + inc(result); + end; +end; + +function SetPlayerIcons(fname:pAnsiChar):integer; +var + i,j:integer; + buf:array [0..255] of AnsiChar; + p,pp:pAnsiChar; + lhIcon:HICON; +begin + result:=LoadLibraryA(fname); + if result<>0 then + begin + p:=StrCopyE(buf,'Player_'); + i:=0; + while i0 then + begin + if Icon<>0 then + DestroyIcon(Icon); + Icon:=lhIcon; + end; + end; + inc(i); + end; + FreeLibrary(result); + end; +end; + +function EnumPlayers(param:MusEnumProc;lParam:LPARAM):bool; +var + tmp:pPlyArray; + i,j:integer; +begin + if (PlyNum>0) and (@param<>nil) then + begin + GetMem(tmp,PlyNum*SizeOf(tPlayerCell)); + move(PlyLink^,tmp^,PlyNum*SizeOf(tPlayerCell)); + i:=0; + j:=PlyNum; + repeat + if not param(tmp^[i].Desc,lParam) then break; + inc(i); + until i=j; + FreeMem(tmp); + result:=true; + end + else + result:=false; +end; + +procedure PreProcess; // BASS to start +var + i:integer; + tmp:tPlayerCell; +begin + i:=1; + while i<(PlyNum-1) do + begin + if (plyLink^[i].flags and WAT_OPT_FIRST)<>0 then + begin + tmp:=plyLink^[i]; + move(plyLink^[0],plyLink^[1],SizeOf(tPlayerCell)*i); + plyLink^[0]:=tmp; +{ + move(plyLink^[i],tmp,SizeOf(tPlayerCell)); + move(plyLink^[0],plyLink^[1],SizeOf(tPlayerCell)*i); + move(tmp,plyLink^[0],SizeOf(tPlayerCell)); +} + break; + end; + inc(i); + end; + if (plyLink^[0].flags and WAT_OPT_LAST)<>0 then + begin + tmp:=plyLink^[0]; + move(plyLink^[1],plyLink^[0],SizeOf(tPlayerCell)*(PlyNum-1)); + plyLink^[PlyNum-1]:=tmp; +{ + move(plyLink^[0],tmp,SizeOf(tPlayerCell)); + move(plyLink^[1],plyLink^[0],SizeOf(tPlayerCell)*(PlyNum-1)); + move(tmp,plyLink^[PlyNum-1],SizeOf(tPlayerCell)); +} + end; +end; + +procedure PostProcess; // Winamp clone to the end +var + i,j:integer; + tmp:tPlayerCell; +begin + i:=1; + j:=PlyNum-1; + while i0 then + begin + tmp:=plyLink^[i]; + move(plyLink^[i+1],plyLink^[i],SizeOf(tPlayerCell)*(PlyNum-i-1)); + plyLink^[PlyNum-1]:=tmp; +{ + move(plyLink^[i],tmp,SizeOf(tPlayerCell)); + move(plyLink^[i+1],plyLink^[i],SizeOf(tPlayerCell)*(PlyNum-i-1)); + move(tmp,plyLink^[PlyNum-1],SizeOf(tPlayerCell)); +}// break; + i:=1; + dec(j); + continue; + end; + inc(i); + end; +end; + +function FindPlayer(desc:PAnsiChar):integer; +var + i:integer; +begin + if (desc<>nil) and (desc^<>#0) then + begin + i:=0; + while i=0 then + result:=plyLink^[i].Notes + else + result:=nil; +end; + +procedure DefFillPlayerList(hwndList:hwnd); +var + item:LV_ITEMA; + lvc:TLVCOLUMN; + i,newItem:integer; + + il:HIMAGELIST; //!! +begin + FillChar(item,SizeOf(item),0); + FillChar(lvc,SizeOf(lvc),0); + ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES); + lvc.mask:=LVCF_FMT or LVCF_WIDTH; + + lvc.fmt:=LVCFMT_LEFT; + lvc.cx:=160; + ListView_InsertColumn(hwndList,0,lvc); + + item.mask:=LVIF_TEXT or LVIF_IMAGE; //!! + i:=0; + + il:=ImageList_Create(16,16,ILC_COLOR32 or ILC_MASK,0,1); //!! + while i=0 then + begin + if (plyLink^[i].flags and WAT_OPT_DISABLED)=0 then + ListView_SetCheckState(hwndList,newItem,TRUE); + end; + inc(i); + end; + ImageList_Destroy(SendMessage(hwndList,LVM_SETIMAGELIST,LVSIL_SMALL,il)); //!! +// ListView_SetColumnWidth(hwndList,0,LVSCW_AUTOSIZE); +end; + +procedure DefCheckPlayerList(hwndList:hwnd); +var + i,j,k:integer; + item:LV_ITEMA; + szTemp:array [0..109] of AnsiChar; + p:pPlayerCell; +begin + FillChar(item,SizeOf(item),0); + item.mask :=LVIF_TEXT; + item.pszText :=@szTemp; + item.cchTextMax:=100; + k:=ListView_GetItemCount(hwndList)-1; + for i:=0 to k do + begin + item.iItem:=i; + SendMessageA(hwndList,LVM_GETITEMA,0,lparam(@item)); + j:=FindPlayer(item.pszText); + if j<>WAT_RES_NOTFOUND then + begin + p:=@plyLink^[j]; + if ListView_GetCheckState(hwndList,i)=0 then + p^.flags:=p^.flags or WAT_OPT_DISABLED + else + p^.flags:=p^.flags and not WAT_OPT_DISABLED; + end; + end; +end; + +procedure ClearTemplate(tmpl:pTmplCell); +begin + with tmpl^ do + begin + mFreeMem(p_class); + mFreeMem(p_text); + mFreeMem(p_class1); + mFreeMem(p_text1); + mFreeMem(p_file); + mFreeMem(p_prefix); + mFreeMem(p_postfix); + end; + FreeMem(tmpl); +end; + +function ServicePlayer(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + p:integer; + i:integer; + nl:pPlyArray; + tmp:tPlayerCell; +begin + result:=WAT_RES_ERROR; + if LoWord(wParam)=WAT_ACT_REGISTER then + begin + if pPlayerCell(lParam)^.Check=nil then + exit; + p:=0; + end + else + p:=FindPlayer(PAnsiChar(lParam)); + case LoWord(wParam) of + + WAT_ACT_REGISTER: begin + p:=FindPlayer(pPlayerCell(lParam)^.Desc); + if (p=WAT_RES_NOTFOUND) or ((wParam and WAT_ACT_REPLACE)<>0) then + begin + if (p<>WAT_RES_NOTFOUND) and ((plyLink^[p].flags and WAT_OPT_ONLYONE)<>0) then + exit; + + if p=WAT_RES_NOTFOUND then + begin + p:=PlyNum; + result:=WAT_RES_OK; + inc(PlyNum); + + if PlyNum>PlyMax then // expand array when append + begin + if PlyMax=0 then + PlyMax:=StartSize + else + inc(PlyMax,Step); + GetMem(nl,PlyMax*SizeOf(tPlayerCell)); + if plyLink<>nil then + begin + move(plyLink^,nl^,PlyNum*SizeOf(tPlayerCell)); + FreeMem(plyLink); + end; + plyLink:=nl; + end; + FillChar(plyLink^[p],SizeOf(tPlayerCell),0); +// doubling notes + if (pPlayerCell(lParam)^.Notes<>nil) and + ((pPlayerCell(lParam)^.flags and WAT_OPT_TEMPLATE)=0) then + begin + i:=(StrLenW(pPlayerCell(lParam)^.Notes)+1)*SizeOf(WideChar); + GetMem(plyLink^[p].Notes,i); + move(pPlayerCell(lParam)^.Notes^,plyLink^[p].Notes^,i); + end + else + plyLink^[p].Notes:=pPlayerCell(lParam)^.Notes; + +// doubling description + i:=StrLen(pPlayerCell(lParam)^.Desc)+1; + GetMem(plyLink^[p].Desc,i); + move(pPlayerCell(lParam)^.Desc^,plyLink^[p].Desc^,i); + +// doubling url + + if pPlayerCell(lParam)^.URL<>nil then + begin + with plyLink^[p] do + begin + i:=StrLen(pPlayerCell(lParam)^.URL)+1; + GetMem(URL,i); + move(pPlayerCell(lParam)^.URL^,URL^,i); + end; + end + else + plyLink^[p].URL:=nil; + + end + else // existing player + begin + if (plyLink^[p].flags and WAT_OPT_TEMPLATE)=0 then + result:=int_ptr(plyLink^[p].Check) + else + begin // remove any info from templates + result:=WAT_RES_OK; + ClearTemplate(pTmplCell(plyLink^[p].Check)); + end; + end; + // fill info + with plyLink^[p] do + begin + flags:=pPlayerCell(lParam)^.flags; + if URL<>nil then + flags:=flags or WAT_OPT_HASURL; + if pPlayerCell(lParam)^.Icon<>0 then + begin + if icon<>0 then + DestroyIcon(icon); + icon:=CopyIcon(pPlayerCell(lParam)^.Icon); + end; + Init :=pPlayerCell(lParam)^.Init; + DeInit :=pPlayerCell(lParam)^.DeInit; + Check :=pPlayerCell(lParam)^.Check; + GetStatus:=pPlayerCell(lParam)^.GetStatus; + GetName :=pPlayerCell(lParam)^.GetName; + GetInfo :=pPlayerCell(lParam)^.GetInfo; + Command :=pPlayerCell(lParam)^.Command; + if Init<>nil then + tInitProc(Init); + end; + +// PreProcess; + PostProcess; + end; + end; + + WAT_ACT_UNREGISTER: begin + if p<>WAT_RES_NOTFOUND then + begin + dec(PlyNum); + if plyLink^[p].DeInit<>nil then + tDeInitProc(plyLink^[p].DeInit); + FreeMem(plyLink^[p].Desc); + if (plyLink^[p].flags and WAT_OPT_TEMPLATE)<>0 then + ClearTemplate(pTmplCell(plyLink^[p].Check)); + if pWAT_RES_NOTFOUND then + begin + plyLink^[p].flags:=plyLink^[p].flags or WAT_OPT_DISABLED; + result:=WAT_RES_DISABLED + end; + end; + + WAT_ACT_ENABLE: begin + if p<>WAT_RES_NOTFOUND then + begin + plyLink^[p].flags:=plyLink^[p].flags and not WAT_OPT_DISABLED; + result:=WAT_RES_ENABLED + end; + end; + + WAT_ACT_GETSTATUS: begin + if p<>WAT_RES_NOTFOUND then + begin + if (plyLink^[p].flags and WAT_OPT_DISABLED)<>0 then + result:=WAT_RES_DISABLED + else + result:=WAT_RES_ENABLED; + end; + end; + + WAT_ACT_SETACTIVE: begin + if p>0 then + begin + tmp:=plyLink^[p]; + move(plyLink^[0],plyLink^[1],SizeOf(tPlayerCell)*p); + plyLink^[0]:=tmp; +{ + move(plyLink^[p],tmp ,SizeOf(tPlayerCell)); + move(plyLink^[0],plyLink^[1],SizeOf(tPlayerCell)*p); + move(tmp ,plyLink^[0],SizeOf(tPlayerCell)); +} + end; +// PreProcess; +// PostProcess; + end; + + end; +end; + +function LoadFromFile(fname:PAnsiChar):integer; +var + buf:pAnsiChar; + ptr:PAnsiChar; + NumPlayers:integer; + pcell:pTmplCell; + rec:tPlayerCell; + st,sec:pointer; +begin + result:=0; + st:=OpenStorage(fname); + if st=nil then exit; + + buf:=GetSectionList(st); + ptr:=buf; + NumPlayers:=0; + while ptr^<>#0 do + begin + sec:=SearchSection(st,ptr); + + FillChar(rec,SizeOf(rec),0); + + GetMem(pcell,SizeOf(tTmplCell)); + StrDup(pcell^.p_class ,GetParamSectionStr(sec,'class' )); + StrDup(pcell^.p_text ,GetParamSectionStr(sec,'text' )); + StrDup(pcell^.p_class1,GetParamSectionStr(sec,'class1')); + StrDup(pcell^.p_text1 ,GetParamSectionStr(sec,'text1' )); + StrDup(pcell^.p_file ,GetParamSectionStr(sec,'file' )); + + AnsiToWide(GetParamSectionStr(sec,'prefix' ),pcell^.p_prefix ); + AnsiToWide(GetParamSectionStr(sec,'postfix'),pcell^.p_postfix); + + rec.URL :=GetParamSectionStr(sec,'url'); + rec.Desc :=ptr; + rec.flags:=GetParamSectionInt(sec,'flags') or WAT_OPT_TEMPLATE; + rec.Check:=pointer(pcell); + + UTF8ToWide(GetParamSectionStr(sec,'notes'),rec.Notes); + + ServicePlayer(WAT_ACT_REGISTER,lparam(@rec)); + + inc(NumPlayers); + while ptr^<>#0 do inc(ptr); + inc(ptr); + end; + + FreeSectionList(buf); + CloseStorage(st); + result:=NumPlayers; +end; + +function CheckTmpl(lwnd:HWND;cell:pTmplCell;flags:integer):HWND; +var + tmp,EXEName:PAnsiChar; + ltmp,lcycle:boolean; + lclass,ltext:PAnsiChar; +begin + lclass:=cell.p_class; + ltext :=cell.p_text; + lcycle:=false; + repeat + result:=lwnd; + if (lclass<>nil) or (ltext<>nil) then + repeat + result:=FindWindowExA(0,result,lclass,ltext); + if result=0 then + break; +// check filename + if cell.p_file<>NIL then + begin + tmp:=Extract(GetEXEByWnd(result,EXEName),true); + mFreeMem(EXEName); + ltmp:=lstrcmpia(tmp,cell.p_file)=0; + mFreeMem(tmp); + if not ltmp then + continue; + end; + exit; + until false; + if lcycle then break; + lclass:=cell.p_class1; + ltext :=cell.p_text1; + if (lclass=nil) and (ltext=nil) then break; + lcycle:=not lcycle; + until false; +end; + +// find active player +function CheckAllPlayers(flags:integer;var status:integer; var PlayerChanged:bool):integer; +const + PrevPlayerName:PAnsiChar=nil; +var + stat,act,oldstat,i,j:integer; + tmp:tPlayerCell; + wwnd,lwnd:HWND; +begin + i:=0; + result:=WAT_RES_NOTFOUND; + PlayerChanged:=true; + PreProcess; + oldstat:=-1; + act:=-1; + stat:=WAT_MES_UNKNOWN; + wwnd:=0; + while i0 then + begin + lwnd:=CheckTmpl(lwnd,plyLink^[i].Check,plyLink^[i].flags); +// find "Winamp" window + if (lwnd<>dword(WAT_RES_NOTFOUND)) and (lwnd<>0) and + ((plyLink^[i].flags and WAT_OPT_WINAMPAPI)<>0) then + begin + wwnd:=WinampFindWindow(lwnd); + if wwnd<>0 then + stat:=WinampGetStatus(wwnd); + end; + end + else + begin + with plyLink^[i] do + begin + lwnd:=tCheckProc(Check)(lwnd,flags); + if (lwnd<>dword(WAT_RES_NOTFOUND)) and (lwnd<>0) and (GetStatus<>nil) then + stat:=tStatusProc(GetStatus)(lwnd); + end; + end; + if (lwnd<>dword(WAT_RES_NOTFOUND)) and (lwnd<>0) then + begin + if (stat=WAT_MES_PLAYING) or ((flags and WAT_OPT_CHECKALL)=0) then + begin + act :=i; + result:=lwnd; + break; + end + else + begin + case stat of + WAT_MES_STOPPED: j:=00; + WAT_MES_UNKNOWN: j:=10; + WAT_MES_PAUSED : j:=20; + else + j:=00; + end; + if oldstat0 then + break; + until false; + if (result<>WAT_RES_NOTFOUND) and (result<>0) and + ((stat=WAT_MES_PLAYING) or ((flags and WAT_OPT_CHECKALL)=0)) then + break; + end; + inc(i); + end; + + if act>=0 then + begin + if result=1 then result:=0 //!! for example, mradio + else if wwnd<>0 then + result:=wwnd; + if act>0 then // to first position + begin + tmp:=plyLink^[act]; + move(plyLink^[0],plyLink^[1],SizeOf(tPlayerCell)*act); + plyLink^[0]:=tmp; +{ + move(plyLink^[act],tmp ,SizeOf(tPlayerCell)); + move(plyLink^[0 ],plyLink^[1],SizeOf(tPlayerCell)*act); + move(tmp ,plyLink^[0],SizeOf(tPlayerCell)); +} + end; + if PrevPlayerName=plyLink^[0].Desc then + PlayerChanged:=false + else + PrevPlayerName:=plyLink^[0].Desc; + status:=stat; + end + else + begin + PrevPlayerName:=nil; + status:=WAT_PLS_NOTFOUND+WAT_MES_UNKNOWN shl 16; + end; + PostProcess; +end; + +function TranslateToApp(code:integer):integer; +begin + case code of + WAT_CTRL_PREV : result:=APPCOMMAND_MEDIA_PREVIOUSTRACK; + WAT_CTRL_PLAY : begin + if IsW2K then // Win2k+ only + result:=APPCOMMAND_MEDIA_PLAY_PAUSE + else + result:=APPCOMMAND_MEDIA_PLAY; + end; + WAT_CTRL_PAUSE: result:=APPCOMMAND_MEDIA_PLAY_PAUSE; + WAT_CTRL_STOP : result:=APPCOMMAND_MEDIA_STOP; + WAT_CTRL_NEXT : result:=APPCOMMAND_MEDIA_NEXTTRACK; + WAT_CTRL_VOLDN: result:=APPCOMMAND_VOLUME_DOWN; + WAT_CTRL_VOLUP: result:=APPCOMMAND_VOLUME_UP; + else + result:=-1; + end; +end; + +function SendCommand(wParam:WPARAM;lParam:LPARAM;flags:integer):int_ptr; +var + dummy:bool; + wnd:HWND; + lstat:integer; +begin + result:=WAT_RES_ERROR; + wnd:=CheckAllPlayers(flags,lstat,dummy); + if wnd<>dword(WAT_RES_NOTFOUND) then + if plyLink^[0].Command<>nil then + result:=tCommandProc(plyLink^[0].Command)(wnd,wParam,lParam) + else if (plyLink^[0].flags and WAT_OPT_WINAMPAPI)<>0 then + result:=WinampCommand(wnd,wParam+(lParam shl 16)) + else if (flags and WAT_OPT_APPCOMMAND)<>0 then + begin + result:=TranslateToApp(wParam); + if result>=0 then + result:=SendMMCommand(wnd,result); + end; +end; + +// Get Info (default) + +function GetSeparator(str:pWideChar):dword; +begin + result:=StrIndexW(str,' '#$2013' '); + if result=0 then + result:=StrIndexW(str,' - '); + if result<>0 then + begin + result:=result-1 + (3 SHL 16); + exit; + end; + result:=StrIndexW(str,#$2013); + if result=0 then + result:=StrIndexW(str,'-'); + if result>0 then + result:=result-1 + (1 SHL 16); +end; + +function DefGetTitle(wnd:HWND;fname,wndtxt:pWideChar):pWideChar; +var + i:integer; + tmp:pWideChar; +begin + if fname<>nil then + tmp:=DeleteKnownExt(ExtractW(fname,true)) + else + tmp:=wndtxt; + if tmp=nil then + begin + result:=nil; + exit; + end; + StrDupW(result,tmp); + i:=GetSeparator(result); + if i>0 then + StrCopyW(result,result+LoWord(i)+HiWord(i)); + if fname<>nil then + mFreeMem(tmp); +end; + +function DefGetArtist(wnd:HWND;fname,wndtxt:pWideChar):pWideChar; +var + i:integer; + tmp:pWideChar; +begin + if fname<>nil then + tmp:=DeleteKnownExt(ExtractW(fname,true)) + else + tmp:=wndtxt; + if tmp=nil then + begin + result:=nil; + exit; + end; + StrDupW(result,tmp); + i:=GetSeparator(result); + if i>0 then + result[LoWord(i)]:=#0; + if fname<>nil then + mFreeMem(tmp); +end; + +function DefGetVersionText(ver:integer):pWideChar; +begin + if ver<>0 then + begin + mGetMem(result,10*SizeOf(WideChar)); + IntToHex(result,ver); + end + else + result:=nil; +end; + +function DefGetWndText(wnd:HWND):pWideChar; +var + p:pWideChar; +begin + if wnd<>0 then + begin + result:=GetDlgText(wnd); + if result<>nil then + begin + if (plyLink^[0].flags and WAT_OPT_TEMPLATE)<>0 then + begin + with pTmplCell(plyLink^[0].Check)^ do + begin + if p_prefix<>nil then + begin + p:=StrPosW(result,p_prefix); + if p=result then + StrCopyW(result,result+StrLenW(p_prefix)); + end; + if p_postfix<>nil then + begin + p:=StrPosW(result,p_postfix); + if p<>nil then + p^:=#0; + end; + end; + end; + end; + end + else + result:=nil; +end; + +procedure ClearSongInfoData(var dst:tSongInfo;withFree:bool); +begin + ClearPlayerInfo (dst,withFree); + ClearChangingInfo(dst,withFree); + ClearFileInfo (dst,withFree); + ClearTrackInfo (dst,withFree); +end; + +procedure CopyChangingInfo(const src:tSongInfo;var dst:tSongInfo); +begin + dst.time :=src.time; + dst.volume :=src.volume; + dst.wndtext:=src.wndtext; +end; + +procedure ClearChangingInfo(var dst:tSongInfo;withFree:bool); +begin + dst.time :=0; + dst.volume:=0; + + if withFree then + mFreeMem(dst.wndtext) + else + dst.wndtext:=nil; +end; + +procedure CopyFileInfo(const src:tSongInfo;var dst:tSongInfo); +begin + dst.fsize:=src.fsize; + dst.date :=src.date; + dst.mfile:=src.mfile; +end; + +procedure ClearFileInfo(var dst:tSongInfo;withFree:bool); +begin + if withFree then + mFreeMem(dst.mfile) + else + dst.mfile:=nil; + dst.fsize:=0; + dst.date :=0; +end; + +procedure CopyPlayerInfo(const src:tSongInfo;var dst:tSongInfo); +begin + dst.player :=src.player; + dst.txtver :=src.txtver; + dst.url :=src.url; + dst.icon :=src.icon; + dst.plyver :=src.plyver; + dst.plwnd :=src.plwnd; + dst.winampwnd:=src.winampwnd; +end; + +procedure ClearPlayerInfo(var dst:tSongInfo;withFree:bool); +begin + if withFree then + begin + mFreeMem(dst.player); + mFreeMem(dst.txtver); + mFreeMem(dst.url); + if dst.icon<>0 then + DestroyIcon(dst.icon); + end + else + begin + dst.player:=nil; + dst.txtver:=nil; + dst.url :=nil; + end; + dst.icon :=0; + dst.plyver :=0; + dst.plwnd :=0; + dst.winampwnd:=0; +end; + +procedure CopyTrackInfo(const src:tSongInfo;var dst:tSongInfo); +begin + dst.artist :=src.artist; + dst.title :=src.title; + dst.album :=src.album; + dst.genre :=src.genre; + dst.comment :=src.comment; + dst.year :=src.year; + dst.lyric :=src.lyric; + dst.cover :=src.cover; + dst.kbps :=src.kbps; + dst.khz :=src.khz; + dst.channels:=src.channels; + dst.track :=src.track; + dst.total :=src.total; + dst.vbr :=src.vbr; + dst.codec :=src.codec; + dst.width :=src.width; + dst.height :=src.height; + dst.fps :=src.fps; +end; + +procedure ClearTrackInfo(var dst:tSongInfo;withFree:bool); +begin + if withFree then + begin + mFreeMem(dst.artist); + mFreeMem(dst.title); + mFreeMem(dst.album); + mFreeMem(dst.genre); + mFreeMem(dst.comment); + mFreeMem(dst.year); + mFreeMem(dst.lyric); + mFreeMem(dst.cover); + end + else + begin + dst.artist :=nil; + dst.title :=nil; + dst.album :=nil; + dst.genre :=nil; + dst.comment:=nil; + dst.year :=nil; + dst.lyric :=nil; + dst.cover :=nil; + end; + dst.kbps :=0; + dst.khz :=0; + dst.channels:=0; + dst.track :=0; + dst.total :=0; + dst.vbr :=0; + dst.codec :=0; + dst.width :=0; + dst.height :=0; + dst.fps :=0; +end; + +function CheckPlayers(var dst:tSongInfo;flags:cardinal):integer; +var + PlayerChanged:bool; + fname:pWideChar; +begin + result:=CheckAllPlayers(flags,dst.status,PlayerChanged); + + if result<>WAT_RES_NOTFOUND then + begin + if PlayerChanged then + begin + ClearPlayerInfo(dst,false); + AnsiToWide(plyLink^[0].Desc,dst.player); + dst.plwnd:=result; + FastAnsiToWide(plyLink^[0].URL,dst.url); + if plyLink^[0].icon<>0 then + dst.icon:=CopyIcon(plyLink^[0].icon) + else if result<>0 then + begin + if GetEXEByWnd(dst.plwnd,fname)<>nil then + begin + dst.icon:=ExtractIconW(hInstance,fname,0); + if dst.icon=1 then + dst.icon:=0; + if dst.icon<>0 then + plyLink^[0].icon:=CopyIcon(dst.icon); + mFreeMem(fname); + end; + end; + + if plyLink^[0].GetInfo<>nil then + tInfoProc(plyLink^[0].GetInfo)(dst,flags or WAT_OPT_PLAYERDATA) + else if (plyLink^[0].flags and WAT_OPT_WINAMPAPI)<>0 then + WinampGetInfo(wparam(@dst),flags or WAT_OPT_PLAYERDATA); + + if (plyLink^[0].flags and WAT_OPT_PLAYERINFO)=0 then + if dst.txtver=NIL then dst.txtver:=DefGetVersionText(dst.plyver); + + result:=WAT_RES_NEWPLAYER; + end + else + begin + dst.plwnd:=result; // to prevent same player, another instance + result:=WAT_RES_OK; + end + end; +end; + +function CheckFile(var dst:tSongInfo;flags:cardinal;timeout:cardinal):integer; +var + fname:pWideChar; + tmp:integer; + remote,FileChanged:boolean; + f:THANDLE; + ftime:int64; +begin + if plyLink^[0].GetName<>nil then + fname:=tNameProc(plyLink^[0].GetName)(dst.plwnd,flags) + else + fname:=nil; + + if (fname=nil) and (dst.plwnd<>0) then + begin + tmp:=0; + if (flags and WAT_OPT_MULTITHREAD)<>0 then tmp:=tmp or gffdMultiThread; + if (flags and WAT_OPT_KEEPOLD )<>0 then tmp:=tmp or gffdOld; + fname:=GetFileFromWnd(dst.plwnd,KnownFileType,tmp,timeout); + end; + + if fname<>nil then + begin + remote:=StrPosW(fname,'://')<>nil; + // file changing time (local/lan only) + if not remote then + begin + f:=Reset(fname); + + if f<>THANDLE(INVALID_HANDLE_VALUE) then + begin + GetFileTime(f,nil,nil,@ftime); + CloseHandle(f); + end; + end; + // same file + if (dst.mfile<>nil) and (lstrcmpiw(dst.mfile,fname)=0) then + begin + if (not remote) and ((flags and WAT_OPT_CHECKTIME)<>0) then + FileChanged:=dst.date<>ftime + else + FileChanged:=false; + end + else // new filename + begin + FileChanged:=true; + end; + + // if not proper ext (we don't working with it) + //!!!! check for remotes + if (not remote) and (CheckExt(fname)=WAT_RES_NOTFOUND) then + begin + mFreeMem(fname); + result:=WAT_RES_NOTFOUND; + exit; + end; + if FileChanged {or isContainer(fname)} then + begin + ClearFileInfo(dst,false); + dst.mfile:=fname; //!! must be when format recognized or remote + dst.date:=ftime; //!! + dst.fsize:=GetFSize(dst.mfile); + result:=WAT_RES_NEWFILE; + end + else + begin + result:=WAT_RES_OK; + mFreeMem(fname); + end; + end + else + begin + result:=WAT_RES_NOTFOUND; + end; +end; + +// Get Info - main procedure +function GetChangingInfo(var dst:tSongInfo;flags:cardinal):integer; +begin + result:=WAT_RES_OK; + + ClearChangingInfo(dst,false); + + if plyLink^[0].GetInfo<>nil then + tInfoProc(plyLink^[0].GetInfo)(dst,flags or WAT_OPT_CHANGES) + else if (plyLink^[0].flags and WAT_OPT_WINAMPAPI)<>0 then + WinampGetInfo(wparam(@dst),flags or WAT_OPT_CHANGES); + + if (plyLink^[0].flags and WAT_OPT_PLAYERINFO)=0 then + if dst.wndtext=NIL then dst.wndtext:=DefGetWndText(dst.plwnd); +end; + +function GetInfo(var dst:tSongInfo;flags:cardinal):integer; +var + oldartist,oldtitle:pWideChar; + fname:pWideChar; + remote:boolean; + lmsnInfo:pMSNInfo; +begin + result:=WAT_RES_OK; + remote:=StrPosW(dst.mfile,'://')<>nil; + +// if remote or ((plyLink^[0].flags and WAT_OPT_PLAYERINFO)<>0) then + oldartist:=dst.artist; oldtitle:=dst.title; + + ClearTrackInfo(dst,false); + + // info from player + if plyLink^[0].GetInfo<>nil then + tInfoProc(plyLink^[0].GetInfo)(dst,flags and not WAT_OPT_CHANGES) + else if (plyLink^[0].flags and WAT_OPT_WINAMPAPI)<>0 then + WinampGetInfo(wparam(@dst),flags and not WAT_OPT_CHANGES); + // info from file + GetFileFormatInfo(dst); + + if (plyLink^[0].flags and WAT_OPT_PLAYERINFO)=0 then + with dst do + begin + if remote then + fname:=nil + else + fname:=mfile; + + lmsnInfo:=GetMSNInfo; + + if lmsnInfo<>nil then + begin + if artist=NIL then StrDupW(artist,lmsnInfo.msnArtist); + if title =NIL then StrDupW(title ,lmsnInfo.msnTitle); + if album =NIL then StrDupW(album ,lmsnInfo.msnAlbum); + end; + + if artist=NIL then artist:=DefGetArtist(plwnd,fname,wndtext); + if title =NIL then title :=DefGetTitle (plwnd,fname,wndtext); + end; + if remote or ((plyLink^[0].flags and WAT_OPT_PLAYERINFO)<>0) or + isContainer(dst.mfile) then + begin + if (oldartist=oldtitle) or + ((oldartist<>nil) and (StrCmpW(dst.artist,oldartist)<>0)) or + ((oldtitle <>nil) and (StrCmpW(dst.title ,oldtitle )<>0)) then + begin + result:=WAT_RES_NEWFILE; + end; + end; +end; + +procedure ClearPlayers; +begin + if PlyNum>0 then + begin + repeat + dec(PlyNum); + with plyLink^[PlyNum] do + begin + if DeInit<>nil then + tDeInitProc(DeInit); + FreeMem(Desc); + if URL<>nil then + FreeMem(URL); + if icon<>0 then + DestroyIcon(icon); + if (flags and WAT_OPT_TEMPLATE)<>0 then + begin + ClearTemplate(pTmplCell(Check)); + mFreeMem(Notes); + end + else if Notes<>nil then + FreeMem(Notes); + end; + until PlyNum=0; + FreeMem(plyLink); + end; +end; + +end. diff --git a/plugins/Watrack/stat/default.tmpl b/plugins/Watrack/stat/default.tmpl new file mode 100644 index 0000000000..0e1920fc5d --- /dev/null +++ b/plugins/Watrack/stat/default.tmpl @@ -0,0 +1,89 @@ +const + IntTmpl:PAnsiChar= +''#13#10+ +''#13#10+ +''#13#10+ +'Report on %currenttime%'#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +'

Report


created %currenttime%

'#13#10+ +'%block_freqartist%'#13#10+ +'

Most popular artists:

'#13#10+ +'%start%'#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +'%end%'#13#10+ +'
%num%.%artist%
%count%
'#13#10+ +'%block_end%'#13#10+ +'%block_freqsongs%'#13#10+ +'

Most frequently played songs:

'#13#10+ +'%start%'#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +'%end%'#13#10+ +'
%num%.%artist% - %title% (%album%)
%count%
'#13#10+ +'%block_end%'#13#10+ +'%block_freqalbum%'#13#10+ +'

Most frequently played albums:

'#13#10+ +'%start%'#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +'%end%'#13#10+ +'
%num%.%album%
%count%
'#13#10+ +'%block_end%'#13#10+ +'%block_lastsongs%'#13#10+ +'

Last played songs:

'#13#10+ +'%start%'#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +'%end%'#13#10+ +'
%num%.[%date%]%artist% - %title%
'#13#10+ +'%block_end%'#13#10+ +'%block_songtime%'#13#10+ +'

Longest songs:

'#13#10+ +'%start%'#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +'%end%'#13#10+ +'
%num%.%artist% - %title%
%length%
'#13#10+ +'%block_end%'#13#10+ +'%block_freqpath%'#13#10+ +'

Most frequently used paths:

'#13#10+ +'%start%'#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +''#13#10+ +'%end%'#13#10+ +'
%num%.%path%
%count%
'#13#10+ +'%block_end%'#13#10+ +'

Total played time is:

'#13#10+ +''#13#10+ +''#13#10+ +'
Total logged music time - %totaltime%Total logged music files - %totalfiles%
'#13#10+ +''#13#10+ +'
'#13#10+ +''#13#10+ +''#13#10; diff --git a/plugins/Watrack/stat/report.inc b/plugins/Watrack/stat/report.inc new file mode 100644 index 0000000000..0cd4fcfb22 --- /dev/null +++ b/plugins/Watrack/stat/report.inc @@ -0,0 +1,315 @@ +{$include default.tmpl} +function ReadTemplate(fname:PAnsiChar;var buf:PAnsiChar):integer; +var + f:THANDLE; + size:integer; +begin + if (fname=nil) or (fname^=#0) then + f:=INVALID_HANDLE_VALUE + else + f:=Reset(fname); + if f=THANDLE(INVALID_HANDLE_VALUE) then + result:=0 + else + begin + size:=FileSize(f); + mGetMem(buf,size+1); + buf[size+1]:=#0; + BlockRead(f,buf^,size); + CloseHandle(f); + result:=size; + end; +end; + +function StatOut(report,log,template:PAnsiChar):boolean; + +const + bufsize = 16384; +var + fout:THANDLE; + tt,tf:array [0..15] of AnsiChar; + timebuf:array [0..17] of AnsiChar; // for current date / time + outbuf:PAnsiChar; + outpos:PAnsiChar; + + procedure OutChar(var pc:PAnsiChar); + begin + outpos^:=pc^; + inc(pc); + inc(outpos); + if (outpos-outbuf)=bufsize then + begin + BlockWrite(fout,outbuf^,bufsize); + outpos:=outbuf; + end; + end; + + procedure OutStr(pc:PAnsiChar); + begin + while pc^<>#0 do + OutChar(pc); + end; + + procedure OutputBlock(var start:PAnsiChar;var Root:pCells;asortmode:integer); + const + blocksize = 8192; + var + i,max,cnt,len:integer; + items:cardinal; + Cell:pStatCell; + ls,ls1:array [0..511] of AnsiChar; + block:array [0..blocksize-1] of AnsiChar; + begin + len:=StrIndex(start,'%end%'); + if len=0 then + len:=StrLen(start) + else + dec(len); + if len>6143 then + err('Template block too large'); + + Resort(Root,asortmode); + + case asortmode of + stArtist,stAlbum,stPath: begin + + Cell:=Root^.Cells[0]; + max:=Cell^.Count; + if asortmode=stPath then OnlyPath(ls,Cell^.MFile); // speed optimization + + for i:=0 to Root^.Count-1 do + begin + with Root^.Cells[i]^ do + begin + AltCount:=0; + if asortmode=stArtist then cnt:=lstrcmpia(Cell^.Artist,Artist) + else if asortmode=stAlbum then cnt:=lstrcmpia(Cell^.Album,Album) + else cnt:=lstrcmpia(ls,OnlyPath(ls1,MFile)); + if cnt=0 then + inc(max,Count) + else + begin + Cell^.AltCount:=max; + Cell:=Root^.Cells[i]; + if asortmode=stPath then OnlyPath(ls,Cell^.MFile); // speed optimization + max:=Count; + end; + end; + end; + Cell^.AltCount:=max; + + Resort(Root,stAltCount); + if (asortmode=stAlbum) and (Root^.Cells[0]^.Album^=#0) then + begin + if Root^.Count>1 then + max:=Root^.Cells[1]^.AltCount + else + max:=0; + end + else + max:=Root^.Cells[0]^.AltCount; + end; + stCount: begin + max:=Root^.Cells[0]^.Count; + end; + stLength: begin + max:=Root^.Cells[0]^.Length; + end; + else + max:=1; + end; + + items:=1; + if ReportItems>0 then + for i:=0 to Root^.Count-1 do + begin + with Root^.Cells[i]^ do + begin + if (asortmode=stAlbum) and (Album^=#0) then continue; + case asortmode of + stArtist, + stAlbum, + stPath : cnt:=AltCount; + stCount : cnt:=Count; + stLength: cnt:=Length; + else + cnt:=1; + end; + if cnt=0 then break; + move(start^,block,len); + block[len]:=#0; + StrReplace(block,'%date%' ,ShowTime(ls,LastTime)); + StrReplace(block,'%length%' ,IntToTime(ls,Length)); + StrReplace(block,'%artist%' ,Artist); + StrReplace(block,'%title%' ,Title); + StrReplace(block,'%album%' ,Album); + StrReplace(block,'%file%' ,MFile); + StrReplace(block,'%path%' ,OnlyPath(ls,MFile)); + StrReplace(block,'%num%' ,IntToStr(ls,items)); + StrReplace(block,'%currenttime%',timebuf); + StrReplace(block,'%totaltime%' ,tt); + StrReplace(block,'%totalfiles%' ,tf); + StrReplace(block,'%percent%' ,IntToStr(ls,round(cnt*100/max))); + StrReplace(block,'%count%' ,IntToStr(ls,cnt)); + OutStr(block); + end; + if items=ReportItems then break; + inc(items); + end; + inc(start,len+5); + end; + +var + TmplBuf:PAnsiChar; + ptr:PAnsiChar; + i,j,k:integer; + size:integer; + lsortmode:integer; + MyTime:TSYSTEMTIME; + Root:pCells; + b1,tmp:PAnsiChar; +begin + result:=false; + GetLocalTime(MyTime); + ShowTime(timebuf,PackTime(MyTime)); + + Lock:=true; + Root:=BuildTree(log,b1); + if Root<>nil then + begin + Resort(Root,stArtist); + Lock:=false; + size:=ReadTemplate(template,TmplBuf); + if size=0 then + begin + StrDup(TmplBuf,IntTmpl); + size:=StrLen(IntTmpl); + end; + ptr:=TmplBuf; + fout:=Rewrite(report); + if fout=THANDLE(INVALID_HANDLE_VALUE) then + exit; + mGetMem(outbuf,bufsize); + outpos:=outbuf; + + i:=0; + k:=0; + for j:=0 to Root^.Count-1 do + begin + inc(k); + with Root^.Cells[j]^ do + inc(i,Length*Count); + end; + IntToTime(tt,i); // total time + IntToStr(tf,k); // total files + + lsortmode:=stDate; + while (ptr-TmplBuf)'%') and (ptr^<>#0) do + OutChar(ptr); + if ptr^=#0 then break; + if StrCmp(ptr,'%block_',7)=0 then + begin + if ptr>@TmplBuf then + begin + if (ptr-1)^<' ' then + k:=-1; + end; + inc(ptr,7); + if StrCmp(ptr,'end%',4)=0 then + begin + i:=4; + end + else if StrCmp(ptr,'freqartist%',11)=0 then + begin + lsortmode:=stArtist; + i:=11; + end + else if StrCmp(ptr,'freqsongs%',10)=0 then + begin + lsortmode:=stCount; + i:=10; + end + else if StrCmp(ptr,'freqalbum%',10)=0 then + begin + lsortmode:=stAlbum; + i:=10; + end + else if StrCmp(ptr,'lastsongs%',10)=0 then + begin + lsortmode:=stDate; + i:=10; + end + else if StrCmp(ptr,'songtime%',9)=0 then + begin + lsortmode:=stLength; + i:=9; + end + else if StrCmp(ptr,'freqpath%',9)=0 then + begin + lsortmode:=stPath; + i:=9; + end + else + begin + OutChar(ptr); + continue; + end; + inc(ptr,i); + if k<0 then + begin + while (ptr^<' ') and (ptr^<>#0) do inc(ptr); + k:=0; + end; + if (ReportMask and lsortmode)=0 then + begin + tmp:=StrPos(ptr,'%block_end%'); + if tmp<>nil then + ptr:=tmp+11 + else + break; + end; + end + else if StrCmp(ptr,'%start%',7)=0 then + begin + if ptr>@TmplBuf then + begin + if (ptr-1)^<' ' then + k:=-1; + end; + inc(ptr,7); + if k<0 then + begin + while (ptr^<' ') and (ptr^<>#0) do inc(ptr); + k:=0; + end; + OutputBlock(ptr,Root,lsortmode); + end + else if StrCmp(ptr,'%currenttime%',13)=0 then + begin + inc(ptr,13); + OutStr(timebuf); + end + else if StrCmp(ptr,'%totalfiles%',12)=0 then + begin + inc(ptr,12); + OutStr(tf); + end + else if StrCmp(ptr,'%totaltime%',11)=0 then + begin + inc(ptr,11); + OutStr(tt); + end + else + OutChar(ptr); + end; + BlockWrite(fout,outbuf^,outpos-outbuf); + CloseHandle(fout); + mFreeMem(outbuf); + mFreeMem(TmplBuf); + ClearStatCells(Root); + result:=true; + end; + mFreeMem(b1); +end; diff --git a/plugins/Watrack/stat/stat.rc b/plugins/Watrack/stat/stat.rc new file mode 100644 index 0000000000..9bedcabf3d --- /dev/null +++ b/plugins/Watrack/stat/stat.rc @@ -0,0 +1,50 @@ +#include "stat_rc.inc" + +LANGUAGE 0,0 + +STATS DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + PUSHBUTTON "Delete", IDC_CLEAR , 242, 11, 56, 14 + LTEXT "Statistic log file", -1 , 16, 17, 148, 12 + EDITTEXT IDC_STATNAME , 6, 29, 214, 14 + PUSHBUTTON "...", IDC_SNBUTTON , 222, 29, 16, 14 + PUSHBUTTON "Sort", IDC_SORTFILE , 242, 29, 56, 14 + RTEXT "Autosort period, days",-1 , 124, 45, 142, 12, SS_CENTERIMAGE + EDITTEXT IDC_AUTOSORT , 270, 45, 28, 12, ES_RIGHT | ES_NUMBER + LTEXT "Report file", -1 , 16, 47, 148, 12 + EDITTEXT IDC_REPNAME , 6, 59, 214, 14 + PUSHBUTTON "...", IDC_RNBUTTON , 222, 59, 16, 14 + PUSHBUTTON "Report", IDC_REPORT , 242, 59, 56, 14 + LTEXT "Template file", -1 , 16, 77, 148, 12 + EDITTEXT IDC_TMPLNAME , 6, 89, 214, 14 + PUSHBUTTON "...", IDC_TNBUTTON , 222, 89, 16, 14 + PUSHBUTTON "Export default", IDC_EXPORTDEF, 242, 89, 56, 14 + + CONTROL "", -1, "STATIC", SS_ETCHEDHORZ, 4, 107, 296, 2 + + GROUPBOX "Show in report", -1, 6, 111, 144, 84 + AUTOCHECKBOX "Freq. songs" , IDC_FREQART , 12, 121, 136, 12, BS_VCENTER + AUTOCHECKBOX "Freq. artists" , IDC_FREQSONG , 12, 133, 136, 12, BS_VCENTER + AUTOCHECKBOX "Freq. album" , IDC_FREQALBUM, 12, 145, 136, 12, BS_VCENTER + AUTOCHECKBOX "Freq. paths" , IDC_FREQPATH , 12, 157, 136, 12, BS_VCENTER + AUTOCHECKBOX "Last played songs", IDC_LASTSONG , 12, 169, 136, 12, BS_VCENTER + AUTOCHECKBOX "Song time" , IDC_SONGTIME , 12, 181, 136, 12, BS_VCENTER + + GROUPBOX "Sort log file", -1, 154, 111, 144, 84 + AUTORADIOBUTTON "by Title" , IDC_BYTITLE , 158, 121, 136, 12, NOT WS_TABSTOP + AUTORADIOBUTTON "by Date" , IDC_BYDATE , 158, 133, 136, 12, NOT WS_TABSTOP + AUTORADIOBUTTON "by Count" , IDC_BYCOUNT , 158, 145, 136, 12, NOT WS_TABSTOP + AUTORADIOBUTTON "by Path" , IDC_BYPATH , 158, 157, 136, 12, NOT WS_TABSTOP + AUTORADIOBUTTON "by Length" , IDC_BYLENGTH , 158, 169, 136, 12, NOT WS_TABSTOP + AUTOCHECKBOX "Reverse order", IDC_DIRECTION, 158, 181, 136, 12, BS_VCENTER | BS_MULTILINE + + LTEXT "Report Items", -1, 38, 208, 112, 12, SS_CENTERIMAGE + EDITTEXT IDC_ITEMS, 6, 208, 28, 12, ES_RIGHT | ES_NUMBER + AUTOCHECKBOX "Open report" , IDC_RUNREPORT, 154, 196, 146, 12, BS_VCENTER + AUTOCHECKBOX "Add report file ext.", IDC_ADDEXT , 154, 208, 146, 12, BS_VCENTER | BS_MULTILINE +} + +BTN_REPORT ICON "wat_report.ico" diff --git a/plugins/Watrack/stat/stat.res b/plugins/Watrack/stat/stat.res new file mode 100644 index 0000000000..eca192d5ba Binary files /dev/null and b/plugins/Watrack/stat/stat.res differ diff --git a/plugins/Watrack/stat/stat_data.inc b/plugins/Watrack/stat/stat_data.inc new file mode 100644 index 0000000000..ec539a3ecd --- /dev/null +++ b/plugins/Watrack/stat/stat_data.inc @@ -0,0 +1,16 @@ +{statistic data} +const + MenuReportPos = 500050001; + +const + smDirect = 1; + smReverse = 2; + +const + stArtist = $0001; + stCount = $0002; + stPath = $0004; + stDate = $0008; + stLength = $0010; + stAltCount = $0020; + stAlbum = $0040; diff --git a/plugins/Watrack/stat/stat_dlg.inc b/plugins/Watrack/stat/stat_dlg.inc new file mode 100644 index 0000000000..64a9b97f7c --- /dev/null +++ b/plugins/Watrack/stat/stat_dlg.inc @@ -0,0 +1,223 @@ +{Statistic Dialog} + +{$include stat_rc.inc} + +procedure SetReportMask(Dlg:hwnd); +begin + ReportMask:=0; + if IsDlgButtonChecked(Dlg,IDC_FREQART)=BST_CHECKED then + ReportMask:=ReportMask or stArtist; + if IsDlgButtonChecked(Dlg,IDC_FREQSONG)=BST_CHECKED then + ReportMask:=ReportMask or stCount; + if IsDlgButtonChecked(Dlg,IDC_FREQPATH)=BST_CHECKED then + ReportMask:=ReportMask or stPath; + if IsDlgButtonChecked(Dlg,IDC_LASTSONG)=BST_CHECKED then + ReportMask:=ReportMask or stDate; + if IsDlgButtonChecked(Dlg,IDC_SONGTIME)=BST_CHECKED then + ReportMask:=ReportMask or stLength; + if IsDlgButtonChecked(Dlg,IDC_FREQALBUM)=BST_CHECKED then + ReportMask:=ReportMask or stAlbum; +end; + +procedure EnableItems(Dlg:hwnd;enable:boolean); +begin + EnableWindow(GetDlgItem(Dlg,IDC_STATNAME) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_SNBUTTON) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_SORTFILE) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_REPORT) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_CLEAR) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_BYTITLE) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_BYDATE) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_BYCOUNT) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_BYPATH) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_BYLENGTH) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_DIRECTION),enable); + EnableWindow(GetDlgItem(Dlg,IDC_REPNAME) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_RNBUTTON) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_ITEMS) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_FREQART) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_FREQSONG) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_FREQALBUM),enable); + EnableWindow(GetDlgItem(Dlg,IDC_FREQPATH) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_LASTSONG) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_SONGTIME) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_RUNREPORT),enable); + EnableWindow(GetDlgItem(Dlg,IDC_ADDEXT) ,enable); + EnableWindow(GetDlgItem(Dlg,IDC_AUTOSORT) ,enable); +end; + +function DlgProcOptions(Dialog:HWnd; hMessage:dword;wParam:WPARAM;lParam:LPARAM):LRESULT; stdcall; +const + changed:boolean=false; +var + buf,buf1:array [0..511] of AnsiChar; + tmp:longbool; + p:PAnsiChar; + f:THANDLE; +begin + result:=0; + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + SetDlgItemInt(Dialog,IDC_ITEMS,ReportItems,false); + if ReportName=nil then + p:='' + else + p:=ReportName; + SetDlgItemTextA(Dialog,IDC_REPNAME,p); + if StatName=nil then + p:='' + else + p:=StatName; + SetDlgItemTextA(Dialog,IDC_STATNAME,p); + if TmplName=nil then + p:='' + else + p:=TmplName; + SetDlgItemTextA(Dialog,IDC_TMPLNAME,p); + SetDlgItemInt(Dialog,IDC_AUTOSORT,AutoSort,false); + CheckDlgButton(Dialog,IDC_RUNREPORT,RunReport); + CheckDlgButton(Dialog,IDC_ADDEXT,DoAddExt); + + CheckDlgButton(Dialog,IDC_BYTITLE ,ord(SortMode=stArtist)); + CheckDlgButton(Dialog,IDC_BYDATE ,ord(SortMode=stDate)); + CheckDlgButton(Dialog,IDC_BYCOUNT ,ord(SortMode=stCount)); + CheckDlgButton(Dialog,IDC_BYPATH ,ord(SortMode=stPath)); + CheckDlgButton(Dialog,IDC_BYLENGTH,ord(SortMode=stLength)); + + if Direction=smReverse then + CheckDlgButton(Dialog,IDC_DIRECTION,BST_CHECKED); + + if (ReportMask and stArtist)<>0 then + CheckDlgButton(Dialog,IDC_FREQART,BST_CHECKED); + if (ReportMask and stAlbum)<>0 then + CheckDlgButton(Dialog,IDC_FREQALBUM,BST_CHECKED); + if (ReportMask and stCount)<>0 then + CheckDlgButton(Dialog,IDC_FREQSONG,BST_CHECKED); + if (ReportMask and stPath)<>0 then + CheckDlgButton(Dialog,IDC_FREQPATH,BST_CHECKED); + if (ReportMask and stDate)<>0 then + CheckDlgButton(Dialog,IDC_LASTSONG,BST_CHECKED); + if (ReportMask and stLength)<>0 then + CheckDlgButton(Dialog,IDC_SONGTIME,BST_CHECKED); + result:=0; + changed:=false; + end; + + WM_COMMAND: begin + if (wParam shr 16)=BN_CLICKED then + begin + case loword(wParam) of + IDC_BYTITLE : SortMode:=stArtist; + IDC_BYDATE : SortMode:=stDate; + IDC_BYCOUNT : SortMode:=stCount; + IDC_BYPATH : SortMode:=stPath; + IDC_BYLENGTH: SortMode:=stLength; + IDC_RUNREPORT: RunReport :=IsDlgButtonChecked(Dialog,IDC_RUNREPORT); + IDC_ADDEXT: DoAddExt :=IsDlgButtonChecked(Dialog,IDC_ADDEXT); + IDC_DIRECTION: begin + if IsDlgButtonChecked(Dialog,IDC_DIRECTION)=BST_CHECKED then + Direction:=smReverse + else + Direction:=smDirect; + end; + + IDC_CLEAR: begin + DeleteFileA(StatName); + exit; + end; + IDC_SNBUTTON: begin + if ShowDlg(buf,StatName) then + SetDlgItemTextA(Dialog,IDC_STATNAME,buf); + end; + IDC_TNBUTTON: begin + if ShowDlg(buf,TmplName) then + SetDlgItemTextA(Dialog,IDC_TMPLNAME,buf); + end; + IDC_RNBUTTON: begin + if ShowDlg(buf,ReportName) then + SetDlgItemTextA(Dialog,IDC_REPNAME,buf); + end; + IDC_SORTFILE: begin + GetDlgItemTextA(Dialog,IDC_STATNAME,buf,511); + if buf[0]<>#0 then + SortFile(buf,SortMode,Direction); + exit; + end; + IDC_EXPORTDEF: begin + if ShowDlg(buf,TmplName) then + begin + f:=Rewrite(buf); + if f=THANDLE(INVALID_HANDLE_VALUE) then + err('Can''t create file') + else + begin + BlockWrite(f,IntTmpl^,StrLen(IntTmpl)); + CloseHandle(f); + end; + end; + exit; + end; + IDC_REPORT: begin + ReportItems:=GetDlgItemInt(Dialog,IDC_ITEMS,tmp,false); + if ReportItems=0 then + ReportItems:=1; + GetDlgItemTextA(Dialog,IDC_REPNAME,buf1,511); + GetDlgItemTextA(Dialog,IDC_TMPLNAME,buf,511); + SetReportMask(Dialog); + CallService(MS_WAT_MAKEREPORT,TWPARAM(@buf),TLPARAM(@buf1)); + end; + end; + end; + if ((wParam shr 16)=EN_CHANGE) or ((wParam shr 16)=BN_CLICKED) then + begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + changed:=true; + end; + result:=1; + end; + + WM_NOTIFY: begin + if (integer(PNMHdr(lParam)^.code)=PSN_APPLY) and changed then + begin + GetDlgItemTextA(Dialog,IDC_STATNAME,buf,511); + mFreeMem(StatName); + if buf[0]<>#0 then + begin + buf1[0]:=#0; + CallService(MS_UTILS_PATHTORELATIVE,TWPARAM(@buf),TLPARAM(@buf1)); + StrDup(StatName,buf1); + end; + + GetDlgItemTextA(Dialog,IDC_REPNAME,buf,511); + mFreeMem(ReportName); + if buf[0]<>#0 then + begin + buf1[0]:=#0; + CallService(MS_UTILS_PATHTORELATIVE,TWPARAM(@buf),TLPARAM(@buf1)); + StrDup(ReportName,buf1); + end; + + GetDlgItemTextA(Dialog,IDC_TMPLNAME,buf,511); + mFreeMem(TmplName); + if buf[0]<>#0 then + begin + buf1[0]:=#0; + CallService(MS_UTILS_PATHTORELATIVE,TWPARAM(@buf),TLPARAM(@buf1)); + StrDup(TmplName,buf1); + end; + + AutoSort:=GetDlgItemInt(Dialog,IDC_AUTOSORT,tmp,false); + ReportItems:=GetDlgItemInt(Dialog,IDC_ITEMS,tmp,false); + if ReportItems=0 then + ReportItems:=1; + SetReportMask(Dialog); + result:=1; + savestat; + changed:=false; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/stat/stat_opt.inc b/plugins/Watrack/stat/stat_opt.inc new file mode 100644 index 0000000000..8d8bed6bb5 --- /dev/null +++ b/plugins/Watrack/stat/stat_opt.inc @@ -0,0 +1,62 @@ +{statistic load/save options} +const + opt_ModStatus :PAnsiChar = 'module/statistic'; + + opt_StatName :PAnsiChar = 'report/statname'; + opt_RepName :PAnsiChar = 'report/repname'; + opt_TmplName :PAnsiChar = 'report/tmplname'; + opt_SortMode :PAnsiChar = 'report/sortmode'; + opt_ReportMask:PAnsiChar = 'report/reportmask'; + opt_ReportItem:PAnsiChar = 'report/reportitems'; + opt_Direction :PAnsiChar = 'report/direction'; + opt_RunReport :PAnsiChar = 'report/runreport'; + opt_AddExt :PAnsiChar = 'report/addext'; + opt_AutoSort :PAnsiChar = 'report/autosort'; + opt_LastSort :PAnsiChar = 'report/lastsort'; + +function GetModStatus:integer; +begin + result:=DBReadByte(0,PluginShort,opt_ModStatus,1); +end; + +procedure SetModStatus(stat:integer); +begin + DBWriteByte(0,PluginShort,opt_ModStatus,stat); +end; + +procedure loadstat; +begin + ReportName :=DBReadString(0,PluginShort,opt_RepName ,nil); + StatName :=DBReadString(0,PluginShort,opt_StatName,nil); + TmplName :=DBReadString(0,PluginShort,opt_TmplName,nil); + DoAddExt :=DBReadByte (0,PluginShort,opt_AddExt ,BST_CHECKED); + RunReport :=DBReadByte (0,PluginShort,opt_RunReport ,BST_UNCHECKED); + Direction :=DBReadByte (0,PluginShort,opt_Direction ,smDirect); + SortMode :=DBReadByte (0,PluginShort,opt_SortMode ,stArtist); + ReportItems:=DBReadWord (0,PluginShort,opt_ReportItem,10); + ReportMask :=DBReadWord (0,PluginShort,opt_ReportMask,$FFFF); + AutoSort :=DBReadByte (0,PluginShort,opt_AutoSort ,1); + LastSort :=DBReadDWord (0,PluginShort,opt_LastSort ,0); +end; + +procedure savestat; +begin + DBWriteString(0,PluginShort,opt_RepName ,ReportName); + DBWriteString(0,PluginShort,opt_StatName,StatName); + DBWriteString(0,PluginShort,opt_TmplName,TmplName); + DBWriteByte (0,PluginShort,opt_AddExt ,DoAddExt); + DBWriteByte (0,PluginShort,opt_RunReport ,RunReport); + DBWriteByte (0,PluginShort,opt_Direction ,Direction); + DBWriteByte (0,PluginShort,opt_SortMode ,SortMode); + DBWriteWord (0,PluginShort,opt_ReportItem ,ReportItems); + DBWriteWord (0,PluginShort,opt_ReportMask ,ReportMask); + DBWriteByte (0,PluginShort,opt_AutoSort ,AutoSort); +// DBWriteDWord (0,PluginShort,opt_LastSort ,LastSort); +end; + +procedure FreeStat; +begin + mFreeMem(ReportName); + mFreeMem(StatName); + mFreeMem(TmplName); +end; diff --git a/plugins/Watrack/stat/stat_rc.inc b/plugins/Watrack/stat/stat_rc.inc new file mode 100644 index 0000000000..ff697e95f7 --- /dev/null +++ b/plugins/Watrack/stat/stat_rc.inc @@ -0,0 +1,29 @@ +const + IDC_STATNAME = 1026; + IDC_SNBUTTON = 1027; + IDC_SORTFILE = 1028; + IDC_REPORT = 1029; + IDC_BYTITLE = 1030; + IDC_BYDATE = 1031; + IDC_BYCOUNT = 1032; + IDC_BYPATH = 1033; + IDC_DIRECTION = 1034; + IDC_REPNAME = 1035; + IDC_RNBUTTON = 1036; + IDC_ITEMS = 1037; + IDC_CLEAR = 1038; + IDC_FREQART = 1040; + IDC_FREQSONG = 1041; + IDC_FREQPATH = 1042; + IDC_LASTSONG = 1043; + IDC_SONGTIME = 1044; + IDC_TMPLNAME = 1045; + IDC_TNBUTTON = 1046; + IDC_EXPORTDEF = 1047; + IDC_RUNREPORT = 1048; + IDC_ADDEXT = 1049; + IDC_FREQALBUM = 1050; + IDC_AUTOSORT = 1051; + IDC_BYLENGTH = 1052; + + BTN_REPORT = 12; diff --git a/plugins/Watrack/stat/stat_vars.inc b/plugins/Watrack/stat/stat_vars.inc new file mode 100644 index 0000000000..ccc7c0c5b2 --- /dev/null +++ b/plugins/Watrack/stat/stat_vars.inc @@ -0,0 +1,21 @@ +{statistic variables} +var + SortMode:dword; + ReportMask:dword; + ReportItems:cardinal; + Direction:cardinal; + RunReport:cardinal; + DoAddExt:cardinal; + AutoSort:cardinal; + LastSort:dword; +const + StatName :PAnsiChar=nil; + ReportName:PAnsiChar=nil; + TmplName :PAnsiChar=nil; +var + hPackLog, + hMakeReport, + hAddToLog, + plStatusHook, + sic, + hMenuReport:THANDLE; diff --git a/plugins/Watrack/stat/statlog.pas b/plugins/Watrack/stat/statlog.pas new file mode 100644 index 0000000000..50af34508d --- /dev/null +++ b/plugins/Watrack/stat/statlog.pas @@ -0,0 +1,650 @@ +{Statistic} +unit StatLog; +{$include compilers.inc} +interface +{$Resource stat.res} +implementation + +uses windows,messages,shellapi,commctrl + ,wrapper,io,wat_api,common,global,m_api,dbsettings,mirutils; + +{$include stat_data.inc} +{$include stat_vars.inc} +{$include stat_opt.inc} + +type + pStatCell = ^tStatCell; + tStatCell = record + Count :integer; + AltCount :integer; + LastTime :dword; + Length :integer; + Artist :PAnsiChar; + Title :PAnsiChar; + MFile :PAnsiChar; + Album :PAnsiChar; + next :pStatCell; // only for fill + end; + +type + pCells = ^tCells; + tCells = record + Count:integer; + Cells:array [0..1] of pStatCell + end; + +const + IcoBtnReport:PAnsiChar='WATrack_Report'; +const + DelimChar = '|'; +const + buflen = 2048; + +const + Lock:boolean=false; + +procedure err(str:PWideChar); +begin + MessageBoxW(0,TranslateW(str),TranslateW('Music Statistic'),MB_OK); +end; + +function OnlyPath(dst,src:PAnsiChar):PAnsiChar; +var + i:integer; +begin + i:=StrLen(src)-1; + while (i>0) and (src[i]<>'\') do dec(i); + StrCopy(dst,src,i); + result:=dst; +end; + +function PackTime(aTime:TSYSTEMTIME):dword; +begin + with aTime do + result:=wSecond+ + (wMinute shl 06)+ + (wHour shl 12)+ + (wDay shl 17)+ + (wMonth shl 22)+ + (((wYear-2000) and $3F) shl 26); +end; + +procedure UnPackTime(aTime:dword;var MyTime:TSYSTEMTIME); +begin + with MyTime do + begin + wYear :=(aTime shr 26)+2000; + wMonth :=(aTime shr 22) and $0F; + wDay :=(aTime shr 17) and $1F; + wHour :=(aTime shr 12) and $1F; + wMinute:=(aTime shr 6 ) and $3F; + wSecond:=aTime and $3F; + end; +end; + +function ShowTime(buf:PAnsiChar;aTime:dword):PAnsiChar; +var + MyTime:TSYSTEMTIME; +begin + UnPackTime(aTime,MyTime); + with MyTime do + begin + IntToStr(buf ,wDay ,2); + IntToStr(buf+3 ,wMonth ,2); + IntToStr(buf+6 ,wYear ,2); + IntToStr(buf+9 ,wHour ,2); + IntToStr(buf+12,wMinute,2); + IntToStr(buf+15,wSecond,2); + end; + buf[2] :='.'; buf[5] :='.'; buf[8] :=' '; + buf[11]:=':'; buf[14]:=':'; buf[17]:=#0; + result:=buf; +end; + +function AppendStr(src:PAnsiChar;var dst:PAnsiChar):PAnsiChar; overload; +begin + dst^:=DelimChar; inc(dst); + while src^<>#0 do + begin + dst^:=src^; + inc(dst); + inc(src); + end; + result:=dst; +end; + +function AppendStr(src:PWideChar;var dst:PAnsiChar):PAnsiChar; overload; +var + p,lp:PAnsiChar; +begin + dst^:=DelimChar; inc(dst); + lp:=WideToUTF8(src,p); + while lp^<>#0 do + begin + dst^:=lp^; + inc(dst); + inc(lp); + end; + mFreeMem(p); + result:=dst; +end; + +procedure AppendStat(fname:PAnsiChar;si:pSongInfo); +var + f:THANDLE; + MyTime:TSYSTEMTIME; + buf:array [0..buflen-1] of char; + lp:PAnsiChar; +begin + if Lock then + exit; + if (si^.artist=NIL) and (si^.title=NIL) and + (si^.album =NIL) and (si^.mfile=NIL) then + exit; + f:=Append(fname); +// if dword(f)=INVALID_HANDLE_VALUE then f:=Rewrite(fname); + if f=THANDLE(INVALID_HANDLE_VALUE) then exit; + FillChar(buf,SizeOf(buf),0); + lp:=@buf; + buf[0]:='1'; buf[1]:=DelimChar; inc(lp,2); // Count + + GetLocalTime(MyTime); + IntToStr(lp,PackTime(MyTime),9); + inc(lp,9); + lp^:=DelimChar; + inc(lp); + IntToStr(lp,si^.total); while lp^<>#0 do inc(lp); + + AppendStr(si^.artist,lp); + AppendStr(si^.title ,lp); + AppendStr(si^.mfile ,lp); + AppendStr(si^.album ,lp); + + lp^:=#$0D; inc(lp); lp^:=#$0A; + BlockWrite(f,buf,lp-PAnsiChar(@buf)+1); + CloseHandle(f); +end; + +procedure OutputStat(fname:PAnsiChar;aCells:pCells); +var + f:THANDLE; + buf:array [0..2047] of char; + lp:PAnsiChar; + i:integer; +begin + f:=Rewrite(fname); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + for i:=0 to aCells^.Count-1 do + begin + lp:=@buf; + with aCells^.Cells[i]^ do + begin + IntToStr(buf,Count); while lp^<>#0 do inc(lp); + lp^:=DelimChar; inc(lp); + IntToStr(lp,LastTime,9); inc(lp,9); + lp^:=DelimChar; inc(lp); + IntToStr(lp,Length); while lp^<>#0 do inc(lp); + AppendStr(Artist,lp); + AppendStr(Title ,lp); + AppendStr(MFile ,lp); + AppendStr(Album ,lp); + + lp^:=#$0D; inc(lp); lp^:=#$0A; + BlockWrite(f,buf,lp-PAnsiChar(@buf)+1); + end; + end; + CloseHandle(f); +end; + +function CutStr(var src:PAnsiChar):PAnsiChar; +begin + result:=src; + while (src^<>DelimChar) and (src^>=' ') do inc(src); + src^:=#0; + inc(src); +end; + +procedure ClearStatCells(aCells:pCells); +begin + with aCells^ do + while Count>0 do + begin + dec(Count); + mFreeMem(Cells[Count]); + end; + mFreeMem(aCells); +end; + +function FillCell(src:PAnsiChar):pStatCell; +var + Cell:pStatCell; +begin + mGetMem(Cell,SizeOf(tStatCell)); + FillChar(Cell^,SizeOf(tStatCell),0); + Cell^.Count :=StrToInt(src); + while src^<>DelimChar do inc(src); inc(src); + Cell^.LastTime:=StrToInt(src); + while src^<>DelimChar do inc(src); inc(src); + Cell^.Length :=StrToInt(src); + while src^<>DelimChar do inc(src); inc(src); + Cell^.Artist:=CutStr(src); + Cell^.Title :=CutStr(src); + Cell^.MFile :=CutStr(src); + Cell^.Album :=CutStr(src); + + result:=Cell; +end; + +function Compare(C1,C2:pStatCell; SortType:integer):integer; +var + ls,ls1:array [0..511] of AnsiChar; +begin + case SortType of + stArtist: begin + result:=lstrcmpia(C1^.Artist,C2^.Artist); + if result=0 then + result:=lstrcmpia(C1^.Title,C2^.Title); + if result=0 then + result:=lstrcmpia(C1^.Album,C2^.Album); + end; + stAlbum: result:=lstrcmpia(C1^.Album,C2^.Album); + stPath : result:=lstrcmpia(OnlyPath(ls,C1^.MFile),OnlyPath(ls1,C2^.MFile)); + stDate : result:=C2^.LastTime-C1^.LastTime; + stCount : result:=C2^.Count-C1^.Count; + stLength : result:=C2^.Length-C1^.Length; + stAltCount: result:=C2^.AltCount-C1.AltCount; + else + result:=0; + end; +end; + +function SwapProc(var Root:pCells;First,Second:integer):integer; +var + p:pStatCell; +begin + p:=Root^.Cells[First]; + Root^.Cells[First]:=Root^.Cells[Second]; + Root^.Cells[Second]:=p; + result:=0; +end; + +procedure Resort(var Root:pCells;sort:integer;adirection:integer=smDirect); + + function CompareProc(First,Second:integer):integer; + begin + result:=Compare(Root^.cells[First],Root^.cells[Second],sort); + if direction=smReverse then + result:=-result; + end; + +var + i,j,gap:longint; +begin + gap:=Root^.Count shr 1; + while gap>0 do + begin + for i:=gap to Root^.Count-1 do + begin + j:=i-gap; + while (j>=0) and (CompareProc(j,UInt(j+gap))>0) do + begin + SwapProc(Root,j,UInt(j+gap)); + dec(j,gap); + end; + end; + gap:=gap shr 1; + end; +// now pack doubles +end; + +function BuildTree(fname:PAnsiChar;var buffer:PAnsiChar):pCells; +var + f:THANDLE; + i,cnt:integer; + FirstCell,CurCell,Cell:pStatCell; + lRec:TWin32FindDataA;//WIN32_FIND_DATAA; + h:THANDLE; + p,p1,p2:PAnsiChar; + ls,buf:PAnsiChar; + arr:pCells; +begin + result:=nil; + buffer:=nil; + h:=FindFirstFileA(fname,lRec); + if h=THANDLE(INVALID_HANDLE_VALUE) then + exit; + i:=lRec.nFileSizeLow; + FindClose(h); + if i<22 then + Exit; + f:=Reset(fname); + if f=THANDLE(INVALID_HANDLE_VALUE) then + exit; + mGetMem(buffer,i+1); + p:=buffer; + BlockRead(f,p^,i); + CloseHandle(f); + p1:=p; + p2:=p+i; + FirstCell:=nil; + mGetMem(buf,buflen); + buf^:=#0; + cnt:=0; + while p#$0D do inc(p); + i:=p-p1; + p^:=#0; + if i>=20 then //min log template + min fname [d:\.e] + begin + ls:=p1; +// skip duplicates one-by-one + while ls^<>DelimChar do inc(ls); inc(ls); // Count + while ls^<>DelimChar do inc(ls); inc(ls); // time + while ls^<>DelimChar do inc(ls); inc(ls); // length + if StrCmp(buf,ls)<>0 then + begin + inc(cnt); + StrCopy(buf,ls); + Cell:=FillCell(p1); + + if FirstCell=nil then + begin + FirstCell:=Cell; + CurCell :=FirstCell; + end + else + begin + CurCell^.next:=Cell; + CurCell:=Cell; + end; + end; + end; + inc(p,2); p1:=p; + end; + mFreeMem(buf); + // Fill array + if cnt>0 then + begin + mGetMem(arr,SizeOf(integer)+cnt*SizeOf(pStatCell)); + arr^.Count:=cnt; + CurCell:=FirstCell; + i:=0; + while CurCell<>nil do + begin + arr^.Cells[i]:=CurCell; + CurCell:=CurCell.next; + inc(i); + end; + result:=arr; + // sort & pack + Resort(arr,stArtist); + + i:=1; + Cell:=arr^.Cells[0]; + while inil then + begin + if (mode<>stArtist) or (adirection<>smDirect) then + Resort(Root,mode,adirection); + OutputStat(buf1,Root); + ClearStatCells(Root); + end; + mFreeMem(buf); + Lock:=false; +end; + +{$include report.inc} + +// --------------- service functions ----------------- + +function ThAddToLog(param:pdword):dword; stdcall; +begin + result:=0; +end; + +procedure ThPackLog(param:pdword); cdecl; +begin + SortFile(StatName,SortMode,Direction); +end; + +function ThMakeReport(param:pdword):dword; stdcall; +begin + result:=0; +end; + +function AddToLog(wParam:WPARAM;lParam:LPARAM):integer;cdecl; +var + fname:PAnsiChar; + log:array [0..511] of AnsiChar; +begin + result:=0; + if (StatName=nil) or (StatName[0]=#0) then + exit; + if wParam=0 then + fname:=StatName + else + fname:=PAnsiChar(wParam); + ConvertFileName(fname,log); +// CallService(MS_UTILS_PATHTOABSOLUTE,dword(fname),dword(@log)); + AppendStat(log,pSongInfo(lParam)); +end; + +function PackLog(wParam:WPARAM;lParam:LPARAM):integer;cdecl; +begin + result:=0; + CloseHandle(mir_forkthread(@ThPackLog,nil)); +end; + +function MakeReport(wParam:WPARAM;lParam:LPARAM):integer;cdecl; +var + report,log,template:array [0..511] of AnsiChar; + l,r:PAnsiChar; +begin + result:=0; + if CallService(MS_WAT_PLUGINSTATUS,2,0)=WAT_RES_DISABLED then + exit; + if (wParam<>0) and (wParam<>MenuReportPos) then + l:=PAnsiChar(wParam) + else + l:=TmplName; + if PAnsiChar(lParam)<>nil then r:=PAnsiChar(lParam) else r:=ReportName; + if (r=nil) or (r^=#0) then + err('Report file name not defined') + else if (StatName=nil) or (StatName^=#0) then + err('Log file name not defined') + else + begin + ConvertFileName(r,report); + ConvertFileName(l,template); + ConvertFileName(StatName,log); +// CallService(MS_UTILS_PATHTOABSOLUTE,dword(r),dword(@report)); +// CallService(MS_UTILS_PATHTOABSOLUTE,dword(l),dword(@template)); +// CallService(MS_UTILS_PATHTOABSOLUTE,dword(StatName),dword(@log)); + if DoAddExt=BST_CHECKED then + ChangeExt(report,'htm'); + if StatOut(report,log,template) then + begin + if RunReport=BST_CHECKED then + begin + ShellExecuteA(0,nil{'open'},report,nil,nil,SW_SHOWNORMAL); + end; + result:=1; + end + else + err('Oops, something wrong!'); + end; +end; + +{$include stat_dlg.inc} + +function NewPlStatus(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + flag:integer; + mi:tClistMenuItem; + CurTime:dword; +begin + result:=0; + case wParam of + WAT_EVENT_NEWTRACK: begin + if (StatName<>nil) and (StatName[0]<>#0) then + begin + AppendStat(StatName,pSongInfo(lParam)); + if AutoSort>0 then + begin + CurTime:=GetCurrentTime; + if (CurTime-LastSort)>=(86400*AutoSort) then + begin + SortFile(StatName,SortMode,Direction); //PackLog(0,0); + LastSort:=CurTime; + DBWriteDWord(0,PluginShort,opt_LastSort,LastSort); + end; + end; + end; + end; + WAT_EVENT_PLUGINSTATUS: begin + case lParam of + 0: flag:=0; + 2: flag:=CMIF_GRAYED; + else // like 1 + exit + end; + FillChar(mi,sizeof(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_FLAGS+flag; + CallService(MS_CLIST_MODIFYMENUITEM,hMenuReport,tlparam(@mi)); + end; + end; +end; + +function IconChanged(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + mi:TCListMenuItem; +begin + result:=0; + FillChar(mi,SizeOf(mi),0); + mi.cbSize:=sizeof(mi); + mi.flags :=CMIM_ICON; + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnReport)); + CallService(MS_CLIST_MODIFYMENUITEM,hMenuReport,tlparam(@mi)); +end; + +// ------------ base interface functions ------------- + +function InitProc(aGetStatus:boolean=false):integer; +var + mi:TCListMenuItem; + sid:TSKINICONDESC; +begin + if aGetStatus then + begin + if GetModStatus=0 then + begin + result:=0; + exit; + end; + end + else + SetModStatus(1); + result:=1; + + hPackLog :=CreateServiceFunction(MS_WAT_PACKLOG ,@PackLog); + hMakeReport:=CreateServiceFunction(MS_WAT_MAKEREPORT,@MakeReport); + hAddToLog :=CreateServiceFunction(MS_WAT_ADDTOLOG ,@AddToLog); + loadstat; + + FillChar(sid,SizeOf(TSKINICONDESC),0); + sid.cbSize:=SizeOf(TSKINICONDESC); + sid.cx:=16; + sid.cy:=16; + sid.szSection.a:='WATrack'; + sid.hDefaultIcon :=LoadImage(hInstance,MAKEINTRESOURCE(BTN_REPORT),IMAGE_ICON,16,16,0); + sid.pszName :=IcoBtnReport; + sid.szDescription.a:='Create Report'; + Skin_AddIcon(@sid); + DestroyIcon(sid.hDefaultIcon); + sic:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged); + + FillChar(mi, sizeof(mi), 0); + mi.cbSize :=sizeof(mi); + mi.flags :=0; + mi.szPopupName.a:=PluginShort; + mi.hIcon :=CallService(MS_SKIN2_GETICON,0,tlparam(IcoBtnReport)); + mi.szName.a :='Create WATrack report'; + mi.pszService :=MS_WAT_MAKEREPORT; + mi.popupPosition:=MenuReportPos; + hMenuReport :=Menu_AddMainMenuItem(@mi); + plStatusHook:=HookEvent(ME_WAT_NEWSTATUS,@NewPlStatus); +end; + +procedure DeInitProc(aSetDisable:boolean); +begin + if aSetDisable then + SetModStatus(0); + + CallService(MS_CLIST_REMOVEMAINMENUITEM,hMenuReport,0); + UnhookEvent(plStatusHook); + UnhookEvent(sic); + DestroyServiceFunction(hPackLog); + DestroyServiceFunction(hMakeReport); + DestroyServiceFunction(hAddToLog); + FreeStat; +end; + +function AddOptionsPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +begin + tmpl:='STATS'; + proc:=@DlgProcOptions; + name:='Statistics'; + result:=0; +end; + +var + Stat:twModule; + +procedure Init; +begin + Stat.Next :=ModuleLink; + Stat.Init :=@InitProc; + Stat.DeInit :=@DeInitProc; + Stat.AddOption :=@AddOptionsPage; + Stat.ModuleName:='Statistic'; + ModuleLink :=@Stat; +end; + +begin + Init; +end. diff --git a/plugins/Watrack/stat/wat_report.ico b/plugins/Watrack/stat/wat_report.ico new file mode 100644 index 0000000000..8e9c02fb93 Binary files /dev/null and b/plugins/Watrack/stat/wat_report.ico differ diff --git a/plugins/Watrack/status/i_hotkey.inc b/plugins/Watrack/status/i_hotkey.inc new file mode 100644 index 0000000000..3ad23ae656 --- /dev/null +++ b/plugins/Watrack/status/i_hotkey.inc @@ -0,0 +1,62 @@ +{main hotkey code} +function InsertProc(wParam:WPARAM;lParam:LPARAM):int_ptr; cdecl; +var + CurWin:HWND; + s:pWideChar; + p:PAnsiChar; + isUnicode:boolean; + i:integer; + j:integer; + tt:tTemplateType; +begin + result:=0; + if DisablePlugin=dsPermanent then + exit; + if Loword(LastStatus)<>WAT_PLS_NORMAL then + exit; +// i:=CallService(MS_WAT_GETMUSICINFO,0,0); + if UseMessages=BST_CHECKED then + begin + CurWin:=GetFocus; + if CurWin<>0 then + begin +// j:=WndToContact(WaitFocusedWndChild(GetForegroundwindow){GetFocus}); + j:=WndToContact(CurWin); + p:=GetContactProtoAcc(j); +// p:=PAnsiChar(CallService(MS_PROTO_GETCONTACTBASEPROTO,j,0)); + if DBReadByte(j,p,'ChatRoom',0)=1 then + begin + isUnicode:=false; + tt:=tmpl_chat; + end + else + begin + isUnicode:=true; + tt:=tmpl_pm; + end; + if SimpleMode<>BST_UNCHECKED then + i:=0 + else + i:=FindProto(p); + s:=GetMacros(tt,i); + // not empty and not disabled + if (s<>nil) and (uint_ptr(s)<>uint_ptr(-1)) then + begin + if StrScanW(s,'{')<>nil then + SendRTF(CurWin,s,isUnicode,UserCP) + else + begin + if isUnicode then + SendMessageW(CurWin,EM_REPLACESEL,0,tlparam(s)) + else + begin + SendMessageA(CurWin,EM_REPLACESEL,0,tlparam(WideToAnsi(s,p,UserCP))); + mFreeMem(p); + end; + end; + mFreeMem(s); + end; + result:=1; + end; + end; +end; diff --git a/plugins/Watrack/status/i_opt_11.inc b/plugins/Watrack/status/i_opt_11.inc new file mode 100644 index 0000000000..55279d3156 --- /dev/null +++ b/plugins/Watrack/status/i_opt_11.inc @@ -0,0 +1,459 @@ +{Templates} +const + DLGED_INIT = $1000; // dialog init, not activate Apply button + DLGED_PROT = $0800; // proto changed + DLGED_STAT = $0400; // status changed + DLGED_PACK = $0200; // needed string packing + DLGED_CHGD = $0100; // something changed + DLGED_MSG = $0001; // message template changed + DLGED_STTT = $0004; // status template changed + DLGED_CHNL = $0008; // channel template changed + DLGED_XTTL = $0010; // xstatus title changed + DLGED_XTTT = $0020; // xstatus template changed + DLGED_TUNE = $0040; // tunes template changed + DLGED_BASE = DLGED_MSG +DLGED_STTT+DLGED_CHNL+ + DLGED_TUNE+DLGED_XTTL+DLGED_XTTT; + +const + maxShowControls = 7; + aListFields:array [0..maxShowControls-1] of integer= ( + IDC_STATUS_TEXT, + IDC_XSTATUS_TITLE, IDC_XSTATUS_TEXT, + IDC_LISTENING_TEXT, + IDC_STAT_ENABLE,IDC_XSTAT_ENABLE,IDC_TUNES_ENABLE); + + aShowFields: array [0..2,0..maxShowControls-1] of integer = ( +{status} (SW_SHOW, SW_HIDE, SW_HIDE, SW_HIDE, SW_SHOW, SW_HIDE, SW_HIDE), +{xstatus} (SW_HIDE, SW_SHOW, SW_SHOW, SW_HIDE, SW_HIDE, SW_SHOW, SW_HIDE), +{tunes} (SW_HIDE, SW_HIDE, SW_HIDE, SW_SHOW, SW_HIDE, SW_HIDE, SW_SHOW)); + +var + CurProto, + CurStatus:integer; + +procedure RedrawFields(Dialog:hwnd;proto:integer=-1); +var + wnd1,wnd:HWND; + p:pWideChar; + i:integer; +begin + Changed:=Changed or DLGED_INIT; + if proto<0 then + proto:=CurProto; + + SetDlgItemTextW(Dialog,IDC_EDIT_MSG, + GetTemplateStr(tmpl_pm,proto,CurStatus)); + + p:=GetTemplateStr(tmpl_stext,proto,CurStatus); + + wnd:=GetDlgItem(Dialog,IDC_STATUS_TEXT); + + SendMessageW(wnd,WM_SETTEXT,0,lparam(p)); + if IsTemplateActive(tmpl_stext,proto,CurStatus) then + begin + EnableWindow(wnd,true); + i:=BST_CHECKED; + end + else + begin + EnableWindow(wnd,false); + i:=BST_UNCHECKED; + end; + CheckDlgButton(Dialog,IDC_STAT_ENABLE,i); + + if IsXStatusSupported(CurProto) then + begin + wnd :=GetDlgItem(Dialog,IDC_XSTATUS_TITLE); + wnd1:=GetDlgItem(Dialog,IDC_XSTATUS_TEXT); + p:=GetTemplateStr(tmpl_xtitle,proto,CurStatus); + SendMessageW(wnd ,WM_SETTEXT,0,lparam(p)); + SendMessageW(wnd1,WM_SETTEXT,0, + lparam(GetTemplateStr(tmpl_xtext,proto,CurStatus))); + + if IsTemplateActive(tmpl_xtitle,proto,CurStatus) then + begin + EnableWindow(wnd ,true); + EnableWindow(wnd1,true); + i:=BST_CHECKED; + end + else + begin + EnableWindow(wnd ,false); + EnableWindow(wnd1,false); + i:=BST_UNCHECKED; + end; + CheckDlgButton(Dialog,IDC_XSTAT_ENABLE,i); + end; + + if IsTunesSupported(CurProto) then + begin + p:=GetTemplateStr(tmpl_tunes,proto,CurStatus); + wnd:=GetDlgItem(Dialog,IDC_LISTENING_TEXT); + SendMessageW(wnd,WM_SETTEXT,0,lparam(p)); + if IsTemplateActive(tmpl_tunes,proto,CurStatus) then + begin + EnableWindow(wnd,true); + i:=BST_CHECKED; + end + else + begin + EnableWindow(wnd,false); + i:=BST_UNCHECKED; + end; + CheckDlgButton(Dialog,IDC_TUNES_ENABLE,i); + end; + + if IsChatSupported(CurProto) then + SetDlgItemTextW(Dialog,IDC_EDIT_CHANNEL, + GetTemplateStr(tmpl_chat,proto,CurStatus)); + + Changed:=Changed and not DLGED_INIT; +end; + +procedure SetScreenFull(Dialog:hwnd); +var + show:integer; + buf:array [0..127] of AnsiChar; + endis:boolean; + wnd:HWND; +begin + Changed:=Changed or DLGED_INIT; + CurStatus:=0; + + CheckDlgButton(Dialog,IDC_IRC_USER ,BST_CHECKED); + CheckDlgButton(Dialog,IDC_IRC_CHANNEL,BST_UNCHECKED); + ShowWindow(GetDlgItem(Dialog,IDC_EDIT_MSG ),SW_SHOW); + ShowWindow(GetDlgItem(Dialog,IDC_EDIT_CHANNEL),SW_HIDE); + + if IsChatSupported(CurProto) then + show:=SW_SHOW + else + show:=SW_HIDE; + + ShowWindow(GetDlgItem(Dialog,IDC_IRC_USER ),show); + ShowWindow(GetDlgItem(Dialog,IDC_IRC_CHANNEL),show); + +// wnd:=GetDlgItem(Dialog,IDC_PROTOLIST); + +//!!!! SendMessage(wnd,CB_SETCURSEL,0,0); //??? + +// SendMessageA(wnd,LVM_GETITEMTEXTA,); +// ListView_GetItemTextA(wnd,CurProto,0,@buf,SizeOf(buf)); + + StrCopy(buf,GetProtoName(CurProto)); + StrCat(buf,PS_ICQ_GETCUSTOMSTATUSICON); + endis:=ServiceExists(buf)<>0; + + EnableWindow(GetDlgItem(Dialog,IDC_CBEX ),endis); + EnableWindow(GetDlgItem(Dialog,IDC_XSTAT_AUDIO),endis); + EnableWindow(GetDlgItem(Dialog,IDC_XSTAT_VIDEO),endis); + if endis then + begin + CheckDlgButton(Dialog,IDC_XSTAT_AUDIO,BST_CHECKED); + CheckDlgButton(Dialog,IDC_XSTAT_VIDEO,BST_UNCHECKED); + end; + + wnd:=GetDlgItem(Dialog,IDC_STATUSLIST); + FillStatusList(CurProto,wnd,true); + SendMessage(wnd,CB_SETCURSEL,0,0); + RedrawFields(Dialog); +end; + +procedure SetTemplate(Dialog:hwnd;idc:integer;Tmpl:tTemplateType); +begin + SetTemplateStr (GetDlgText(Dialog,ABS(idc)),Tmpl,CurProto,CurStatus); + SetTemplateActive(idc>0 ,Tmpl,CurProto,CurStatus); +end; + +procedure SaveChanges(Dialog:hwnd); +var + i,j:integer; +begin + if (Changed and DLGED_BASE)<>0 then + begin + if (Changed and DLGED_MSG )<>0 then SetTemplate(Dialog,IDC_EDIT_MSG ,tmpl_pm); + if (Changed and DLGED_CHNL)<>0 then SetTemplate(Dialog,IDC_EDIT_CHANNEL,tmpl_chat); + + + if (Changed and DLGED_STTT)<>0 then + begin + if IsDlgButtonChecked(Dialog,IDC_STAT_ENABLE)<>BST_UNCHECKED then + i:=IDC_STATUS_TEXT + else + i:=-IDC_STATUS_TEXT; + SetTemplate(Dialog,i,tmpl_stext); + end; + + if (Changed and DLGED_TUNE)<>0 then + begin + if IsDlgButtonChecked(Dialog,IDC_TUNES_ENABLE)<>BST_UNCHECKED then + i:=IDC_LISTENING_TEXT + else + i:=-IDC_LISTENING_TEXT; + SetTemplate(Dialog,i,tmpl_tunes); + end; + + if (Changed and (DLGED_XTTL or DLGED_XTTT))<>0 then + begin + if IsDlgButtonChecked(Dialog,IDC_XSTAT_ENABLE)<>BST_UNCHECKED then + begin + i:=IDC_XSTATUS_TITLE; + j:=IDC_XSTATUS_TEXT; + end + else + begin + i:=-IDC_XSTATUS_TITLE; + j:=-IDC_XSTATUS_TEXT; + end; + if (Changed and DLGED_XTTL)<>0 then SetTemplate(Dialog,i,tmpl_xtitle); + if (Changed and DLGED_XTTT)<>0 then SetTemplate(Dialog,j,tmpl_xtext); + end; + + Changed:=Changed and (not DLGED_BASE); + end; +end; + +function SaveCBExValue(Dialog:HWnd;direct:boolean):cardinal; +var + wnd:HWND; + i,j,shift:cardinal; +begin + wnd:=GetDlgItem(Dialog,IDC_CBEX); + i:=GetProtoSetting(CurProto,true); + + if (IsDlgButtonChecked(Dialog,IDC_XSTAT_VIDEO)<>BST_UNCHECKED) xor direct then + shift:=0 + else + shift:=8; + + j:=SendMessage(wnd,CB_GETCURSEL,0,0); + i:=(i and ($FFFF0000 or ($FF shl (8-shift)))) or (j shl shift); + + SetProtoSetting(CurProto,i,true); + + result:=(i shr (8-shift)) and $FF; +end; + +procedure FillCBType(Dialog:hwnd;proto:pAnsiChar=nil); +var + wnd:HWND; + j:integer; +begin + wnd:=GetDlgItem(Dialog,IDC_CBSTATYPE); + SendMessage(wnd,CB_RESETCONTENT,0,0); + + CB_AddStrDataW(wnd,TranslateW('Status'),0); + if IsXStatusSupported(uint_ptr(proto)) then CB_AddStrDataW(wnd,TranslateW('XStatus'),1); + if IsTunesSupported (uint_ptr(proto)) then CB_AddStrDataW(wnd,TranslateW('Tunes' ),2); + + SendMessage(wnd,CB_SETCURSEL,0,0); + + for j:=0 to maxShowControls-1 do + ShowWindow(GetDlgItem(Dialog,aListFields[j]),aShowFields[0][j]); +end; + +function DlgProcOptions11(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +var + Item:LV_ITEMA; + buf:array [0..127] of AnsiChar; + i,j:integer; + wnd:HWND; + b:boolean; +begin + result:=0; + case hMessage of + WM_DESTROY: begin + ListView_SetImageList(GetDlgItem(Dialog,IDC_STATUSLIST),0,LVSIL_SMALL); + ListView_SetImageList(GetDlgItem(Dialog,IDC_PROTOLIST ),0,LVSIL_SMALL); + end; + + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + Changed:=DLGED_INIT; + FillProtoList(GetDlgItem(Dialog,IDC_PROTOLIST),true); + CurProto :=0; + SetScreenFull(Dialog); + FillCBType(Dialog,nil); + SendMessage(Dialog,WM_COMMAND,(CBN_SELCHANGE shl 16)+IDC_CBSTATYPE, + GetDlgItem(Dialog,IDC_CBSTATYPE)); + result:=0; + Changed:=0; + end; + + WM_COMMAND: begin + case wParam shr 16 of + EN_CHANGE: begin + if (Changed and DLGED_INIT)=0 then + begin + Changed:=Changed or DLGED_CHGD or DLGED_PACK; + case loword(wParam) of + IDC_EDIT_MSG : Changed:=Changed or DLGED_MSG; + IDC_EDIT_CHANNEL : Changed:=Changed or DLGED_CHNL; + IDC_STATUS_TEXT : Changed:=Changed or DLGED_STTT; + IDC_XSTATUS_TITLE : Changed:=Changed or DLGED_XTTL; + IDC_XSTATUS_TEXT : Changed:=Changed or DLGED_XTTT; + IDC_LISTENING_TEXT: Changed:=Changed or DLGED_TUNE; + end; + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + + CBN_SELCHANGE: begin + case loword(wParam) of + IDC_CBSTATYPE: begin + i:=CB_GetData(lParam); + for j:=0 to maxShowControls-1 do + ShowWindow(GetDlgItem(Dialog,aListFields[j]),aShowFields[i][j]); + end; + + IDC_CBEX: begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + end; + + BN_CLICKED: begin + case LoWord(wParam) of + IDC_CMD_DEFAULT: begin + RedrawFields(Dialog,0); + Changed:=Changed or DLGED_CHGD or DLGED_BASE; + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + IDC_CMD_RESET: begin + RedrawFields(Dialog); + end; + + IDC_STAT_ENABLE, IDC_XSTAT_ENABLE, IDC_TUNES_ENABLE: begin + case LoWord(wParam) of + IDC_STAT_ENABLE: begin + Changed:=Changed or DLGED_STTT; + EnableWindow(GetDlgItem(Dialog,IDC_STATUS_TEXT), + IsDlgButtonChecked(Dialog,IDC_STAT_ENABLE)<>BST_UNCHECKED); + end; + IDC_XSTAT_ENABLE: begin + b:=IsDlgButtonChecked(Dialog,IDC_XSTAT_ENABLE)<>BST_UNCHECKED; + EnableWindow(GetDlgItem(Dialog,IDC_XSTATUS_TITLE),b); + EnableWindow(GetDlgItem(Dialog,IDC_XSTATUS_TEXT ),b); + Changed:=Changed or DLGED_XTTL; + Changed:=Changed or DLGED_XTTT; + end; + IDC_TUNES_ENABLE: begin + Changed:=Changed or DLGED_TUNE; + EnableWindow(GetDlgItem(Dialog,IDC_LISTENING_TEXT), + IsDlgButtonChecked(Dialog,IDC_TUNES_ENABLE)<>BST_UNCHECKED); + end; + end; + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + + IDC_XSTAT_VIDEO, IDC_XSTAT_AUDIO: begin + SendDlgItemMessage(Dialog,IDC_CBEX,CB_SETCURSEL,SaveCBExValue(Dialog,false),0); + end; + IDC_HELP_COLOR: begin + ShowColorHelpDlg(Dialog); + exit; + end; + IDC_HELP_FORMAT: begin + MessageBoxW(0,TranslateW(sFormatHelp),TranslateW('Format text Info'),0); + exit; + end; + IDC_HELP_VARIABLES: begin + CallService(MS_WAT_MACROHELP,Dialog,0); + exit; + end; + IDC_IRC_USER: begin +// CheckDlgButton(Dialog,IDC_IRC_USER ,BST_CHECKED); +// CheckDlgButton(Dialog,IDC_IRC_CHANNEL,BST_UNCHECKED); + ShowWindow(GetDlgItem(Dialog,IDC_EDIT_MSG ),SW_SHOW); + ShowWindow(GetDlgItem(Dialog,IDC_EDIT_CHANNEL),SW_HIDE); + end; + IDC_IRC_CHANNEL: begin +// CheckDlgButton(Dialog,IDC_IRC_USER ,BST_UNCHECKED); +// CheckDlgButton(Dialog,IDC_IRC_CHANNEL,BST_CHECKED); + ShowWindow(GetDlgItem(Dialog,IDC_EDIT_CHANNEL),SW_SHOW); + ShowWindow(GetDlgItem(Dialog,IDC_EDIT_MSG ),SW_HIDE); + end; + else + SaveChanges(Dialog); //?? + end; + end; + end; + + end; + + WM_HELP: begin + case PHELPINFO(lParam).iCtrlId of + IDC_EDIT_MSG,IDC_EDIT_CHANNEL,IDC_XSTATUS_TITLE, + IDC_STATUS_TEXT,IDC_XSTATUS_TEXT,IDC_LISTENING_TEXT: + CallService(MS_WAT_MACROHELP,Dialog,0); + end; + end; + + WM_NOTIFY: begin + if (Changed and DLGED_INIT)<>0 then + exit; + if integer(PNMLISTVIEW(lParam)^.hdr.code)=LVN_ITEMCHANGED then + begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + if ((PNMLISTVIEW(lParam)^.uNewState and LVIS_FOCUSED)<>0) then + begin + SaveChanges(Dialog); + + if PNMLISTVIEW(lParam)^.hdr.idFrom=IDC_PROTOLIST then + begin + CheckStatusList(GetDlgItem(Dialog,IDC_STATUSLIST),CurProto); + SaveCBExValue(Dialog,true); + CurProto:=PNMLISTVIEW(lParam)^.iItem; + SetScreenFull(Dialog); +// ListView_GetItemTextA(PNMLISTVIEW(lParam)^.hdr.hwndFrom,CurProto,0,@buf,SizeOf(buf)); + StrCopy(buf,GetProtoName(CurProto)); + wnd:=GetDlgItem(Dialog,IDC_CBEX); + FillCBType(Dialog,buf); + if AddCBEx(wnd,buf)<>0 then + begin + i:=GetProtoSetting(CurProto,true); + SendMessage(wnd,CB_SETCURSEL,i and $FF,0); + end; + end + + else //IDC_STATUSLIST + begin + Item.iItem:=PNMLISTVIEW(lParam)^.iItem; + Item.mask:=LVIF_PARAM; + SendMessageA(PNMLISTVIEW(lParam)^.hdr.hwndFrom,LVM_GETITEMA,0,tlparam(@Item)); +// ListView_GetItemA(PNMLISTVIEW(lParam)^.hdr.hwndFrom,Item); + CurStatus:=GetStatusNum(Item.lParam); + RedrawFields(Dialog); + end; + end + + else if PNMLISTVIEW(lParam)^.uNewState<>0 then + begin + if PNMLISTVIEW(lParam)^.hdr.idFrom=IDC_PROTOLIST then + Changed:=Changed or DLGED_PROT or DLGED_CHGD + else + Changed:=Changed or DLGED_STAT or DLGED_CHGD; + end; + end + + else if integer(PNMHdr(lParam)^.code)=PSN_APPLY then + begin + if (Changed and DLGED_PROT)<>0 then + begin + CheckProtoList(GetDlgItem(Dialog,IDC_PROTOLIST)); + Changed:=Changed and not DLGED_PROT; + end; + if (Changed and DLGED_STAT)<>0 then + begin + CheckStatusList(GetDlgItem(Dialog,IDC_STATUSLIST),CurProto); + Changed:=Changed and not DLGED_STAT; + end; + SaveCBExValue(Dialog,true); + SaveChanges(Dialog); + SaveTemplates; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/status/i_opt_12.inc b/plugins/Watrack/status/i_opt_12.inc new file mode 100644 index 0000000000..7414ecf9d7 --- /dev/null +++ b/plugins/Watrack/status/i_opt_12.inc @@ -0,0 +1,108 @@ +{Templates} + +procedure SetScreenLite(Dialog:HWnd); +var + p:pWideChar; +begin + Changed:=Changed or DLGED_INIT; + + p:=GetTemplateStr(tmpl_pm ,0,0); + SetDlgItemTextW(Dialog,IDC_EDIT_MSG ,p); + p:=GetTemplateStr(tmpl_xtitle,0,0); + SetDlgItemTextW(Dialog,IDC_XSTATUS_TITLE,p); + p:=GetTemplateStr(tmpl_stext ,0,0); + SetDlgItemTextW(Dialog,IDC_STATUS_TEXT ,p); + p:=GetTemplateStr(tmpl_chat ,0,0); + SetDlgItemTextW(Dialog,IDC_EDIT_CHANNEL ,p); + + Changed:=Changed and not DLGED_INIT; +end; + +procedure SetTemplateLite(Dialog:HWnd;idc:integer;Tmpl:tTemplateType); +begin + SetTemplateStr(GetDlgText(Dialog,idc),Tmpl,0,0); +end; + +procedure SaveChangesLite(Dialog:HWnd); +begin + if (Changed and DLGED_BASE)<>0 then + begin + if (Changed and DLGED_MSG )<>0 then SetTemplateLite(Dialog,IDC_EDIT_MSG ,tmpl_pm); + if (Changed and DLGED_CHNL)<>0 then SetTemplateLite(Dialog,IDC_EDIT_CHANNEL,tmpl_chat); + if (Changed and DLGED_XTTL)<>0 then + begin + SetTemplateLite(Dialog,IDC_XSTATUS_TITLE,tmpl_xtitle); + end; + if (Changed and DLGED_STTT)<>0 then + begin + SetTemplateLite(Dialog,IDC_STATUS_TEXT,tmpl_stext); + SetTemplateLite(Dialog,IDC_STATUS_TEXT,tmpl_xtext); + SetTemplateLite(Dialog,IDC_STATUS_TEXT,tmpl_tunes); + end; + + Changed:=Changed and (not DLGED_BASE); + SaveTemplates; + end; +end; + +function DlgProcOptions12(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lparam; stdcall; +begin + result:=0; + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + SetScreenLite(Dialog); + result:=0; + Changed:=0; + end; + + WM_COMMAND: begin + if (Changed and DLGED_INIT)=0 then + begin + case wParam shr 16 of + EN_CHANGE: begin + Changed:=Changed or DLGED_CHGD or DLGED_PACK; + case loword(wParam) of + IDC_EDIT_MSG : Changed:=Changed or DLGED_MSG; + IDC_XSTATUS_TITLE : Changed:=Changed or DLGED_XTTL; + IDC_STATUS_TEXT : Changed:=Changed or DLGED_STTT; + IDC_EDIT_CHANNEL : Changed:=Changed or DLGED_CHNL; + end; + end; + BN_CLICKED: begin + case LoWord(wParam) of + IDC_CMD_RESET: begin + SetScreenLite(Dialog); + end; + IDC_HELP_COLOR: begin + ShowColorHelpDlg(Dialog); + exit; + end; + IDC_HELP_FORMAT: begin + MessageBoxW(0,TranslateW(sFormatHelp),TranslateW('Format text Info'),0); + exit; + end; + IDC_HELP_VARIABLES: begin + CallService(MS_WAT_MACROHELP,Dialog,0); + exit; + end; + end; + end; + else + exit; + end; + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + end; + + WM_HELP: CallService(MS_WAT_MACROHELP,Dialog,0); + + WM_NOTIFY: begin + if integer(PNMHdr(lParam)^.code)=PSN_APPLY then + SaveChangesLite(Dialog); + end; + + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/status/i_opt_3.inc b/plugins/Watrack/status/i_opt_3.inc new file mode 100644 index 0000000000..3defc68b54 --- /dev/null +++ b/plugins/Watrack/status/i_opt_3.inc @@ -0,0 +1,106 @@ +{format specific} + +function DlgProcOptions3(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):lresult; stdcall; +const + dlginit:boolean=false; +var + wnd:HWND; + b:boolean; +begin + result:=0; + case hMessage of + WM_INITDIALOG: begin + dlginit:=false; + TranslateDialogDefault(Dialog); + + MakeHint(Dialog,IDC_SIMPLEMODE, + 'If this option is "ON", one templates will be used with all '+ + 'protocols, protocol and player (media) statuses. Template option page will be '+ + 'changed next time.'); + CheckDlgButton(Dialog,IDC_SIMPLEMODE,SimpleMode); + MakeHint(Dialog,IDC_INDEPENDED, + 'If this option is "ON", XStatus doesn''t depend of protocol status.'); + CheckDlgButton(Dialog,IDC_INDEPENDED,XIndepended); + MakeHint(Dialog,IDC_USESTATUS, + 'If this option is "ON", status text will be replaced by music info.'); + CheckDlgButton(Dialog,IDC_USESTATUS,UseStatus); + MakeHint(Dialog,IDC_USEMSGS, + 'If this option is "ON", you can paste music info to your '+ + 'message window pressing hotkey.'); + CheckDlgButton(Dialog,IDC_USEMSGS,UseMessages); + MakeHint(Dialog,IDC_KEEPSTATUS, + 'If this option is "ON", XStatus not changed when player shutdowned.'); + CheckDlgButton(Dialog,IDC_KEEPSTATUS,KeepStatus); + MakeHint(Dialog,IDC_CLEARXSTAT, + 'xStatus will cleared before text changing and restored with new text later.'); + CheckDlgButton(Dialog,IDC_CLEARXSTAT,ClearXStat); + MakeHint(Dialog,IDC_EXTSTATUS, + 'If this option is "ON", XStatus will be changed to "Music" and '+ + 'status text will be replaced by music info.'); + CheckDlgButton(Dialog,IDC_EXTSTATUS ,UseExtStatus); + MakeHint(Dialog,IDC_LISTENINGTO, + 'If this option is "ON", "Listening To" protocol property will be filled '+ + 'by music info.'); + CheckDlgButton(Dialog,IDC_LISTENINGTO,UseListeningTo); + + wnd:=GetDlgItem(Dialog,IDC_SETXSTATUS); +// SendMessage(wnd,CB_RESETCONTENT,0,0); + CB_AddStrDataW(wnd,TranslateW('any XStatus is set' ),0,0); + CB_AddStrDataW(wnd,TranslateW('''Music'' status is set' ),1,1); + CB_AddStrDataW(wnd,TranslateW('XStatus is empty or ''Music'''),2,2); + CB_SelectData(wnd,XStatusSet); + + SendMessage(Dialog,WM_COMMAND,(BN_CLICKED shl 16)+IDC_EXTSTATUS, + GetDlgItem(Dialog,IDC_EXTSTATUS)); + + dlginit:=true; + result:=0; + end; + + WM_COMMAND: begin + if ((wParam shr 16)=BN_CLICKED) and (LoWord(wParam)=IDC_EXTSTATUS) then + begin + b:=IsDlgButtonchecked(Dialog,IDC_EXTSTATUS)<>BST_UNCHECKED; + EnableWindow(GetDlgItem(Dialog,IDC_INDEPENDED),b); + EnableWindow(GetDlgItem(Dialog,IDC_CLEARXSTAT),b); +// EnableWindow(GetDlgItem(Dialog,IDC_OLDXSTATUS),b); +// EnableWindow(GetDlgItem(Dialog,IDC_ONLYMUSIC ),b); + EnableWindow(GetDlgItem(Dialog,IDC_SETXSTATUS),b); + EnableWindow(GetDlgItem(Dialog,IDC_KEEPSTATUS),b); + end; + + case wParam shr 16 of + CBN_SELCHANGE, + EN_CHANGE, + BN_CLICKED: SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + result:=1; + end; + + WM_NOTIFY: begin + if dlginit then + begin + case integer(PNMHdr(lParam)^.code) of + LVN_ITEMCHANGED: begin + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + end; + + PSN_APPLY: begin + SimpleMode :=IsDlgButtonChecked(Dialog,IDC_SIMPLEMODE); + XIndepended :=IsDlgButtonChecked(Dialog,IDC_INDEPENDED); + UseMessages :=IsDlgButtonChecked(Dialog,IDC_USEMSGS); + UseStatus :=IsDlgButtonChecked(Dialog,IDC_USESTATUS); + UseExtStatus :=IsDlgButtonChecked(Dialog,IDC_EXTSTATUS); + KeepStatus :=IsDlgButtonChecked(Dialog,IDC_KEEPSTATUS); + ClearXStat :=IsDlgButtonChecked(Dialog,IDC_CLEARXSTAT); + UseListeningTo:=IsDlgButtonChecked(Dialog,IDC_LISTENINGTO); + XStatusSet :=CB_GetData(GetDlgItem(Dialog,IDC_SETXSTATUS)); + SaveOpt; + end; + end; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/status/i_opt_status.inc b/plugins/Watrack/status/i_opt_status.inc new file mode 100644 index 0000000000..09e0c208ce --- /dev/null +++ b/plugins/Watrack/status/i_opt_status.inc @@ -0,0 +1,49 @@ +{} +const + opt_ModStatus :PAnsiChar = 'module/statuses'; + + opt_UseStatus :PAnsiChar = 'usestatus'; + opt_UseExtStat :PAnsiChar = 'useextstat'; + opt_UseMsgs :PAnsiChar = 'usemsgs'; + opt_XStatusSet :PAnsiChar = 'xstatusset'; + opt_KeepStatus :PAnsiChar = 'keepstatus'; + opt_Independed :PAnsiChar = 'independed'; + opt_ClearXStat :PAnsiChar = 'clearxstat'; + opt_SimplMode :PAnsiChar = 'simplemode'; + opt_ListeningTo:PAnsiChar = 'listeningto'; + +function GetModStatus:integer; +begin + result:=DBReadByte(0,PluginShort,opt_ModStatus,1); +end; + +procedure SetModStatus(stat:integer); +begin + DBWriteByte(0,PluginShort,opt_ModStatus,stat); +end; + +procedure LoadOpt; +begin + SimpleMode :=DBReadByte(0,PluginShort,opt_SimplMode ,BST_CHECKED); + UseStatus :=DBReadByte(0,PluginShort,opt_UseStatus ,BST_CHECKED); + UseExtStatus :=DBReadByte(0,PluginShort,opt_UseExtStat ,BST_CHECKED); + UseMessages :=DBReadByte(0,PluginShort,opt_UseMsgs ,BST_CHECKED); + KeepStatus :=DBReadByte(0,PluginShort,opt_KeepStatus ,BST_UNCHECKED); + XIndepended :=DBReadByte(0,PluginShort,opt_Independed ,BST_CHECKED); + ClearXStat :=DBReadByte(0,PluginShort,opt_ClearXStat ,BST_UNCHECKED); + UseListeningTo:=DBReadByte(0,PluginShort,opt_ListeningTo,BST_UNCHECKED); + XStatusSet :=DBReadByte(0,PluginShort,opt_XStatusSet ,1); +end; + +procedure SaveOpt; +begin + DBWriteByte(0,PluginShort,opt_SimplMode ,SimpleMode); + DBWriteByte(0,PluginShort,opt_UseStatus ,UseStatus); + DBWriteByte(0,PluginShort,opt_UseExtStat ,UseExtStatus); + DBWriteByte(0,PluginShort,opt_UseMsgs ,UseMessages); + DBWriteByte(0,PluginShort,opt_KeepStatus ,KeepStatus); + DBWriteByte(0,PluginShort,opt_Independed ,XIndepended); + DBWriteByte(0,PluginShort,opt_ClearXStat ,ClearXStat); + DBWriteByte(0,PluginShort,opt_ListeningTo,UseListeningTo); + DBWriteByte(0,PluginShort,opt_XStatusSet ,XStatusSet); +end; diff --git a/plugins/Watrack/status/i_opt_tmpl.inc b/plugins/Watrack/status/i_opt_tmpl.inc new file mode 100644 index 0000000000..9f5ea87907 --- /dev/null +++ b/plugins/Watrack/status/i_opt_tmpl.inc @@ -0,0 +1,244 @@ +{Save/load options} + +const + opt_numstr:PAnsiChar = 'template/numstr'; +const + ppref = 'proto/'; + spref = 'strings/'; + +procedure SaveTemplates; +var + i,lProtoStatus:cardinal; + lTmplType:tTemplateType; + p:PAnsiChar; + buf:PAnsiChar; + NumProto:cardinal; + tmpl:pStrTemplate; + tmp:SmallInt; + setting:array [0..63] of AnsiChar; + pset:PAnsiChar; +begin + DBWriteWord(0,PluginShort,opt_numstr,NumString); + StrCopy(setting,spref); + pset:=StrEnd(setting); + for i:=1 to NumString do + begin + IntToStr(pset,i); + DBWriteUnicode(0,PluginShort,setting,strings^[i].text); + end; + + NumProto:=GetNumProto; + mGetMem(buf,16384); + for i:=0 to NumProto do + begin + pset:=StrCopyE(setting,ppref); + pset:=StrCopyE(pset,GetProtoName(i)); + + StrCopy(pset,'/XStatus'); + DBWriteWord(0,PluginShort,setting,GetProtoSetting(i,true)); + inc(pset); + if i<>0 then + begin + StrCopy(pset,'enabled'); + DBWriteWord(0,PluginShort,setting,GetProtoSetting(i)); + end; + + p:=buf; + tmpl:=@StrTemplates^[i]; + pset[3]:=#0; + for lProtoStatus:=0 to NumStatus-1 do + for lTmplType:=tmpl_first to tmpl_last do + begin + tmp:=tmpl^[lProtoStatus,lTmplType]; + if tmp=0 then + begin + if p<>buf then + begin + p^:=','; + inc(p); + end; + p^:='0'; inc(p); // for compatibility + p^:=AnsiChar(lProtoStatus +ORD('0')); inc(p); + p^:=AnsiChar(ORD(lTmplType)+ORD('0')); inc(p); + end + else if (tmp<>0) and (tmp<>smallint(dubtmpl)) then + begin + pset[0]:='0'; // for compatibility + pset[1]:=AnsiChar(lProtoStatus +ORD('0')); + pset[2]:=AnsiChar(ORD(lTmplType)+ORD('0')); + DBWriteWord(0,PluginShort,setting,word(tmp)); + end; + end; + if p<>buf then + begin + p^:=#0; + StrCopy(pset,'empty'); + DBWriteString(0,PluginShort,setting,buf); + end; + end; + mFreeMem(buf); +end; + +procedure InitDefault; +var + tmpl:pStrTemplate; +begin + NumString:=8; + mGetMem (strings ,SizeOf(tMyString)*NumString); + FillChar(strings^,SizeOf(tMyString)*NumString,0); + + if isVarsInstalled then + begin + StrDupW(strings^[1].text,defAltTemplate); + StrDupW(strings^[4].text,defAltChannelText); + end + else + begin + StrDupW(strings^[1].text,defTemplate); + StrDupW(strings^[4].text,defChannelText); + end; + StrDupW(strings^[2].text,defStatusTitle); + StrDupW(strings^[3].text,defStatusText); + + tmpl:=@StrTemplates^[DefaultTemplate]; + if tmpl^[0,tmpl_first]=smallint(dubtmpl) then + begin + // music played + tmpl^[0,tmpl_pm ]:=1; + tmpl^[0,tmpl_chat ]:=4; + tmpl^[0,tmpl_xtitle]:=2; + tmpl^[0,tmpl_stext ]:=3; + tmpl^[0,tmpl_xtext ]:=3; + end; +end; + +function EnumSettingsProc(const szSetting:PAnsiChar;lParam:LPARAM):int; cdecl; +var + p:^PAnsiChar; + i:cardinal; + pp:AnsiChar; +begin + if StrCmp(ppref,szSetting,Length(ppref))=0 then + begin + i:=StrLen(szSetting)+1; + pp:=szSetting[i-2]; + if (pp>='0') and (pp<='9') then + begin + p:=pointer(lParam); + move(szSetting^,p^^,i); + inc(p^,i); + end; + end; + result:=0; +end; + +function EnumTemplates:PAnsiChar; +var + ces:TDBCONTACTENUMSETTINGS; + p:PAnsiChar; +begin + mGetMem(result,16384); + result^:=#0; + p:=result; + ces.pfnEnumProc:=@EnumSettingsProc; + ces.lParam :=lparam(@p); + ces.szModule :=PluginShort; + ces.ofsSettings:=0; + CallService(MS_DB_CONTACT_ENUMSETTINGS,0,lparam(@ces)); +end; + +procedure LoadTemplates; +var + buf:PAnsiChar; + lProtoStatus,i,j:cardinal; + lTmplType:tTemplateType; + p:PAnsiChar; + pc:PAnsiChar; + NumProto:cardinal; + tmpl:pStrTemplate; + setting:array [0..63] of AnsiChar; + pset:PAnsiChar; +begin + NumString:=DBReadWord(0,PluginShort,opt_numstr,0); + if NumString>0 then + begin + mGetMem (strings ,SizeOf(tMyString)*NumString); + FillChar(strings^,SizeOf(tMyString)*NumString,0); + StrCopy(setting,spref); + pset:=StrEnd(setting); + for i:=1 to NumString do + begin + IntToStr(pset,i); + strings^[i].text:=DBReadUnicode(0,PluginShort,setting,nil); + end; + + NumProto:=GetNumProto; + buf:=EnumTemplates; + for i:=0 to NumProto do + begin + pset:=StrCopyE(setting,ppref); + pset:=StrCopyE(pset,GetProtoName(i)); + + StrCopy(pset,'/XStatus'); + j:=DBReadWord(0,PluginShort,setting,$080B); +{!! + if j=0 then + j:=DefaultXStatus; +} + SetProtoSetting(i,j,true); + + inc(pset); + if i<>0 then + begin + StrCopy(pset,'enabled'); + SetProtoSetting(i,DBReadWord(0,PluginShort,setting,psf_all)); + end; + + tmpl:=@StrTemplates^[i]; + StrCopy(pset,'empty'); + pc:=DBReadString(0,PluginShort,setting,nil); + if pc<>nil then + begin + p:=pc; + if (p^>='0') and (p^<='9') then + while p^<>#0 do + begin + lProtoStatus := ORD(p[1])-ORD('0'); + lTmplType :=tTemplateType(ORD(p[2])-ORD('0')); + tmpl^[lProtoStatus,lTmplType]:=0; + inc(p,3); + if p^=',' then + inc(p); + end; + mFreeMem(pc); + end; + + pc:=buf; + pset^:=#0; + j:=StrLen(setting); + pset[3]:=#0; + while pc^<>#0 do + begin + if StrCmp(pc,setting,j)=0 then // only proper proto + begin + pc:=StrEnd(pc); + lProtoStatus := ORD((pc-2)^)-ORD('0'); + lTmplType :=tTemplateType(ORD((pc-1)^)-ORD('0')); + + pset[0]:='0'; + pset[1]:=AnsiChar(lProtoStatus +ORD('0')); + pset[2]:=AnsiChar(ORD(lTmplType)+ORD('0')); + + tmpl^[lProtoStatus,lTmplType]:= + DBReadWord(0,PluginShort,setting,dubtmpl); + end + else + pc:=StrEnd(pc); + inc(pc); + end; + end; + mFreeMem(buf); + end + else + InitDefault; +end; diff --git a/plugins/Watrack/status/i_st_rc.inc b/plugins/Watrack/status/i_st_rc.inc new file mode 100644 index 0000000000..c17768c2e7 --- /dev/null +++ b/plugins/Watrack/status/i_st_rc.inc @@ -0,0 +1,45 @@ +{DLG 1 - common} +const + IDC_USEMSGS = 2025; + IDC_HOTKEYGLOB = 2026; + IDC_STAT_HOTKEY = 2027; + IDC_USESTATUS = 2028; + IDC_EXTSTATUS = 2029; +// IDC_ONLYMUSIC = 2030; + IDC_KEEPSTATUS = 2031; + IDC_SIMPLEMODE = 2032; +// IDC_NOTES = 2033; + IDC_INDEPENDED = 2034; +// IDC_OLDXSTATUS = 2035; + IDC_CLEARXSTAT = 2036; + IDC_LISTENINGTO = 2037; + + IDC_SETXSTATUS = 2030; + +{DLG 2 - templates} +const + IDC_HELP_FORMAT = 1025; + IDC_HELP_COLOR = 1027; + IDC_HELP_VARIABLES = 1028; + {special} + IDC_EDIT_MSG = 2032; + IDC_STATUS_TEXT = 2034; + IDC_EDIT_CHANNEL = 2035; + IDC_XSTATUS_TITLE = 2036; + IDC_XSTATUS_TEXT = 2037; + IDC_LISTENING_TEXT = 2038; + IDC_STAT_ENABLE = 2039; + IDC_CBSTATYPE = 2040; + IDC_XSTAT_ENABLE = 2041; + IDC_TUNES_ENABLE = 2042; + + IDC_PROTOLIST = 1037; + IDC_STATUSLIST = 1038; + IDC_IRC_CHANNEL = 1041; + IDC_IRC_USER = 1042; + IDC_CMD_RESET = 1044; + IDC_CMD_DEFAULT = 1045; + + IDC_CBEX = 1046; + IDC_XSTAT_VIDEO = 1047; + IDC_XSTAT_AUDIO = 1048; diff --git a/plugins/Watrack/status/i_st_vars.inc b/plugins/Watrack/status/i_st_vars.inc new file mode 100644 index 0000000000..e1696c3621 --- /dev/null +++ b/plugins/Watrack/status/i_st_vars.inc @@ -0,0 +1,26 @@ +{} +const +{ + OldStatusText:array [0..15] of pWideChar = + (nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,nil); +} + OldXStatus:array [0..31] of byte = + (255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, + 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255); +var + UseListeningTo:cardinal; + SimpleMode :cardinal; + UseStatus :cardinal; + UseExtStatus :cardinal; + UseMessages :cardinal; + KeepStatus :cardinal; + XIndepended :cardinal; + XStatusSet :cardinal; + ClearXStat :cardinal; + hINS :THANDLE; +// hLTo :THANDLE; + plStatusHook :THANDLE; + +const + Changed:cardinal=0; + LastStatus:integer=WAT_PLS_NOTFOUND; diff --git a/plugins/Watrack/status/i_status.inc b/plugins/Watrack/status/i_status.inc new file mode 100644 index 0000000000..a7e3d2e5ef --- /dev/null +++ b/plugins/Watrack/status/i_status.inc @@ -0,0 +1,223 @@ +{Status and XStatus processing} + +// XStatus +const + xsnum = 31; + +function ListenProc(wParam:WPARAM;lParam:LPARAM):int_ptr; cdecl; +begin + // ignoring incoming ListeningTo info, uses internal + if PLISTENINGTOINFO(lParam).cbSize=SizeOf(TLISTENINGTOINFO) then + begin + result:=int_ptr(GetMacros(tmpl_tunes,0)); // need real proto number here + if result=-1 then result:=0; + end + else + begin + result:=CallService(MS_WAT_REPLACETEXT,0,wParam); + end; +end; + +function IsOurStatus(protomask,status:dword):boolean; +var + mask:dword; +begin +{ if status=ID_STATUS_OFFLINE then mask:=M_STAT_OFFLINE + else } + if status=ID_STATUS_ONLINE then mask:=psf_online + else if status=ID_STATUS_INVISIBLE then mask:=psf_invisible + else if status=ID_STATUS_AWAY then mask:=psf_shortaway + else if status=ID_STATUS_NA then mask:=psf_longaway + else if status=ID_STATUS_DND then mask:=psf_heavydnd + else if status=ID_STATUS_OCCUPIED then mask:=psf_lightdnd + else if status=ID_STATUS_FREECHAT then mask:=psf_freechat + else if status=ID_STATUS_ONTHEPHONE then mask:=psf_onthephone + else if status=ID_STATUS_OUTTOLUNCH then mask:=psf_outtolunch + else mask:=0; + result:=(protomask and mask)<>0; +end; + +function NewPlStatus(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + si:pSongInfo; + i,j:integer; + xstat:integer; + txt,title:pWideChar; + proto,ls:PAnsiChar; + mask,status:dword; + todo,isvideo:bool; + oldstatus:integer; + staudio,stvideo:integer; + lti:TLISTENINGTOINFO; + buf,buf1:array [0..31] of WideChar; + doClear:boolean; +begin + result:=0; + si:=pSongInfo(lParam); + + case wParam of + WAT_EVENT_NEWTRACK: begin + isvideo:=pSongInfo(lParam)^.width<>0; + doClear:=false; + end; + + WAT_EVENT_PLAYERSTATUS: begin + LastStatus:=lParam; + if (loword(lParam)=WAT_PLS_NORMAL) then + exit; + doClear:=true; + end; + else + exit; // not accept template changes + end; + + i:=GetNumProto; + for j:=1 to i do + begin + proto:=GetProtoName(j); + mask:=GetProtoSetting(j); + + if (SimpleMode<>BST_UNCHECKED) or ((mask and psf_enabled)<>0) then + begin + + if (UseStatus<>BST_UNCHECKED) or (UseExtStatus<>BST_UNCHECKED) then + begin + status:=CallProtoService(proto,PS_GETSTATUS,0,0); + todo :=(SimpleMode<>BST_UNCHECKED) or IsOurStatus(mask,status); + end + else + begin + status:=ID_STATUS_ONLINE; + todo :=true; + end; + + if (UseListeningTo<>BST_UNCHECKED) and + IsTunesSupported(j) then +// (ProtoServiceExists(proto,PS_SET_LISTENINGTO)<>0) then + begin + if doClear then + CallProtoService(proto,PS_SET_LISTENINGTO,0,0) + else if (wParam=WAT_EVENT_NEWTRACK) then + begin + lti.cbSize :=SizeOf(lti); + if si.width<>0 then + lti.szType.W:='Video' + else + lti.szType.W:='Music'; + lti.szArtist.W:=si.artist; + lti.szAlbum .W:=si.album; + lti.szTitle .W:=si.title; + lti.szTrack .W:=IntToStr(buf1,si.track); + lti.szYear .W:=si.year; + lti.szGenre .W:=si.genre; + lti.szLength.W:=IntToStr(buf,si.total); + lti.szPlayer.W:=si.player; + lti.dwFlags :=LTI_UNICODE; + + CallProtoService(proto,PS_SET_LISTENINGTO,0,tlparam(@lti)); + end; + end; + + if UseStatus<>BST_UNCHECKED then + if todo then + begin + if SimpleMode<>BST_UNCHECKED then + txt:=GetMacros(tmpl_stext,0) + else + txt:=GetMacros(tmpl_stext,j); + if uint_ptr(txt)<>uint_ptr(-1) then + begin + if (txt=nil) or (txt^=#0) then + ls:=nil + else + WideToAnsi(txt,ls,UserCP); + SetStatus(proto,-status,ls); + mFreeMem(ls); + mFreeMem(txt); + end; + end; + + if UseExtStatus<>BST_UNCHECKED then + begin + if todo or (XIndepended<>BST_UNCHECKED) then + begin + if IsXStatusSupported(j) then + begin + if doClear then // player status changed to no music/no player + begin + + if KeepStatus=BST_UNCHECKED then + begin + // just restoring savedstatus if was. no text changing + if OldXStatus[j]<>255 then + begin + oldstatus:=OldXStatus[j]; + OldXStatus[j]:=255; + SetXStatus(proto,oldstatus,pWideChar(-1),pWideChar(-1)); + end; + end; + + end + else + begin + if SimpleMode<>BST_UNCHECKED then + txt:=GetMacros(tmpl_xtext,0) + else + txt:=GetMacros(tmpl_xtext,j); + if uint_ptr(txt)<>uint_ptr(-1) then // status template presents + begin + // XStatus for audio/video + if SimpleMode<>BST_UNCHECKED then + begin + stvideo := 8; + staudio := 11; + end + else + begin + mask:=GetProtoSetting(j,true); + staudio:=mask and $FF; + stvideo:=(mask shr 8) and $FF; + end; + // Check, what we able to do something + oldstatus:=GetXStatus(proto,nil,nil); + if XStatusSet<>0 then // no matter which xstatus + begin + if not ((oldstatus=staudio) or (oldstatus=stvideo) or // music + ((oldstatus=0) and (XStatusSet=2))) then // empty + begin + mFreeMem(txt); + continue; //!! do nothing! + end; + end; + if isvideo then + xstat:=stvideo + else + xstat:=staudio; + + if xstat=0 then // not choosed, keep old (current) + xstat:=oldstatus + else + begin + if OldXStatus[j]=255 then + OldXStatus[j]:=oldstatus; + end; + + if ClearXStat<>BST_UNCHECKED then + SetXStatus(proto,0); + + if SimpleMode<>BST_UNCHECKED then + title:=GetMacros(tmpl_xtitle,0) + else + title:=GetMacros(tmpl_xtitle,j); + SetXStatus(proto,xstat,txt,title); + mFreeMem(title); + mFreeMem(txt); + end; + end; + end; + end; + end; + + end; + end; +end; diff --git a/plugins/Watrack/status/status.pas b/plugins/Watrack/status/status.pas new file mode 100644 index 0000000000..b5db16bb1c --- /dev/null +++ b/plugins/Watrack/status/status.pas @@ -0,0 +1,142 @@ +{Statistic} +unit Status; +{$include compilers.inc} +interface +{$Resource status.res} +implementation + +uses + windows,messages,commctrl, + common,m_api,mirutils,protocols,dbsettings,wrapper, + global,wat_api,hlpdlg,CBEx,myRTF,Tmpl; + +const + HKN_INSERT:PansiChar = 'WAT_Insert'; + +procedure reghotkey; +var + hkrec:HOTKEYDESC; +begin +// if DisablePlugin=dsPermanent then +// exit; + FillChar(hkrec,SizeOf(hkrec),0); + with hkrec do + begin + cbSize :=HOTKEYDESC_SIZE_V1; + pszName :=HKN_INSERT; + pszDescription.a:='Global WATrack hotkey'; + pszSection.a :=PluginName; + pszService :=MS_WAT_INSERT; + DefHotKey :=((HOTKEYF_ALT or HOTKEYF_CONTROL) shl 8) or VK_F5; +// lParam :=0; + end; + CallService(MS_HOTKEY_REGISTER,0,lparam(@hkrec)); +end; + +{$include i_st_vars.inc} +{$include i_st_rc.inc} +{$include i_opt_status.inc} +{$include i_hotkey.inc} +{$include i_status.inc} +{$include i_opt_3.inc} +{$include i_opt_11.inc} +{$include i_opt_12.inc} + +// ------------ base interface functions ------------- + +var + mStatus:twModule; + +function InitProc(aGetStatus:boolean=false):integer; +begin + if aGetStatus then + begin + if GetModStatus=0 then + begin + result:=0; + exit; + end; + end + else + SetModStatus(1); + result:=1; + + LoadOpt; + CreateProtoList; + CreateTemplates; + hINS:=CreateServiceFunction(MS_WAT_INSERT,@InsertProc); + reghotkey; + plStatusHook:=HookEvent(ME_WAT_NEWSTATUS,@NewPlStatus); + +// mStatus.ModuleStat:=1; + +// if ServiceExists(MS_LISTENINGTO_GETPARSEDTEXT)<>0 then +// hLTo:=CreateServiceFunction(MS_LISTENINGTO_GETPARSEDTEXT,@ListenProc); +end; + +procedure DeInitProc(aSetDisable:boolean); +var + j:integer; +begin + if aSetDisable then + SetModStatus(0); + + for j:=1 to GetNumProto do + begin + if (SimpleMode<>BST_UNCHECKED) or ((GetProtoSetting(j) and psf_enabled)<>0) then + CallProtoService(GetProtoName(j),PS_SET_LISTENINGTO,0,0); + end; +// DestroyServiceFunction(hLTo); + DestroyServiceFunction(hINS); + UnhookEvent(plStatusHook); + FreeProtoList; + FreeTemplates; + +// mStatus.ModuleStat:=0; +end; + +function AddOptionsPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +const + count:integer=2; +begin + if count=0 then + count:=2; + case count of + 2: begin + tmpl:='COMMON'; + proc:=@DlgProcOptions3; + name:='Status (common)'; + end; + 1: begin + if SimpleMode=BST_UNCHECKED then + begin + tmpl:='TEMPLATE11'; + proc:=@DlgProcOptions11; + end + else + begin + tmpl:='TEMPLATE12'; + proc:=@DlgProcOptions12; + end; + name:='Status (templates)'; + end + end; + + dec(count); + result:=count; +end; + +procedure Init; +begin + mStatus.Next :=ModuleLink; + mStatus.Init :=@InitProc; + mStatus.DeInit :=@DeInitProc; + mStatus.AddOption :=@AddOptionsPage; + mStatus.ModuleName:='Statuses'; +// mStatus.ModuleStat:=0; + ModuleLink :=@mStatus; +end; + +begin + Init; +end. diff --git a/plugins/Watrack/status/status.rc b/plugins/Watrack/status/status.rc new file mode 100644 index 0000000000..9a1c78c476 --- /dev/null +++ b/plugins/Watrack/status/status.rc @@ -0,0 +1,88 @@ +#include "i_st_rc.inc" + +LANGUAGE 0,0 + +COMMON DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + GROUPBOX "Options", -1, 2, 2, 188, 218, WS_TABSTOP + AUTOCHECKBOX "Simple Template mode", IDC_SIMPLEMODE , 6, 12, 182, 14, BS_VCENTER | BS_MULTILINE// | BS_NOTIFY + + AUTOCHECKBOX "Insert in messages" , IDC_USEMSGS , 6, 34, 182, 14, BS_VCENTER | BS_MULTILINE// | BS_NOTIFY + AUTOCHECKBOX "Use status messages" , IDC_USESTATUS , 6, 50, 182, 14, BS_VCENTER | BS_MULTILINE// | BS_NOTIFY + AUTOCHECKBOX "Use listening info" , IDC_LISTENINGTO, 6, 66, 182, 14, BS_VCENTER | BS_MULTILINE// | BS_NOTIFY + + AUTOCHECKBOX "Use XStatus" , IDC_EXTSTATUS , 6, 86, 182, 14, BS_VCENTER | BS_MULTILINE// | BS_NOTIFY + AUTOCHECKBOX "Independed XStatus" , IDC_INDEPENDED, 14, 102, 174, 14, BS_VCENTER | BS_MULTILINE// | BS_NOTIFY + AUTOCHECKBOX "Clear xStatus before set new one" , IDC_CLEARXSTAT, 14, 118, 174, 14, BS_VCENTER | BS_MULTILINE// | BS_NOTIFY + AUTOCHECKBOX "Keep 'Music' XStatus" , IDC_KEEPSTATUS, 14, 134, 174, 14, BS_VCENTER | BS_MULTILINE// | BS_NOTIFY +// AUTOCHECKBOX "Use existing XStatus" , IDC_OLDXSTATUS, 14, 134, 174, 14, BS_VCENTER | BS_MULTILINE// | BS_NOTIFY +// AUTOCHECKBOX "Only if 'Music' status was set", IDC_ONLYMUSIC , 14, 150, 174, 14, BS_VCENTER | BS_MULTILINE// | BS_NOTIFY + LTEXT "Set XStatus when...", -1, 14, 150, 174, 14 + COMBOBOX IDC_SETXSTATUS, 14, 166, 174, 96, CBS_DROPDOWNLIST | WS_VSCROLL +} + +TEMPLATE11 DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + PUSHBUTTON "Color", IDC_HELP_COLOR , 184, 1, 26, 12 + PUSHBUTTON "Format", IDC_HELP_FORMAT , 213, 1, 32, 12 + PUSHBUTTON "Variables", IDC_HELP_VARIABLES, 248, 1, 52, 12 + + CTEXT "Protocols", -1, 6, 2, 80, 10 + CONTROL "", IDC_PROTOLIST, "SysListView32", WS_BORDER | WS_TABSTOP | LVS_NOCOLUMNHEADER | LVS_SHOWSELALWAYS | LVS_SINGLESEL | LVS_REPORT, 6, 12, 80, 92, WS_EX_CONTROLPARENT + CTEXT "Statuses", -1, 90, 2, 92, 10 + CONTROL "", IDC_STATUSLIST, "SysListView32", WS_BORDER | WS_TABSTOP | LVS_NOCOLUMNHEADER | LVS_SHOWSELALWAYS | LVS_SINGLESEL | LVS_REPORT, 90, 12, 92, 92, WS_EX_CONTROLPARENT + + AUTORADIOBUTTON "User message", IDC_IRC_USER , 196, 51, 102, 12, NOT WS_TABSTOP | WS_GROUP + AUTORADIOBUTTON "Channel message", IDC_IRC_CHANNEL, 196, 63, 102, 12, NOT WS_TABSTOP + + PUSHBUTTON "Reset", IDC_CMD_RESET , 184, 103, 56, 12 + PUSHBUTTON "Default", IDC_CMD_DEFAULT, 242, 103, 56, 12 + + LTEXT "Template", -1, 16, 106, 166, 10, SS_CENTERIMAGE + EDITTEXT IDC_EDIT_MSG , 6, 116, 290, 44, ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL + EDITTEXT IDC_EDIT_CHANNEL, 6, 116, 290, 44, ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL + + AUTOCHECKBOX "Enable Status message" , IDC_STAT_ENABLE , 6, 161, 174, 12, BS_VCENTER | BS_MULTILINE + AUTOCHECKBOX "Enable XStatus message", IDC_XSTAT_ENABLE, 6, 161, 174, 12, BS_VCENTER | BS_MULTILINE + AUTOCHECKBOX "Enable Tunes message" , IDC_TUNES_ENABLE, 6, 161, 174, 12, BS_VCENTER | BS_MULTILINE + COMBOBOX IDC_CBSTATYPE,196,161,100,56,CBS_DROPDOWNLIST | WS_VSCROLL | NOT WS_TABSTOP + EDITTEXT IDC_STATUS_TEXT , 6, 175, 290, 45, ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL + EDITTEXT IDC_XSTATUS_TITLE , 6, 175, 290, 14, ES_AUTOHSCROLL + EDITTEXT IDC_XSTATUS_TEXT , 6, 192, 290, 28, ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL + EDITTEXT IDC_LISTENING_TEXT , 6, 175, 290, 45, ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | WS_VSCROLL + + AUTORADIOBUTTON "Audio", IDC_XSTAT_AUDIO, 186, 75, 54, 12, NOT WS_TABSTOP | BS_RIGHT | BS_LEFTTEXT | WS_GROUP + AUTORADIOBUTTON "Video", IDC_XSTAT_VIDEO, 244, 75, 54, 12, NOT WS_TABSTOP + + CONTROL "", IDC_CBEX, "ComboBoxEx32", + WS_GROUP | WS_TABSTOP | WS_VSCROLL | CBS_AUTOHSCROLL | CBS_DROPDOWNLIST, 186, 88, 112, 100 +} + +TEMPLATE12 DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + PUSHBUTTON "Color", IDC_HELP_COLOR , 184, 4, 26, 12 + PUSHBUTTON "Format", IDC_HELP_FORMAT , 213, 4, 32, 12 + PUSHBUTTON "Variables", IDC_HELP_VARIABLES, 248, 4, 52, 12 + + PUSHBUTTON "Reset", IDC_CMD_RESET, 6, 4, 56, 12 + LTEXT "This is simplified version of template editor. This templates will be used with all protocols, protocol and player (media) statuses", + -1, 6,20,290,22 + + CTEXT "Template", -1, 6, 42, 290, 10 + EDITTEXT IDC_EDIT_MSG, 6, 52, 290, 48, ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL + CTEXT "Chat Template", -1, 6, 102, 290, 10 + EDITTEXT IDC_EDIT_CHANNEL, 6, 112, 290, 48, ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL + + CTEXT "[X]Status Title / Text", -1, 6, 165, 290, 10 + EDITTEXT IDC_XSTATUS_TITLE, 6, 175, 290, 14, ES_AUTOHSCROLL + EDITTEXT IDC_STATUS_TEXT , 6, 192, 290, 28, ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN +} diff --git a/plugins/Watrack/status/status.res b/plugins/Watrack/status/status.res new file mode 100644 index 0000000000..fba2526583 Binary files /dev/null and b/plugins/Watrack/status/status.res differ diff --git a/plugins/Watrack/status/tmpl.pas b/plugins/Watrack/status/tmpl.pas new file mode 100644 index 0000000000..4adcd20bdf --- /dev/null +++ b/plugins/Watrack/status/tmpl.pas @@ -0,0 +1,304 @@ +unit Tmpl; + +interface +// ----- main data ----- +type + tTemplateType = ( + tmpl_pm ,tmpl_chat, + tmpl_xtitle,tmpl_xtext, + tmpl_stext , + tmpl_tunes); +const + tmpl_first = tmpl_pm; + tmpl_last = tmpl_tunes; +{ +const + TMPL_EMPTY = 0; + TMPL_PARENT = $4000; + TMPL_INACTIVE = ; +} +procedure CreateTemplates; +procedure FreeTemplates; +procedure SaveTemplates; + +function SetTemplateActive(active:boolean;aType:tTemplateType;proto:cardinal=0; + ProtoStatus:integer=0):boolean; +function IsTemplateActive(aType:tTemplateType;proto:cardinal=0; + ProtoStatus:integer=0):boolean; +function GetTemplateStr(aType:tTemplateType;proto:cardinal=0; + ProtoStatus:integer=0):PWideChar; +function SetTemplateStr(aStr:PWideChar;aType:tTemplateType;proto:cardinal=0; + ProtoStatus:integer=0):integer; + +function GetMacros(TmplType:tTemplateType;proto:integer):pWideChar; + +implementation + +uses common, m_api, windows, dbsettings, mirutils, protocols,wat_api,global; + +const + dubtmpl = $4000; +const + DefaultTemplate = 0; + NumStatus = 10; + +type + pStrTemplate = ^tStrTemplate; + tStrTemplate = array [0..NumStatus-1,tTemplateType] of SmallInt; + +type + pMyString = ^tMyString; + tMyString = record + count:cardinal; // link count + text :pWideChar; + end; + pMyStrArray = ^tMyStrArray; + tMyStrArray = array [1..1000] of tMyString; + +type + tTmpl = integer; + pStrTemplates = ^tStrTemplates; + tStrTemplates = array [0..100] of tStrTemplate; + +const + NumTemplates:cardinal=0; + StrTemplates:pStrTemplates=nil; + +var + strings:pMyStrArray; + NumString:cardinal; + +const + defTemplate = 'I am listening to %artist% - "%title%"'; + defChannelText = '/me listening to %artist% - "%title%"'; + defStatusTitle = 'Now listening to'; + defStatusText = '%artist% - %title%'; + + defAltTemplate = 'I am listening to %artist% - %title%?iflonger(%album%,0, (from "%album%"),)'; + defAltChannelText = '/me listening to %artist% - %title%?iflonger(%album%,0, (from "%album%"),)'; + +// ----- procedures ----- +{$include i_opt_tmpl.inc} + +function AddString(var newstr:PWideChar):cardinal; +var + i:cardinal; + tmp:pMyStrArray; +begin + for i:=1 to NumString do // search in table + begin + if StrCmpW(newstr,strings^[i].text)=0 then + begin + result:=i; + mFreeMem(newstr); + exit; + end; + end; + Inc(NumString); + mGetMem(tmp,SizeOf(tMyString)*NumString); + move(strings^,tmp^,SizeOf(tMyString)*(NumString-1)); + mFreeMem(strings); + strings:=tmp; + tmp^[NumString].count:=0; + tmp^[NumString].text:=newstr; + result:=NumString; +end; + +procedure PackStrings; +var + i,j:integer; + OldNumString:cardinal; + lTmplType:tTemplateType; + lProtoStatus:cardinal; + tmp:pMyStrArray; + NumProto:integer; + tmpl:pStrTemplate; +begin + // clear counters + for i:=1 to NumString do + strings^[i].count:=0; + // counts strings + NumProto:=GetNumProto; + for i:=0 to NumProto do + begin + tmpl:=@StrTemplates^[i]; + for lProtoStatus:=0 to NumStatus-1 do + for lTmplType:=tmpl_first to tmpl_last do + begin + j:=tmpl^[lProtoStatus,lTmplType]; + if j>0 then + inc(strings^[j].count); + end; + end; + // delete strings + i:=1; + OldNumString:=NumString; + + if DisablePlugin=dsEnabled then + DisablePlugin:=dsTemporary; + + while Cardinal(i)<=NumString do + begin + if strings^[i].count=0 then + begin + mFreeMem(strings^[i].text); + if cardinal(i)i then + dec(tmpl^[lProtoStatus,lTmplType]); + end; + end; + end; + dec(NumString); + continue; + end; + inc(i); + end; + if OldNumString<>NumString then + begin + mGetMem(tmp,SizeOf(tMyString)*NumString); + move(strings^,tmp^,SizeOf(tMyString)*NumString); + mFreeMem(strings); + strings:=tmp; + end; + +// if DisablePlugin<0 then +// SetTitle; + if DisablePlugin<>dsPermanent then + DisablePlugin:=dsEnabled; + +end; + +function SetTemplateActive(active:boolean;aType:tTemplateType;proto:cardinal=0; + ProtoStatus:integer=0):boolean; +var + res:smallint; +begin + if proto>NumTemplates then + proto:=0; + + res:=ABS(StrTemplates^[proto][ProtoStatus,aType]); + if not active then res:=-res; + StrTemplates^[proto][ProtoStatus,aType]:=res; + result:=res>0; +end; + +function IsTemplateActive(aType:tTemplateType;proto:cardinal=0; + ProtoStatus:integer=0):boolean; +begin + if proto>NumTemplates then + proto:=0; + + result:=StrTemplates^[proto][ProtoStatus,aType]>0; +end; + +function GetTmplString(num:integer):pWideChar; +begin + if (num>0) and (Cardinal(num)<=NumString) then + result:=strings^[num].text + else + result:=nil; +end; + +function GetTemplateStr(aType:tTemplateType;proto:cardinal=0; + ProtoStatus:integer=0):PWideChar; +var + i:smallint; +begin + if proto>NumTemplates then + proto:=0; + + i:=abs(StrTemplates^[proto ][ProtoStatus,aType]); + if i=smallint(dubtmpl) then begin i:=abs(StrTemplates^[proto ][0 ,aType]); + if i=smallint(dubtmpl) then begin i:=abs(StrTemplates^[DefaultTemplate][ProtoStatus,aType]); + if i=smallint(dubtmpl) then i:=abs(StrTemplates^[DefaultTemplate][0 ,aType]); end; end; + if i=smallint(dubtmpl) then + i:=0; + + result:=GetTmplString(ABS(i)); //normalize +end; + +function SetTemplateStr(aStr:PWideChar;aType:tTemplateType;proto:cardinal=0; + ProtoStatus:integer=0):integer; +var + tmpl:pStrTemplate; + tmp,tmp1:smallint; +begin + tmpl:=@StrTemplates^[proto]; + + if (aStr=nil) or (aStr^=#0) then + result:=0 + else + result:=AddString(aStr); + + tmp1:=result; + tmp:=tmpl^[0,aType]; + if tmp1=tmp then + tmp1:=smallint(dubtmpl) + else if tmp=smallint(dubtmpl) then + begin + if tmp1=tmpl^[0,aType] then + tmp1:=smallint(dubtmpl); + end; + tmpl^[ProtoStatus,aType]:=tmp1; +end; + +procedure CreateTemplates; +var + i:integer; +begin + NumTemplates:=GetNumProto; + // Size in bytes + i:=SizeOf(tStrTemplate)*(NumTemplates+1); + mGetMem(StrTemplates,i); + // size in words + FillWord(StrTemplates^,i div 2,dubtmpl); + LoadTemplates; +end; + +procedure FreeTemplates; +begin + mFreeMem(StrTemplates); + while NumString>0 do + begin + mFreeMem(strings^[NumString].text); + dec(NumString); + end; + mFreeMem(strings); +end; + +function GetMacros(TmplType:tTemplateType;proto:integer):pWideChar; +var + r:PWideChar; + status:integer; +begin + if proto=0 then + r:=GetTemplateStr(TmplType,0,0) + else + begin + status:=GetProtoStatusNum(proto); + if IsTemplateActive(TmplType,proto,status) then + r:=GetTemplateStr(TmplType,proto,status) + else + begin + result:=pWideChar(-1); + exit; + end; + end; + + if r=nil then + result:=nil + else + result:=pWideChar(CallService(MS_WAT_REPLACETEXT,0,lparam(r))); +end; + +end. diff --git a/plugins/Watrack/templates/i_expkey.inc b/plugins/Watrack/templates/i_expkey.inc new file mode 100644 index 0000000000..f6594acebb --- /dev/null +++ b/plugins/Watrack/templates/i_expkey.inc @@ -0,0 +1,34 @@ +{main hotkey code} +const + HKN_EXPORT:PAnsiChar = 'WAT_Export'; + +function ExportProc(wParam:WPARAM;lParam:LPARAM):int_ptr; cdecl; +var + p:pWideChar; +begin + result:=0; + if DisablePlugin<>dsPermanent then + begin + p:=pointer(CallService(MS_WAT_REPLACETEXT,0,tlparam(ExportText))); + SendString(0,p); + mFreeMem(p); + end; +end; + +procedure reginshotkey; +var + hkrec:HOTKEYDESC; +begin + FillChar(hkrec,SizeOf(hkrec),0); + with hkrec do + begin + cbSize :=HOTKEYDESC_SIZE_V1; + pszName :=HKN_EXPORT; + pszDescription.a:='WATrack data insert hotkey'; + pszSection.a :=PluginName; + pszService :=MS_WAT_EXPORT; + DefHotKey :=((HOTKEYF_ALT or HOTKEYF_SHIFT) shl 8) or VK_F7; +// lParam :=0; + end; + CallService(MS_HOTKEY_REGISTER,0,lparam(@hkrec)); +end; diff --git a/plugins/Watrack/templates/i_macro.inc b/plugins/Watrack/templates/i_macro.inc new file mode 100644 index 0000000000..68c0be6e33 --- /dev/null +++ b/plugins/Watrack/templates/i_macro.inc @@ -0,0 +1,149 @@ +{Macro help dialog} + +procedure SaveAliases; +var + buf:array [0..31] of AnsiChar; + i:integer; + p:PAnsiChar; +begin + p:=StrCopyE(buf,'alias/'); + for i:=0 to numvars-1 do + begin +// if vars[i].alias<>nil then + DBWriteUnicode(0,PluginShort,IntToStr(p,i),vars[i].alias); + end; +end; + +procedure LoadAliases; +var + buf:array [0..31] of AnsiChar; + i:integer; + p:PAnsiChar; +begin + p:=StrCopyE(buf,'alias/'); + for i:=0 to numvars-1 do + vars[i].alias:=DBReadUnicode(0,PluginShort,IntToStr(p,i),nil); +end; + +procedure FreeAliases; +var + i:integer; +begin + for i:=0 to numvars-1 do + mFreeMem(vars[i].alias); +end; + +function MacroHelpDlg(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):integer; stdcall; +const + Changed:bool=false; +var + i:integer; + itemw:LV_ITEMW; + lvc:LV_COLUMN; + wnd:hwnd; + ws:PWideChar; + s:pAnsiChar; + rc:TRECT; +begin + result:=0; + case hMessage of + + WM_INITDIALOG: begin + FillChar(itemw,SizeOf(itemw),0); + FillChar(lvc ,SizeOf(lvc) ,0); + wnd:=GetDlgItem(Dialog,IDC_MACROHELP); + SendMessage(wnd,LVM_SETUNICODEFORMAT,1,0); + lvc.mask:=LVCF_FMT; + lvc.fmt :=LVCFMT_LEFT; + ListView_InsertColumn(wnd,0,lvc); + itemw.mask:=LVIF_TEXT; + for i:=0 to numvars-1 do + begin + itemw.iItem:=i; + ws:=vars[i].alias; + if ws=nil then + ws:=vars[i].name; + itemw.pszText:=ws; + SendMessageW(wnd,LVM_INSERTITEMW,0,tlparam(@itemw)); + end; + ListView_SetColumnWidth(wnd,0,LVSCW_AUTOSIZE); + ListView_InsertColumn(wnd,1,lvc); + itemw.iSubItem:=1; + s:=nil; + for i:=0 to numvars-1 do + begin + itemw.iItem:=i; + if vars[i].help<>nil then + s:=vars[i].help; + itemw.pszText:=TranslateA2W(s); + SendMessageW(wnd,LVM_SETITEMTEXTW,i,tlparam(@itemw)); + mFreeMem(itemw.pszText); + end; + ListView_SetColumnWidth(wnd,1,LVSCW_AUTOSIZE); + result:=1; + Changed:=false; + TranslateDialogDefault(Dialog); + end; + + WM_SIZE: begin + GetClientRect(Dialog,rc); + InflateRect(rc,-8,-8); + MoveWindow(GetDlgItem(Dialog,IDC_MACROHELP), + rc.left,rc.top,rc.right-rc.left,rc.bottom-rc.top,true); + end; + + WM_COMMAND: begin + if (wParam shr 16)=BN_CLICKED then + case loword(wParam) of + IDOK, IDCANCEL: DestroyWindow(Dialog); + end; + end; + + WM_DESTROY: begin + if Changed then + begin + SaveAliases; + Changed:=false; + RegisterVariables; + end; + end; + + WM_NOTIFY: begin + if wParam=IDC_MACROHELP then + begin + case integer(PNMHdr(lParam)^.code) of + LVN_ENDLABELEDITW: begin + with PLVDISPINFO(lParam)^ do + begin + if item.pszText<>nil then + begin + item.mask:=LVIF_TEXT; + if pWideChar(item.pszText)^=#0 then + pWideChar(item.pszText):=vars[item.iItem].name; + SendMessageW(hdr.hWndFrom,LVM_SETITEMW,0,tlparam(@item)); + mFreeMem(vars[item.iItem].alias); + StrDupW(vars[item.iItem].alias,pWideChar(item.pszText)); + result:=1; + end; + Changed:=true; + end; + end; + + NM_DBLCLK: begin + if PNMListView(lParam)^.iItem>=0 then + begin + SendMessage(PNMHdr(lParam)^.hWndFrom,LVM_EDITLABEL, + PNMListView(lParam)^.iItem,0); + end; + end; + end; + end; + end; + + end; +end; + +function WATMacroHelp(wParam:WPARAM;lParam:LPARAM):int;cdecl; +begin + result:=CreateDialogParamW(hInstance,'MACRO',wParam,@MacroHelpDlg,0); +end; diff --git a/plugins/Watrack/templates/i_opt_it.inc b/plugins/Watrack/templates/i_opt_it.inc new file mode 100644 index 0000000000..a9ce27ebea --- /dev/null +++ b/plugins/Watrack/templates/i_opt_it.inc @@ -0,0 +1,50 @@ +{} +const + opt_LoCaseType:PAnsiChar = 'locase'; + opt_FSPrec :PAnsiChar = 'precision'; + opt_FSizePost :PAnsiChar = 'fsizepost'; + opt_FSizeMode :PAnsiChar = 'fsizemode'; + opt_WriteCBR :PAnsiChar = 'writecbr'; + opt_ReplaceSpc:PAnsiChar = 'replacespc'; + opt_PlayerCaps:PAnsiChar = 'playercaps'; + opt_ExportText:PAnsiChar = 'exporttext'; + + opt_export :PAnsiChar = 'template/export'; + spref = 'strings/'; + +procedure LoadOpt; +var + setting:array [0..63] of AnsiChar; +begin + PlayerCaps :=DBReadByte (0,PluginShort,opt_PlayerCaps,0); + LoCaseType :=DBReadByte (0,PluginShort,opt_LoCaseType,BST_UNCHECKED); + ReplaceSpc :=DBReadByte (0,PluginShort,opt_ReplaceSpc,BST_CHECKED); + FSPrecision:=DBReadByte (0,PluginShort,opt_FSPrec ,0); + FSizePost :=DBReadByte (0,PluginShort,opt_FSizePost ,0); + FSizeMode :=DBReadDWord (0,PluginShort,opt_FSizeMode ,1); + WriteCBR :=DBReadByte (0,PluginShort,opt_WriteCBR ,0); + if DBGetSettingType(0,PluginShort,opt_ExportText)=DBVT_DELETED then + begin + IntToStr(StrCopyE(setting,spref),DBReadWord(0,PluginShort,opt_export,3)); + ExportText:=DBReadUnicode(0,PluginShort,setting,nil); + end + else + ExportText:=DBReadUnicode(0,PluginShort,opt_ExportText); +end; + +procedure SaveOpt; +begin + DBWriteByte (0,PluginShort,opt_PlayerCaps,PlayerCaps); + DBWriteByte (0,PluginShort,opt_LoCaseType,LoCaseType); + DBWriteByte (0,PluginShort,opt_ReplaceSpc,ReplaceSpc); + DBWriteByte (0,PluginShort,opt_FSPrec ,FSPrecision); + DBWriteByte (0,PluginShort,opt_FSizePost ,FSizePost); + DBWriteDWord (0,PluginShort,opt_FSizeMode ,FSizeMode); + DBWriteByte (0,PluginShort,opt_WriteCBR ,WriteCBR); + DBWriteUnicode(0,PluginShort,opt_ExportText,ExportText); +end; + +procedure FreeOpt; +begin + mFreeMem(ExportText); +end; diff --git a/plugins/Watrack/templates/i_text.inc b/plugins/Watrack/templates/i_text.inc new file mode 100644 index 0000000000..fa0c966728 --- /dev/null +++ b/plugins/Watrack/templates/i_text.inc @@ -0,0 +1,135 @@ +{} +procedure Replace(dst:pWideChar;macro:integer;value:PWideChar); +var + buf:array [0..63] of WideChar; + pc:pWideChar; +begin + buf[0]:='%'; + pc:=vars[macro].alias; + if pc=nil then + pc:=vars[macro].name; + StrCopyW(buf+1,pc); + pc:=StrEndW(buf); + pc^:='%'; + (pc+1)^:=#0; + StrReplaceW(dst,buf,value); +end; + +function ReplaceAll(s:PWideChar):pWideChar; +var + tmp:integer; + pp,p:pWideChar; + ws:array [0..127] of WideChar; + ls:pWideChar; + i:integer; + tmpstr:pWideChar; + Info:pSongInfo; +begin + Info:=pointer(CallService(MS_WAT_RETURNGLOBAL,0,0)); + mGetMem(ls,32768); + StrCopyW(ls,s); + StrReplaceW(ls,'{tab}',#9); + + StrCopyW(ws,Info^.player); + case PlayerCaps of + 1: LowerCase(ws); + 2: UpperCase(ws); + end; + Replace(ls,mn_player,ws); + Replace(ls,mn_file ,Info^.mfile); + Replace(ls,mn_year ,Info^.year); + Replace(ls,mn_genre ,Info^.genre); + GetExt(Info^.mfile,ws); + if LoCaseType=BST_CHECKED then + LowerCase(ws) + else + UpperCase(ws); + Replace(ls,mn_type ,ws); + Replace(ls,mn_track,IntToStr(ws,Info^.track)); +// codec + ws[0]:=WideChar( Info^.codec and $FF); + ws[1]:=WideChar((Info^.codec shr 8) and $FF); + ws[2]:=WideChar((Info^.codec shr 16) and $FF); + ws[3]:=WideChar((Info^.codec shr 24) and $FF); + ws[4]:=#0; + //fps + IntToStr(ws,Info^.fps div 100); + i:=0; + repeat + inc(i); + until ws[i]=#0; + ws[i]:='.'; + IntToStr(pWideChar(@ws[i+1]),Info^.fps mod 100); + Replace(ls,mn_fps ,ws); + Replace(ls,mn_txtver ,Info^.txtver); + Replace(ls,mn_height ,IntToStr(ws,Info^.height)); + Replace(ls,mn_width ,IntToStr(ws,Info^.width)); + Replace(ls,mn_kbps ,IntToStr(ws,Info^.kbps)); + Replace(ls,mn_bitrate,ws); + if Info^.vbr<>0 then + p:=chVBR + else if WriteCBR=0 then + p:=nil + else + p:=chCBR; + Replace(ls,mn_vbr ,p); + Replace(ls,mn_khz ,IntToStr(ws,Info^.khz)); + Replace(ls,mn_samplerate,ws); + Replace(ls,mn_channels ,IntToStr(ws,Info^.channels)); + case Info^.channels of + 1: p:=chMono; + 2: p:=chStereo; + 5,6: p:=ch51; + end; + Replace(ls,mn_mono,p); + Replace(ls,mn_size, + IntToK(ws,Info^.fsize,FSizeMode,FSPrecision,FSizePost)); + Replace(ls,mn_length,IntToTime(ws,Info^.total)); + Replace(ls,mn_total ,ws); + case Info^.status of + WAT_MES_PLAYING: pp:=splPlaying; + WAT_MES_PAUSED : pp:=splPaused; + else + {WAT_MES_STOPPED:} pp:=splStopped; + end; + Replace(ls,mn_status,TranslateW(pp)); + Replace(ls,mn_nstatus,pp); + Replace(ls,mn_lyric ,Info^.lyric); + Replace(ls,mn_cover ,Info^.cover); + Replace(ls,mn_volume,IntToStr(ws,loword(Info^.volume))); + + mGetMem(tmpstr,32767); + + StrCopyW(tmpstr,Info^.artist); + if ReplaceSpc=BST_CHECKED then CharReplaceW(tmpstr ,'_',' '); + Replace(ls,mn_artist,tmpstr); + + StrCopyW(tmpstr,Info^.title); + if ReplaceSpc=BST_CHECKED then CharReplaceW(tmpstr ,'_',' '); + Replace(ls,mn_title,tmpstr); + + StrCopyW(tmpstr,Info^.album); + if ReplaceSpc=BST_CHECKED then CharReplaceW(tmpstr ,'_',' '); + Replace(ls,mn_album,tmpstr); + + StrCopyW(tmpstr,Info^.comment); + if ReplaceSpc=BST_CHECKED then CharReplaceW(tmpstr ,'_',' '); + Replace(ls,mn_comment,tmpstr); + + StrCopyW(tmpstr,Info^.wndtext); + if ReplaceSpc=BST_CHECKED then CharReplaceW(tmpstr ,'_',' '); + Replace(ls,mn_wndtext,tmpstr); + + mFreeMem(tmpstr); + + Replace(ls,mn_version,IntToHex(ws,Info^.plyver)); + Replace(ls,mn_time ,IntToTime(ws,Info^.time)); + if Info^.total>0 then + tmp:=(Info^.time*100) div Info^.total + else + tmp:=0; + Replace(ls,mn_percent,IntToStr(ws,tmp)); + Replace(ls,mn_playerhome,Info^.url); + + result:=ls; +end; diff --git a/plugins/Watrack/templates/i_tmpl_dlg.inc b/plugins/Watrack/templates/i_tmpl_dlg.inc new file mode 100644 index 0000000000..185f91d608 --- /dev/null +++ b/plugins/Watrack/templates/i_tmpl_dlg.inc @@ -0,0 +1,117 @@ +{} +function DlgProcOptions(Dialog:HWnd;hMessage:UINT;wParam:WPARAM;lParam:LPARAM):integer; stdcall; +begin + result:=0; + case hMessage of + WM_INITDIALOG: begin + TranslateDialogDefault(Dialog); + + if not isVarsInstalled then + ShowWindow(GetDlgItem(Dialog,IDC_VAR_HELP),SW_HIDE) + else + SendDlgItemMessage(Dialog,IDC_VAR_HELP,BM_SETIMAGE,IMAGE_ICON, + CallService(MS_VARS_GETSKINITEM,0,VSI_HELPICON)); + + SendDlgItemMessage(Dialog,IDC_MACRO_HELP,BM_SETIMAGE,IMAGE_ICON, + CallService(MS_SKIN_LOADICON,SKINICON_OTHER_HELP,0)); + + MakeHint(Dialog,IDC_REPLACESPC, + 'Replaces "_" (underscores) globally in pasted os status text,'+ + ' sometimes may be useful'); + CheckDlgButton(Dialog,IDC_REPLACESPC,ReplaceSpc); + + CheckDlgButton(Dialog,IDC_LOCASE,LoCaseType); + + CheckDlgButton(Dialog,IDC_FSIZEBYTE,ord(FSizeMode=1)); + CheckDlgButton(Dialog,IDC_FSIZEKILO,ord(FSizeMode=1024)); + CheckDlgButton(Dialog,IDC_FSIZEMEGA,ord(FSizeMode=1024*1024)); + + SetDlgItemInt (Dialog,IDC_PRECISION,FSPrecision,false); + CheckDlgButton(Dialog,IDC_POSTNONE ,ord(FSizePost=0)); + CheckDlgButton(Dialog,IDC_POSTSMALL,ord(FSizePost=1)); + CheckDlgButton(Dialog,IDC_POSTMIX ,ord(FSizePost=2)); + CheckDlgButton(Dialog,IDC_POSTLARGE,ord(FSizePost=3)); + + CheckDlgButton(Dialog,IDC_ALLCAP ,ord(PlayerCaps=2)); + CheckDlgButton(Dialog,IDC_SMALLCAP,ord(PlayerCaps=1)); + CheckDlgButton(Dialog,IDC_MIXCAP ,ord(PlayerCaps=0)); + + CheckDlgButton(Dialog,IDC_WRITECBR1,ord(WriteCBR=0)); + CheckDlgButton(Dialog,IDC_WRITECBR2,ord(WriteCBR<>0)); + + SetDlgItemTextW(Dialog,IDC_EXPORT_TEXT,ExportText); + end; + + WM_COMMAND: begin + if (wParam shr 16)=BN_CLICKED then + begin + case loword(wParam) of + IDC_VAR_HELP : ShowVarHelp (Dialog); + IDC_MACRO_HELP: CallService(MS_WAT_MACROHELP,Dialog,0); + IDC_ALLCAP: begin + CheckDlgButton(Dialog,IDC_ALLCAP ,BST_CHECKED); + CheckDlgButton(Dialog,IDC_SMALLCAP,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MIXCAP ,BST_UNCHECKED); + end; + IDC_SMALLCAP: begin + CheckDlgButton(Dialog,IDC_ALLCAP ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_SMALLCAP,BST_CHECKED); + CheckDlgButton(Dialog,IDC_MIXCAP ,BST_UNCHECKED); + end; + IDC_MIXCAP: begin + CheckDlgButton(Dialog,IDC_ALLCAP ,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_SMALLCAP,BST_UNCHECKED); + CheckDlgButton(Dialog,IDC_MIXCAP ,BST_CHECKED); + end; + end; + end; + if ((wParam shr 16)=EN_CHANGE) or ((wParam shr 16)=BN_CLICKED) then + SendMessage(GetParent(Dialog),PSM_CHANGED,0,0); + result:=1; + end; + + WM_NOTIFY: begin + if integer(PNMHdr(lParam)^.code)=PSN_APPLY then + begin + ReplaceSpc:=IsDlgButtonChecked(Dialog,IDC_REPLACESPC); + LoCaseType:=IsDlgButtonChecked(Dialog,IDC_LOCASE); + if IsDlgButtonChecked(Dialog,IDC_WRITECBR1)=BST_CHECKED then + WriteCBR:=0 + else //if IsDlgButtonChecked(Dialog,IDC_WRITECBR2)=BST_CHECKED then + WriteCBR:=1; + if IsDlgButtonChecked(Dialog,IDC_FSIZEBYTE)=BST_CHECKED then + FSizeMode:=1 + else if IsDlgButtonChecked(Dialog,IDC_FSIZEKILO)=BST_CHECKED then + FSizeMode:=1024 + else// if IsDlgButtonChecked(Dialog,IDC_FSIZEMEGA)=BST_CHECKED then + FSizeMode:=1024*1024; + + if IsDlgButtonChecked(Dialog,IDC_MIXCAP)=BST_CHECKED then + PlayerCaps:=0 + else if IsDlgButtonChecked(Dialog,IDC_SMALLCAP)=BST_CHECKED then + PlayerCaps:=1 + else// if IsDlgButtonChecked(Dialog,IDC_ALLCAP)=BST_CHECKED then + PlayerCaps:=2; + + if IsDlgButtonChecked(Dialog,IDC_POSTNONE)=BST_CHECKED then + FSizePost:=0 + else if IsDlgButtonChecked(Dialog,IDC_POSTSMALL)=BST_CHECKED then + FSizePost:=1 + else if IsDlgButtonChecked(Dialog,IDC_POSTMIX)=BST_CHECKED then + FSizePost:=2 + else// if IsDlgButtonChecked(Dialog,IDC_POSTLARGE)=BST_CHECKED then + FSizePost:=3; + FSPrecision:=GetDlgItemInt(Dialog,IDC_PRECISION,pbool(nil)^,false); + if FSPrecision>3 then + FSPrecision:=3; + + mFreeMem(ExportText); + ExportText:=GetDlgText(Dialog,IDC_EXPORT_TEXT); + + SaveOpt; + end; + end; + else + {result:=}DefWindowProc(Dialog,hMessage,wParam,lParam); + end; +end; diff --git a/plugins/Watrack/templates/i_tmpl_rc.inc b/plugins/Watrack/templates/i_tmpl_rc.inc new file mode 100644 index 0000000000..5b444a45be --- /dev/null +++ b/plugins/Watrack/templates/i_tmpl_rc.inc @@ -0,0 +1,21 @@ +const + IDC_PRECISION = 1025; + IDC_FSIZEBYTE = 1026; + IDC_FSIZEKILO = 1027; + IDC_FSIZEMEGA = 1028; + IDC_POSTNONE = 1029; + IDC_POSTSMALL = 1030; + IDC_POSTMIX = 1031; + IDC_POSTLARGE = 1032; + IDC_LOCASE = 1033; + IDC_WRITECBR1 = 1034; + IDC_WRITECBR2 = 1035; + IDC_ALLCAP = 1036; + IDC_MIXCAP = 1037; + IDC_SMALLCAP = 1038; + IDC_EXPORT_TEXT = 1039; + IDC_REPLACESPC = 1040; + IDC_MACRO_HELP = IDHELP;//1041; + IDC_VAR_HELP = 1042; + + IDC_MACROHELP = 1025; diff --git a/plugins/Watrack/templates/i_variables.inc b/plugins/Watrack/templates/i_variables.inc new file mode 100644 index 0000000000..a43c77b8c2 --- /dev/null +++ b/plugins/Watrack/templates/i_variables.inc @@ -0,0 +1,185 @@ +{Variables support} +function GetField(ai:PARGUMENTSINFO):int_ptr; cdecl; +var + i,j:integer; + res,ws:pWideChar; + s:array [0..31] of WideChar; + rs:boolean; + si:pSongInfo; +begin + i:=0; + repeat + ws:=vars[i].alias; + if ws=nil then + ws:=vars[i].name; + if lstrcmpiw(PWideChar(ai^.argv^),ws)=0 then + break; + inc(i); + until i=numvars; + ws:=nil; + j:=-1; + rs:=true; + si:=pointer(CallService(MS_WAT_RETURNGLOBAL,0,0)); + case i of + mn_wndtext: ws:=si^.wndtext; + mn_artist : ws:=si^.artist; + mn_title : ws:=si^.title; + mn_album : ws:=si^.album; + mn_genre : ws:=si^.genre; + mn_file : begin ws:=si^.mfile; rs:=false; end; + mn_year : ws:=si^.year; + mn_comment: ws:=si^.comment; + mn_player : begin + StrCopyW(s,si^.player); + case PlayerCaps of + 1: LowerCase(s); + 2: UpperCase(s); + end; + ws:=@s; + end; + mn_lyric : ws:=si^.lyric; + mn_cover : ws:=si^.cover; + mn_txtver : ws:=si^.txtver; + mn_type: begin + GetExt(si^.mfile,s); + if LoCaseType=BST_CHECKED then + LowerCase(s); +// else +// UpperCase(s); + ws:=@s; + end; + mn_size: begin + IntToK(s,si^.fsize,FSizeMode,FSPrecision,FSizePost); + ws:=@s; + end; + mn_fps: begin + IntToStr(s,si^.fps div 100); + ws:=@s; + while ws^<>#0 do inc(ws); + ws^:='.'; + IntToStr(ws+1,si^.fps mod 100); + ws:=@s; + end; + mn_codec: begin + s[0]:=WideChar( si^.codec and $FF); + s[1]:=WideChar((si^.codec shr 8) and $FF); + s[2]:=WideChar((si^.codec shr 16) and $FF); + s[3]:=WideChar((si^.codec shr 24) and $FF); + s[4]:=#0; + ws:=@s; + end; + mn_vbr: if si^.vbr<>0 then + ws:=chVBR + else if WriteCBR<>0 then + ws:=chCBR; + mn_status: case si^.status of + WAT_MES_STOPPED: ws:=TranslateW(splStopped); + WAT_MES_PLAYING: ws:=TranslateW(splPlaying); + WAT_MES_PAUSED : ws:=TranslateW(splPaused); + end; + mn_nstatus: case si^.status of + WAT_MES_STOPPED: ws:=splStopped; + WAT_MES_PLAYING: ws:=splPlaying; + WAT_MES_PAUSED : ws:=splPaused; + end; + mn_mono: begin + case si^.channels of + 1: ws:=chMono; + 2: ws:=chStereo; + 5,6: ws:=ch51; + end; + end; + mn_playerhome: ws:=si^.url; + else + begin + case i of + mn_volume : j:=loword(si^.volume); + mn_width : j:=si^.width; + mn_height : j:=si^.height; + mn_kbps, + mn_bitrate : j:=si^.kbps; + mn_khz, + mn_samplerate: j:=si^.khz; + mn_channels : j:=si^.channels; + mn_track : j:=si^.track; + mn_percent: begin + if si^.total>0 then + j:=(si^.time*100) div si^.total + else + j:=0; + end; + else + begin + case i of + mn_total, + mn_length : IntToTime(s,si^.total); + mn_time : IntToTime(s,si^.time); + mn_version: IntToHex (s,si^.plyver); + else + result:=0; + exit; + end; + ws:=@s; + end; + end; + end; + end; + if (ws=nil) and (j>=0) then + begin + IntToStr(s,j); + ws:=@s; + end; + + StrDupW(ws,ws); + If rs and (ReplaceSpc=BST_CHECKED) then + CharReplaceW(ws,'_',' '); + i:=StrLenW(ws); + mGetMem(res,(i+1)*SizeOf(WideChar)); + if ws<>nil then + begin + StrCopyW(res,ws); + mFreeMem(ws); + end + else + res[0]:=#0; + result:=int_ptr(res); +end; + +function FreeField(szReturn:PAnsiChar):int; cdecl; +begin + mFreeMem(szReturn); + result:=1; +end; + +procedure RegisterVariables; +const + Prefix:PAnsiChar = 'WATrack'#9; +var + rt:TTOKENREGISTER; + i,j:integer; + s:array [0..127] of AnsiChar; + p:pvar; +begin + if not isVarsInstalled then + exit; + + rt.cbSize :=SizeOf(rt); + rt.memType :=TR_MEM_OWNER; + rt.flags :=TRF_FIELD or TRF_CLEANUP or + TRF_UNICODE or TRF_PARSEFUNC or TRF_CLEANUPFUNC; + rt.szService :=@GetField; + rt.szCleanupService:=@FreeField; + j:=StrLen(Prefix); + move(Prefix^,s,j); + rt.szHelpText:=@s; + for i:=0 to numvars-1 do + begin + p:=@vars[i]; + rt.szTokenString.w:=p.alias; + if rt.szTokenString.w=nil then + rt.szTokenString.w:=p.name; + if p.help<>nil then + StrCopy(s+j,p.help); + CallService(MS_VARS_REGISTERTOKEN,0,lparam(@rt)); + end; +end; diff --git a/plugins/Watrack/templates/templates.pas b/plugins/Watrack/templates/templates.pas new file mode 100644 index 0000000000..ec56580852 --- /dev/null +++ b/plugins/Watrack/templates/templates.pas @@ -0,0 +1,113 @@ +unit templates; +{$include compilers.inc} +interface +{$Resource templates.res} +implementation + +uses + messages,windows,commctrl, + common,syswin,wrapper, + m_api,dbsettings,mirutils, + wat_api,global,macros; + +const + splStopped:PWideChar = 'stopped'; + splPlaying:PWideChar = 'playing'; + splPaused :PWideChar = 'paused'; + chMono :PWideChar = 'mono'; + chStereo :PWideChar = 'stereo'; + ch51 :PWideChar = '5.1'; + chVBR :PWideChar = 'VBR'; + chCBR :PWideChar = 'CBR'; + +const + LoCaseType :integer=0; + WriteCBR :integer=0; + ReplaceSpc :integer=0; + FSizeMode :integer=1024*1024; + FSizePost :integer=2; + FSPrecision :integer=2; + PlayerCaps :integer=0; + ExportText:pWideChar=nil; + +{$include i_tmpl_rc.inc} +{$include i_variables.inc} +{$include i_macro.inc} +{$include i_text.inc} +{$include i_opt_it.inc} +{$include i_tmpl_dlg.inc} +{$include i_expkey.inc} + +function WATReplaceText(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + p:pWideChar; +begin + if (lParam<>0) and (pWideChar(lParam)^<>#0) then + begin + if isVarsInstalled then + result:=int_ptr(ParseVarString(pWideChar(lParam))) + else + result:=int_ptr(ReplaceAll(pWideChar(lParam))); + if (result<>0) and (pWideChar(result)^=#0) then + begin + p:=PWideChar(result); + mFreeMem(p); + result:=0; + end; + end + else + result:=0; +end; + +// ------------ base interface functions ------------- + +function AddOptionsPage(var tmpl:pAnsiChar;var proc:pointer;var name:PAnsiChar):integer; +begin + tmpl:='FORMAT'; + proc:=@DlgProcOptions; + name:='Templates'; + result:=0; +end; + +var + hEXP, + hMacro, + hReplace:THANDLE; + +function InitProc(aGetStatus:boolean=false):integer; +begin + result:=1; + hEXP :=CreateServiceFunction(MS_WAT_EXPORT ,@ExportProc); + hReplace:=CreateServiceFunction(MS_WAT_REPLACETEXT,@WATReplaceText); + hMacro :=CreateServiceFunction(MS_WAT_MACROHELP ,@WATMacroHelp); + LoadOpt; + LoadAliases; + RegisterVariables; + reginshotkey; +end; + +procedure DeInitProc(aSetDisable:boolean); +begin + DestroyServiceFunction(hReplace); + DestroyServiceFunction(hEXP); + DestroyServiceFunction(hMacro); + FreeAliases; + FreeOpt; +end; + +var + Tmpl:twModule; + +procedure Init; +begin + Tmpl.Next :=ModuleLink; + Tmpl.Init :=@InitProc; + Tmpl.DeInit :=@DeInitProc; + Tmpl.AddOption :=@AddOptionsPage; + Tmpl.ModuleName:=nil; + ModuleLink :=@Tmpl; +end; + +begin + Init; +end. diff --git a/plugins/Watrack/templates/templates.rc b/plugins/Watrack/templates/templates.rc new file mode 100644 index 0000000000..f7e8ff1f20 --- /dev/null +++ b/plugins/Watrack/templates/templates.rc @@ -0,0 +1,51 @@ +#include "i_tmpl_rc.inc" + +LANGUAGE 0,0 + +FORMAT DIALOGEX 0, 0, 304, 226, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE +EXSTYLE WS_EX_CONTROLPARENT +FONT 8, "MS Shell Dlg", 0, 0 +{ + GROUPBOX "Options", -1, 2, 2, 188, 161, WS_TABSTOP + AUTOCHECKBOX "Replace underlines with spaces", IDC_REPLACESPC, 6, 12, 182, 14, BS_VCENTER | BS_MULTILINE | BS_NOTIFY + + EDITTEXT IDC_PRECISION, 192, 60, 20, 12, ES_RIGHT | ES_NUMBER + GROUPBOX "File size", -1, 192, 2, 64, 54 + AUTORADIOBUTTON "Bytes" , IDC_FSIZEBYTE, 196, 14, 50, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "Kilobytes", IDC_FSIZEKILO, 196, 28, 50, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "Megabytes", IDC_FSIZEMEGA, 196, 42, 50, 10, NOT WS_TABSTOP + LTEXT "Precision", -1, 216, 62, 84, 12 + GROUPBOX "Postfix", -1, 258, 2, 42, 54 + AUTORADIOBUTTON "none", IDC_POSTNONE , 262, 12, 30, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "kb" , IDC_POSTSMALL, 262, 23, 30, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "Kb" , IDC_POSTMIX , 262, 34, 30, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "KB" , IDC_POSTLARGE, 262, 45, 30, 10, NOT WS_TABSTOP +// CONTROL "", -1, "STATIC", SS_ETCHEDHORZ, 192, 77, 108, 2 + GROUPBOX "VBR macro", -1, 192, 77, 108, 34 + AUTORADIOBUTTON "VBR or empty", IDC_WRITECBR1, 198, 87, 96, 10, NOT WS_TABSTOP + AUTORADIOBUTTON "VBR or CBR" , IDC_WRITECBR2, 198, 99, 96, 10, NOT WS_TABSTOP + GROUPBOX "Player name letters", -1, 192, 115, 108, 48 + RADIOBUTTON "All uppercase", IDC_ALLCAP , 198, 127, 96, 10, NOT WS_TABSTOP + RADIOBUTTON "Do not change", IDC_MIXCAP , 198, 139, 96, 10, NOT WS_TABSTOP + RADIOBUTTON "All lowercase", IDC_SMALLCAP, 198, 151, 96, 10, NOT WS_TABSTOP + + AUTOCHECKBOX "lowercase %type%", IDC_LOCASE, 193,164, 108, 14 + + LTEXT "Export text template",-1, 6, 164 ,142, 14, SS_CENTERIMAGE + EDITTEXT IDC_EXPORT_TEXT, 4, 180, 296, 42, + ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN +// PUSHBUTTON "V", IDC_VAR_HELP ,154,163,16,16 +// PUSHBUTTON "M", IDC_MACRO_HELP,172,163,16,16 + CONTROL "V" ,IDC_VAR_HELP ,"MButtonClass",WS_TABSTOP,154,163,16,16,$18000000 + CONTROL "M" ,IDC_MACRO_HELP ,"MButtonClass",WS_TABSTOP,172,163,16,16,$18000000 +} + +MACRO DIALOGEX 0, 0, 240, 176, 0 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_SIZEBOX +EXSTYLE WS_EX_CONTROLPARENT +CAPTION "WATrack Macro Info" +FONT 8, "MS Shell Dlg", 0, 0 +{ + CONTROL "", IDC_MACROHELP, "SysListView32", WS_BORDER | WS_TABSTOP | LVS_NOCOLUMNHEADER | LVS_EDITLABELS | LVS_SHOWSELALWAYS | LVS_SINGLESEL | LVS_REPORT, 6, 6, 228, 164, WS_EX_CONTROLPARENT +} diff --git a/plugins/Watrack/templates/templates.res b/plugins/Watrack/templates/templates.res new file mode 100644 index 0000000000..d23e804915 Binary files /dev/null and b/plugins/Watrack/templates/templates.res differ diff --git a/plugins/Watrack/wat_api.pas b/plugins/Watrack/wat_api.pas new file mode 100644 index 0000000000..52fd0f2650 --- /dev/null +++ b/plugins/Watrack/wat_api.pas @@ -0,0 +1,183 @@ +unit wat_api; + +interface + +uses windows; + +{$Include m_music.inc} + +function GenreName(idx:cardinal):pWideChar; + +implementation + +uses common; + +const + MAX_MUSIC_GENRES = 148; + +Genres:array [0..MAX_MUSIC_GENRES-1] of PWideChar = ( +{0} 'Blues', +{1} 'Classic Rock', +{2} 'Country', +{3} 'Dance', +{4} 'Disco', +{5} 'Funk', +{6} 'Grunge', +{7} 'Hip-Hop', +{8} 'Jazz', +{9} 'Metal', +{10} 'New Age', +{11} 'Oldies', +{12} 'Other', +{13} 'Pop', +{14} 'R&B', +{15} 'Rap', +{16} 'Reggae', +{17} 'Rock', +{18} 'Techno', +{19} 'Industrial', +{20} 'Alternative', +{21} 'Ska', +{22} 'Death Metal', +{23} 'Pranks', +{24} 'Soundtrack', +{25} 'Euro-Techno', +{26} 'Ambient', +{27} 'Trip-Hop', +{28} 'Vocal', +{29} 'Jazz+Funk', +{30} 'Fusion', +{31} 'Trance', +{32} 'Classical', +{33} 'Instrumental', +{34} 'Acid', +{35} 'House', +{36} 'Game', +{37} 'Sound Clip', +{38} 'Gospel', +{39} 'Noise', +{40} 'AlternRock', +{41} 'Bass', +{42} 'Soul', +{43} 'Punk', +{44} 'Space', +{45} 'Meditative', +{46} 'Instrumental Pop', +{47} 'Instrumental Rock', +{48} 'Ethnic', +{49} 'Gothic', +{50} 'Darkwave', +{51} 'Techno-Industrial', +{52} 'Electronic', +{53} 'Pop-Folk', +{54} 'Eurodance', +{55} 'Dream', +{56} 'Southern Rock', +{57} 'Comedy', +{58} 'Cult', +{59} 'Gangsta', +{60} 'Top 40', +{61} 'Christian Rap', +{62} 'Pop/Funk', +{63} 'Jungle', +{64} 'Native American', +{65} 'Cabaret', +{66} 'New Wave', +{67} 'Psychadelic', +{68} 'Rave', +{69} 'Showtunes', +{70} 'Trailer', +{71} 'Lo-Fi', +{72} 'Tribal', +{73} 'Acid Punk', +{74} 'Acid Jazz', +{75} 'Polka', +{76} 'Retro', +{77} 'Musical', +{78} 'Rock & Roll', +{79} 'Hard Rock', +{80} 'Folk', +{81} 'Folk-Rock', +{82} 'National Folk', +{83} 'Swing', +{84} 'Fast Fusion', +{85} 'Bebob', +{86} 'Latin', +{87} 'Revival', +{88} 'Celtic', +{89} 'Bluegrass', +{90} 'Avantgarde', +{91} 'Gothic Rock', +{92} 'Progressive Rock', +{93} 'Psychedelic Rock', +{94} 'Symphonic Rock', +{95} 'Slow Rock', +{96} 'Big Band', +{97} 'Chorus', +{98} 'Easy Listening', +{99} 'Acoustic', +{100} 'Humour', +{101} 'Speech', +{102} 'Chanson', +{103} 'Opera', +{104} 'Chamber Music', +{105} 'Sonata', +{106} 'Symphony', +{107} 'Booty Brass', +{108} 'Primus', +{109} 'Porn Groove', +{110} 'Satire', +{111} 'Slow Jam', +{112} 'Club', +{113} 'Tango', +{114} 'Samba', +{115} 'Folklore', +{116} 'Ballad', +{117} 'Poweer Ballad', +{118} 'Rhytmic Soul', +{119} 'Freestyle', +{120} 'Duet', +{121} 'Punk Rock', +{122} 'Drum Solo', +{123} 'A Capela', +{124} 'Euro-House', +{125} 'Dance Hall', +{126} 'Goa', +{127} 'Drum & Bass', +{128} 'Club-House', +{129} 'Hardcore', +{130} 'Terror', +{131} 'Indie', +{132} 'BritPop', +{133} 'Negerpunk', +{134} 'Polsk Punk', +{135} 'Beat', +{136} 'Christian Gangsta Rap', +{137} 'Heavy Metal', +{138} 'Black Metal', +{139} 'Crossover', +{140} 'Contemporary Christian', +{141} 'Christian Rock', +{142} 'Merengue', +{143} 'Salsa', +{144} 'Trash Metal', +{145} 'Anime', +{146} 'JPop', +{147} 'Synthpop'); + +function GenreName(idx:cardinal):pWideChar; +begin + if idxhInstance then + FreeLibrary(hIconDLL); +end; + +type + PAWKIconButton = ^TAWKIconButton; + TAWKIconButton = record + descr:PAnsiChar; + name :PAnsiChar; + id :int_ptr; + end; +const + CtrlIcoLib:array [WAT_CTRL_FIRST..WAT_CTRL_LAST,AST_NORMAL..AST_PRESSED] of + TAWKIconButton = ( + ((descr:'Prev' ;name:'WATrack_Prev' ; id:IDI_PREV_NORMAL), + (descr:'Prev Hovered' ;name:'WATrack_PrevH' ; id:IDI_PREV_HOVERED), + (descr:'Prev Pushed' ;name:'WATrack_PrevP' ; id:IDI_PREV_PRESSED)), + + ((descr:'Play' ;name:'WATrack_Play' ; id:IDI_PLAY_NORMAL), + (descr:'Play Hovered' ;name:'WATrack_PlayH' ; id:IDI_PLAY_HOVERED), + (descr:'Play Pushed' ;name:'WATrack_PlayP' ; id:IDI_PLAY_PRESSED)), + + ((descr:'Pause' ;name:'WATrack_Pause' ; id:IDI_PAUSE_NORMAL), + (descr:'Pause Hovered' ;name:'WATrack_PauseH' ; id:IDI_PAUSE_HOVERED), + (descr:'Pause Pushed' ;name:'WATrack_PauseP' ; id:IDI_PAUSE_PRESSED)), + + ((descr:'Stop' ;name:'WATrack_Stop' ; id:IDI_STOP_NORMAL), + (descr:'Stop Hovered' ;name:'WATrack_StopH' ; id:IDI_STOP_HOVERED), + (descr:'Stop Pushed' ;name:'WATrack_StopP' ; id:IDI_STOP_PRESSED)), + + ((descr:'Next' ;name:'WATrack_Next' ; id:IDI_NEXT_NORMAL), + (descr:'Next Hovered' ;name:'WATrack_NextH' ; id:IDI_NEXT_HOVERED), + (descr:'Next Pushed' ;name:'WATrack_NextP' ; id:IDI_NEXT_PRESSED)), + + ((descr:'Volume Down' ;name:'WATrack_VolDn' ; id:IDI_VOLDN_NORMAL), + (descr:'Volume Down Hovered';name:'WATrack_VolDnH' ; id:IDI_VOLDN_HOVERED), + (descr:'Volume Down Pushed' ;name:'WATrack_VolDnP' ; id:IDI_VOLDN_PRESSED)), + + ((descr:'Volume Up' ;name:'WATrack_VolUp' ; id:IDI_VOLUP_NORMAL), + (descr:'Volume Up Hovered' ;name:'WATrack_VolUpH' ; id:IDI_VOLUP_HOVERED), + (descr:'Volume Up Pushed' ;name:'WATrack_VolUpP' ; id:IDI_VOLUP_PRESSED)), + + ((descr:'Slider' ;name:'WATrack_Slider' ; id:IDI_SLIDER_NORMAL), + (descr:'Slider Hovered' ;name:'WATrack_SliderH'; id:IDI_SLIDER_HOVERED), + (descr:'Slider Pushed' ;name:'WATrack_SliderP'; id:IDI_SLIDER_PRESSED)) + ); + +function RegisterButtonIcons:boolean; +var + sid:TSKINICONDESC; + buf:array [0..511] of AnsiChar; + hIconDLL:THANDLE; + i,j:integer; + path:pAnsiChar; +begin + if not IconsLoaded then + begin + path:='icons\'+ICOCtrlName; +// ConvertFileName(sid.szDefaultFile.a,buf); + CallService(MS_UTILS_PATHTOABSOLUTE,wparam(path),lparam(@buf)); + + hIconDLL:=LoadLibraryA(buf); + if hIconDLL=0 then // not found + begin + sid.szDefaultFile.a:='plugins\'+ICOCtrlName; +// ConvertFileName(sid.szDefaultFile.a,buf); + CallService(MS_UTILS_PATHTOABSOLUTE,wparam(path),lparam(@buf)); + hIconDLL:=LoadLibraryA(buf); + end; + + if hIconDLL<>0 then + begin + FreeLibrary(hIconDLL); + FillChar(sid,SizeOf(sid),0); + sid.flags:=0; + sid.cbSize:=SizeOf(TSKINICONDESC); + sid.cx:=16; + sid.cy:=16; + + sid.szSection.a :='WATrack/Frame Controls'; + sid.szDefaultFile.a:=path; + i:=WAT_CTRL_FIRST; + repeat + j:=AST_NORMAL; + repeat + // increment from 1 by order, so - just decrease number (for iconpack import) + sid.iDefaultIndex :=CtrlIcoLib[i][j].id-1; + sid.pszName :=CtrlIcoLib[i][j].name; + sid.szDescription.a:=CtrlIcoLib[i][j].descr; + + Skin_AddIcon(@sid); + Inc(j); + until j>AST_PRESSED; + Inc(i); + until i>WAT_CTRL_LAST; + IconsLoaded:=true; + end; + end; + + result:=IconsLoaded; +end; + +function GetIcon(action:integer;stat:integer):cardinal; +begin + result:=CallService(MS_SKIN2_GETICON,0, + lparam(CtrlIcoLib[action][stat].name)); +end; + +function GetIconDescr(action:integer):pAnsiChar; +begin + result:=CtrlIcoLib[action][AST_NORMAL].descr; +end; + +end. diff --git a/plugins/Watrack/watrack.dpr b/plugins/Watrack/watrack.dpr new file mode 100644 index 0000000000..2702c4852f --- /dev/null +++ b/plugins/Watrack/watrack.dpr @@ -0,0 +1,675 @@ +{$include compilers.inc} +{$IFDEF COMPILER_16_UP} + {$WEAKLINKRTTI ON} + {.$RTTI EXPLICIT METHODS([]) PROPERTIES([]) FIELDS([])} +{$ENDIF} +{$IMAGEBASE $13000000} +library WATrack; +uses + // FastMM not compatible with FPC, internal for delphi xe +// {$IFNDEF COMPILER_16_UP}{$IFNDEF FPC}fastmm4,{$ENDIF}{$ENDIF} + m_api,dbsettings,activex,winampapi, + Windows,messages,commctrl,//uxtheme, + srv_format,srv_player,wat_api,wrapper, + common,syswin,HlpDlg,mirutils + ,global,waticons,io,macros, msninfo + ,myshows in 'myshows\myshows.pas' + ,lastfm in 'lastfm\lastfm.pas' + ,statlog in 'stat\statlog.pas' + ,popups in 'popup\popups.pas' + ,proto in 'proto\proto.pas' + ,status in 'status\status.pas' + ,tmpl in 'status\tmpl.pas' + ,templates in 'templates\templates.pas' +{$IFDEF KOL_MCK} + ,kolframe in 'kolframe\kolframe.pas' +{$ENDIF} + {$include lst_players.inc} + {$include lst_formats.inc} +; + +{$include res\i_const.inc} + +{$Resource res\watrack.res} + +{$include i_vars.inc} + +const + MenuDisablePos = 500050000; + +function MirandaPluginInfoEx(mirandaVersion:DWORD):PPLUGININFOEX; cdecl; +begin + result:=@PluginInfo; + PluginInfo.cbSize :=SizeOf(TPLUGININFOEX); + PluginInfo.shortName :=PluginName; + PluginInfo.version :=$0000060C; + PluginInfo.description:='Paste played music info into message window or status text'; + PluginInfo.author :='Awkward'; + PluginInfo.authorEmail:='panda75@bk.ru; awk1975@ya.ru'; + PluginInfo.copyright :='(c) 2005-2012 Awkward'; + PluginInfo.homepage :='http://code.google.com/p/delphi-miranda-plugins/'; + PluginInfo.flags :=UNICODE_AWARE; + PluginInfo.uuid :=MIID_WATRACK; +end; + +{$include i_options.inc} +{$include i_timer.inc} +{$include i_gui.inc} +{$include i_opt_dlg.inc} +{$include i_cover.inc} + +function ReturnInfo(enc:WPARAM;cp:LPARAM=CP_ACP):pointer; +begin + if enc<>WAT_INF_UNICODE then + begin + ClearSongInfoData(tSongInfo(SongInfoA),true); + move(SongInfo,SongInfoA,SizeOf(tSongInfo)); + with SongInfoA do + begin + FastWideToAnsi(SongInfo.url,url); + if enc=WAT_INF_ANSI then + begin + WideToAnsi(SongInfo.artist ,artist ,cp); + WideToAnsi(SongInfo.title ,title ,cp); + WideToAnsi(SongInfo.album ,album ,cp); + WideToAnsi(SongInfo.genre ,genre ,cp); + WideToAnsi(SongInfo.comment,comment,cp); + WideToAnsi(SongInfo.year ,year ,cp); + WideToAnsi(SongInfo.mfile ,mfile ,cp); + WideToAnsi(SongInfo.wndtext,wndtext,cp); + WideToAnsi(SongInfo.player ,player ,cp); + WideToAnsi(SongInfo.txtver ,txtver ,cp); + WideToAnsi(SongInfo.lyric ,lyric ,cp); + WideToAnsi(SongInfo.cover ,cover ,cp); + WideToAnsi(SongInfo.url ,url ,cp); + end + else + begin + WideToUTF8(SongInfo.artist ,artist); + WideToUTF8(SongInfo.title ,title); + WideToUTF8(SongInfo.album ,album); + WideToUTF8(SongInfo.genre ,genre); + WideToUTF8(SongInfo.comment,comment); + WideToUTF8(SongInfo.year ,year); + WideToUTF8(SongInfo.mfile ,mfile); + WideToUTF8(SongInfo.wndtext,wndtext); + WideToUTF8(SongInfo.player ,player); + WideToUTF8(SongInfo.txtver ,txtver); + WideToUTF8(SongInfo.lyric ,lyric); + WideToUTF8(SongInfo.cover ,cover); + WideToUTF8(SongInfo.url ,url); + end; + end; + result:=@SongInfoA; + end + else + result:=@SongInfo; +end; + +function WATReturnGlobal(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +begin + if wParam=0 then wParam:=WAT_INF_UNICODE; + if lParam=0 then lParam:=MirandaCP; + + result:=int_ptr(ReturnInfo(wParam,lParam)); +end; + +function WATGetFileInfo(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var +// si:TSongInfo; + dst:pSongInfo; + extw:array [0..7] of WideChar; + f:THANDLE; + p:PWideChar; +begin + result:=1; + if (lParam=0) or (pSongInfo(lParam).mfile=nil) then exit; + dst:=pointer(lParam); + StrDupW(p,dst^.mfile); + ClearTrackInfo(dst^,false); //!!!! + dst^.mfile:=p; +// FillChar(dst,SizeOf(dst),0); +// FillChar(si,SizeOf(si),0); +{ + if flags and WAT_INF_ANSI<>0 then + AnsiToWide(dst^.mfile,si.mfile) + else if flags and WAT_INF_UTF<>0 then + UTFToWide(dst^.mfile,si.mfile) + else + si.mfile:=dst^.mfile; +} + f:=Reset(dst^.mfile); + if dword(f)<>INVALID_HANDLE_VALUE then + GetFileTime(f,nil,nil,@dst^.date); + CloseHandle(f); + dst^.fsize:=GetFSize(dst^.mfile); + GetExt(dst^.mfile,extw); + if GetFileFormatInfo(dst^)<>WAT_RES_NOTFOUND then + begin + with dst^ do + begin + if (cover=nil) or (cover^=#0) then + GetCover(cover,mfile); + if (lyric=nil) or (lyric^=#0) then + GetLyric(lyric,mfile); + end; + result:=0; +// ReturnInfo(si,dst,wParam and $FF); + end; +end; + +function WATGetMusicInfo(wParam:WPARAM;lParam:LPARAM):int;cdecl; +type + ppointer = ^pointer; +const + giused:cardinal=0; +var + flags:cardinal; + buf:PWideChar; + OldPlayerStatus:integer; + stat:integer; + newplayer:bool; +begin + result:=WAT_RES_NOTFOUND; + if DisablePlugin=dsPermanent then + exit; + + //----- Return old info if main timer ----- + if giused<>0 then + begin + result:=WAT_RES_OK; + if lParam<>0 then + ppointer(lParam)^:=ReturnInfo(wParam and $FF); + exit; + end; + + giused:=1; + + OldPlayerStatus:=WorkSI.status; + + //----- Checking player ----- + // get player status too + flags:=0; + if CheckAll<>BST_UNCHECKED then flags:=flags or WAT_OPT_CHECKALL; + // no need old data, clear +// ClearPlayerInfo(WorkSI,false); + result:=CheckPlayers(WorkSI,flags); + if result=WAT_RES_NEWPLAYER then + begin + newplayer:=true; + NotifyEventHooks(hHookWATStatus,WAT_EVENT_NEWPLAYER,tlparam(@WorkSI)); + result:=WAT_RES_OK; + end + else // !!!! (need to add) must remember about same player, another instance + newplayer:=false; + + // Checking player status + if result=WAT_RES_OK then + begin + if not newplayer then //!!cheat + SongInfo.plwnd:=WorkSI.plwnd; + + // player stopped - no need file info + if WorkSI.status=WAT_MES_STOPPED then + begin + ClearFileInfo (WorkSI,false); + ClearChangingInfo(WorkSI,false); + ClearTrackInfo (WorkSI,false); + + if Hiword(OldPlayerStatus)<>WAT_MES_STOPPED then + begin + NotifyEventHooks(hHookWATStatus,WAT_EVENT_PLAYERSTATUS,WAT_MES_STOPPED); + end; + + ClearFileInfo (SongInfo,true); + ClearChangingInfo(SongInfo,true); + ClearTrackInfo (SongInfo,true); + if newplayer then + begin + ClearPlayerInfo(SongInfo,true); + CopyPlayerInfo (WorkSI,SongInfo); + end; + WorkSI.status:=(WAT_MES_STOPPED shl 16) or (WAT_PLS_NOMUSIC and $FFFF); + SongInfo.status:=WorkSI.status; + end + else + begin + //----- Get file (no file, new file, maybe new) ----- + // file info will be replaced (name most important only) + flags:=0; + if CheckTime <>BST_UNCHECKED then flags:=flags or WAT_OPT_CHECKTIME; + if UseImplant<>BST_UNCHECKED then flags:=flags or WAT_OPT_IMPLANTANT; + if MTHCheck <>BST_UNCHECKED then flags:=flags or WAT_OPT_MULTITHREAD; + if KeepOld <>BST_UNCHECKED then flags:=flags or WAT_OPT_KEEPOLD; + + // requirement - old file name + result:=CheckFile(WorkSI,flags,TimeoutForThread); + + // here - place for Playerstatus event + // high word - song status (play, pause,stop, nothing) + // low word - player status (normal,no music, nothing) + case WorkSI.status of + WAT_MES_PLAYING, + WAT_MES_PAUSED: stat:=WAT_PLS_NORMAL; + WAT_MES_UNKNOWN: // depends of file search + begin + if result=WAT_RES_NOTFOUND then + stat:=WAT_PLS_NOMUSIC + else + stat:=WAT_PLS_NORMAL; + end; + else // really, this way blocked already + {WAT_MES_STOPPED:} stat:=WAT_PLS_NOMUSIC; + end; + WorkSI.status:=(WorkSI.status shl 16) or (stat and $FFFF); + + if OldPlayerStatus<>WorkSI.status then + begin + NotifyEventHooks(hHookWATStatus,WAT_EVENT_PLAYERSTATUS,WorkSI.status); + end; + + // no playing file - clear all file info + if stat=WAT_PLS_NOMUSIC then + begin + ClearFileInfo (WorkSI,false); + ClearChangingInfo(WorkSI,false); + ClearTrackInfo (WorkSI,false); + + ClearFileInfo (SongInfo,true); + ClearChangingInfo(SongInfo,true); + ClearTrackInfo (SongInfo,true); + + if newplayer then + begin + ClearPlayerInfo(SongInfo,true); + CopyPlayerInfo (WorkSI,SongInfo); + end; + SongInfo.status:=WorkSI.status; + end; + // now time for changes (window text, volume) + // just when music presents + if stat=WAT_PLS_NORMAL then + begin + GetChangingInfo(WorkSI,flags); + // full info requires + // "no music" case blocked + if (result=WAT_RES_NEWFILE) or // new file + ((result=WAT_RES_OK) and // if not new but... + (((wParam and WAT_INF_CHANGES)=0) or // ... ask for full info + (StrPosW(WorkSI.mfile,'://')<>nil) or // ... or remote file + isContainer(WorkSI.mfile))) then // ... or container like CUE + begin + // requirement: old artist/title for remote files + stat:=GetInfo(WorkSI,flags); + + // covers + if (WorkSI.cover=nil) or (WorkSI.cover^=#0) then + GetCover(WorkSI.cover,WorkSI.mfile) + else + begin + mGetMem(buf,MAX_PATH*SizeOf(WideChar)); + GetTempPathW(MAX_PATH,buf); + if StrCmpW(buf,WorkSI.cover,StrLenW(buf))=0 then + begin + GetExt(WorkSI.cover,StrCatEW(buf,'\wat_cover.')); + DeleteFileW(buf); + MoveFileW(WorkSI.cover,buf); + mFreeMem(WorkSI.cover); + WorkSI.cover:=buf; + end + else + mFreeMem(buf); + end; + // lyric + if (WorkSI.lyric=nil) or (WorkSI.lyric^=#0) then + GetLyric(WorkSI.lyric,WorkSI.mfile); + +// file info will be updated anyway, so - just update it + if result=WAT_RES_NEWFILE then + begin + ClearFileInfo(SongInfo,true); + CopyFileInfo (WorkSI,SongInfo); + end; + ClearTrackInfo(SongInfo,true); + CopyTrackInfo (WorkSI,SongInfo); + + if newplayer then + begin + ClearPlayerInfo(SongInfo,true); + CopyPlayerInfo (WorkSI,SongInfo); + end; + ClearChangingInfo(SongInfo,true); + CopyChangingInfo (WorkSI,SongInfo); + SongInfo.status:=WorkSI.status; + + if stat=WAT_RES_NEWFILE then + result:=WAT_RES_NEWFILE; + + if result=WAT_RES_NEWFILE then + NotifyEventHooks(hHookWATStatus,WAT_EVENT_NEWTRACK,tlparam(@SongInfo)); + end + else // just changing infos + begin + if newplayer then + begin + ClearPlayerInfo(SongInfo,true); + CopyPlayerInfo (WorkSI,SongInfo); + end; + ClearChangingInfo(SongInfo,true); + CopyChangingInfo (WorkSI,SongInfo); + SongInfo.status:=WorkSI.status; + end; + end; + end; + + if lParam<>0 then + ppointer(lParam)^:=ReturnInfo(wParam and $FF); + end + //----- Player not found ----- + else + begin + if OldPlayerStatus<>WorkSI.status then + begin + ClearSongInfoData(WorkSI,false); // player info must be empty anyway + ClearSongInfoData(SongInfo,true); + SongInfo.status:=WAT_PLS_NOTFOUND+WAT_MES_UNKNOWN shl 16; + + NotifyEventHooks(hHookWATStatus,WAT_EVENT_PLAYERSTATUS, + WAT_PLS_NOTFOUND+WAT_MES_UNKNOWN shl 16); + end; + +{ + if OldPlayerStatus<>WorkSI.status then + begin + NotifyEventHooks(hHookWATStatus,WAT_EVENT_PLAYERSTATUS, + WAT_PLS_NOTFOUND+WAT_MES_UNKNOWN shl 16); + end; + + ClearSongInfoData(WorkSI,false); // player info must be empty anyway + WorkSI.status:=WAT_PLS_NOTFOUND+WAT_MES_UNKNOWN shl 16; + + ClearSongInfoData(SongInfo,true); + SongInfo.status:=WAT_PLS_NOTFOUND+WAT_MES_UNKNOWN shl 16; +} + + if lParam<>0 then + ppointer(lParam)^:=nil; + end; + + giused:=0; +end; + +function PressButton(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + flags:integer; +begin + if DisablePlugin=dsPermanent then + result:=0 + else + begin + flags:=0; + if UseImplant<>BST_UNCHECKED then flags:=flags or WAT_OPT_IMPLANTANT; + if mmkeyemu <>BST_UNCHECKED then flags:=flags or WAT_OPT_APPCOMMAND; + if CheckAll <>BST_UNCHECKED then flags:=flags or WAT_OPT_CHECKALL; + result:=SendCommand(wParam,lParam,flags); + end; +end; + +function WATPluginStatus(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + f1:integer; +begin + if wParam=2 then + begin + result:=PluginInfo.version; + exit; + end; + if DisablePlugin=dsPermanent then + result:=1 + else + result:=0; + if (integer(wParam)<0) or (wParam=MenuDisablePos) then + begin + if result=0 then + wParam:=1 + else + wParam:=0; + end; + case wParam of + 0: begin + if DisablePlugin=dsPermanent then //?? + begin + StartTimer; + DisablePlugin:=dsEnabled; + end; + f1:=0; + end; + 1: begin + StopTimer; + DisablePlugin:=dsPermanent; + f1:=CMIF_CHECKED; + end; + else + exit; + end; + DBWriteByte(0,PluginShort,opt_disable,DisablePlugin); + + ChangeMenuIcons(f1); + + NotifyEventHooks(hHookWATStatus,WAT_EVENT_PLUGINSTATUS,DisablePlugin); +end; + +function WaitAllModules(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + ptr:pwModule; +begin + result:=0; + + CallService(MS_SYSTEM_REMOVEWAIT,wParam,0); + + ptr:=ModuleLink; + while ptr<>nil do + begin + if @ptr^.Init<>nil then + ptr^.ModuleStat:=ptr^.Init(true); + ptr:=ptr^.Next; + end; + + if mTimer<>0 then + TimerProc(0,0,0,0); + + StartTimer; + + NotifyEventHooks(hHookWATLoaded,0,0); + CloseHandle(hEvent); +end; + +function OnModulesLoaded(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + p:PAnsiChar; +begin + UnhookEvent(onloadhook); + + CallService(MS_DBEDIT_REGISTERSINGLEMODULE,twparam(PluginShort),0); + + hTimer:=0; + + OleInitialize(nil); + + if RegisterIcons then + wsic:=HookEvent(ME_SKIN2_ICONSCHANGED,@IconChanged) + else + wsic:=0; + + CreateMenus; + + if ServiceExists(MS_TTB_ADDBUTTON)<>0 then + onloadhook:=HookEvent(ME_TTB_MODULELOADED,@OnTTBLoaded) + else + ttbState:=0; + + ProcessFormatLink; + ProcessPlayerLink; + p:=GetAddonFileName(nil,'player','plugins','ini'); + if p<>nil then + begin + LoadFromFile(p); + mFreeMem(p); + end; + + p:=GetAddonFileName(nil,'watrack_icons','icons','dll'); + if p<>nil then + begin + SetPlayerIcons(p); + mFreeMem(p); + end; + + IsMultiThread:=true; + + hEvent:=CreateEvent(nil,true,true,nil); + if hEvent<>0 then + begin + p:='WAT_INIT'; + hWATI:=CreateServiceFunction(p,@WaitAllModules); + CallService(MS_SYSTEM_WAITONHANDLE,hEvent,tlparam(p)); + end; + + loadopt; + if DisablePlugin=dsPermanent then + CallService(MS_WAT_PLUGINSTATUS,1,0); + + StartMSNHook; + + result:=0; +end; + +procedure FreeVariables; +begin + ClearSongInfoData(SongInfo ,true); + ClearSongInfoData(tSongInfo(SongInfoA),true); + ClearSongInfoData(WorkSI ,false); // not necessary really + mFreeMem(CoverPaths); + ClearFormats; + ClearPlayers; +end; + +procedure FreeServices; +begin + DestroyServiceFunction(hGFI); + DestroyServiceFunction(hRGS); + + DestroyServiceFunction(hWI); + DestroyServiceFunction(hGMI); + DestroyServiceFunction(hPS); + DestroyServiceFunction(hPB); + DestroyServiceFunction(hWATI); + DestroyServiceFunction(hWC); + + DestroyServiceFunction(hFMT); + DestroyServiceFunction(hPLR); +end; + +function PreShutdown(wParam:WPARAM;lParam:LPARAM):int;cdecl; +var + buf:array [0..511] of WideChar; + fdata:WIN32_FIND_DATAW; + fi:THANDLE; + p:PWideChar; + ptr:pwModule; +begin + StopMSNHook; + + NotifyEventHooks(hHookWATStatus,WAT_EVENT_PLAYERSTATUS,WAT_PLS_NOTFOUND); + + if hwndTooltip<>0 then + DestroyWindow(hwndTooltip); + + if ttbState<>0 then + begin + if ServiceExists(MS_TTB_REMOVEBUTTON)>0 then + CallService(MS_TTB_REMOVEBUTTON,TWPARAM(ttbState),0); + ttbState:=0; + end; + + StopTimer; + ptr:=ModuleLink; + while ptr<>nil do + begin + if @ptr^.DeInit<>nil then + ptr^.DeInit(false); + ptr:=ptr^.Next; + end; + +// UnhookEvent(plStatusHook); + UnhookEvent(hHookShutdown); + UnhookEvent(opthook); + if wsic<>0 then UnhookEvent(wsic); + + FreeServices; + FreeVariables; + + DestroyHookableEvent(hHookWATLoaded); + DestroyHookableEvent(hHookWATStatus); + + OleUnInitialize; + + //delete cover files + buf[0]:=#0; + GetTempPathW(511,buf); + p:=StrEndW(buf); + StrCopyW(p,'wat_cover.*'); + + fi:=FindFirstFileW(buf,fdata); + if fi<>THANDLE(INVALID_HANDLE_VALUE) then + begin + repeat + StrCopyW(p,fdata.cFileName); + DeleteFileW(buf); + until not FindNextFileW(fi,fdata); + FindClose(fi); + end; + + result:=0; +end; + +function Load():int; cdecl; +begin + result:=0; + Langpack_register; + + DisablePlugin:=dsPermanent; + + hHookWATLoaded:=CreateHookableEvent(ME_WAT_MODULELOADED); + hHookWATStatus:=CreateHookableEvent(ME_WAT_NEWSTATUS); + hHookShutdown :=HookEvent(ME_SYSTEM_OKTOEXIT,@PreShutdown); + opthook :=HookEvent(ME_OPT_INITIALISE ,@OnOptInitialise); + + hGFI:=CreateServiceFunction(MS_WAT_GETFILEINFO ,@WATGetFileInfo); + hRGS:=CreateServiceFunction(MS_WAT_RETURNGLOBAL ,@WATReturnGlobal); + + hGMI:=CreateServiceFunction(MS_WAT_GETMUSICINFO ,@WATGetMusicInfo); + hPS :=CreateServiceFunction(MS_WAT_PLUGINSTATUS ,@WATPluginStatus); + hPB :=CreateServiceFunction(MS_WAT_PRESSBUTTON ,@PressButton); + hWI :=CreateServiceFunction(MS_WAT_WINAMPINFO ,@WinampGetInfo); + hWC :=CreateServiceFunction(MS_WAT_WINAMPCOMMAND,@WinampCommand); + + hFMT:=CreateServiceFunction(MS_WAT_FORMAT,@ServiceFormat); + hPLR:=CreateServiceFunction(MS_WAT_PLAYER,@ServicePlayer); + + FillChar(SongInfoA,SizeOf(SongInfoA),0); + FillChar(SongInfo ,SizeOf(SongInfo ),0); + FillChar(WorkSI ,SizeOf(SongInfo ),0); + onloadhook:=HookEvent(ME_SYSTEM_MODULESLOADED,@OnModulesLoaded); +end; + +function Unload:int; cdecl; +begin + result:=0; +end; + +exports + Load, Unload, + MirandaPluginInfoEx; + +begin +end. diff --git a/plugins/Watrack/winampapi.pas b/plugins/Watrack/winampapi.pas new file mode 100644 index 0000000000..e53e88a247 --- /dev/null +++ b/plugins/Watrack/winampapi.pas @@ -0,0 +1,277 @@ +{Winamp-like - base class} +unit winampapi; +{$include compilers.inc} + +interface + +uses windows,messages; + +const + WinampClass = 'Winamp v1.x'; + WinampTail = ' - Winamp'; + +function WinampGetStatus(wnd:HWND):integer; +function WinampGetWindowText(wnd:HWND):pWideChar; +function WinampFindWindow(wnd:HWND):HWND; +function WinampCommand(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +function WinampGetInfo(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; + +const + WM_WA_IPC = WM_USER; + IPC_GETVERSION = 0; + IPC_ISPLAYING = 104; + IPC_GETINFO = 126; + IPC_GETOUTPUTTIME = 105; + IPC_WRITEPLAYLIST = 120; + IPC_GETLISTLENGTH = 124; + IPC_GETLISTPOS = 125; + IPC_ISFULLSTOP = 400; //!! + IPC_INETAVAILABLE = 242; //!! + IPC_GETPLAYLISTFILE = 211; + + IPC_IS_PLAYING_VIDEO = 501; + + IPC_PLAYFILE = 100; + IPC_STARTPLAY = 102; + IPC_SETVOLUME = 122; // -666 returns the current volume. + IPC_GET_SHUFFLE = 250; + IPC_SET_SHUFFLE = 252; + IPC_JUMPTOTIME = 106; + +const + WINAMP_PREV = 40044; + WINAMP_PLAY = 40045; + WINAMP_PAUSE = 40046; + WINAMP_STOP = 40047; + WINAMP_NEXT = 40048; + WINAMP_VOLUMEUP = 40058; // turns the volume up a little + WINAMP_VOLUMEDOWN = 40059; // turns the volume down a little + +implementation + +uses common,wat_api; + +function WinampFindWindow(wnd:HWND):HWND; +var + pr,pr1:dword; +begin + GetWindowThreadProcessId(wnd,@pr); + result:=0; + repeat + result:=FindWindowEx(0,result,WinampClass,nil); + if result<>0 then + begin + GetWindowThreadProcessId(result,@pr1); + if pr=pr1 then + break; + end + else + break; + until false; +end; + +// ----------- Get player info ------------ + +function GetVersion(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_WA_IPC,0,IPC_GETVERSION); +end; + +function GetVersionText(wnd:HWND):pWideChar; +var + ver:integer; + s:array [0..31] of WideChar; + p:pWideChar; +begin + ver:=GetVersion(wnd); + p:=@s; + IntToStr(p,ver shr 12); + while p^<>#0 do inc(p); + p^:='.'; + IntToStr(p+1,(ver shr 4) and $F); + while p^<>#0 do inc(p); + p^:='.'; + IntToStr(p+1,ver and $F); + StrDupW(result,PWideChar(@s)); +end; + +function WinampGetStatus(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_WA_IPC,0,IPC_ISPLAYING); + // 0 - stopped, 1 - playing + if result>1 then + result:=WAT_MES_PAUSED; +{ + if result=0 then // !! only for remote media! + begin + result:=SendMessage(wnd,WM_WA_IPC,0,IPC_ISFULLSTOP); + if result<>0 then + result:=WAT_MES_STOPPED + else + result:=WAT_MES_PLAYING; + end; +} +end; + +function WinampGetWindowText(wnd:HWND):pWideChar; +var + a:cardinal; + pc:pWideChar; +begin + a:=GetWindowTextLengthW(wnd); + mGetMem(result,(a+1)*SizeOf(WideChar)); + if GetWindowTextW(wnd,result,a+1)>0 then + begin + pc:=StrPosW(result,WinampTail); + if pc<>nil then + begin + pc^:=#0; + pc:=StrPosW(result,'. '); + if pc<>nil then + StrCopyW(result,pc+2); + end; + end; +end; + +// --------- Get file info ---------- + +function GetKbps(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_WA_IPC,1,IPC_GETINFO); + if result>1000 then + result:=result div 1000; +end; + +function GetKhz(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_WA_IPC,0,IPC_GETINFO); + if result>1000 then + result:=result div 1000; +end; + +function GetChannels(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_WA_IPC,2,IPC_GETINFO); +end; + +function GetTotalTime(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_WA_IPC,1,IPC_GETOUTPUTTIME); +end; + +function GetElapsedTime(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_WA_IPC,0,IPC_GETOUTPUTTIME) div 1000; +end; + +function GetVolume(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_WA_IPC,-666,IPC_SETVOLUME); + result:=(result shl 16)+(result shr 4); +end; + +function WinampGetInfo(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + wnd:HWND; +begin + result:=0; + with pSongInfo(wParam)^ do + begin + if winampwnd<>0 then + wnd:=winampwnd + else + wnd:=plwnd; + + if (lParam and WAT_OPT_PLAYERDATA)<>0 then + begin + if plyver=0 then + begin + plyver:=GetVersion(wnd); + txtver:=GetVersionText(wnd); + end; + end + else if (lParam and WAT_OPT_CHANGES)<>0 then + begin + volume:=GetVolume(wnd); + if status<>WAT_MES_STOPPED then + time:=GetElapsedTime(wnd); +// wndtext:=WinampGetWindowText(wnd); + end + else + begin + if kbps =0 then kbps :=GetKbps(wnd); + if khz =0 then khz :=GetKhz(wnd); + if channels=0 then channels:=GetChannels(wnd); + if total =0 then total :=GetTotalTime(wnd); + end; + end; +end; + +// ------- Commands ---------- + +function Play(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_COMMAND,WINAMP_PLAY,0); +end; + +function Pause(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_COMMAND,WINAMP_PAUSE,0); +end; + +function Stop(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_COMMAND,WINAMP_STOP,0); +end; + +function Next(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_COMMAND,WINAMP_NEXT,0); +end; + +function Prev(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_COMMAND,WINAMP_PREV,0); +end; + +function VolDn(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_COMMAND,WINAMP_VOLUMEDOWN,0); +end; + +function VolUp(wnd:HWND):integer; +begin + result:=SendMessage(wnd,WM_COMMAND,WINAMP_VOLUMEUP,0); +end; + +procedure SetVolume(wnd:HWND;value:cardinal); +begin + SendMessage(wnd,WM_WA_IPC,value shl 4,IPC_SETVOLUME); +end; + +function Seek(wnd:HWND;value:integer):integer; +begin + result:=SendMessage(wnd,WM_WA_IPC,0,IPC_GETOUTPUTTIME) div 1000; + SendMessage(wnd,WM_WA_IPC,value*1000,IPC_JUMPTOTIME); +end; + +function WinampCommand(wParam:WPARAM;lParam:LPARAM):int_ptr;cdecl; +var + wnd:HWND; +begin + wnd:=wParam; + case LoWord(lParam) of + WAT_CTRL_PREV : result:=Prev (wnd); + WAT_CTRL_PLAY : result:=Play (wnd); + WAT_CTRL_PAUSE: result:=Pause(wnd); + WAT_CTRL_STOP : result:=Stop (wnd); + WAT_CTRL_NEXT : result:=Next (wnd); + WAT_CTRL_VOLDN: result:=VolDn(wnd); + WAT_CTRL_VOLUP: result:=VolUp(wnd); + WAT_CTRL_SEEK : result:=Seek (wnd,lParam shr 16); + else + result:=0; + end; +end; + +end. -- cgit v1.2.3