slloyd has asked for the wisdom of the Perl Monks concerning the following question:

It looks like mciSendString does not work with Windows 7. Instead we are supposed to use mciSendCommand. Problem is that I cannot seem to figure out how to use it. A small example using Win32::API would be wonderful. Thanks.
s/te/ve/

Replies are listed 'Best First'.
Re: Win32::API syntax for mciSendCommand?
by ikegami (Patriarch) on Sep 22, 2010 at 23:10 UTC

    mciSendCommand is actually pretty simple. The tricky part is preparing the structure for its fourth argument, since the structure varies based on the second argument.

    I imagine it would look like the following:

    package MCI; use strict; use warnings; use Encode qw( decode ); use Win32::API qw( ); use constant { # Messages MCI_INFO => 0x80A MCI_RECORD => 0x80F, ... # Flags MCI_NOTIFY => 0x01, MCI_WAIT => 0x02, ... }; my $send_command = Win32::API->new( 'Winmm.dll', 'mciSendCommandW', 'NNNP', 'N', ); sub send_command { my ($device, $msg, $flags, $packed_parms) = @_; my $rv = $send_command->Call($device, $msg, $flags, $packed_parms); return 1 if $rv == 0; die(MCI::Error->new($rv)); } sub info { my ($device, $flags, $win_handle, $max_chars) = @_; $max_chars ||= 256; my $size = $max_chars * 2; my $str_buf = "\0" x $size; # MCI_INFO_PARMS my $packed_params = pack("IPI", $win_handle, $str_buf, $size, ); return undef if !send_command( $device, MCI_INFO, $flags, $packed_params, ); my ($new_size) = unpack("x4x4I", $packed_params); return decode('UCS-2le', substr($str_buf, 0, $new_size)); # Or $ne +w_size-2? } sub record { my ($device, $flags, $win_handle, $from, $to) = @_; # MCI_RECORD_PARMS my $packed_params = pack('III', $win_handle, $from, $to, ); return send_command( $device, MCI_RECORD, $flags, $packed_params, ); } ... 1;
    package MCI::Error; use strict; use warnings; sub new { my ($class, $error) = @_; my $msg = ...mciGetErrorString...; return bless({ code => $error & 0xFFFF, driver_id => $error >> 16, msg => $msg, }, $class); } ... 1;
Re: Win32::API syntax for mciSendCommand?
by Anonymous Monk on Sep 22, 2010 at 21:47 UTC
    Well, the function is described at MSDN like this:
    MCIERROR mciSendCommand(
        MCIDEVICEID IDDevice,
        UINT uMsg,
        DWORD_PTR fdwCommand,
        DWORD_PTR dwParam
    );
    So, naively choosing "long" ("N") for each parameter without looking at the headers to see exactly what things like "MCIDEVICEID" means, I would do something like this:
    Win32::API->Import("winmm", "mciSendCommand", "NNNN", "N") or die $^E; my $result = mciSendCommand($qux, $quux, $quuux, $quuuux);
    If you don't want to import the function into the current namespace, use my $coderef = Win32::API->new("winmm", "mciSendCommand", ...); instead and call like $coderef->(args).

    Now, on my Vista 64-bit system, importing that function works and calling it with all-zero parameters does not result in a crash, so we're on the right track. (Though, those DWORD_PTR arguments may need to be of type "P" -- test and see what works).

    Hope that helps.

      Thanks. I will give it a try.
      s/te/ve/