Csound Csound-dev Csound-tekno Search About

Re: how to pipe -L events in linux/unix

Date1998-06-16 17:55
FromPaul Winkler
SubjectRe: how to pipe -L events in linux/unix
Thanks John F., Toby, Jens, and Nicola, for your help.

I should perhaps have been more specific in my post. What I'm eventually 
trying to create is a little C app with a GUI (possibly written in 
Tcl/Tk) which will basically use csound as a sound-generating engine, 
and will pipe line events to it in realtime in response to various user 
actions. Obviously there's lots of directions you could go with an 
interface like that (see CECILIA) but for starters, being extremely 
pedestrian, I'm thinking "drum machine". :)  

I've been exploring the various suggestions you guys sent. I made a 
simple orc that uses a single oscil, with p4 being pitch in cps and p5 
being amplitude in dB. That works, no problem. Now here's several short 
bits of c code and some comments on each one:

Attempt 1, "piper1.c", based on Toby's suggestion: 

#include 
#include   /* need these for mkfifo() */
#include 

FILE *ofp;

int main(void)
{
	mkfifo("/tmp/Barf", 0666);
	system("ls -l /tmp/Barf");  /* just to be take a look. */
	if ((ofp = fopen("/tmp/Barf" , "w" )) == NULL) {
		printf("Can't open /tmp/Barf. Bye.\n");
		exit(1);
	}
	printf("Opened /tmp/Barf for writing.\n");
	exit(0);
	/* Neither of the above exits takes place!!! */	
	system("Csound -L /tmp/Barf -b 8192 -odevaudio 
/home/pw/Orcs+Scores/osciltest.orc /home/pw/Orcs+Scores/osciltest.sco");
        /* Here's where I would put code to write some score events */
	/* Now get rid of the FIFO. */
	system("rm /tmp/Barf");
	return 0;
}

Obviously, something's not right. The system() call wasn't happening so 
I put the two exit() calls in there to see what was happening when I 
tried to open the fifo. When I run piper1, it gets as far as the ls -l 
and then nothing else happens. No reported errors, it doesn't exit, just 
sits there doing nothing until I kill it.

Moving along, here's piper2.c:

/***** Attempt to write line events to a pipe and get csound to read 
them. This method works, but it seems the events arrive all at the same 
time, and not until pclose() is called... so how can I get instantaneous 
results from each fprintf() ? ***/

#include 

FILE *fp;

int main(void)
{

	fp = popen("csound -d -L stdin -b 8192 -odevaudio \
                    home/pw/Orcs+Scores/osciltest.orc \
                    /home/pw/Orcs+Scores/osciltest.sco", "w");
	sleep(2); /* give csound a moment to get started... */
	fprintf(fp, "i1 0 2 300 75\n");
	sleep(1);  /* attempt to send another event 1 second later */
	fprintf(fp, "i1 0 2 400 75\n");
	sleep(10); /* testing... */
	pclose(fp);
	return 0;
}

The sleep(10) line is there because I suspected csound wasn't receiving 
the line events until the pclose call, and I was right. I want each 
fprintf() to deliver its score event instantly...

So now I try jpff's first suggestion:
>... use -L and a filename starting with a | to start a process
> which delivers events ...

OK, I write this little code in piper3.c:

#include 

int main(void)
{
	/*  Invoke this prog with "csound -d -L "|piper3" -b 8192 -odevaudio 
/home/pw/Orcs+Scores/osciltest.orc /home/pw/Orcs+Scores/osciltest.sco */
	printf("i1 0 2 300 75\n");
	sleep(1);
	printf("i1 0 2 400 75\n");
	return 0;
}

Then at the shell prompt I do this:
csound -d -L "|piper3" -b 8192 -odevaudio 
/home/pw/Orcs+Scores/osciltest.orc /home/pw/Orcs+Scores/osciltest.sco

This doesn't work right. Csound complains that it's unable to open the 
line device for reading. piper3 does run, though, and prints the two 
events on stdout like I expected.

Finally, John's last suggestion:

>Altrenatively fire up the sub-process for Csound and attach
>stdin of the subprocess to some pipe (if you cannot use 
>dup2, socket etc then look at popen) and you are off.

Well, we've already gone over popen. I had a look at the man pages for 
dup2 and socket and got nowhere. dup2 just says it duplicates a file 
descriptor-- how does that help? And socket was just beyond me... I was 
totally guessing on the arguments, had no idea what protocol was 
appropriate, and even if I did, I have no idea what to do next.

Any more ideas, folks?

Thanks again,

PW

______________________________________________________
Get Your Private, Free Email at http://www.hotmail.com

Date1998-06-17 07:47
FromJens Kilian
SubjectRe: how to pipe -L events in linux/unix
> Moving along, here's piper2.c:
> 
> /***** Attempt to write line events to a pipe and get csound to read 
> them. This method works, but it seems the events arrive all at the same 
> time, and not until pclose() is called... so how can I get instantaneous 
> results from each fprintf() ? ***/

Try fflush(fp) after each fprintf(fp, ...).

        Jens.
--
mailto:jjk@acm.org                 phone:+49-7031-14-7698 (HP TELNET 778-7698)
  http://www.bawue.de/~jjk/          fax:+49-7031-14-7351
PGP:       06 04 1C 35 7B DC 1F 26 As the air to a bird, or the sea to a fish,
0x555DA8B5 BB A2 F0 66 77 75 E1 08 so is contempt to the contemptible. [Blake]

Date1998-06-17 11:04
FromNicola Bernardini
SubjectRe: how to pipe -L events in linux/unix
Dear Paul,

my sensation is that whatever you wrote in C should be working right
away as a Unix shell first (that's the way I did my tests before).
The code you wrote practically duplicates what the shell does when you
do something like, say:


echo "i1 0 10 32000 440" | csound -L stdin -do devaudio thisandthat.orc

(is there a need for a sco? It did not for me - it said it was replacing
with a dummy sco)

In a normal situation, this *SHOULD* work. The point is that there is
no real name for stdin so we don't know what to put there. Another thing
I tried was:

csound -L /tmp/fifo -do devaudio thisandthat.orc && \
	echo "i1 0 10 32000 440" >> /tmp/fifo

which means "start csound sucking from a fifo and if successeful write
in that fifo". I tried every way around, first echo and then csound or first
csound and then echo. Does'nt work either because csound evidently opens the fifo
queue, does not block waiting for input and thinks there's something wrong
and exits. Even sending csound and or echo in the background does not help
if csound fread() does'nt block because there's no way to synchronize the
two events (that's precisely what blocking is for). I did not have time
to test the "|/tmp/fifo" syntax - somebody should do it and report though.

Tomorrow I have some travelling time and I'll work on this problem (which
interests me too) and I'll find a solution (if nobody else finds one in
the meantime, of course), at least for linux (and I believe most other
unix systems - sorry about the others, I can't test/debug them; I'll
try to make things clean and portable though). 

In the meantime, my suggestion is again: on unix/linux systems, there's
no point in programming these kind of things in C *first*;
prototypes can be made and  *have* to work with shells otherwise
something seriously wrong is at work (see above). And forget sockets, that's
another story - pipes are fine and they work really well for the kind
of things you want to do.

Ciao for now

Nicola

------------------------------------------------------------------------
Nicola Bernardini
E-mail: nicb@axnet.it
 
Re graphics: A picture is worth 10K words -- but only those to describe
the picture.  Hardly any sets of 10K words can be adequately described
with pictures.
On Tue, 16 Jun 1998, Paul Winkler wrote:

[snip]
> Thanks John F., Toby, Jens, and Nicola, for your help.
> 
> I should perhaps have been more specific in my post. What I'm eventually 
> trying to create is a little C app with a GUI (possibly written in 
> Tcl/Tk) which will basically use csound as a sound-generating engine, 
> and will pipe line events to it in realtime in response to various user 
> actions. Obviously there's lots of directions you could go with an 
> interface like that (see CECILIA) but for starters, being extremely 
> pedestrian, I'm thinking "drum machine". :)  
> 
> I've been exploring the various suggestions you guys sent. I made a 
> simple orc that uses a single oscil, with p4 being pitch in cps and p5 
> being amplitude in dB. That works, no problem. Now here's several short 
> bits of c code and some comments on each one:
> 
> Attempt 1, "piper1.c", based on Toby's suggestion: 
> 
> #include 
> #include   /* need these for mkfifo() */
> #include 
> 
> FILE *ofp;
> 
> int main(void)
> {
> 	mkfifo("/tmp/Barf", 0666);
> 	system("ls -l /tmp/Barf");  /* just to be take a look. */
> 	if ((ofp = fopen("/tmp/Barf" , "w" )) == NULL) {
> 		printf("Can't open /tmp/Barf. Bye.\n");
> 		exit(1);
> 	}
> 	printf("Opened /tmp/Barf for writing.\n");
> 	exit(0);
> 	/* Neither of the above exits takes place!!! */	
> 	system("Csound -L /tmp/Barf -b 8192 -odevaudio 
> /home/pw/Orcs+Scores/osciltest.orc /home/pw/Orcs+Scores/osciltest.sco");
>         /* Here's where I would put code to write some score events */
> 	/* Now get rid of the FIFO. */
> 	system("rm /tmp/Barf");
> 	return 0;
> }
> 
> Obviously, something's not right. The system() call wasn't happening so 
> I put the two exit() calls in there to see what was happening when I 
> tried to open the fifo. When I run piper1, it gets as far as the ls -l 
> and then nothing else happens. No reported errors, it doesn't exit, just 
> sits there doing nothing until I kill it.
> 
> Moving along, here's piper2.c:
> 
> /***** Attempt to write line events to a pipe and get csound to read 
> them. This method works, but it seems the events arrive all at the same 
> time, and not until pclose() is called... so how can I get instantaneous 
> results from each fprintf() ? ***/
> 
> #include 
> 
> FILE *fp;
> 
> int main(void)
> {
> 
> 	fp = popen("csound -d -L stdin -b 8192 -odevaudio \
>                     home/pw/Orcs+Scores/osciltest.orc \
>                     /home/pw/Orcs+Scores/osciltest.sco", "w");
> 	sleep(2); /* give csound a moment to get started... */
> 	fprintf(fp, "i1 0 2 300 75\n");
> 	sleep(1);  /* attempt to send another event 1 second later */
> 	fprintf(fp, "i1 0 2 400 75\n");
> 	sleep(10); /* testing... */
> 	pclose(fp);
> 	return 0;
> }
> 
> The sleep(10) line is there because I suspected csound wasn't receiving 
> the line events until the pclose call, and I was right. I want each 
> fprintf() to deliver its score event instantly...
> 
> So now I try jpff's first suggestion:
> >... use -L and a filename starting with a | to start a process
> > which delivers events ...
> 
> OK, I write this little code in piper3.c:
> 
> #include 
> 
> int main(void)
> {
> 	/*  Invoke this prog with "csound -d -L "|piper3" -b 8192 -odevaudio 
> /home/pw/Orcs+Scores/osciltest.orc /home/pw/Orcs+Scores/osciltest.sco */
> 	printf("i1 0 2 300 75\n");
> 	sleep(1);
> 	printf("i1 0 2 400 75\n");
> 	return 0;
> }
> 
> Then at the shell prompt I do this:
> csound -d -L "|piper3" -b 8192 -odevaudio 
> /home/pw/Orcs+Scores/osciltest.orc /home/pw/Orcs+Scores/osciltest.sco
> 
> This doesn't work right. Csound complains that it's unable to open the 
> line device for reading. piper3 does run, though, and prints the two 
> events on stdout like I expected.
> 
> Finally, John's last suggestion:
> 
> >Altrenatively fire up the sub-process for Csound and attach
> >stdin of the subprocess to some pipe (if you cannot use 
> >dup2, socket etc then look at popen) and you are off.
> 
> Well, we've already gone over popen. I had a look at the man pages for 
> dup2 and socket and got nowhere. dup2 just says it duplicates a file 
> descriptor-- how does that help? And socket was just beyond me... I was 
> totally guessing on the arguments, had no idea what protocol was 
> appropriate, and even if I did, I have no idea what to do next.
> 
> Any more ideas, folks?
> 
> Thanks again,
> 
> PW
> 
> ______________________________________________________
> Get Your Private, Free Email at http://www.hotmail.com
>