Update to a Command Line MP3 Player for Windows

November 23rd, 2020 – It appears that the cmdmp3 software now plays .wav files.  I didn’t do anything special to enable this, so it must pertain to something changing in Windows’ multimedia subsystem.

If the .mp3 functionality works on your machine, you might try playing a .wav.  Now, back to the original blog post.

In 2009, I was tinkering with the Windows multimedia subsystem and I wrote a short program to play MP3 audio files from the command-line ( cmdmp3.exe ).  I created a second program that was a GUI application ( cmdmp3win.exe ) for those who didn’t want the console window to show.

Unfortunately, something about the old Microsoft C compiler that I use seems to trigger various anti-malware programs.

I adapted the two programs so that they would build under the MinGW GCC compiler this morning.

The sources and executable files for these programs can be found at:


The Github repo for the sources is here:


// cmdmp3
// A command-line MP3 player for Windows
// (console-mode version)
// License: MIT / X11
// Copyright (c) 2009, 2015 by James K. Lawless
// jimbo@radiks.net  http://jiml.us
// See http://www.mailsend-online.com/license2015.php
// To build, use the following MinGW command:
//    gcc -o cmdmp3.exe -lwinmm cmdmp3.c

#include <windows.h>
#include <stdio.h>
#include <string.h>

void sendCommand(char *);

