1

Тема: Ahk: Управление MPC-HC

День добрый, снова выхожу на связь.

Нашел сообщение от teadrinker:
http://forum.script-coding.com/viewtopi … 69#p112669
Заинтересовался, а какую еще можно запросить информацию и как можно управлять плеером MPC-HC?
Особенно меня интересует:
-открытие плей листов
-сохранение плей листов
-сортировка плей листов
-перемешивание (randomize) файлов
-случайное воспроизведение (shiffle) файлов
-удаление текущего файла в корзину

Благодарю.

2 (изменено: svoboden, 2017-08-09 21:55:15)

Re: Ahk: Управление MPC-HC

Читайте. Также у MPC-HC есть свое api. Управлять MPC-HC можно с помощью сообщений.

3

Re: Ahk: Управление MPC-HC

Прочитал, покурил, читал мнение наших зарубежных товарищей. Прогресс пока не наметился.
На форуме я не первый день, так что, некоторые собеседники примерно представляют мой уровень владения предметом (не очень высокий).
Может быть уважаемый teadrinker напишет свой код с комментариями и если есть у кого какие наработки в этом вопросе, тоже выкладывайте. Любой информации буду рад.

4 (изменено: svoboden, 2017-08-13 14:33:05)

Re: Ahk: Управление MPC-HC

Да что там непонятного? Например, если код, который вы указали выше работает, то смотрите api, запрашиваете в коде, например, список аудиодорожек 0xA0003001 вместо 0xA0003002. Дальше, вместо 0x50000003 пишите, допустим, 0x50000005 (узнает список аудиодорожек) и заменяете параметры в MsgBox или еще где-нибудь для этой команды. Может еще CMD_PLAYMODE := 0x50000002 надо дописать.
P.S.
Может, я чего-нибудь пропустил, дальше сами додумайтесь.

5 (изменено: teadrinker, 2017-08-13 16:23:11)

Re: Ahk: Управление MPC-HC

upsi_daezium, согласен с предыдущим оратором. Принцип я показал, а других наработок нет. При создании своего скрипта пользовался только этим (там есть кое-какие комментарии). Если хотите получить

-открытие плей листов
-сохранение плей листов
-сортировка плей листов
-перемешивание (randomize) файлов
-случайное воспроизведение (shiffle) файлов
-удаление текущего файла в корзину

я бы только платно взялся, поскольку самому не нужно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

6

Re: Ahk: Управление MPC-HC

Лично я в апи не увидел работу с плей-листами.

7

Re: Ahk: Управление MPC-HC

Плохо посмотрел.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8 (изменено: Malcev, 2017-08-13 20:34:23)

Re: Ahk: Управление MPC-HC

Приведи ссылку.
Вот, что вижу я:

// List of files in the playlist
    // Parameter 1: file path 0
    // Parameter 2: file path 1
    // ...
    // Parameter n: active file, -1 if no active file
    CMD_PLAYLIST            = 0x50000006,

    // Add a new file to playlist (did not start playing)
    // Parameter 1: file path
    CMD_ADDTOPLAYLIST       = 0xA0001000,

    // Remove all files from playlist
    CMD_CLEARPLAYLIST       = 0xA0001001,

    // Start playing playlist
    CMD_STARTPLAYLIST       = 0xA0001002,

    CMD_REMOVEFROMPLAYLIST  = 0xA0001003,   // TODO

    // Ask for the current playlist
    // return a CMD_PLAYLIST
    CMD_GETPLAYLIST         = 0xA0003003,

9

Re: Ahk: Управление MPC-HC

Так разве этого не достаточно?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

10

Re: Ahk: Управление MPC-HC

Ну а как там сделать, например, -случайное воспроизведение (shiffle) файлов?

11

Re: Ahk: Управление MPC-HC

Как-то можно, наверное. Там есть событие CMD_STATE, которое отправляется при открытии и закрытии файлов. По закрытию получаем список файлов плейлиста, стираем плейлист в плеере, полученный плейлист сортируем, создаём новый, стартуем. Ну это теория, я не пробовал.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

12 (изменено: Malcev, 2017-08-13 21:08:54)

Re: Ahk: Управление MPC-HC

Ну это костыли (это я к тому, что не увидел работу с плей-листами в апи) и к тому же Randomize.
А shuffle отличается от Randomize, тем, что список файлов в плейлисте не изменяется, а просто они проигрываются в случайном порядке.

13

Re: Ahk: Управление MPC-HC

Ещё есть команда CMD_SETINDEXPLAYLIST для установки активного трека в плейлисте, написано, что она DOESN'T WORK, но может уже работает, надо пробовать.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14

Re: Ahk: Управление MPC-HC

Randomize у меня так делает:

