Thread: [mpg123-users] Win32/64 remote control
Brought to you by:
sobukus
From: Myles <smp...@gm...> - 2015-12-25 03:37:12
|
Hi forum-- I'm trying to use mpg123 -R. I've tried in a cmd window and also via a Ruby script w/ Open3.popen3(). Neither method works. Is this a known limitation/bug? I tried to open a bug ticket on SourceForge, but it says I have to be authorized. And I don't see any authorization request buttons. Thanks, --Myles PS I have remote control working perfectly in Linux. I'm trying to port my application to Windows, but hit the skids here. |
From: Thomas O. <tho...@or...> - 2015-12-25 12:26:02
|
Am Thu, 24 Dec 2015 21:36:44 -0600 schrieb Myles <smp...@gm...>: > Hi forum-- > > I'm trying to use mpg123 -R. I've tried in a cmd window and also via a Ruby > script w/ Open3.popen3(). Are you using a certain win32/win64 binary? Built mpg123 from sources? I was under the impression that only the -C terminal control doesn't work under Windows. I think I remember -R working. What does happen in cmd when starting mpg123 -R? Alrighty then, Thomas |
From: Myles <smp...@gm...> - 2015-12-29 20:50:14
|
Hi Thomas-- Thanks for reply. Sorry for lag, but just getting back from holiday break. Here's what happens: c:\jamskicker\mpg123-1.22.0-x86-64>mpg123.exe -R High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3 version 1.22.0; written and copyright by Michael Hipp and others free software (LGPL) without any warranty but with best wishes @R MPG123 (ThOr) v8 ^C c:\jamskicker\mpg123-1.22.0-x86-64>LOAD 'LOAD' is not recognized as an internal or external command, operable program or batch file. Mpg123 pauses at 'v8', but everything I type is not echo'd nor does anything. But then when I ctrl-C, cmd empties the buffered strokes and tries to interpret them. If this is just due to the (idiotic) vagaries of MS's cmd "interface" and the way stdin/out/err work, I can live with using it via script (Ruby). But I can't get it working from script either. I even tried PowerShell ISE (I'm no expert at PS). PS C:\jamskicker\mpg123-1.22.0-x86> echo "LOAD PossibleDelayed.mp3" | .\mpg123.exe -R I don't want to cast too much blame at MS since things like irb work ok in a cmd window. So I'm pretty sure something is broken in mpg123. I'm not really prepared to build sources on this Windows machine. I've had bad experiences with cygwin/mingw corrupting my windows filesystem (weird permissions that made it nearly impossible to delete files), so I'd rather not put any of that on my work computer. As you can see, I'm using the 1.22.0 build. Thanks again Thomas! --Myles On Fri, Dec 25, 2015 at 6:26 AM Thomas Orgis <tho...@or...> wrote: > Am Thu, 24 Dec 2015 21:36:44 -0600 > schrieb Myles <smp...@gm...>: > > > Hi forum-- > > > > I'm trying to use mpg123 -R. I've tried in a cmd window and also via a > Ruby > > script w/ Open3.popen3(). > > Are you using a certain win32/win64 binary? Built mpg123 from sources? > I was under the impression that only the -C terminal control doesn't > work under Windows. I think I remember -R working. What does happen in > cmd when starting mpg123 -R? > > > Alrighty then, > > Thomas > > ------------------------------------------------------------------------------ > _______________________________________________ > mpg123-users mailing list > mpg...@li... > https://lists.sourceforge.net/lists/listinfo/mpg123-users > |
From: Myles <smp...@gm...> - 2015-12-29 23:06:36
|
Hi again Thomas-- Darn. I was hopeful, but still not working. require 'open3' require 'fileutils' #FileUtils.touch('mpg123.control') File.unlink('mpg123.control') #Open3.popen3('mpg123.exe -R --fifo mpg123.control') do |stdin, stdout, sterr, wait_threads| Open3.pipeline_rw('mpg123.exe -R --fifo mpg123.control') do |stdin, stdout, wait_threads| sleep 1 cmd_term = "\r\n" File.open('mpg123.control', 'w+') do |fh| cmd = "LOAD PossibleDelayed.mp3" puts cmd fh.write "#{cmd}#{cmd_term}" fh.flush end sleep 5 File.open('mpg123.control', 'a') do |fh| cmd = "QUIT" puts cmd fh.write "#{cmd}#{cmd_term}" fh.flush end end Output from above: c:\Git\songmixd\mpg123-1.22.0-x86>ruby remote_control_test.rb High Performance MPEG 1.0/2.0/2.5 Audio Player for Layers 1, 2 and 3 version 1.22.0; written and copyright by Michael Hipp and others free software (LGPL) without any warranty but with best wishes LOAD PossibleDelayed.mp3 QUIT I also tried the commented lines and they didn't work (and a lot of other random stuff I tried). I do see the mpg123.exe process running in the Windows Task Manager GUI. It's just not getting the messages. I should also note that just running: mpg123 PossibleDelayed.mp3 plays the song as expected. Anything else? I'm also open to other alternatives to drive mp3 playback from a Ruby script on Windows. I did some Googling for alternatives and tripped across MP3 Control Server (http://mp3control.sourceforge.net) and skimmed the guy's code and found this: # Open an instance of mpg123, our high-performance mp3 player @@mpg123 = IO::popen("#{@mpg123} -R -", 'r+') :) (meant to be run on Linux obviously). Oh well.... Thanks again, --Myles On Tue, Dec 29, 2015 at 3:17 PM Thomas Orgis <th...@or...> wrote: > (again for the list) > > > Mpg123 pauses at 'v8', but everything I type is not echo'd nor does > > anything. > > Ah, right, the memory comes back: select() doesn't work on win32 > standard input, hence the control interface, running in the same thread > as the decoding, cannot quickly peek stdin for commands. We really > should give you an error in this case. All code for control is built in > and active, but never gets an idea about you having typed anything. > > The communication that works in Windows is using a FIFO. > > mpg123 -R --fifo mpg123.control > > (or some other name, my memory is hazy on the rules for FIFO names on > Windows). Once you connected to mpg123 using that FIFO, the control > works just like STDIN on a Unix box. > > So, the bug here is about extra code to make stdin work (not my me) or > at least a proper error when activating the control interface without a > way that it actually can work. > > > Alrighty then, > > Thomas > > -- > Thomas Orgis - Source Mage GNU/Linux Developer (http://www.sourcemage.org) > OrgisNetzOrganisation ---)=- http://orgis.org > GPG public key 60D5CAFE: http://thomas.orgis.org/public_key > Fingerprint: D021 FF8E CF4B E097 19D6 1A27 231C 4CBC 60D5 CAFE > |
From: Thomas O. <tho...@or...> - 2015-12-29 23:24:35
|
Am Tue, 29 Dec 2015 23:06:19 +0000 schrieb Myles <smp...@gm...>: > Open3.pipeline_rw('mpg123.exe -R --fifo mpg123.control') do |stdin, stdout, > wait_threads| > sleep 1 > cmd_term = "\r\n" > File.open('mpg123.control', 'w+') do |fh| Are you listening on the standard output of mpg123? You're opening a 3-way pipe, yes? Mpg123 could get stuck writing where noone is listing. Can you just start mpg123 independently and just open the FIFO in your program? I have the suspicion that you need to access the FIFO / named pipe differently: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365590%28v=vs.85%29.aspx Under Unix, it's just like opening a regular file, not so on Windows. Alrighty then, Thomas |
From: Myles <smp...@gm...> - 2015-12-29 23:31:12
|
I had already visited the MSDN site at that link thinking just like you (nothing is ever as it seems [it should be] in Windows). I'm running the script like so in a cmd window: ruby remote_control_test.rb My naive expectation is that audio will just start playing (remember, just giving 'mpg123 file.mp3' works on the command line). I also tried launching with rubyw.exe. That didn't work either. You know, I bet you're right. I bet I need to empty (and keep emptying) the stdout pipe to let mpg123 progress. I'm out of time today. I'll try that when I'm back in the saddle again. And if it doesn't work, I'll also try independent launch/write. On Tue, Dec 29, 2015 at 5:24 PM Thomas Orgis <tho...@or...> wrote: > Am Tue, 29 Dec 2015 23:06:19 +0000 > schrieb Myles <smp...@gm...>: > > > Open3.pipeline_rw('mpg123.exe -R --fifo mpg123.control') do |stdin, > stdout, > > wait_threads| > > sleep 1 > > cmd_term = "\r\n" > > File.open('mpg123.control', 'w+') do |fh| > > Are you listening on the standard output of mpg123? You're opening a > 3-way pipe, yes? Mpg123 could get stuck writing where noone is listing. > > Can you just start mpg123 independently and just open the FIFO in your > program? I have the suspicion that you need to access the FIFO / named > pipe differently: > > > https://msdn.microsoft.com/en-us/library/windows/desktop/aa365590%28v=vs.85%29.aspx > > Under Unix, it's just like opening a regular file, not so on Windows. > > > Alrighty then, > > Thomas > |
From: Myles <smp...@gm...> - 2015-12-30 05:26:04
|
I tried launching independently and just writing to it. No dice. I spent a few hours looking at Ruby's win32-pipe gem. I can get their Hello World working. I checked the mpg123 source code. Do you guys prepend \\.pipe\ to the name? That's what the Ruby win32-pipe code does. See here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365588(v=vs.85).aspx LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); And in the Ruby gem: https://github.com/djberg96/win32-pipe/blob/ffi/lib/win32/pipe.rb # Abstract initializer for base class. This handles automatic prepending # of '\\.\pipe\' to each named pipe so that you don't have to. Don't # use this directly. Add the full implementation in subclasses. # # The default pipe mode is PIPE_WAIT. # # The default open mode is FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH. # def initialize(name, pipe_mode = DEFAULT_PIPE_MODE, open_mode = DEFAULT_OPEN_MODE, pipe_buffer_size = DEFAULT_PIPE_BUFFER_SIZE) @name = "\\\\.\\pipe\\" + name And in the server sub-class: https://github.com/djberg96/win32-pipe/blob/ffi/lib/win32/pipe/server.rb def initialize(name, pipe_mode = 0, open_mode = Pipe::ACCESS_DUPLEX, pipe_buffer_size = DEFAULT_PIPE_BUFFER_SIZE) super(name, pipe_mode, open_mode, pipe_buffer_size) @pipe = CreateNamedPipe( @name, @open_mode, @pipe_mode, PIPE_UNLIMITED_INSTANCES, pipe_buffer_size, pipe_buffer_size, PIPE_TIMEOUT, nil ) mpg123 code: int win32_fifo_mkfifo(const char *path) { HANDLE ret; win32_fifo_close(); #ifdef WANT_WIN32_UNICODE wchar_t *str; if(win32_utf8_wide(path,&str,NULL) == 0) { fprintf(stderr,"Cannot get FIFO name, likely out of memory\n"); return -1; } #if (DEBUG == 1) fwprintf(stderr,L"CreateNamedPipeW %ws\n", str); #endif ret = CreateNamedPipeW(str,PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE,1,255,255,0,NULL); free(str); #else #if (DEBUG == 1) fprintf(stderr,"CreateNamedPipeA %s\n", path); #endif ret = CreateNamedPipeA(path,PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,PIPE_TYPE_BYTE,1,255,255,0,NULL); #endif /* WANT_WIN32_UNICODE */ if(ret == INVALID_HANDLE_VALUE) return -1; fifohandle = ret; /* Wait for client */ ConnectNamedPipe(fifohandle,&ov1); WaitForSingleObjectEx(fifohandle,INFINITE,TRUE); return 0; } #endif /* WANT_WIN32_FIFO */ On Tue, Dec 29, 2015 at 5:30 PM Myles <smp...@gm...> wrote: > I had already visited the MSDN site at that link thinking just like you > (nothing is ever as it seems [it should be] in Windows). I'm running the > script like so in a cmd window: > > ruby remote_control_test.rb > > My naive expectation is that audio will just start playing (remember, just > giving 'mpg123 file.mp3' works on the command line). I also tried launching > with rubyw.exe. That didn't work either. > > You know, I bet you're right. I bet I need to empty (and keep emptying) > the stdout pipe to let mpg123 progress. I'm out of time today. I'll try > that when I'm back in the saddle again. And if it doesn't work, I'll also > try independent launch/write. > > > On Tue, Dec 29, 2015 at 5:24 PM Thomas Orgis <tho...@or...> > wrote: > >> Am Tue, 29 Dec 2015 23:06:19 +0000 >> schrieb Myles <smp...@gm...>: >> >> > Open3.pipeline_rw('mpg123.exe -R --fifo mpg123.control') do |stdin, >> stdout, >> > wait_threads| >> > sleep 1 >> > cmd_term = "\r\n" >> > File.open('mpg123.control', 'w+') do |fh| >> >> Are you listening on the standard output of mpg123? You're opening a >> 3-way pipe, yes? Mpg123 could get stuck writing where noone is listing. >> >> Can you just start mpg123 independently and just open the FIFO in your >> program? I have the suspicion that you need to access the FIFO / named >> pipe differently: >> >> >> https://msdn.microsoft.com/en-us/library/windows/desktop/aa365590%28v=vs.85%29.aspx >> >> Under Unix, it's just like opening a regular file, not so on Windows. >> >> >> Alrighty then, >> >> Thomas >> > |
From: Thomas O. <tho...@or...> - 2015-12-30 09:46:15
|
Am Wed, 30 Dec 2015 05:25:46 +0000 schrieb Myles <smp...@gm...>: > I checked the mpg123 source code. Do you guys prepend \\.pipe\ to the name? > That's what the Ruby win32-pipe code does. > > See here: > https://msdn.microsoft.com/en-us/library/windows/desktop/aa365588(v=vs.85).aspx > > LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); Nope, see http://scm.orgis.org/view/mpg123/tags/1.22.0/src/win32_support.c?revision=3595 . We just use the name you provide. You have to specify the full thing. Alrighty then, Thomas |
From: Myles <smp...@gm...> - 2015-12-30 15:16:13
|
GOT IT!! mpg123 -R --fifo \\.\pipe\foo require 'win32/pipe' include Win32 pipe_client = Pipe::Client.new("foo") pipe_client.write("LOAD PossibleDelayed.mp3\n") pipe_client.close More than I ever... ever... wanted to know about IPC in Windows. Looking back on the experience, wouldn't it be best if mpg123 offered a TCP socket-based interface instead? Ie, something that's more standard across the Big3 platforms? Thanks Thomas!! --Myles On Wed, Dec 30, 2015 at 3:46 AM Thomas Orgis <tho...@or...> wrote: > Am Wed, 30 Dec 2015 05:25:46 +0000 > schrieb Myles <smp...@gm...>: > > > I checked the mpg123 source code. Do you guys prepend \\.pipe\ to the > name? > > That's what the Ruby win32-pipe code does. > > > > See here: > > > https://msdn.microsoft.com/en-us/library/windows/desktop/aa365588(v=vs.85).aspx > > > > LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); > > Nope, see > > > http://scm.orgis.org/view/mpg123/tags/1.22.0/src/win32_support.c?revision=3595 > > . We just use the name you provide. You have to specify the full thing. > > > Alrighty then, > > Thomas > |
From: Thomas O. <tho...@or...> - 2015-12-31 10:27:03
|
Am Wed, 30 Dec 2015 15:15:57 +0000 schrieb Myles <smp...@gm...>: > GOT IT!! Good. You know, this Windows thing is usable after all, after you read a lot of docs and ask random people in the net;-) > wouldn't it be best if mpg123 offered a TCP > socket-based interface instead? Ie, something that's more standard across > the Big3 platforms? You know, that is a really funny arc there. I started working on mpg123 to modify its remote control interface to better integrate into a music playing daemon that is controlled via TCP. Later I created libmpg123 and my daemon is using that instead. While the approach with the separate binary worked nicely, it was also more of a learning experience writing the multithreaded code that communicates with said binary via all 3 streams (stdin for commands, stdout for data, stderr for responses). Using the decoding library is much simpler if you don't need the controlled program to handle audio output. I have the impression that this is actually the hard part for people: Writing a program that handles the timing of decoding audio and feeding it to a playback device, while still doing other stuff. A TCP-controlled daemon makes this easier, like any OS API for "play this audio file", sure. While it is entirely possible to shoehorn TCP into the control interface, too, I hesitate to turn mpg123 into a network server. It used to be an innocent tool to decode MPEG audio files on your computer. Also, I guess the TCP API for Windows is different from POSIX so that there would be effort for porting by one of our Windows people in various states of being busy. It is interesting that demand for mpg123 being more of a media framework keeps popping up. After all, there are toolkits to help you adding audio/video to your application, like Gstreamer … or JACK, even Pulseaudio. The mpg123 application has a funny feature set that grew over time to support several niche applications. You could consider it a result of evolution formed by emerging use cases triggering an assortment of hacks (like our own HTTP client code!) as opposed to a kind of intelligent design. Well, evolution proved to be quite successful over some billion years (on this or other planets;-). Maybe mpg123 also has a good deal of fitness for survival with all its warts and the odd limb here or there compared to all the software that is designed to do the things that it does, but properly. I need to keep that in mind when restructuring parts of mpg123 into reusable libraries like libmpg123. There is libout123 in the upcoming 1.23 release, and I'm contemplating adding an input library to match that, wrapping over libmpg123 and others to support simple playback of more formats. I am annoyed at times that mpg123 doesn't know how to play WAV files even if it produces them. Linking in libsndfile to handle this and similar formats is just too easy. Considering the evolutionary nature of mpg123 features, I guess I should also include mpg123's naive HTTP code in that library, like I included the output buffer in libout123. It's by no means a proper HTTP client, but it is enough code to get some streaming audio from the web. This is all in contrast with using other full-featured programs and libraries, but I guess this is actually a dedicated niche: Provide a certain audio playback feature set with rather small code size and minimal dependencies to external code. But, to get back to the point, I have to think hard about that before adding TCP server support. With that I'm getting into the territory of http://dermixd.de/, the project that actually got me into maintaining mpg123 many years ago. Alrighty then, Thomas |
From: Myles <smp...@gm...> - 2015-12-31 05:56:53
|
Me again. Now that I have remote-control figured out, on to the next problem. I need to process the stdout/stderr on the fly. Windows is, yet again, ridiculous when it comes to how mysteriously IO processing works when a process is launched from a script. I've decided it's probably best to just run mpg123 in the background and send its output to an intermediate file, and then read that file from the parent process. This very nearly works: pid = Process.spawn("mpg123.exe -v -R --fifo \\\\.\\pipe\\foo", { [:out, :err] => 'mpg123.out' } ) sleep 10 Process.kill "INT", pid exit However, there's nothing in mpg123.out *until* the process is INT'd. Ie, it's getting buffered. I see this in mpg123 code: if (param.remote_err) outstream = stderr; else outstream = stdout; fprintf(outstream, "@R MPG123 (ThOr) v8\n"); Would it be possible to have outstream set to unbuffered? Either by default, or via an option? Or do I need to create my own build of mpg123? Or would unbuffering and/or fflush'ing not even work? Thanks! --Myles On Wed, Dec 30, 2015 at 9:15 AM Myles <smp...@gm...> wrote: > GOT IT!! > > mpg123 -R --fifo \\.\pipe\foo > > require 'win32/pipe' > include Win32 > pipe_client = Pipe::Client.new("foo") > pipe_client.write("LOAD PossibleDelayed.mp3\n") > pipe_client.close > > More than I ever... ever... wanted to know about IPC in Windows. Looking > back on the experience, wouldn't it be best if mpg123 offered a TCP > socket-based interface instead? Ie, something that's more standard across > the Big3 platforms? > > Thanks Thomas!! > --Myles > > On Wed, Dec 30, 2015 at 3:46 AM Thomas Orgis <tho...@or...> > wrote: > >> Am Wed, 30 Dec 2015 05:25:46 +0000 >> schrieb Myles <smp...@gm...>: >> >> > I checked the mpg123 source code. Do you guys prepend \\.pipe\ to the >> name? >> > That's what the Ruby win32-pipe code does. >> > >> > See here: >> > >> https://msdn.microsoft.com/en-us/library/windows/desktop/aa365588(v=vs.85).aspx >> > >> > LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); >> >> Nope, see >> >> >> http://scm.orgis.org/view/mpg123/tags/1.22.0/src/win32_support.c?revision=3595 >> >> . We just use the name you provide. You have to specify the full thing. >> >> >> Alrighty then, >> >> Thomas >> > |
From: Thomas O. <tho...@or...> - 2015-12-31 10:40:20
|
Am Thu, 31 Dec 2015 05:56:36 +0000 schrieb Myles <smp...@gm...>: > I've decided it's probably best > to just run mpg123 in the background and send its output to an intermediate > file, and then read that file from the parent process. I don't think that this is an appoach that will make you happy. Creating a temporary file for transient messages between programs (as opposed to a named pipe wich does not actually store data on disk) is a kludge that should be avoided. > However, there's nothing in mpg123.out *until* the process is INT'd. Ie, > it's getting buffered. Yes, on multiple levels, perhaps. Normally, when you use Open3, the stdout of mpg123 would also be buffered. I'd recommend to use --remote-err and read the messages from stderr, as that _should_ be unbuffered. A random source on the web suggests that it might be not that simple: http://www.aps.anl.gov/epics/tech-talk/2014/msg00149.php . > Would it be possible to have outstream set to unbuffered? As I said, this should be the case with --remote-err, but in redirecting that to a file, I presume that this might enable caching again. Not sure at all, you might try, Note that even buffered stdout works nicely for me in a quick test with shell$ mpg123 -R | cat . I see all lines right away (actually wondering about hat, remember this differently for other systems where I had to use expect's unbuffer command). > default, or via an option? Or do I need to create my own build of mpg123? > Or would unbuffering and/or fflush'ing not even work? At least using --remote-err in Open3 should give you the messages right away. It _might_ work with redirecting to the file, too, but I don't know. Alrighty then, Thomas |
From: Myles <smp...@gm...> - 2015-12-31 15:12:36
|
I have to run (literally; marathon coming up in a few weeks), but I wanted to give stderr a try before I left. Naturally, it didn't work. It always comes back to "Microsoft, in their infinite wisdom, did it differently". https://sourceware.org/ml/gdb-patches/2013-08/msg00422.html Also, ISO C (C99/TC3/N1256, 7.19.3 Files, point 7) says: "As initially opened, the standard error stream is not fully buffered; the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device." Note that stderr might be either unbuffered or line buffered, but _never_ fully buffered. And most implementations default to leaving stderr always unbuffered (so that error output comes out immediately). However, the Windows runtime, in its infinite wisdom, makes stderr fully buffered if connected to a pipe. So all this makes me very much question the desire to detect if a native Win32 GDB is running under Cygwin. I want to talk about what I'm doing with mpg123 to see what you think is the best direction to go. I should mention, I already have mpg123 working *perfectly* with my Ruby code on an RPi2 feeding audio into my music listening amplifier. I'm trying to port the *working* code to Windows and I've unloaded a few clips of finger-gun into my head in the process -- all over the remote control. I'm not above creating an FFI interface to libmpg123 and taking direct control instead of (the always annoying on Windows) IPC. Or taking a completely different approach. Well, let me hammer it out in a nutshell. I'm using the Ruby script to construct a playlist and feed song files to mpg123. That Ruby script will, in the future, be controlled via web browser and Node.js IPC (I already have the Node<->Ruby socket interface working on Windows and li/unix). And all bidirectional. So: <---> mpg123 ----> sound-device-on-host-OS Ruby <----> Node.js <------> socket.io <-----> browser So the html will have simple stuff like "now playing" display and a play/pause button. Eventually it will be a lot more complex with the wondrous ideas in my head :), but before going there, I'm trying to get all the communication pipes working. And the kicker is that I'd *like* to get it working on Windows. It's almost as much a quest as anything since *my* usage will be via RPi2/Raspbian. But eventually, I'd like to package it up as a "service" on Windows (I have the Ruby daemonized on my linux version). More later, but got to get my miles.... Thanks again and again Thomas! On Thu, Dec 31, 2015 at 4:40 AM Thomas Orgis <tho...@or...> wrote: > Am Thu, 31 Dec 2015 05:56:36 +0000 > schrieb Myles <smp...@gm...>: > > > I've decided it's probably best > > to just run mpg123 in the background and send its output to an > intermediate > > file, and then read that file from the parent process. > > I don't think that this is an appoach that will make you happy. > Creating a temporary file for transient messages between programs (as > opposed to a named pipe wich does not actually store data on disk) is a > kludge that should be avoided. > > > However, there's nothing in mpg123.out *until* the process is INT'd. Ie, > > it's getting buffered. > > Yes, on multiple levels, perhaps. Normally, when you use Open3, the > stdout of mpg123 would also be buffered. I'd recommend to use > --remote-err and read the messages from stderr, as that _should_ be > unbuffered. A random source on the web suggests that it might be not > that simple: http://www.aps.anl.gov/epics/tech-talk/2014/msg00149.php . > > > > Would it be possible to have outstream set to unbuffered? > > As I said, this should be the case with --remote-err, but in > redirecting that to a file, I presume that this might enable caching > again. Not sure at all, you might try, > > Note that even buffered stdout works nicely for me in a quick test with > > shell$ mpg123 -R | cat > > . I see all lines right away (actually wondering about hat, remember > this differently for other systems where I had to use expect's unbuffer > command). > > > default, or via an option? Or do I need to create my own build of mpg123? > > Or would unbuffering and/or fflush'ing not even work? > > At least using --remote-err in Open3 should give you the messages right > away. It _might_ work with redirecting to the file, too, but I don't know. > > > Alrighty then, > > Thomas > |
From: Myles <smp...@gm...> - 2016-01-01 03:55:22
|
www.maracuya-jukebox.com Very impressive Marek! We're going to have to work on your taste in music though ;). The "magic" in what I'm trying to create is an interface that allows creating playlists according to "profiles" that act upon your entire music collection. I have all kinds of ideas to make them malleable. For example, let's say I want to random shuffle all 4000 of my prog-rock library, but I want to mix in anything from OSI at 3x the rate of everything else. That kind of stuff, but a whole lot more. I've never found a music player that lets me play my big bucket of mp3's just the way I'd like to hear them. For another example, I'm hearing a Transatlantic song during my full library shuffle. I pull out my pad/phone and hit one or two buttons to play just that album, one time (or twice, or...), unshuffled, and then go right back to the big-library-shuffle when it's done (ie, an "instant temporary profile"). And on and on... Found The Holy Grail!! (or so I thought, read on) When I composed the Google search that found this link, I didn't even include "Ruby". That was just a happy coincidence :). It's funny how far down the same path me and this other poor guy have gone. I haven't even absorbed what the magic bean is yet. I'll give it a try and report back. CAN YOU BELIEVE how hard it is to guide IO streams in Windows? Jeez, what a bunch of idiots working there. Apple made a stroke of pure genius (and obviousness) to put all their eggs in the Unix basket. I'm not an Apple fan, but I will always take my hat off to them for staking their future on something that was NIH. http://blog.x-aeon.com/2011/12/19/how-to-pilot-external-processes-stdin-and-stdout-in-real-time-using-ruby/ "I hope this will help other people by avoiding them the 2 headache days I got to come up with this solution!" Too late :). I'm coming up on 2 days myself.. :(. Didn't work. I'm able to read the stream of output (ie, the @F frame output updates), but only in blocks of whatever the Windows pipe buffer size is (4K I think). I could live with that, except I always get left hanging waiting for that last piece of output that hasn't filled the buffer. I presently rely on that. With a little fancy footwork, my working-linux version launches the next LOAD perfectly timed with the end of a currently playing song. It's virtually gapless. So I need to get the output no worse than line-buffered. The internet is absolutely awash with people having this same problem. And there is NO answer. Microsoft gives the parent process no control over turning buffering on/off, setting block or line buffering, the size of the buffer... NOTHING. And you can't create a pseudo-tty to trick the child process into thinking it's being run from a cmd.exe window (line buffered). And you can't "push" a flush request upstream. How do I submit an enhancement request to Microsoft (har har)? So!, looks like I'm going to have to re-build mpg123 and add flushing to the output. If I get it working ok, might it be absorbed as a new feature (--force-line-flush, or something like that). Wish me luck! On Thu, Dec 31, 2015 at 3:11 PM Myles <smp...@gm...> wrote: > Very impressive Marek! We're going to have to work on your taste in music > though ;). However, the "magic" in what I'm trying to create is an > interface that allows creating playlists according to "profiles" that act > upon your entire music collection. I have all kinds of ideas to make them > malleable. For example, let's say I want to random shuffle all 4000 of my > prog-rock library, but I want to mix in anything from OSI at 3x the rate of > everything else. That kind of stuff, but a whole lot more. I've never found > a music player that lets me play my big bucket of mp3's just the way I'd > like to hear them. And with the flexibility to, for another example, I'm > hearing a Transatlantic song during my full library shuffle. I pull out my > pad/phone and hit one or two buttons to play just that album, one time, > unshuffled, and then go right back to the big-library-shuffle when it's > done. And on and on... > > Yep. Marek picked up on my debilitating love of Ruby :). Life is difficult > when you love a language so much you loath the thought of writing anything > else. That said, I had a weird disinterest in learning Rails for this > project. It's my first "web app", so I wanted to do what the Romans do. No > way I was going to get away from learning JavaScript if I'm in Rome. So I > read a million web framework Hello Worlds and gravitated to Node/socket.io. > Don't get me started on how much I hate Python (as compared to Ruby) :). > > The Holy Grail!! When I composed the Google search that found this link, I > didn't even include "Ruby". That was just a happy coincidence :). It's > funny how far down the same path me and this other poor guy have gone. I > haven't even absorbed what the magic bean is yet. I'll give it a try and > report back. CAN YOU BELIEVE how hard it is to guide IO streams in Windows? > Jeez, what a bunch of idiots working there. Apple made a stroke of pure > genius (and obviousness) to put all their eggs in the Unix basket. I'm not > an Apple fan, but I will always take my hat off to them for staking their > future on something that was NIH. > > > http://blog.x-aeon.com/2011/12/19/how-to-pilot-external-processes-stdin-and-stdout-in-real-time-using-ruby/ > > "I hope this will help other people by avoiding them the 2 headache > days I got to come up with this solution!" > > Too late :). I'm coming up on 2 days myself... > > On Thu, Dec 31, 2015 at 9:26 AM Marek Będkowski <ma...@be...> > wrote: > >> Hi Myles >> >> Seems like you're trying to do smth similar I did last year, maybe you >> can have a look. I took the same path in the beginning - trying to pipe >> everything to the mpg123 but eventually this seemed like a dead end to me >> so I wrote integration for nodes called node-mpg123n and integrated it into >> my project. >> >> You can visit my projects website: www.maracuya-jukebox.com and source >> code on github: https://github.com/bendi/maracuya-jukebox >> >> Yes I know you're Ruby fan but hopefully you can take some inspiration >> from my work :) >> >> Marek >> 2015-12-31 16:12 GMT+01:00 Myles <smp...@gm...>: >> >>> I have to run (literally; marathon coming up in a few weeks), but I >>> wanted to give stderr a try before I left. Naturally, it didn't work. It >>> always comes back to "Microsoft, in their infinite wisdom, did it >>> differently". >>> >>> >>> https://sourceware.org/ml/gdb-patches/2013-08/msg00422.html >>> >>> Also, ISO C (C99/TC3/N1256, 7.19.3 Files, point 7) says: "As initially >>> opened, the standard error stream is not fully buffered; the standard input >>> and standard output streams are fully buffered if and only if the stream >>> can be determined not to refer to an interactive device." Note that stderr >>> might be either unbuffered or line buffered, but _never_ fully buffered. >>> And most implementations default to leaving stderr always unbuffered (so >>> that error output comes out immediately). However, the Windows runtime, in >>> its infinite wisdom, makes stderr fully buffered if connected to a pipe. So >>> all this makes me very much question the desire to detect if a native Win32 >>> GDB is running under Cygwin. >>> >>> I want to talk about what I'm doing with mpg123 to see what you think is >>> the best direction to go. I should mention, I already have mpg123 working >>> *perfectly* with my Ruby code on an RPi2 feeding audio into my music >>> listening amplifier. I'm trying to port the *working* code to Windows and >>> I've unloaded a few clips of finger-gun into my head in the process -- all >>> over the remote control. >>> >>> I'm not above creating an FFI interface to libmpg123 and taking direct >>> control instead of (the always annoying on Windows) IPC. Or taking a >>> completely different approach. >>> >>> Well, let me hammer it out in a nutshell. I'm using the Ruby script to >>> construct a playlist and feed song files to mpg123. That Ruby script will, >>> in the future, be controlled via web browser and Node.js IPC (I already >>> have the Node<->Ruby socket interface working on Windows and li/unix). And >>> all bidirectional. So: >>> >>> <---> mpg123 ----> sound-device-on-host-OS >>> Ruby >>> <----> Node.js <------> socket.io <-----> browser >>> >>> So the html will have simple stuff like "now playing" display and a >>> play/pause button. Eventually it will be a lot more complex with the >>> wondrous ideas in my head :), but before going there, I'm trying to get all >>> the communication pipes working. And the kicker is that I'd *like* to get >>> it working on Windows. It's almost as much a quest as anything since *my* >>> usage will be via RPi2/Raspbian. But eventually, I'd like to package it up >>> as a "service" on Windows (I have the Ruby daemonized on my linux version). >>> >>> More later, but got to get my miles.... >>> >>> Thanks again and again Thomas! >>> >>> On Thu, Dec 31, 2015 at 4:40 AM Thomas Orgis <tho...@or...> >>> wrote: >>> >>>> Am Thu, 31 Dec 2015 05:56:36 +0000 >>>> schrieb Myles <smp...@gm...>: >>>> >>>> > I've decided it's probably best >>>> > to just run mpg123 in the background and send its output to an >>>> intermediate >>>> > file, and then read that file from the parent process. >>>> >>>> I don't think that this is an appoach that will make you happy. >>>> Creating a temporary file for transient messages between programs (as >>>> opposed to a named pipe wich does not actually store data on disk) is a >>>> kludge that should be avoided. >>>> >>>> > However, there's nothing in mpg123.out *until* the process is INT'd. >>>> Ie, >>>> > it's getting buffered. >>>> >>>> Yes, on multiple levels, perhaps. Normally, when you use Open3, the >>>> stdout of mpg123 would also be buffered. I'd recommend to use >>>> --remote-err and read the messages from stderr, as that _should_ be >>>> unbuffered. A random source on the web suggests that it might be not >>>> that simple: http://www.aps.anl.gov/epics/tech-talk/2014/msg00149.php . >>>> >>>> >>>> > Would it be possible to have outstream set to unbuffered? >>>> >>>> As I said, this should be the case with --remote-err, but in >>>> redirecting that to a file, I presume that this might enable caching >>>> again. Not sure at all, you might try, >>>> >>>> Note that even buffered stdout works nicely for me in a quick test with >>>> >>>> shell$ mpg123 -R | cat >>>> >>>> . I see all lines right away (actually wondering about hat, remember >>>> this differently for other systems where I had to use expect's unbuffer >>>> command). >>>> >>>> > default, or via an option? Or do I need to create my own build of >>>> mpg123? >>>> > Or would unbuffering and/or fflush'ing not even work? >>>> >>>> At least using --remote-err in Open3 should give you the messages right >>>> away. It _might_ work with redirecting to the file, too, but I don't >>>> know. >>>> >>>> >>>> Alrighty then, >>>> >>>> Thomas >>>> >>> >>> >>> ------------------------------------------------------------------------------ >>> >>> _______________________________________________ >>> mpg123-users mailing list >>> mpg...@li... >>> https://lists.sourceforge.net/lists/listinfo/mpg123-users >>> >>> |
From: Thomas O. <tho...@or...> - 2016-01-01 10:45:00
|
Am Fri, 01 Jan 2016 03:55:04 +0000 schrieb Myles <smp...@gm...>: > […] For another example, I'm hearing a Transatlantic song > during my full library shuffle. I pull out my pad/phone and hit one or two > buttons to play just that album, one time […] Interesting idea for runtime playlist management. > working-linux version launches the next LOAD perfectly timed with the end > of a currently playing song. It's virtually gapless. So I need to get the > output no worse than line-buffered. I see a useful feature that I might just add for those situations; having to time the LOAD command to make it "virtually gapless" doesn't really cut it when I worked so hard for proper gapless playback in mpg123. I imagine a command to enqueue the next file to load once this one finishes, LOADNEXT or such. Getting exact timing out of piped commands will always be tricky. > So!, looks like I'm going to have to re-build mpg123 and add flushing to > the output. If I get it working ok, might it be absorbed as a new feature > (--force-line-flush, or something like that). Wish me luck! Well, a first hack would be to add flushing to generic_sendmsg() in control_generic.c (first function in file): void generic_sendmsg (const char *fmt, ...) { va_list ap; fprintf(outstream, "@"); va_start(ap, fmt); vfprintf(outstream, fmt, ap); va_end(ap); fprintf(outstream, "\n"); fflush(outstream); /* Ensure timely appearance of message. */ } (wondering if I should reduce it to one printf call using a copy of fmt there, too) Just add that line in a downloaded source tarball (with generated configure script) and try to build things in MinGW32 shell using windows-builds.sh or plain ./configure && make. I am wondering if that fflush() would hurt if it's always there, not even bothering for a command line switch. Alrighty then, Thomas |
From: Myles <smp...@gm...> - 2016-01-01 17:39:07
|
Yes! I have been considering requesting a remote-controlled queue since I first started working with the remote interface, with my main goal being to get *truly* gapless playback. If I can't listen to DSotM in gapless perfection, then what's the point of all of this :)??!! I work in Electrical Engineering simulation software support. When my customers have a problem, we usually have to do two things, 1) devise the enhancement for the long term, and 2) get them through the day with a workaround. So we should (probably) have both now. Enhancement ========== QUEUE_ADD(or PUSH?), QUEUE_CLEAR, QUEUE_READ, QUEUE_POP. PLAY will start the queue rolling. STOP should eject the currently playing song. So "queue next" would be achieved with STOP then PLAY. QUEUE_POP would remove the next item waiting in the queue (but not affect what's currently playing). I don't think I need POP, but it should probably be there for completeness. Once a song is playing, it is free and clear of the QUEUE. Only PAUSE/STOP will control it. That's my first pass it. What did I miss? Get me through the day ================= Add flushing and re-build. I may have time to try it tonight. Can I use MinGW, or should I use MSVC? I can't imagine why fflushing() every line would hurt performance and/or power consumption in any application. The only time it will really come into play is when @F's start flying out. And someone that is sensitive to it can always make it SILENT. I would just push it out there and see if anyone complains. But let's make sure it works first. I bet Microsoft still has a few more tricks up their sleeve. On Fri, Jan 1, 2016 at 4:44 AM Thomas Orgis <tho...@or...> wrote: > Am Fri, 01 Jan 2016 03:55:04 +0000 > schrieb Myles <smp...@gm...>: > > > […] For another example, I'm hearing a Transatlantic song > > during my full library shuffle. I pull out my pad/phone and hit one or > two > > buttons to play just that album, one time […] > > Interesting idea for runtime playlist management. > > > working-linux version launches the next LOAD perfectly timed with the end > > of a currently playing song. It's virtually gapless. So I need to get the > > output no worse than line-buffered. > > I see a useful feature that I might just add for those situations; > having to time the LOAD command to make it "virtually gapless" doesn't > really cut it when I worked so hard for proper gapless playback in > mpg123. I imagine a command to enqueue the next file to load once this > one finishes, LOADNEXT or such. Getting exact timing out of piped > commands will always be tricky. > > > So!, looks like I'm going to have to re-build mpg123 and add flushing to > > the output. If I get it working ok, might it be absorbed as a new feature > > (--force-line-flush, or something like that). Wish me luck! > > Well, a first hack would be to add flushing to generic_sendmsg() in > control_generic.c (first function in file): > > void generic_sendmsg (const char *fmt, ...) > { > va_list ap; > fprintf(outstream, "@"); > va_start(ap, fmt); > vfprintf(outstream, fmt, ap); > va_end(ap); > fprintf(outstream, "\n"); > fflush(outstream); /* Ensure timely appearance of message. */ > } > > (wondering if I should reduce it to one printf call using a copy of fmt > there, too) > > Just add that line in a downloaded source tarball (with generated > configure script) and try to build things in MinGW32 shell using > windows-builds.sh or plain ./configure && make. > > I am wondering if that fflush() would hurt if it's always there, not > even bothering for a command line switch. > > > Alrighty then, > > Thomas > |
From: Thomas O. <tho...@or...> - 2016-01-01 18:43:56
|
Am Fri, 01 Jan 2016 17:38:50 +0000 schrieb Myles <smp...@gm...>: > Enhancement > ========== > QUEUE_ADD(or PUSH?), QUEUE_CLEAR, QUEUE_READ, QUEUE_POP. The question I see is the one between a local hack of simply having exactly one slot for a following track or enabling full management of the playlist. The existing playlist code in mpg123, which obviously(?) should be re-used, is designed for one-time creation and optional shuffling of a list. Some care is needed when turning this into something dynamic. I'm also thinking about the funky option of LOADing a playlist file. Btw., with my music playing daemon that uses mpg123 code for decoding, I opted not to integrate playlist management at all. Instead it offers gapless playback via multiple mixer channels (a channel with a track each), where the end of one track triggers seamless start of another one. This got extended into a general scripting mechanism that allows to start/stop tracks based on certain time stamps of reference tracks. The main points was to keep string management associated with playlists out of the C/C++ code … for sure, it has its own complexity. Talk about possible mpg123 extensions occuring means I perhaps should really just get a release of the current important changes in trunk before muddying the waters further. I was contemplating creation of a decoder wrapper library to enable mpg123 to read some more file types, as ironic as that may seem. Simply too much work went into those funny generic audio player features to not being able to even play back the WAV files mpg123 itself produces. To hash out my current idea: 1. release of mpg123 1.23.0 (celebrate that number after missing 1.2.3;-) with libout123, reworked terminal UI, lots of little bug fixes, among those proper clipping for ARM) 2. work on mpg123 2.0.0 with code cleanup, multiple input formats via input library combining libmpg123 with others (basically libsndfile+libmpg123 … perhaps including mpg123's funny HTTP client and playlist code, too) The reworked playlist management including runtime modification of it would be part of step 2, after deciding if playlist parsing and management should be part of that new lib. Actually, it could be interesting to have a whole album (playlist) abstracted as a single file by that lib. This used to be tricky with MPEG audio files before libmpg123 introduced sample-accurate access to them. Well, I guess you get the picture that the proper solution is not coming right away (unless in form of a local hack for separate playlist in control_generic.c). > Get me through the day > ================= > Add flushing and re-build. I may have time to try it tonight. Can I > use MinGW, or should I use MSVC? MinGW is the primary platform that mpg123 is built with on Windows systems. With MSVC, there are only project files to get the libmpg123 DLL, not the whole application. > I can't imagine why fflushing() > every line would hurt performance and/or power consumption in any > application. Yeah, since it even should be a noop when called after each line on _normal_ systems. As long as I have one fprintf for a single character in there, I should not worry of the performance of a single additional function call;-) > complains. But let's make sure it works first. I bet Microsoft still > has a few more tricks up their sleeve. Yes, waiting for your results. If it helps, we could add it with #ifdef WIN32, maybe even without that. Alrighty then, Thomas |
From: Myles <smp...@gm...> - 2016-01-02 22:01:31
|
Progress report: Hurray! Note: Please do not forget to copy the libltdl DLL from MSYS to the dynamic build directories... So I have a successful compilation on Windows. Of course, it wasn't quite as easy as it should've been, but it never is, eh?? Hopefully tonight I'll muster up the energy to make the simple edit, recompile, and test. If not tonight, then definitely tomorrow... (57 miles in 5 days, so energy is running low) On Fri, Jan 1, 2016 at 12:43 PM Thomas Orgis <tho...@or...> wrote: > Am Fri, 01 Jan 2016 17:38:50 +0000 > schrieb Myles <smp...@gm...>: > > > Enhancement > > ========== > > QUEUE_ADD(or PUSH?), QUEUE_CLEAR, QUEUE_READ, QUEUE_POP. > > The question I see is the one between a local hack of simply having > exactly one slot for a following track or enabling full management of > the playlist. The existing playlist code in mpg123, which obviously(?) > should be re-used, is designed for one-time creation and optional > shuffling of a list. Some care is needed when turning this into > something dynamic. I'm also thinking about the funky option of LOADing > a playlist file. > > Btw., with my music playing daemon that uses mpg123 code for decoding, > I opted not to integrate playlist management at all. Instead it offers > gapless playback via multiple mixer channels (a channel with a track > each), where the end of one track triggers seamless start of another > one. This got extended into a general scripting mechanism that allows > to start/stop tracks based on certain time stamps of reference tracks. > > The main points was to keep string management associated with playlists > out of the C/C++ code … for sure, it has its own complexity. > > Talk about possible mpg123 extensions occuring means I perhaps should > really just get a release of the current important changes in trunk > before muddying the waters further. I was contemplating creation of a > decoder wrapper library to enable mpg123 to read some more file types, > as ironic as that may seem. Simply too much work went into those funny > generic audio player features to not being able to even play back the > WAV files mpg123 itself produces. > > To hash out my current idea: > > 1. release of mpg123 1.23.0 (celebrate that number after missing > 1.2.3;-) with libout123, reworked terminal UI, lots of little bug > fixes, among those proper clipping for ARM) > 2. work on mpg123 2.0.0 with code cleanup, multiple input formats via > input library combining libmpg123 with others (basically > libsndfile+libmpg123 … perhaps including mpg123's funny HTTP client > and playlist code, too) > > The reworked playlist management including runtime modification of it > would be part of step 2, after deciding if playlist parsing and > management should be part of that new lib. > > Actually, it could be interesting to have a whole album (playlist) > abstracted as a single file by that lib. This used to be tricky with > MPEG audio files before libmpg123 introduced sample-accurate access to > them. > > Well, I guess you get the picture that the proper solution is not > coming right away (unless in form of a local hack for separate playlist > in control_generic.c). > > > Get me through the day > > ================= > > Add flushing and re-build. I may have time to try it tonight. Can I > > use MinGW, or should I use MSVC? > > MinGW is the primary platform that mpg123 is built with on Windows > systems. With MSVC, there are only project files to get the libmpg123 > DLL, not the whole application. > > > I can't imagine why fflushing() > > every line would hurt performance and/or power consumption in any > > application. > > Yeah, since it even should be a noop when called after each line on > _normal_ systems. As long as I have one fprintf for a single character > in there, I should not worry of the performance of a single additional > function call;-) > > > complains. But let's make sure it works first. I bet Microsoft still > > has a few more tricks up their sleeve. > > Yes, waiting for your results. If it helps, we could add it with #ifdef > WIN32, maybe even without that. > > > Alrighty then, > > Thomas > |