0

I am trying to play a .mp3 file in python using winmm.dll (ctypes.windll.winmm). But when I try to get a length of some file in milliseconds, instead of actual length (05:23 = about 323000 ms) I get just 3. Time format got by status command is "m", and it doesn't change after set command. Here is some code that illustrates the problem:

from ctypes import windll, c_buffer

fp = 'song.mp3'
alias = 'test'

buf = c_buffer(255)
r = windll.winmm.mciSendStringW(f'open "{fp}" alias {alias}', buf, 254, 0)
print(r)

buf = c_buffer(255)
r = windll.winmm.mciSendStringW(f'status {alias} time format', buf, 254, 0)
print(r, buf.value)

buf = c_buffer(255)
r = windll.winmm.mciSendStringW(f'set {alias} time format milliseconds', buf, 254, 0)
print(r)

buf = c_buffer(255)
r = windll.winmm.mciSendStringW(f'status {alias} time format', buf, 254, 0)
print(r, buf.value)

buf = c_buffer(255)
r = windll.winmm.mciSendStringW(f'status {alias} length', buf, 254, 0)
print(r, buf.value)

And its output:

0
0 b'm'
0
0 b'm'
0 b'3'

Thanks in advance for your help!

Mortasen
  • 117
  • 1
  • 8
  • You have ***Undefined Behavior***. https://stackoverflow.com/questions/58610333/c-function-called-from-python-via-ctypes-returns-incorrect-value/58611011#58611011. – CristiFati Dec 15 '19 at 16:13

1 Answers1

0

As I specified in my comment this is a classic Undefined Behavior example. Check [SO]: C function called from Python via ctypes returns incorrect value (@CristiFati's answer) for more details.
Also, you're mixing 8bit and 16bit strings.

Listing [Python 3.Docs]: ctypes - A foreign function library for Python.

code00.py:

#!/usr/bin/env python3

import sys
import ctypes as ct
from ctypes import wintypes as wt


def main(*argv):
    winmm_dll = ct.WinDLL("Winmm.dll")
    mciSendString  = winmm_dll.mciSendStringW
    mciSendString.argtypes = (wt.LPCWSTR, wt.LPWSTR, wt.UINT, wt.HANDLE)
    mciSendString.restype = wt.DWORD

    file_name = "./SampleAudio_0.4mb.mp3"  # Downloaded from https://www.sample-videos.com/audio/mp3/crowd-cheering.mp3
    alias_name = "test00"
    status_commands = [
        f"status {alias_name} time format",
        f"status {alias_name} length",
    ]

    commands = [f"open \"{file_name}\" alias {alias_name}"]
    commands.extend(status_commands)
    commands.append(f"set {alias_name} time format ms")
    commands.extend(status_commands)
    commands.append(f"close {alias_name}")

    out_buf_len = 0xFF
    out_buf = ct.create_unicode_buffer(out_buf_len)
    for command in commands:
        print(f"Sending {command}...")
        res = mciSendString(command, out_buf, out_buf_len, None)
        print(f"  Result: {res}\n  Output: {out_buf.value}")


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    main(*sys.argv[1:])
    print("\nDone.")

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q059343461]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32

Sending open "./SampleAudio_0.4mb.mp3" alias test00...
  Result: 0
  Output: 1
Sending status test00 time format...
  Result: 0
  Output: milliseconds
Sending status test00 length...
  Result: 0
  Output: 27746
Sending set test00 time format ms...
  Result: 0
  Output:
Sending status test00 time format...
  Result: 0
  Output: milliseconds
Sending status test00 length...
  Result: 0
  Output: 27746
Sending close test00...
  Result: 0
  Output:

Done.
CristiFati
  • 38,250
  • 9
  • 50
  • 87