f11::
SetControlDelay -1
SetWinDelay -1
ControlClick, SysListView322,A,,R,,NA
WinWait, ahk_class #32768
ControlSend,,a
Return

15 (изменено: svoboden, 2017-08-15 00:35:38)

Re: Ahk: Управление MPC-HC

Зачем так? С помощью сообщений, наверное, можно легко установить этот Randomize, только их надо как-то отловить.

16

Re: Ahk: Управление MPC-HC

svoboden пишет:

наверное, можно легко установить этот Randomize

Жду вашего кода.

17 (изменено: svoboden, 2017-08-14 15:52:01)

Re: Ahk: Управление MPC-HC

Malcev пишет:

Жду вашего кода.

Там не очень просто отлавливать эти сообщения, например, отловить сообщение воспроизведение файла "SendMessage,0x0111,889,,,ahk_class MediaPlayerClassicW" у меня пока не выходит, хотя сообщение работает. Вывод: значит, есть где-то сообщение этого randomize. Просто мне не очень интересно разбираться с этим MPC-HC.

18

Re: Ahk: Управление MPC-HC

SendMessage,0x0111 - WM_COMMAND - это обращение к меню.
А в меню пункта randomize нету.

19

Re: Ahk: Управление MPC-HC

Так есть же сообщения для SysListView322.

20

Re: Ahk: Управление MPC-HC

А при чем тут SysListView322?
Отправлять надо в ahk_class #32768, а для это нужно дождаться его появления.

21 (изменено: svoboden, 2017-08-14 16:38:44)

Re: Ahk: Управление MPC-HC

Так вроде программа простая, в которой проходят сообщения еще. И что, разве нельзя как-нибудь добраться к этому меню данным способом?

22

Re: Ahk: Управление MPC-HC

Если вы хотите только отсортировать список, то можно попробовать отослать сообщение:
https://msdn.microsoft.com/en-us/librar … s.85).aspx
А потом проинформировать родительское окно об изменениях.

23 (изменено: svoboden, 2017-08-17 00:47:40)

Re: Ahk: Управление MPC-HC

Вот мой randomize, правда, его еще доделать надо, что мне вообще не хочется:

for v in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] {
Random, v, 0, 10
r = 430%v%
SendMessage,0x0111,r,,,ahk_class MediaPlayerClassicW
Exit
}
return

24 (изменено: Malcev, 2017-08-14 21:51:19)

Re: Ahk: Управление MPC-HC

У меня ваш код не работает.
Что именно вы пытаетесь сделать?
ИМХО если вы хотите изменить этот листбокс через сообщения, то единственный вариант получать DC и писать в память процесса, примерно как сделал teadrinker тут:
http://forum.script-coding.com/viewtopi … 42#p109142

25 (изменено: svoboden, 2017-08-17 00:46:38)

Re: Ahk: Управление MPC-HC

Нет.
• Навигация.
• Плейлист.
• Отлавливаете сообщения "SendMessage,0x111".
• И запускаете в случайном порядке, то есть, записываете случайную цифру в переменную тут 430%r%.

Запустите код еще раз. Если число совпадет, то аудиодорожка не поменяется, (но это можно исправить).
Так должно всегда работать:

1::
for v in [1,2,3,4,5,6,7,8,9,10] {
Random, v, 0, 10
r = 430%v%
SendMessage,0x0111,r,,,ahk_class MediaPlayerClassicW
}
return

26

Re: Ahk: Управление MPC-HC

А при чем тут сортировка плейлиста и выбор номера проигрываемого трека?

27 (изменено: svoboden, 2017-08-14 22:15:06)

Re: Ahk: Управление MPC-HC

Так нет никакой сортировки, это выбор нужной аудиодорожки в плейлисте.

28

Re: Ahk: Управление MPC-HC

Так задача заключается в сортировке плей-листа, а не выборе нужной или рендомной дорожки.

29 (изменено: svoboden, 2017-08-14 22:25:15)

Re: Ahk: Управление MPC-HC

Не знаю, я понял вопрос, как воспроизвести аудиодорожки в случайном порядке.

30

Re: Ahk: Управление MPC-HC

Получилось сделать shuffle и рандомизацию плейлиста:

MPC_HC.Init()
Return

$F9:: MPC_HC.RandPlayList()

$F10:: TrayTip,, % "Рандомное воспроизведение " . ( (MPC_HC.shuffle := !MPC_HC.shuffle) ? "в" : "от" ) . "ключено"

$F11::
   info := MPC_HC.GetThrackInfo()
   MsgBox, % "title = "       . info.title       . "`n"
           . "author = "      . info.author      . "`n" 
           . "description = " . info.description . "`n"
           . "filename = "    . info.filename    . "`n" 
           . "duration = "    . info.duration
   Return