int main(int argc,char **argv) {
   char shortBuffer[MAX_PATH];
   char cmdBuff[MAX_PATH + 64];
   printf("cmdmp3 v2.0\n");
   printf("Command-line MP3 player\n");
   printf("by Jim Lawless - http://jiml.us\n\n");

   if(argc<2) {
      fprintf(stderr,"Syntax:\n\tcmdmp3 \"c:\\path to file\\file.mp3\"\n");
      return 1;
      // Get the shortened path because the MCI string interpreter uses spaces
      // as a separator.  If spaces appear in the commands, parts of the filename
      // would be interpreted as paramters to the given command.
   if(!*shortBuffer) {
      fprintf(stderr,"Cannot shorten filename \"%s\"\n",argv[1]);
      return 1;
   sendCommand("Close All");

   sprintf(cmdBuff,"Open %s Type MPEGVideo Alias theMP3",shortBuffer);

   sendCommand("Play theMP3 Wait");
   return 0;

   // Send a string to the Media Control Interface
   // If an error occurs, display it and the string
   // that produced the error.
void sendCommand(char *s) {
   int i;
   if(i) {
         fprintf(stderr,"Error %d when sending %s\n",i,s);

The command line to compile each is as follows:

gcc cmdmp3.c -lwinmm -o cmdmp3.exe

gcc cmdmp3win.c -lwinmm -mwindows -o cmdmp3win.exe

To play an MP3 file with either, enter:

cmdmp3 mp3filename


cmdmp3win mp3filename

About Jim Lawless

I've been programming computers for about 39 years ... 33 of that professionally. I've been a teacher, I've worked as a consultant, and have written articles here and there for publications like Dr. Dobbs Journal, The C/C++ Users Journal, Nuts and Volts, and others.
This entry was posted in Programming and tagged . Bookmark the permalink.

47 Responses to Update to a Command Line MP3 Player for Windows

  1. Myron says:

    Thanks for writing this program. I just started using etmTk, which is a task manager program on Sourceforge, but it doesn’t have built-in functionality to actually play sound files for reminder alerts. Your program did the trick.

  2. ankur says:

    I renamed the executable to play.exe and now I tell my friends that my windows cmd is smarter than theirs as it plays files on typing “play filename.mp3”. Thanks a lot.

  3. GOZARCK says:

    Thank you Jim, i was made it an installer in batch, but The only thing missing was the background music.Now my batch installer is complete.
    thanks again.

  4. Doe says:

    Hey Jim, thanks for writing this tool. I’ve just found that it fails to play mp3 files that have spaces in the filenames every time. I tried some ways like and , just doesn’t work. It shows me this:
    Error 259 when sending Open Walk Away.mp3 Type MPEGVideo Alias theMP3
    Error 263 when sending Play theMP3 Wait

    Do you know how to solve this?

    • Doe says:

      I tried some ways like
      cmdmp3 “Walk Away.mp3”
      cmdmp3 “” “Walk Away.mp3”

    • Jim Lawless says:

      Is it possible that you’re on a volume that does not allow shortened names?

      In the same folder, what output do you see if you type:

      dir /x “walk away.mp3”


      I had used a method in the original code to try to use the shortened version of the filename. Another user said they had luck with using single quotes around the filename. I would have to embed this in a new version ( likely as an option after the filename. )

      • Doe says:

        Thanks for your response!
        The output is like this:(Excuse me for using a Chinese system, but I think you can understand what the text means)
        E:\m\ali>dir /x “walk away.mp3”
        驱动器 E 中的卷是 新加卷
        卷的序列号是 7AF3-FC38

        E:\m\ali 的目录

        2013/09/24 17:03 4,160,288 Walk Away.mp3
        1 个文件 4,160,288 字节
        0 个目录 36,405,497,856 可用字节

        I tried single quotes, but the problem remains. It seems like when I use quotes, cmdmp3 is able to recognize which file to play, yet playing is still unable.

      • Jim Lawless says:

        As I suspected, you’re on a volume that doesn’t allow shortened filenames. I’ll have to add an option to enclose the filename in quotes before passing it into the media interface.

      • Doe says:


      • Jim Lawless says:

        It’ll be a while before I am able to do this. Could you please try the following?

        Consider the filename walk away.mp3

        When you run cmdmp3, please first enclose walk away.mp3 in single-quotes:

        ‘walk away.mp3’

        Then, enclose that entire phrase in double-quotes:

        ” ‘walk away.mp3’ ”

        So that your command reads:

        cmdmp3 ” ‘walk away.mp3’ ”

        (Please do not copy and paste out of this reply as I think the editor will alter some of the dquote characters. )

      • Doe says:

        After I tried this, the output is

        Cannot shorten filename ” ‘walk away.mp3’ “

      • Jim Lawless says:

        OK. I’ll try to make a fix, soon.

  5. Dave H says:

    I’m running Windows 7 and I get the following errors:
    cmdmp3 c:\dogs.mp3

    Error 277 when sending Open C:\dogs.mp3 Type MPEGVideo Alias theMP3
    Error 263 when sending Play theMP3 Wait

    Any idea what might be going on?

  6. Mark says:

    I tried to compile both programs from source by using MinGW. Cmdmp3 and cmdmp3win were successfully compiled. Cmdmp3 works fine, but cmdmp3win isn´t working at all 😦 No matter what mp3 i try to play,a message box explaining the syntax pops up – no playback at all.
    The precompiled cmdmp3win from above works fine…

    Any ideas?

  7. Mark says:

    I am really sorry!

    Used the wrong command line…

    Everything is compiling/working fine now 🙂

  8. Howard Mosley says:

    Yea this isnt working on my windows 10 pro…
    Error 277 when sending Open C:\dogs.mp3 Type MPEGVideo Alias theMP3
    Error 263 when sending Play theMP3 Wait

  9. GGBce says:

    Hi, I appreciated you easy MP3 Reader, but if possible, could you add 2 new options:

    1. A possibility to add an argument option to stop playing at end of the file (cmdmp3.exe /stop myfile.mp3).

    2. Just add an argument for /? or /help to known how typing command 😉

  10. Christoph says:

    Could you add a command to the application to select the Windows Playback device?

    Many Thanks
    Christoph 🙂

    • Jim Lawless says:

      Hi, Christoph. Sorry, but I have no plans to do so at this time. Have you tried other programs/scripts to change the default playback device before calling cmdmp3?

  11. Hi Jim, Thank You for all your efforts! Any way to adjust the volume? My application uses cmdmp3 and winamp together, the only way I can come even close to balancing the output volumes, is to crank winamp full blast but of course then winamp distorts.


    • Jim Lawless says:

      I have no plans to add sound controls to cmdmp3, but there are some other command-line apps that allow you to control the volume. Those could be used in conjunction with cmdmp3. There’s one called SndVol.exe in %windows%\system32 that has a command-line interface, but the documentation I could find seems sparse. There are some other free ones out there that may be easier to use.

  12. Laurent says:

    Hi Jim

    When trying to compile cmdmp3.c, I get the following error :

    D:\Dvpt\SandBox\cmdmp3>gcc -o cmdmp3.exe -lwinmm cmdmp3.c
    C:\Users\Laurent\AppData\Local\Temp\cciI2uDK.o:cmdmp3.c:(.text+0x14c): undefined
    reference to `mciSendStringA@16′
    collect2.exe: error: ld returned 1 exit status

    Here is the gcc version, if it matters :

    D:\Dvpt\SandBox\cmdmp3>gcc -v
    Using built-in specs.
    Target: mingw32
    Configured with: ../src/gcc-6.3.0/configure –build=x86_64-pc-linux-gnu –host=m
    ingw32 –target=mingw32 –with-gmp=/mingw –with-mpfr –with-mpc=/mingw –with-i
    sl=/mingw –prefix=/mingw –disable-win32-registry –with-arch=i586 –with-tune=
    generic –enable-languages=c,c++,objc,obj-c++,fortran,ada –with-pkgversion=’Min
    GW.org GCC-6.3.0-1′ –enable-static –enable-shared –enable-threads –with-dwar
    f2 –disable-sjlj-exceptions –enable-version-specific-runtime-libs –with-libic
    onv-prefix=/mingw –with-libintl-prefix=/mingw –enable-libstdcxx-debug –enable
    -libgomp –disable-libvtv –enable-nls
    Thread model: win32
    gcc version 6.3.0 (MinGW.org GCC-6.3.0-1)

    BTW, libwinmm.a is in the /lib directory :

    C:\MinGW\lib>ls libwinmm*.*


    D:\Dvpt\SandBox\cmdmp3>ld –verbose | grep SEARCH_DIR | tr -s ‘; ‘ \r\n

    So where the catch ? 😉

    Thanks for your help !

    • Jim Lawless says:

      Could you try to compile again adding the -v to the gcc command line…

      gcc -v -o cmdmp3.exe -lwinmm cmdmp3.c

      …and send me the output?

      • Laurent says:

        Hi Jim. Here it is :

        D:\Dvpt\SandBox\cmdmp3>gcc -v -o cmdmp3.exe -lwinmm cmdmp3.c
        Using built-in specs.
        Target: mingw32
        Configured with: ../src/gcc-6.3.0/configure –build=x86_64-pc-linux-gnu –host=m
        ingw32 –target=mingw32 –with-gmp=/mingw –with-mpfr –with-mpc=/mingw –with-i
        sl=/mingw –prefix=/mingw –disable-win32-registry –with-arch=i586 –with-tune=
        generic –enable-languages=c,c++,objc,obj-c++,fortran,ada –with-pkgversion=’Min
        GW.org GCC-6.3.0-1′ –enable-static –enable-shared –enable-threads –with-dwar
        f2 –disable-sjlj-exceptions –enable-version-specific-runtime-libs –with-libic
        onv-prefix=/mingw –with-libintl-prefix=/mingw –enable-libstdcxx-debug –enable
        -libgomp –disable-libvtv –enable-nls
        Thread model: win32
        gcc version 6.3.0 (MinGW.org GCC-6.3.0-1)
        COLLECT_GCC_OPTIONS=’-v’ ‘-o’ ‘cmdmp3.exe’ ‘-mtune=generic’ ‘-march=i586′
        c:/mingw/bin/../libexec/gcc/mingw32/6.3.0/cc1.exe -quiet -v -iprefix c:\mingw\b
        in\../lib/gcc/mingw32/6.3.0/ cmdmp3.c -quiet -dumpbase cmdmp3.c -mtune=generic –
        march=i586 -auxbase cmdmp3 -version -o C:\Users\Laurent\AppData\Local\Temp\ccLjP
        GNU C11 (MinGW.org GCC-6.3.0-1) version 6.3.0 (mingw32)
        compiled by GNU C version 6.3.0, GMP version 6.1.2, MPFR version 3.1.5,
        MPC version 1.0.3, isl version 0.15
        GGC heuristics: –param ggc-min-expand=100 –param ggc-min-heapsize=131072
        ignoring duplicate directory “c:/mingw/lib/gcc/../../lib/gcc/mingw32/6.3.0/inclu
        ignoring nonexistent directory “/mingw/include”
        ignoring duplicate directory “c:/mingw/lib/gcc/../../include”
        ignoring duplicate directory “c:/mingw/lib/gcc/../../lib/gcc/mingw32/6.3.0/inclu
        ignoring duplicate directory “c:/mingw/lib/gcc/../../lib/gcc/mingw32/6.3.0/../..
        ignoring nonexistent directory “/mingw/include”
        #include “…” search starts here:
        #include search starts here:
        End of search list.
        GNU C11 (MinGW.org GCC-6.3.0-1) version 6.3.0 (mingw32)
        compiled by GNU C version 6.3.0, GMP version 6.1.2, MPFR version 3.1.5,
        MPC version 1.0.3, isl version 0.15
        GGC heuristics: –param ggc-min-expand=100 –param ggc-min-heapsize=131072
        Compiler executable checksum: 384cad586f05ed581a9c068b2f18b408
        COLLECT_GCC_OPTIONS=’-v’ ‘-o’ ‘cmdmp3.exe’ ‘-mtune=generic’ ‘-march=i586′
        c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/as.exe -v -o C:\U
        sers\Laurent\AppData\Local\Temp\ccxinGsd.o C:\Users\Laurent\AppData\Local\Temp\c
        GNU assembler version 2.28 (mingw32) using BFD version (GNU Binutils) 2.28
        COLLECT_GCC_OPTIONS=’-v’ ‘-o’ ‘cmdmp3.exe’ ‘-mtune=generic’ ‘-march=i586′
        c:/mingw/bin/../libexec/gcc/mingw32/6.3.0/collect2.exe -plugin c:/mingw/bin/../
        libexec/gcc/mingw32/6.3.0/liblto_plugin-0.dll -plugin-opt=c:/mingw/bin/../libexe
        c/gcc/mingw32/6.3.0/lto-wrapper.exe -plugin-opt=-fresolution=C:\Users\Laurent\Ap
        pData\Local\Temp\ccB4Fr17.res -plugin-opt=-pass-through=-lmingw32 -plugin-opt=-p
        ass-through=-lgcc -plugin-opt=-pass-through=-lgcc_eh -plugin-opt=-pass-through=-
        lmoldname -plugin-opt=-pass-through=-lmingwex -plugin-opt=-pass-through=-lmsvcrt
        -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32 -plugi
        n-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-opt=-p
        ass-through=-lmingw32 -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=
        -lgcc_eh -plugin-opt=-pass-through=-lmoldname -plugin-opt=-pass-through=-lmingwe
        x -plugin-opt=-pass-through=-lmsvcrt -Bdynamic -o cmdmp3.exe c:/mingw/bin/../lib
        /gcc/mingw32/6.3.0/../../../crt2.o c:/mingw/bin/../lib/gcc/mingw32/6.3.0/crtbegi
        n.o -Lc:/mingw/bin/../lib/gcc/mingw32/6.3.0 -Lc:/mingw/bin/../lib/gcc -Lc:/mingw
        /bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/lib -Lc:/mingw/bin/../lib/gcc/
        mingw32/6.3.0/../../.. -lwinmm C:\Users\Laurent\AppData\Local\Temp\ccxinGsd.o -l
        mingw32 -lgcc -lgcc_eh -lmoldname -lmingwex -lmsvcrt -ladvapi32 -lshell32 -luser
        32 -lkernel32 -lmingw32 -lgcc -lgcc_eh -lmoldname -lmingwex -lmsvcrt c:/mingw/bi
        C:\Users\Laurent\AppData\Local\Temp\ccxinGsd.o:cmdmp3.c:(.text+0x14c): undefined
        reference to `mciSendStringA@16’
        collect2.exe: error: ld returned 1 exit status

        Thanks !

      • Jim Lawless says:

        I tried the command-line options (which used to work ages ago) and I received a slightly different error message. However, when I moved the command-line parameters around, things went a little better:

        Please try:

        gcc cmdmp3.c -lwinmm -o cmdmp3.exe

        gcc cmdmp3win.c -lwinmm -mwindows -o cmdmp3win.exe

        Note that this player hasn’t worked for a while on Windows 10. The OS doesn’t go through the multimedia libs to play MP3’s unless you install some codecs to make that happen.

  13. Laurent says:

    Hi Jim – Excellent ! Thanks !

    For the record, I had to use _argv and _argc (not doubled underscore), and add to cmdmp3win.c to make it work.

    Anyway, thanks for your help.

    • Jim Lawless says:

      I have no idea when those parameters became positional … the old format used to work. Yes, I had someone tell me about _argc and _argv a while back, too. I just don’t compile this code any more, so I don’t catch any of these as they break.

  14. David Vere says:

    Thanks, Jim,
    such a simple tool, yet strangely hard to find amid the plelthora of monster applications (wmplayer, winamp, groove, itunes &c)
    Wanted to make the windowless version my default player – but forseeing a problem stopping if I accidentally started the wrong piece, I made the windowed version my default, and adjusted its window to a very small size, just big enough to click and [Ctrl]C as and when required.
    Best tools, do one job, and do it well.

  15. Jim Lawless says:

    Glad to hear it, David. I thought that cmdmp3’s days were numbered when it stopped working on my newer PC, but it continues to work on my other Windows machines running the same version of the OS.

  16. Ron Kierstead says:

    Thanks so much for this valuable little utility.

    I downloaded it, extracted the executable I wanted and copied it to C:\Windows\System32

    Now I can pretend when using git bash on windohs that I really am running a decent machine, although I might have changed the filename to “aplay.exe” just to be consistent over four or five machines.

    aplay angry.wav


    • Jim Lawless says:

      If it’s playing WAV files then it’s not my utility. 😉 I do plan on making a WAV file player equivalent at some point, though.

      • Ron Kierstead says:

        I hate to be that guy… but your utility is playing wav files on my windows box unless some crazy aliasing is working with WSL.

        It plays wav files… Should I create an issue on your github? 😛


      • Jim Lawless says:

        Wow! Sometimes I even amaze myself!

        I’ll have to try this on one of my alternate machines. cmdmp3 won’t run on my primary Windows machine. I have issues on it similar to the ones others describe above.

      • Jim Lawless says:

        You’re right, Ron. It worked. I guess I’ll add the appropriate WAV API call into the source as an option as well as MessageBeep() in the near future. I want to add the appropriate WAV API call so that WAV’s can be played no matter what media drivers have been installed.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s