class MPC_HC
{
   Init(MpcPath := "")  {
      OnMessage( WM_COPYDATA := 0x4A, ObjBindMethod(this, "WM_COPYDATA_READ") )
      MyHwnd := A_ScriptHwnd + 0
      if MpcPath  {
         try Run, "%MpcPath%" /slave %MyHwnd%
         catch e {
            MsgBox, % e.Message "`n" e.Extra
            ExitApp
         }
      }
      else  {
         if WinExist("ahk_class MediaPlayerClassicW")  {
            WinGet, MpcPath, ProcessPath
            Run, "%MpcPath%" /slave %MyHwnd%
         }
         else  {
            try Run, "mpc-hc" /slave %MyHwnd%
            catch  {
               try Run, "mpc-hc64" /slave %MyHwnd%
               catch e  {
                  MsgBox, % e.Message "`n" e.Extra "`n`nУкажите путь к mpc-hc.exe при создании экземпляра объекта!"
                  ExitApp
               }
            }
         }
      }
      start := A_TickCount
      while !this.Connected && (A_TickCount - start < 3000)
         Sleep, 10
      if !this.Connected  {
         MsgBox, Не удалось полключиться к MPC-HC.exe
         ExitApp
      }
      handling := ObjBindMethod(this, "PreventShuffle")
      for k, v in ["LButton", "Space", "PgUp", "PgDn"]
         Hotkey, % "~" . v, % handling, On
      OnExit( ObjBindMethod(this, "Exit") )
   }
   
   Exit()  {
      this.WM_COPYDATA_SEND(CMD_CLOSEAPP := 0xA0004006)
   }
   
   PreventShuffle()  {
      if WinActive("ahk_id" this.hMPC) && this.shuffle  {
         this.shuffle := false
         timer := ObjBindMethod(this, "LButtonTimer")
         SetTimer, % timer, -2000
      }
   }
   
   LButtonTimer()  {
      this.shuffle := true
   }

   WM_COPYDATA_READ(wp, lp)  {
      static CMD_CONNECT    := 0x50000000, CMD_STATE    := 0x50000001, CMD_PLAYMODE        := 0x50000002
           , CMD_NOWPLAYING := 0x50000003, CMD_PLAYLIST := 0x50000006, CMD_CURRENTPOSITION := 0x50000007
           , MLS_LOADED := 2, MLS_CLOSING := 3, PS_PAUSE := 1, start := 0

      dwData := NumGet(lp+0, "UInt")
      lpData := StrGet(NumGet(lp + A_PtrSize*2), "UTF-16")

      if (dwData = CMD_CONNECT)  {
         this.hMPC := lpData
         this.Connected := true
      }
      if (dwData = CMD_NOWPLAYING)
         this.NowPlaying := lpData
      
      if (dwData = CMD_PLAYMODE)  {
         if (this.shuffle && lpData = PS_PAUSE)
            dwData := CMD_STATE, lpData := MLS_CLOSING
      }
      if (dwData = CMD_STATE)  {
         if (lpData = MLS_LOADED)  {
            timer := ObjBindMethod(this, "GetInfo")
            SetTimer, % timer, -50
         }
         if (this.shuffle && lpData = MLS_CLOSING && (A_TickCount - start) > 2000)  {
            timer := ObjBindMethod(this, "ShuffleTimer")
            SetTimer, % timer, -200
            start := A_TickCount
         }
      }
      if (dwData = CMD_PLAYLIST)
         this.PlayList := lpData
      
      if (dwData = CMD_CURRENTPOSITION)
         this.position := lpData
      
      Return true
   }
   
   GetInfo()  {
      this.GetPlayList()
      this.GetThrackInfo()
   }

   WM_COPYDATA_SEND(dwData, cbData := 0, lpData := 0)  {
      VarSetCapacity(COPYDATASTRUCT, A_PtrSize*3, 0)
      NumPut(dwData, COPYDATASTRUCT)
      NumPut(cbData, &COPYDATASTRUCT + A_PtrSize)
      NumPut(lpData, &COPYDATASTRUCT + A_PtrSize*2)
      SendMessage, WM_COPYDATA := 0x4A, A_ScriptHwnd, &COPYDATASTRUCT,, % "ahk_id" this.hMPC
   }
   
   ShuffleTimer()  {
      static WM_COMMAND := 0x111, prevList, tracks := {}, _tracks
      
      RegExMatch(this.PlayList, "(.+)\|(.+)", list)
      if (list1 != prevList)  {
         tracks := {}, prevList := list1
         Loop, parse, list1, |
            tracks[A_Index] := true
         _tracks := tracks.Clone()
      }
      _tracks.Delete(list2 + 1)
      arr := []
      for k in _tracks
         arr.Push(k)
      if !arr.HasKey(1)  {
         _tracks := tracks.Clone()
         _tracks.Delete(list2 + 1)
         for k in _tracks
            arr.Push(k)
      }
      Random, rand, 1, arr.MaxIndex()
      SendMessage, WM_COMMAND, 4300 + arr[rand] - 1,,, % "ahk_id" this.hMPC
   }
   
   GetPlayList()  {
      this.PlayList := ""
      this.WM_COPYDATA_SEND(CMD_GETPLAYLIST := 0xA0003003)
      start := A_TickCount
      while !this.PlayList && (A_TickCount - start < 1000)
         Sleep, 10
      Return this.PlayList
   }

   GetThrackInfo()  {
      this.NowPlaying := ""
      this.WM_COPYDATA_SEND(CMD_GETNOWPLAYING := 0xA0003002)
      start := A_TickCount
      while !this.NowPlaying && (A_TickCount - start < 1000)
         Sleep, 10
      if !info := this.NowPlaying
         Return
      obj := {}
      Loop, parse, info, |
         obj[["title", "author", "description", "filename", "duration"][A_Index]] := A_LoopField
      this.NowPlayingInfo := obj
      Return obj
   }
   
   RandPlayList()  {
      static CMD_PLAYPAUSE   := 0xA0000003, CMD_ADDTOPLAYLIST      := 0xA0001000, CMD_CLEARPLAYLIST := 0xA0001001
           , CMD_SETPOSITION := 0xA0002000, CMD_GETCURRENTPOSITION := 0xA0003004, WM_COMMAND := 0x111
           
      filename := this.NowPlayingInfo.filename
      Loop 2
         this.WM_COPYDATA_SEND(CMD_PLAYPAUSE)
      ( this.PlayList = "" && this.GetPlayList() )
      RegExMatch(this.PlayList, "(.+)\|(.+)", list)
      this.WM_COPYDATA_SEND(CMD_CLEARPLAYLIST)
      Sort, list1, D| Random
      Loop, parse, list1, |
      {
         VarSetCapacity(var, 0)
         VarSetCapacity(var, len := StrPut(A_LoopField, "UTF-16")*2, 0)
         StrPut(A_LoopField, &var, "UTF-16")
         this.WM_COPYDATA_SEND(CMD_ADDTOPLAYLIST, len, &var)
         (A_LoopField = filename && index := A_Index - 1)
      }
      this.GetPlayList()
      if (filename = "")
         Return
      
      this.position := ""
      this.WM_COPYDATA_SEND(CMD_GETCURRENTPOSITION)
      start := A_TickCount
      while (this.position = "") && (A_TickCount - start < 2000)
         Sleep, 10
      SendMessage, WM_COMMAND, 4300 + index,,, % "ahk_id" this.hMPC
      VarSetCapacity(var, 0)
      VarSetCapacity(var, len := StrPut(this.position, "UTF-16")*2, 0)
      StrPut(this.position, &var, "UTF-16")
      Sleep, 100
      this.WM_COPYDATA_SEND(CMD_SETPOSITION, len, &var)
   }
}

Правда, если рандомизацию плейлиста вызывать при воспроизведении, не удаётся избежать прерывания звучания.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

31

Re: Ahk: Управление MPC-HC

У меня shuffle не работает.
При нажатии на кнопку следующего трека играет следующий трек.

32

Re: Ahk: Управление MPC-HC

Так и должно быть. Рандомно трек выбирается после окончания текущего.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

33

Re: Ahk: Управление MPC-HC

Так подглючивает.
Перепрыгивает всё время на первый трек.

34

Re: Ahk: Управление MPC-HC

Ну, не знаю, у меня нормально работает. Может, от версии зависит, я обновил до последней, а старая вообще крашилась при отправке некоторых команд.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

35 (изменено: Malcev, 2017-08-16 18:53:21)

Re: Ahk: Управление MPC-HC

Ну и то, что время рендомизации плейлиста зависит от количества файлов нём - не очень удобно, так как при большом количестве файлов (1000 и больше) ждать приходится долго.
Кстати, реально ли подменить этот плейлист своим, как ты это сделал в блокноте (увеличил-уменьшил шрифт)?

36

Re: Ahk: Управление MPC-HC

Malcev пишет:

при большом количестве файлов (1000 и больше) ждать приходится долго.

SetBatchLines добавить надо, наверно.

Malcev пишет:

реально ли подменить этот плейлист своим, как ты это сделал в блокноте

Думаю, реально, но не так, как в том коде. Нужно знать, где он в памяти находится, т. к. если просто заменить список в окне, скорее всего это ничего не даст.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

37

Re: Ahk: Управление MPC-HC

teadrinker пишет:

SetBatchLines добавить надо, наверно.

Добавлял, с ним еще дольше (вначале набирает скорость, а потом начинает тормозить).
А ты сподвигнешься когда-нибудь написать ликбез о том, как производить такие замены?
Тема-то интересная.

38

Re: Ahk: Управление MPC-HC

Если ты про код с блокнотом, то тема сколь интересная, столь малоизученная, в особенности для 64-битных процессов. Информации мало, да и ассемблер знать нужно, без него не получится полноценно внедрять dll в чужой процесс. В том примере был очень простой случай.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

39

Re: Ahk: Управление MPC-HC

Вроде, с помощью этого можно:
https://github.com/Kalamity/classMemory … Memory.ahk

40 (изменено: teadrinker, 2017-08-16 21:34:35)

Re: Ahk: Управление MPC-HC

С помощью, может и можно, но библиотека, по-моему, не для этого. Ключевая функция для внедрения кода в чужой процесс — CreateRemoteThread, её я там не обнаружил.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

41

Re: Ahk: Управление MPC-HC

Вот ещё:

#singleinstance force 

; Run a 32 bit version of notepade and then start this script
; On 64 bit systems it can be found here C:\Windows\SysWOW64\notepad.exe
WinGet, targetPID, PID, ahk_exe notepad.exe

PROCESS_ALL_ACCESS := 0x1F0FFF
MEM_COMMIT := 0x1000
MEM_RELEASE := 0x8000
PAGE_EXECUTE_READWRITE := 64

; This function will be written to the remote process
; It takes a single argument, the address of a data structure. 
; This data structure contains all the information on the function to call and the parameters.
; CreateRemoteThread will invoke this proxyCaller function which will then call the target function.

proxyCallerString := "558BEC83EC1C53568B75088B068B4E0C83650800578B7E088945EC8B46046A048945F88D46105B85C97E6C8B1083FA01750C03C38B108955FCFF75FCEB3483FA02751A03C38B1003C38955FC8B108955F4FF75F4FF75FC83450808EB1883FA03751703C3D900D95DF483EC04D945F4D91C24015D0803C3EB1B3BD3751703C3DD00DD5DF083EC08DD45F0DD1C248345080883C0084975948365E4008365E8008D45E48945FC83FF01750AFF55F88B5DFC8903EB2F83FF02750FFF55F88B5DFC890383C3048913EB1B83FF03750AFF55F88B5DFCD91BEB0C3BFB7508FF55F88B5DFCDD1B837DEC0175030365088B45E489068B45E86A0C894604585F5E5BC9C3"
; Convert the proxyCaller string to a machine code function stored at &proxyCaller
sizeProxyCaller := hexToCharArray(proxyCallerString, proxyCaller)
if !hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", targetPID)
   exit("failed to open process")
; Allocate room in remote process for our proxy caller function
If !pProxyFunction := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "Ptr", sizeProxyCaller, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
   exit("Couldn't allocate memory for proxy function")
; Write the proxy caller function 
if !DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pProxyFunction, "Ptr", &proxyCaller, "Ptr", sizeProxyCaller, "Ptr", 0)
   exit("Couldn't write the function")

; Create some unicode strings and write them to notepad
titleSize := StrPutVar("This is a title", title, "UTF-16")
messageSize := StrPutVar("Hello from notepad!", message, "UTF-16")

If !pTitle := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "Ptr", titleSize, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
   exit("Couldn't allocate memory")
if !DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pTitle, "Ptr", &title, "Ptr", titleSize, "Ptr", 0)
   exit("Couldn't write")
If !pMessage := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "Ptr", messageSize, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
   exit("Couldn't allocate memory")
if !DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pMessage, "Ptr", &message, "Ptr", messageSize, "Ptr", 0)
   exit("Couldn't write")

; System functions are stored at the same addresses for each process (ignoring 32 vs 64 bit applications)
; So just find the address of the msgbox function in this script, as it will be the same in notepad
msgboxAddress := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "User32"), "AStr", "MessageBoxW") 
; create a data structure which contains the function call type, function address, function return type, and each parameter/argument
; windows API use stdcall so function type is "". Pass pointers to the message and title strings i.e. pMessage and pTitle.
paramSize := createParams(parameters, "", msgboxAddress, returnType := "int", ["UInt", 0], ["UInt", pMessage], ["UInt", pTitle], ["UInt", 0x00001000 | 0x00000002])


; Allocate some room for this structure and write it to the remote process
If !pBufferParameters := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "Ptr", paramSize, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
   exit("Couldn't allocate memory for parameters")
if !DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferParameters, "Ptr", &parameters, "Ptr", paramSize, "Ptr", 0)
   exit("Couldn't write the parameters")
; create a remote thread and have it run our proxy/caller function and pass it the address of the parameter structure
if !hThread := DllCall("CreateRemoteThread", "Ptr", hProc, "UInt", 0, "UInt", 0, "Ptr", pProxyFunction, "Ptr", pBufferParameters, "UInt", 0, "UInt", 0)
   exit("Couldn't start thread")
DllCall("WaitForSingleObject", "Ptr", hThread, "UInt", 0xFFFFFFFF)
if !DllCall("ReadProcessMemory", "Ptr",  hProc, "Ptr", pBufferParameters, "int*", result, "UInt", 4, "Ptr",0)
   exit("RPM failed")
msgbox % "Result: " result

exit()




hexToCharArray(hexString, byref var)
{
  sizeBytes := strlen(hexString)//2
  VarSetCapacity(var, sizeBytes)
  loop, % sizeBytes
    numput("0x" substr(hexString, A_Index * 2 - 1, 2), var, A_Index - 1, "UChar")
  return sizeBytes
}

exit(msg := "")
{
   global
   if (msg != "")
    msgbox % msg

   if pProxyFunction
       DllCall("VirtualFreeEx","Ptr",hProc,"Ptr", pProxyFunction,"Ptr", sizeProxyCaller, MEM_RELEASE)
   if pBufferParameters
       DllCall("VirtualFreeEx","Ptr",hProc,"Ptr", pBufferParameters,"Ptr", paramSize, MEM_RELEASE)   
    if pTitle
       DllCall("VirtualFreeEx","Ptr",hProc,"Ptr", pTitle,"Ptr", paramSize, MEM_RELEASE)  
    if pMessage
       DllCall("VirtualFreeEx","Ptr",hProc,"Ptr", pMessage,"Ptr", paramSize, MEM_RELEASE)
    if hProc
      DllCall("CloseHandle", "Ptr", hProc)
   exitapp 
}

/*
Param structure
// This structure is written to remote memory and holds the function address, type and parameters
// with which the function should be called
// offset      value
// 0        functionType / calling convention 
// 4        targetFunctionAddress
// 8        (Function) returnType 
// 12       param count
// Params are listed in reverse order (right to left i.e. last to first)
// 16       lastParamType
// 20       lastParamValue (either 4 bytes or 8 bytes)
// 24 or 28 secondToLastParamType 
// ......
*/
/*
  // param/return types (the values the injected function expects)
  int int32Type = 1; 
  int int64Type = 2;
  int floatType = 3;
  int doubleType = 4;
  // functionType 
  int cdeclType = 1;
*/
; variable:     The created structure is stored inside this variable
; functionType:  Pass the string "cdecl" to call cdecl functions or leave it blank to call stdcall functions 
; targetFunctionAddress: The address of the target function....
; returnType: can be any of the listed param types, as wells as void or null ("")
; params:  Is variadic and accepts an object i.e. ["Int64", 5]  means param type is Int64 with a value of 5
;  
; returns the size of the structure

createParams(byRef variable, functionType, targetFunctionAddress, returnType, params*)
{
    ; These are used to lookup the IDs for the both the return types and the param types
    static aTypeSize := {   "":         {ID: 0} ; void return type
                        ,   Void:       {ID: 0} ; void return type 
                        ,   Char:       {size: 4, ID: 1}
                        ,   UChar:      {size: 4, ID: 1}
                        ,   Short:      {size: 4, ID: 1}
                        ,   UShort:     {size: 4, ID: 1}
                        ,   Int:        {size: 4, ID: 1}
                        ,   UInt:       {size: 4, ID: 1}
                        ,   Int64:      {size: 8, ID: 2}
                        ,   Float:      {size: 4, ID: 3}
                        ,   Double:     {size: 8, ID: 4}}

    VarSetCapacity(variable, 16 + round(params.MaxIndex()) * 12, 0)
    if instr(functionType, "cdecl") 
        NumPut(1, variable, 0, "Int") ; 1 = cdecl 
    NumPut(targetFunctionAddress, variable, 4, "UInt")
    if !aTypeSize.hasKey(returnType)
        return -1 ; invalid return type 
    NumPut(aTypeSize[returnType].ID, variable, 8, "Int") ; return type 0 = none, 1 32bit, 2 64bit 
    NumPut(round(params.MaxIndex()), variable, 12, "Int")
    offset := 16
   ; params need to be written in reverse order (right to left)
    while paramObj := params.Remove()
    {
        type := paramObj.1, value := paramObj.2
        if !aTypeSize.hasKey(type)
            return -2 ; invalid param type           
        NumPut(aTypeSize[type].ID, variable, offset, "Int"),  offset += 4
        NumPut(value, variable, offset, type), offset += aTypeSize[type].size
   }
   return offset ; size bytes
}

StrPutVar(string, ByRef var, encoding)
{
    ; Ensure capacity.
    VarSetCapacity( var, StrPut(string, encoding)
        ; StrPut returns char count, but VarSetCapacity needs bytes.
        * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) )
    ; Copy or convert the string.
    return StrPut(string, &var, encoding)  * ((encoding="utf-16"||encoding="cp1200") ? 2 : 1) 
}

42 (изменено: teadrinker, 2017-08-16 22:11:07)

Re: Ahk: Управление MPC-HC

Это, вроде, я видел. Только для 32-битных процессов, да и часть машинным кодом идёт, что не способствует пониманию. У меня есть аналогичный вариант, дополненный ассемблером, там хотя бы понятно, что происходит.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

43

Re: Ahk: Управление MPC-HC

А как думаешь, сработает ли такое - заинжектить в процесс autohotkey.dll и уже из нее посылать wm_notify родительскому окну об изменениях в плейлисте?

44

Re: Ahk: Управление MPC-HC

Не думаю, что так можно чего-то добиться. Думаю, что сначала формируется плейлист, затем он отображается в окне. Изменение текста в окне, скорее всего, никак не повлияет на реальный плейлист.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

45

Re: Ahk: Управление MPC-HC

То есть если повторить все сообщения, перехваченные через microsoft spy++, которые происходят после удаления файла из  плейлиста ни к чему не приведут?

46

Re: Ahk: Управление MPC-HC

Если повторить все сообщения, может и сработать, ведь так ты фактически продублируешь ручное удаления файла. Думаю, даже достаточно будет просто послать {del}. Но если удалять через меню плейлиста, тогда перехваченных сообщений будет недостаточно, т. к. от этого меню не приходит сообщений.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

47 (изменено: svoboden, 2017-08-19 16:04:08)

Re: Ahk: Управление MPC-HC

Можно сделать проще, включить опцию сохранять настройки в ini файле и перезаписывать строку "ShufflePlaylistItems". Но изменения, наверное, вступают в силу только после перезагрузки MPC-HC. Имхо, может, можно как-нибудь сделать, чтобы настройки применялись сразу к открытому MPC-HC?

48

Re: Ahk: Управление MPC-HC

svoboden, ну к примеру, у вас есть ahk-скрипт, который при загрузке считывает настройки из ini-файла. Как сделать, чтобы он считывал настройки в нужный момент по желанию пользователя?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

49 (изменено: svoboden, 2017-08-17 20:15:29)

Re: Ahk: Управление MPC-HC

teadrinker, не считывал, а я думаю, чтобы перезаписывал. Такое можно легко сделать, только программу нужно будет перезагрузить. Еще можно управлять MPC-HC через Web.

50

Re: Ahk: Управление MPC-HC

Ну хорошо, а как сделать, чтобы ahk-скрипт их перезаписывал?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

51 (изменено: svoboden, 2017-08-17 20:18:54)

Re: Ahk: Управление MPC-HC

Надо читать, изучать.
P.S. Я просто подсказал идею, как можно так сделать. Хотел спросить, как сделать, чтобы настройки применились к активному окну MPC-HC.

52

Re: Ahk: Управление MPC-HC

Так вы сначала решите более простой вопрос, как то же самое сделать с ahk-скриптом.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

53 (изменено: svoboden, 2017-08-17 21:59:08)

Re: Ahk: Управление MPC-HC

teadrinker, я вас не очень хорошо понимаю. Есть же команда IniRead.

54

Re: Ahk: Управление MPC-HC

Спасибо, что сообщили. Но представьте, что скрипт уже скомпилирован, как вам эта команда поможет?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

55 (изменено: svoboden, 2017-08-17 20:51:00)

Re: Ahk: Управление MPC-HC

Все равно слабо понимаю вас, почему скрипт должен быть скомпилирован? Можно использовать FileAppend, в чем проблема.

56

Re: Ahk: Управление MPC-HC

svoboden пишет:

Все равно слабо понимаю вас, почему скрипт должен быть скомпилирован?

А разве MPC-HC не скомпилирован? Как FileAppend поможет для считывания настроек?
Просто вы спрашиваете, как заставить MPC обновить настройки. Вот я и предлагаю сначала разобраться, можно ли это сделать с простым ahk-скриптом, который уже скомпилирован, и если можно, то как.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

57 (изменено: svoboden, 2017-08-18 13:52:19)

Re: Ahk: Управление MPC-HC

stealzy, так двойным кликом мышкой можно запускать скрипт, если не знаете.
teadrinker, пускай и нельзя сделать это обычным ahk скриптом, можно просто заменить ini файл.

58

Re: Ahk: Управление MPC-HC

svoboden пишет:

можно просто заменить ini файл

И что, тогда настройки в скрипте сразу обновятся? Вы попробуйте написать скрипт, который считывает в начале работы настройки из ini-файла, запустите его, а потом замените ini-файл. В скрипте настройки изменятся?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

59 (изменено: svoboden, 2017-08-18 13:48:57)

Re: Ahk: Управление MPC-HC

teadrinker пишет:

И что, тогда настройки в скрипте сразу обновятся?

В каком еще скрипте? В программе должны обновиться. Но они обновляются только, когда программа открывается повторно.

60

Re: Ahk: Управление MPC-HC

Не, ну я понял про программу. А как этого в скрипте добиться?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

61

Re: Ahk: Управление MPC-HC

Так это я задал этот вопрос, я просто подсказал, что настройки плейлиста хранятся в ini файле. Можно как-нибудь обращаться к ним, а не через api. Еще через Web можно управлять MPC-HC.

62

Re: Ahk: Управление MPC-HC

svoboden, ну к примеру, у вас есть ahk-скрипт, который при загрузке считывает настройки из ini-файла. Как сделать, чтобы он считывал настройки в нужный момент по желанию пользователя?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

63

Re: Ahk: Управление MPC-HC

Можно еще скачать исходник, посмотреть, почему меню не отправляет сообщений (скорее всего TPM_NONOTIFY стоит).
Поправить и скомпилировать заново.

64

Re: Ahk: Управление MPC-HC

Malcev пишет:

Поправить и скомпилировать заново.

Вот это уже серьёзный подход!

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

65 (изменено: svoboden, 2017-08-17 21:57:08)

Re: Ahk: Управление MPC-HC

Я про ini файл, пока ничего не знаю, думал, что как обычный файл можно перезаписывать.
P.S. Я тоже про сообщения хотел идею написать, что можно в исходниках добавить. Но подумал, через файлы настроек будет проще.

66 (изменено: svoboden, 2017-08-17 22:10:32)

Re: Ahk: Управление MPC-HC

stealzy, премного благодарен, сам бы не догадался. Только вопрос не в этом, был у меня.

67

Re: Ahk: Управление MPC-HC

teadrinker пишет:

Как сделать, чтобы он считывал настройки в нужный момент по желанию пользователя?

1::IniWrite, 0, C:\Program Files\MPC-HC\mpc-hc.ini, Settings, ShufflePlaylistItems
2::IniWrite, 1, C:\Program Files\MPC-HC\mpc-hc.ini, Settings, ShufflePlaylistItems

Теперь понятнее, что я имею в виду?

68

Re: Ahk: Управление MPC-HC

Не-а. Вы привели пример записи в ini-файл. А как он будет их считывать?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

69 (изменено: svoboden, 2017-08-19 15:43:24)

Re: Ahk: Управление MPC-HC

Данным способом настройки применяются к MPC-HC, когда программа закрыта. При открытии программы настройки уже есть.
P.S. Дальше я хотел, чтобы вы подсказали, как их можно обновить (считать) эти настройки.

70 (изменено: teadrinker, 2017-08-18 01:19:32)

Re: Ahk: Управление MPC-HC

svoboden пишет:

Дальше я хотел, чтобы вы подсказали, как их можно обновить (считать) эти настройки.

Тогда вам сюда. Я пытался выяснить у вас, как, по вашему предположению, нужно было бы поступить, чтобы заставить считать настройки не MPC, а обычный AHK-скрипт.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

71 (изменено: svoboden, 2017-08-18 01:41:37)

Re: Ahk: Управление MPC-HC

teadrinker пишет:

заставить считать настройки не MPC, а обычный AHK-скрипт.

Я не знаю, как нужно считывать обычный ahk-скрипт, поэтому и хочу, чтобы вы подсказали, как можно его считать.

72

Re: Ahk: Управление MPC-HC

svoboden пишет:

Я не знаю, как нужно считывать обычный ahk-скрипт

Да не скрипт нужно считывать, а вот, предположим, ...

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

73

Re: Ahk: Управление MPC-HC

svoboden пишет:

Данным способом, настройки применяются к MPC-HC, когда программа закрыта, при открытии программы, настройки уже есть.
p.s. Дальше я хотел, чтобы вы подсказали, как их можно обновить (считать) эти настройки.

Как заставить плеер считать заново настройки? А это в нём предусмотрено вообще? Если он их читает один раз при запуске, то и шабаш.

74 (изменено: svoboden, 2017-08-18 13:43:30)

Re: Ahk: Управление MPC-HC

YMP пишет:

А это в нём предусмотрено вообще?

Так я видел тут на форуме много примеров, где делается то, что не предусмотрено. И как-бы, это мой вопрос, как сделать, чтобы плеер читал настройки.

75

Re: Ahk: Управление MPC-HC

Никак не сделаете.

76

Re: Ahk: Управление MPC-HC

svoboden, патчите в памяти программы, если не лень.