From vboehm at gmx.ch Wed Oct 3 04:15:23 2007 From: vboehm at gmx.ch (=?ISO-8859-1?Q?volker_b=F6hm?=) Date: Wed Oct 3 04:15:17 2007 Subject: [java-dev] working with JitterObjects in mxj that don't output jitter matrices Message-ID: hi, i'm trying to write a class for mxj that incorporates a JitterObject. from the examples this seems to be straight forward for objects that process and output jitter matrices, like in the "javajitterfirsttest.pat" example, where jit.sobel and jit.brcosa are used with the "matrixcalc" message: mybrcosa.matrixcalc(inname,mymatrix2); etc. but what about using a jitter object, which doesn't output a jitter matrix? i'd like to find the mean value of a 2d 1 plane matrix using jit.3m e.g. JitterObject my3m = new JitterObject("jit.3m"); my3m.matrixcalc(myInputMatrix, ???); thanks for any pointers. volker. From jkc at musork.com Wed Oct 3 11:41:57 2007 From: jkc at musork.com (Joshua Kit Clayton) Date: Wed Oct 3 11:42:04 2007 Subject: [java-dev] working with JitterObjects in mxj that don't output jitter matrices In-Reply-To: References: Message-ID: <1F795B0B-93E4-44F1-8216-D0AC4EDBC449@musork.com> On Oct 3, 2007, at 3:15 AM, volker b?hm wrote: > but what about using a jitter object, which doesn't output a jitter > matrix? > > i'd like to find the mean value of a 2d 1 plane matrix using jit.3m > e.g. > > JitterObject my3m = new JitterObject("jit.3m"); > my3m.matrixcalc(myInputMatrix, ???); If null doesn't work as a second argument to matrixcalc, you can just pass in any matrix (duplicate the input). The values you are looking for are available as attributes after the matrixcalc method has finished executing. Their names are "max" "mean" "min" and will return arrays of values. Hope this helps. -Joshua From vboehm at gmx.ch Wed Oct 3 12:51:10 2007 From: vboehm at gmx.ch (=?ISO-8859-1?Q?volker_b=F6hm?=) Date: Wed Oct 3 12:51:04 2007 Subject: [java-dev] working with JitterObjects in mxj that don't output jitter matrices In-Reply-To: <1F795B0B-93E4-44F1-8216-D0AC4EDBC449@musork.com> References: <1F795B0B-93E4-44F1-8216-D0AC4EDBC449@musork.com> Message-ID: <910D0937-2006-4C66-B5CB-FF029290485E@gmx.ch> On 03 Oct 2007, at 19:41, Joshua Kit Clayton wrote: > > On Oct 3, 2007, at 3:15 AM, volker b?hm wrote: > >> but what about using a jitter object, which doesn't output a >> jitter matrix? >> >> i'd like to find the mean value of a 2d 1 plane matrix using jit. >> 3m e.g. >> >> JitterObject my3m = new JitterObject("jit.3m"); >> my3m.matrixcalc(myInputMatrix, ???); > > If null doesn't work as a second argument to matrixcalc, you can > just pass in any matrix (duplicate the input). > > The values you are looking for are available as attributes after > the matrixcalc method has finished executing. Their names are "max" > "mean" "min" and will return arrays of values. > > Hope this helps. yes, it does! null works as second argument. i didn't know about the attribute-thing. my3m.matrixcalc(myInputMatrix, null); int[] mean = my3m.getAttrIntArray("mean"); this works fine for me. thanks, joshua. volker. From puuukeey at comcast.net Thu Oct 4 20:28:21 2007 From: puuukeey at comcast.net (Matthew Aidekman) Date: Thu Oct 4 20:28:23 2007 Subject: [java-dev] Max 5 Message-ID: <1ca0b.4705a145@www.cycling74.com> I've been working for a year and a half on a huge java program hosted in max. what does max 5 mean for me? I'm REALLY NERVOUS! From bthrew at gmail.com Thu Oct 4 20:50:34 2007 From: bthrew at gmail.com (barry threw) Date: Thu Oct 4 20:50:42 2007 Subject: [java-dev] Max 5 In-Reply-To: <1ca0b.4705a145@www.cycling74.com> References: <1ca0b.4705a145@www.cycling74.com> Message-ID: Probably means you are getting a credit card. b On Oct 4, 2007, at 7:28 PM, Matthew Aidekman wrote: > > I've been working for a year and a half on a huge java program > hosted in max. what does max 5 mean for me? > > I'm REALLY NERVOUS! > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev Barry Threw Media Art and Technology San Francisco, CA Work: 857-544-3967 Email: bthrew@gmail.com IM: captogreadmore (AIM) http:/www.barrythrew.com From leopold.frey at free.fr Fri Oct 5 00:52:42 2007 From: leopold.frey at free.fr (=?ISO-8859-1?Q?L=E9opold_Frey?=) Date: Fri Oct 5 00:52:44 2007 Subject: [java-dev] Max 5 In-Reply-To: References: <1ca0b.4705a145@www.cycling74.com> Message-ID: <4705DF3A.7040508@free.fr> > On Oct 4, 2007, at 7:28 PM, Matthew Aidekman wrote: >> I've been working for a year and a half on a huge java program hosted >> in max. what does max 5 mean for me? >> >> I'm REALLY NERVOUS! Hi matthew, "Anything written in Javascript to work in jsui or Java to work with mxj will work fine in Max 5." >From David Z. article. I suppose we can trust him ;) leo From puuukeey at comcast.net Fri Oct 5 02:33:04 2007 From: puuukeey at comcast.net (Matthew Aidekman) Date: Fri Oct 5 02:33:06 2007 Subject: [java-dev] Re: Max 5 In-Reply-To: <1ca0b.4705a145@www.cycling74.com> Message-ID: <1ca20.4705f6c0@www.cycling74.com> awesome. I read the entire article. odd... I've been told I have a disability. I didn't think it was that severe. From katzenklaus at gmx.de Fri Oct 5 11:51:49 2007 From: katzenklaus at gmx.de (Iltis) Date: Fri Oct 5 11:51:49 2007 Subject: [java-dev] mjx crashes max immediately Message-ID: <1ca66.470679b4@www.cycling74.com> Hi everybody, I have some problems with Max 4.5.7 and mxj on Windows XP with Java JDK jdk1.6.0_02, JRE 1.5.0_09 and JRE 1.6.0_02. Each time I start an mxj object max crashes immediately without any error message. I downloaded the max version 4.6 but there is the same problem. Also on my other computer. Do I have to set any pathes to use the mxj object ?(never tried java+max on a PC, on MAC it went fine) Best Iltis From c74-mailinglists at e--j.com Fri Oct 5 13:22:48 2007 From: c74-mailinglists at e--j.com (Emmanuel Jourdan) Date: Fri Oct 5 13:22:59 2007 Subject: [java-dev] mjx crashes max immediately In-Reply-To: <1ca66.470679b4@www.cycling74.com> References: <1ca66.470679b4@www.cycling74.com> Message-ID: <55AB474B-8B53-422A-88FF-D08637382BB2@e--j.com> On 5 oct. 07, at 19:51, Iltis wrote: > Hi everybody, > > I have some problems with Max 4.5.7 and mxj on Windows XP with > Java JDK jdk1.6.0_02, JRE 1.5.0_09 and JRE 1.6.0_02. Each time I > start an mxj object max crashes immediately without any error > message. I downloaded the max version 4.6 but there is the same > problem. Also on my other computer. Do I have to set any pathes to > use the mxj object ?(never tried java+max on a PC, on MAC it went > fine) Do you have 4.6.3 installed? I remember an issue on windows about java 1.6. which were solved by the 4.6.3 installation: http://www.cycling74.com/twiki/bin/view/FAQs/WindowsJavaCrash Cheers, ej From katzenklaus at gmx.de Fri Oct 5 13:27:00 2007 From: katzenklaus at gmx.de (Iltis) Date: Fri Oct 5 13:27:02 2007 Subject: [java-dev] a bit better In-Reply-To: <1ca66.470679b4@www.cycling74.com> Message-ID: <1ca74.47069003@www.cycling74.com> after having changed the: max.java.config.txt with this line max.dynamic.class.dir C:\Programme\Gemeinsame Dateien\Cycling '74\java\classes the objects oft this directory work without crashing max. But in the Max out window it says: • error: (mxj) unknown option DateienCycling in max.java.config.txt. MXJ System CLASSPATH: C:\Programme\Gemeinsame Dateien\Cycling '74\java\lib\jode-1.1.2-pre-embedded.jar C:\Programme\Gemeinsame Dateien\Cycling '74\java\lib\max.jar MXJClassloader CLASSPATH: C:\Programme\Gemeinsame Dateien\Cycling '74\java\classes\ C:\ProgrammeGemeinsame (mxj classloader) dynamic classpath entry C:\ProgrammeGemeinsame\ does not exist. What the hell? Iltis From katzenklaus at gmx.de Fri Oct 5 18:27:58 2007 From: katzenklaus at gmx.de (Iltis) Date: Fri Oct 5 18:28:00 2007 Subject: [java-dev] Re: mjx crashes max immediately In-Reply-To: <55AB474B-8B53-422A-88FF-D08637382BB2@e--j.com> Message-ID: <1ca9c.4706d68e@www.cycling74.com> Jeah, that was a good solution! Meanwhile I tested version 4.6 and it only worked when my Anti Virus was disabeld ;-) Thanks!!!!! From evrard.g at gmail.com Mon Oct 8 05:34:52 2007 From: evrard.g at gmail.com (guillaume) Date: Mon Oct 8 05:34:54 2007 Subject: [java-dev] adding a path to the classpath Message-ID: <1cb6c.470a15dc@www.cycling74.com> hi all, i'm trying to add a temporary path to the classpath in the init procedure of my application, but i can't manage to do it. the javadoc shows a "addDirectory" method for the MXJClassLoader class, but it's protected. All i can do is getting the current paths... Is there a way to do this? G. From topher at topher.com Mon Oct 8 11:28:13 2007 From: topher at topher.com (topher lafata) Date: Mon Oct 8 11:28:14 2007 Subject: [java-dev] adding a path to the classpath In-Reply-To: <1cb6c.470a15dc@www.cycling74.com> References: <1cb6c.470a15dc@www.cycling74.com> Message-ID: i don't think it was ever intended to be used that way but... you could use reflection to call the method even though it protected. good luck. t No look at reflection can be complete without talking about how to break one of the most sacred of all the rules in Java. Everyone knows that you cannot call a private method from outside of the class that defines it. Right? Well you can't if you stick to conventional techniques, but with reflection you can do darn near anything. The first thing you need to call a private method is the Method instance that goes with the method you want to call. You can't get this from getMethod; it only returns public methods. The way to get hold of a private (or protected) method is to use getDeclaredMethod. While getMethod takes a client's view of a class and only returns public methods, getDeclaredMethod returns all of the methods declared by one class. In the example below, we use it to get at the Method object for the very private removeRange method on the java.util.ArrayList class: ArrayList list = new ArrayList(); list.add("Larry"); list.add("Moe"); list.add("Curley"); System.out.println("The list is: " + list); Class klass = list.getClass(); Class[] paramTypes = { Integer.TYPE, Integer.TYPE }; Method m = klass.getDeclaredMethod("removeRange", paramTypes); Object[] arguments = { new Integer(0), new Integer(2) }; m.setAccessible(true); m.invoke(list, arguments); System.out.println("The new list is: " + list); Once you have a private method, calling it is a simple matter of clicking off the final setAccessable safety and having at it: On Oct 8, 2007, at 04:34 AM, guillaume wrote: > > hi all, > > i'm trying to add a temporary path to the classpath in the init > procedure of my application, but i can't manage to do it. > the javadoc shows a "addDirectory" method for the MXJClassLoader > class, but it's protected. All i can do is getting the current > paths... > > Is there a way to do this? > > G. > > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev From evrard.g at gmail.com Mon Oct 8 11:34:49 2007 From: evrard.g at gmail.com (guillaume) Date: Mon Oct 8 11:34:51 2007 Subject: [java-dev] Re: adding a path to the classpath In-Reply-To: Message-ID: <1cb91.470a6a39@www.cycling74.com> hi topher, thanks for your help. i'm trying this kind of code right now : import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; /** * Useful class for dynamically changing the classpath, adding classes during runtime. * @author unknown */ public class ClasspathHacker { /** * Parameters of the method to add an URL to the System classes. */ private static final Class[] parameters = new Class[]{URL.class}; /** * Adds a file to the classpath. * @param s a String pointing to the file * @throws IOException */ public static void addFile(String s) throws IOException { File f = new File(s); addFile(f); }//end method /** * Adds a file to the classpath * @param f the file to be added * @throws IOException */ public static void addFile(File f) throws IOException { addURL(f.toURL()); }//end method /** * Adds the content pointed by the URL to the classpath. * @param u the URL pointing to the content to be added * @throws IOException */ public static void addURL(URL u) throws IOException { URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader(); Class sysclass = URLClassLoader.class; try { Method method = sysclass.getDeclaredMethod("addURL",parameters); method.setAccessible(true); method.invoke(sysloader,new Object[]{ u }); } catch (Throwable t) { t.printStackTrace(); throw new IOException("Error, could not add URL to system classloader"); }//end try catch }//end method } i think it should work soon... From leopold.frey at free.fr Tue Oct 9 06:00:23 2007 From: leopold.frey at free.fr (Léopold Frey) Date: Tue Oct 9 06:00:25 2007 Subject: [java-dev] Re: SOLUTION! Long Filename Support in Max with Java In-Reply-To: <1c13a.46e6c512@www.cycling74.com> Message-ID: <1cbe8.470b6d55@www.cycling74.com> Hi rick, sorry for the long delay but I've been working on so many different things lately that I had no time to dig into this problem. Are you saying you have multiple partitions on the same drive? I do not have a machine that has that case to test it. I have multiple drives and I know that works. Which OSX version are you using? I've made a series of tests on my powerbook (G4 PPC Mac Os 10.4.10) the problem appears in MaxMSP 4.5.7 and MaxMSP 4.6.3 with different partitions on the same drive, network mounted drives or external drives. on my iMac (Intel core 2 duo Mac Os 10.4.10 MaxMSP 4.6.3) everything is fine no matter the hard drive the file is on. So it seems to be more a Intel/PPC specific problem. Anyway, I've found a workaround : [code] public void convert(String s1) { //Need to make sure this string does not need to be converted if(s1.matches(".*#[0-9]+\\..*") && s1.matches(".*:.*")) { outlet(0,Atom.newAtom(s1)); } else { // replace strange characters s2 = s2.replace(""+((char)14848),":/"); s2 = s2.replace(""+((char)12032),"/"); outlet(0,Atom.newAtom(s2)); } } [/code] Thanks Leo From mattijs at smadsteck.nl Thu Oct 11 02:43:09 2007 From: mattijs at smadsteck.nl (Mattijs Kneppers) Date: Thu Oct 11 02:43:10 2007 Subject: [java-dev] Re: Eclipse is mean In-Reply-To: <1ccc8.470d7a96@www.cycling74.com> Message-ID: <1cce4.470de21c@www.cycling74.com> Moved this topic to the Java forum, list users please reply to the Java list. -- SmadSteck - http://www.smadsteck.nl Hard- and software for interactive audiovisual sampling From owen at owengreen.net Thu Oct 11 02:57:02 2007 From: owen at owengreen.net (Owen Green) Date: Thu Oct 11 02:58:29 2007 Subject: [java-dev] Re: Eclipse is mean In-Reply-To: <1cce4.470de21c@www.cycling74.com> References: <1cce4.470de21c@www.cycling74.com> Message-ID: <470DE55E.9010205@owengreen.net> Mattijs, On the mailing list I don't get to see the original post, just your note below. Is there some way of moving posts between forums that would still result in proper mailing-list behaviour? If not, can you quote the op when moving messages? Cheers, O Mattijs Kneppers wrote: > Moved this topic to the Java forum, list users please reply to the Java list. > -- > SmadSteck - http://www.smadsteck.nl > Hard- and software for interactive audiovisual sampling > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev > From c74-mailinglists at e--j.com Thu Oct 11 02:59:18 2007 From: c74-mailinglists at e--j.com (Emmanuel Jourdan) Date: Thu Oct 11 02:59:33 2007 Subject: [java-dev] Re: [dev] Eclipse is mean In-Reply-To: <1ccc8.470d7a96@www.cycling74.com> References: <1ccc8.470d7a96@www.cycling74.com> Message-ID: On 11 oct. 07, at 10:21, Timothy Dalbey wrote: > What is the command to compile mxj objects from eclipse? I have > already configed th max.jar file and entered the eclipse classpath > into the max config file. I are n??b. Did you try the Ben's tutorial? http://www.cycling74.com/forums/index.php? t=msg&rid=0&S=0fe30139a0e6a4ee7f754a88cfb89865&th=23447&goto=94321#msg_9 4321 ej From owen at owengreen.net Thu Oct 11 03:00:00 2007 From: owen at owengreen.net (Owen Green) Date: Thu Oct 11 03:00:14 2007 Subject: [java-dev] Re: Eclipse is mean In-Reply-To: <1cce4.470de21c@www.cycling74.com> References: <1cce4.470de21c@www.cycling74.com> Message-ID: <470DE610.1070004@owengreen.net> The OP was: > I am trying to compile mxj projects outside of quickie and eclipse > doesnt seem to want to compile for me. I have added the max.jar file > to eclipse and I also entered my eclipse classpath into the config > file for max. Maybe I just dont know th right command for eclipse? > what should I do to compile from eclispe? > > Thanks. Project | Build All should do it (I like to have Build Automatically checked so it compiles when I save). Does this work for you? -- O Mattijs Kneppers wrote: > Moved this topic to the Java forum, list users please reply to the > Java list. -- SmadSteck - http://www.smadsteck.nl Hard- and software > for interactive audiovisual sampling > _______________________________________________ java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev > From mattijs at smadsteck.nl Thu Oct 11 03:34:55 2007 From: mattijs at smadsteck.nl (Mattijs Kneppers) Date: Thu Oct 11 03:35:11 2007 Subject: [java-dev] Re: Re: Eclipse is mean In-Reply-To: <470DE55E.9010205@owengreen.net> Message-ID: <1cce9.470dee3c@www.cycling74.com> Ah, I see. Thanks for the feedback. Mattijs Quote: owen wrote on Thu, 11 October 2007 10:57 ---------------------------------------------------- > Mattijs, > > On the mailing list I don't get to see the original post, just your note > below. Is there some way of moving posts between forums that would > still result in proper mailing-list behaviour? If not, can you quote the > op when moving messages? > > Cheers, > O > > Mattijs Kneppers wrote: > > Moved this topic to the Java forum, list users please reply to the Java list. > > -- > > SmadSteck - http://www.smadsteck.nl > > Hard- and software for interactive audiovisual sampling > > > > ---------------------------------------------------- -- SmadSteck - http://www.smadsteck.nl Hard- and software for interactive audiovisual sampling From andrew at moceanic.com Thu Oct 11 04:38:32 2007 From: andrew at moceanic.com (Andrew Robertson) Date: Thu Oct 11 04:38:35 2007 Subject: [java-dev] Parse text as list/Atom Message-ID: <1ccef.470dfd27@www.cycling74.com> Hi, I want to input a filename as a list e.g. 34f_24353.aiff and extract the part after the 34f_ as numbers I'm thinking I would input via public void list(a) then make a string (how do I do that?) and then search for the underscore. If anyone has an idea how to process this information (the actual problem will be for say forty soundfiles) please post back. At the moment, I just get errors about the type - symbol I was trying something like this: public void list(Atom[] list) { Atom a; Atom b; a = list[0]; file_name = parse(a.toString()); //b = a.toString(); //file_name = parse(b); }//end list process From c74-mailinglists at e--j.com Thu Oct 11 04:54:43 2007 From: c74-mailinglists at e--j.com (Emmanuel Jourdan) Date: Thu Oct 11 04:54:57 2007 Subject: [java-dev] Parse text as list/Atom In-Reply-To: <1ccef.470dfd27@www.cycling74.com> References: <1ccef.470dfd27@www.cycling74.com> Message-ID: <994CF1C5-4C6B-47DD-97BA-4910D02C4FF4@e--j.com> On 11 oct. 07, at 19:38, Andrew Robertson wrote: > Hi, > > I want to input a filename as a list e.g. > 34f_24353.aiff > > and extract the part after the 34f_ as numbers > > I'm thinking I would input via public void list(a) > then make a string (how do I do that?) > and then search for the underscore. > > If anyone has an idea how to process this information > (the actual problem will be for say forty soundfiles) please post > back. At the moment, I just get errors about the type - symbol > > I was trying something like this: > > > public void list(Atom[] list) > { > > Atom a; > Atom b; > > a = list[0]; > file_name = parse(a.toString()); > //b = a.toString(); > //file_name = parse(b); > }//end list process You have to use the anything method to do that because 34f_24353.aiff is not a list but a symbol: public void anything(String s, Atom[] a) { String file_name = s; // do whatever you want with that string } Cheers, ej From lists at simonadcock.co.uk Fri Oct 12 06:36:07 2007 From: lists at simonadcock.co.uk (lists@simonadcock.co.uk) Date: Fri Oct 12 06:36:37 2007 Subject: [java-dev] mxj~ crackling when moving windows etc Message-ID: <001c01c80ccc$85bd8170$170ba8c0@simonslaptop> Hello, Has anybody else experienced audio breaking up when using an mxj~? Even the simplest mxj~ object seems to make loud crackling sounds when I move or resize a window. A bit gutting as I've just spent far too much time building a bunch of effects! Should have done a bit more testing first. (Win Max 4.6.3) Thanks, Simon -------------- next part -------------- An HTML attachment was scrubbed... URL: http://www.cycling74.com/pipermail/java-dev/attachments/20071012/266da90f/attachment.htm From owen at owengreen.net Fri Oct 12 06:39:33 2007 From: owen at owengreen.net (Owen Green) Date: Fri Oct 12 06:39:41 2007 Subject: [java-dev] mxj~ crackling when moving windows etc In-Reply-To: <001c01c80ccc$85bd8170$170ba8c0@simonslaptop> References: <001c01c80ccc$85bd8170$170ba8c0@simonslaptop> Message-ID: <470F6B05.7070600@owengreen.net> Hi, What's your CPU usage like? Crackling often indicates a resource shortage. When you say moving windows - which ones? Max windows, or are you doing Java gui things? -- Owen lists@simonadcock.co.uk wrote: > Hello, > > > > Has anybody else experienced audio breaking up when using an mxj~? Even the > simplest mxj~ object seems to make loud crackling sounds when I move or > resize a window. A bit gutting as I've just spent far too much time building > a bunch of effects! Should have done a bit more testing first. (Win Max > 4.6.3) > > > > Thanks, > > Simon > > > > > ------------------------------------------------------------------------ > > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev From lists at simonadcock.co.uk Fri Oct 12 07:33:51 2007 From: lists at simonadcock.co.uk (simon adcock) Date: Fri Oct 12 07:33:52 2007 Subject: [java-dev] Re: mxj~ crackling when moving windows etc In-Reply-To: <470F6B05.7070600@owengreen.net> Message-ID: <1cd78.470f77be@www.cycling74.com> You're right it is a CPU thing. I'm not doing anything fancy whatsoever - for testing I've got an mxj~ object that simply copies the in to the out so the cpu reads more or less 0%, then I'll do something like minimize the patch, or drag the patcher window somewhere and the CPU shoots up and the sound crackles. hmm... does this mean I should really be doing this in C instead of Java? Simon From owen at owengreen.net Fri Oct 12 07:40:05 2007 From: owen at owengreen.net (Owen Green) Date: Fri Oct 12 07:42:33 2007 Subject: [java-dev] Re: mxj~ crackling when moving windows etc In-Reply-To: <1cd78.470f77be@www.cycling74.com> References: <1cd78.470f77be@www.cycling74.com> Message-ID: <470F7935.8000508@owengreen.net> I can't see any intrinsic reason why it should, but I'll admit to be being a bit mystified. At this point it may help to know some details, like os, java version etc. If you post your code, I can test here and see if I can replicate (or spot any boo-boos). -- Owen simon adcock wrote: > You're right it is a CPU thing. I'm not doing anything fancy > whatsoever - for testing I've got an mxj~ object that simply copies > the in to the out so the cpu reads more or less 0%, then I'll do > something like minimize the patch, or drag the patcher window > somewhere and the CPU shoots up and the sound crackles. hmm... does > this mean I should really be doing this in C instead of Java? > > Simon _______________________________________________ java-dev > mailing list java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev > From gary.nelson at oberlin.edu Fri Oct 12 07:44:36 2007 From: gary.nelson at oberlin.edu (Gary Lee Nelson) Date: Fri Oct 12 07:44:39 2007 Subject: [java-dev] Re: [maxmsp] Buf.OP updates In-Reply-To: <470F74AB.6070908@owengreen.net> Message-ID: I am looking at adding functions to buf.OP. The main one is a strip silence function that removes zero-valued samples from the beginning and end of a buffer. The following appears in the header of the source code: /** * a collection of buffer utilities * * created on Apr 12, 2004 * @author bbn * * TODO support joint operations on more than one channel. * ie, DC offset * */ Owen says the author is probably Ben Neville but the code is three years old. I would like to add the multi-channel functions because I am working with quad files. My silence trimmer would work like this: -Search each track for the earliest non-zero sample and save the earliest of those as the start point for a copy (in case one channel starts before the others) -Do the same from the end keeping the location of the latest non-zero sample. -Size a second receiving buffer to end-start and copy all channels to it On 10/12/07 9:20 AM, "Owen Green" wrote: > Hi Gary, > > It's maybe Ben Neville. If you get stuck in, I'd be interested in > helping - we should take further discussion to java-dev. Cheers Gary Lee Nelson Oberlin College www.timara.oberlin.edu/GaryLeeNelson From lists at simonadcock.co.uk Fri Oct 12 08:05:14 2007 From: lists at simonadcock.co.uk (simon adcock) Date: Fri Oct 12 08:05:15 2007 Subject: [java-dev] Re: Re: mxj~ crackling when moving windows etc In-Reply-To: <470F7935.8000508@owengreen.net> Message-ID: <1cd80.470f7f1a@www.cycling74.com> That would be great thanks. I'm using Win XP, Max 4.6.3, JRE 1.5.0.120. Below is the code I'm testing with: -- import com.cycling74.max.*; import com.cycling74.msp.*; public class thru extends MSPPerformer { private static final String[] INLET_ASSIST = new String[]{ "input (sig)" }; private static final String[] OUTLET_ASSIST = new String[]{ "output (sig)" }; public thru() { declareInlets(new int[]{SIGNAL}); declareOutlets(new int[]{SIGNAL}); setInletAssist(INLET_ASSIST); setOutletAssist(OUTLET_ASSIST); } public void dspsetup(MSPSignal[] ins, MSPSignal[] outs) { } public void perform(MSPSignal[] ins, MSPSignal[] outs) { int i; float[] in = ins[0].vec; float[] out = outs[0].vec; int vec_size = ins[0].n; for(i = 0; i < vec_size; i++) { out[i] = in[i]; } } } -- Thanks, Simon From andrew at moceanic.com Fri Oct 12 09:16:50 2007 From: andrew at moceanic.com (Andrew Robertson) Date: Fri Oct 12 09:16:52 2007 Subject: [java-dev] Re: Parse text as list/Atom In-Reply-To: <1ccef.470dfd27@www.cycling74.com> Message-ID: <1cd88.470f8fe2@www.cycling74.com> Hi Emmanuel, Thanks for your reply. That's great. the filename is now a string. if I wanted to convert that into an array of atoms (or strings) how would I do that? Regards, Andrew From c74-mailinglists at e--j.com Fri Oct 12 09:26:58 2007 From: c74-mailinglists at e--j.com (Emmanuel Jourdan) Date: Fri Oct 12 09:27:11 2007 Subject: [java-dev] Re: Parse text as list/Atom In-Reply-To: <1cd88.470f8fe2@www.cycling74.com> References: <1cd88.470f8fe2@www.cycling74.com> Message-ID: <4EA279E6-5D80-46AF-A582-E672D8711CA4@e--j.com> On 13 oct. 07, at 00:16, Andrew Robertson wrote: > Hi Emmanuel, > > Thanks for your reply. That's great. the filename is now a string. > if I wanted to convert that into an array of atoms (or strings) how > would I do that? If you want to have an array, you have to send more than one item. For example if you send "34f_24353.aiff 34f_24354.aiff 34f_24355.aiff" (without the quotes) to your object, the anything method will be called, the s string will contain 34f_24353.aiff, and your Atom array will have a size of 2 (34f_24354.aiff and 34f_24355.aiff) that you can get with a[0].getString() and a [1].getString() if I remember correctly. Cheers, ej From owen at owengreen.net Fri Oct 12 09:35:19 2007 From: owen at owengreen.net (Owen Green) Date: Fri Oct 12 09:36:15 2007 Subject: [java-dev] Re: Parse text as list/Atom In-Reply-To: <1cd88.470f8fe2@www.cycling74.com> References: <1cd88.470f8fe2@www.cycling74.com> Message-ID: <470F9437.4020607@owengreen.net> Hi Andrew, String.split() (Java 1.5 +) or StringTokenizer (for older versions) may be of help. -- Owen Andrew Robertson wrote: > Hi Emmanuel, > > Thanks for your reply. That's great. the filename is now a string. > if I wanted to convert that into an array of atoms (or strings) how would I do that? > > Regards, > Andrew > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev > From tmd4u at virginia.edu Fri Oct 12 10:08:34 2007 From: tmd4u at virginia.edu (Timothy Dalbey) Date: Fri Oct 12 10:08:36 2007 Subject: [java-dev] Re: Eclipse is mean In-Reply-To: <1ccc7.470d7a33@www.cycling74.com> Message-ID: <1cd8d.470f9c02@www.cycling74.com> Ok, I followed all the instruction provided in Ben's tutorial. Problem: Quickie no longer functions. The red X supossedly resolved with mail.jar does not disappear. Also, it is not register compilations in Max/MSP. ARG. From c.veit at inode.at Fri Oct 19 11:21:32 2007 From: c.veit at inode.at (Christian Veit) Date: Fri Oct 19 11:21:33 2007 Subject: [java-dev] Re: Re: Re: Re: caching javaclasses? In-Reply-To: <4A354239-E6AC-4BDA-B681-D4ED21CD9088@e--j.com> Message-ID: <1cfbc.4718e79b@www.cycling74.com> so now i have a really fine solution.. i have written three mxj objects.. two connection objects (one for upstream and one for downstream connections) with these both objects i can define my connections.. and with the third object (the Reloader Object) i can define my mxj object wich i like to reload.. after sending the connections to my reload object i only have to send a reload message and my mxj will be reinstatntiated.. so developing mxj objects is more comfortable.. thanks for help i've got from you c From Thinksamuel at yahoo.com Sun Oct 21 06:38:35 2007 From: Thinksamuel at yahoo.com (Samuel Van Ransbeeck) Date: Sun Oct 21 06:38:36 2007 Subject: [java-dev] Re: experience with stockwatch anyone? In-Reply-To: <1c736.46fd5153@www.cycling74.com> Message-ID: <1d025.471b4849@www.cycling74.com> Ok, so i managed to do the first part (getting more info from the SE) myself (however, still have to compile it) but another problem is, I want to get the numbers hat i get in number boxes to use those numbers as a source for my composition. Apparently you have to create an outlet for that, but what should i write declareOutlets(new int[]{DataTypes.ALL}); this is alrteady there, but i now i only get in a message box. What do I have to write to get a separate outlet for numbers? Thanks in advance amuel btw, here is the full code as it appears in the java folder of max import com.cycling74.max.*; import java.net.*; import java.io.*; import java.util.Hashtable; import java.util.Vector; import java.util.Enumeration; //finance.yahoo.com/d/quotes.csv?f=sl1d1t1c1ohgv&e=.csv&s=INTC+SUNW public class StockWatch extends MaxObject implements Runnable, Executable { //Attributes double interval = 30 * 1000; //30 seconds static final int SYM = 0; static final int LAST_TRADE = 1; static final int DAY = 2; static final int TIME = 3; static final int CHANGE = 4; private String _base_url = "http://finance.yahoo.com/d/quotes.csv?f=sl1d1t1c1ohgv&e=.csv"; private String _sym_string = "&s="; private Hashtable _syms; private boolean _first_sym = true; private Thread _t; private MaxClock _cl; public StockWatch(Atom[] args) { declareInlets(new int[]{DataTypes.ALL}); declareOutlets(new int[]{DataTypes.ALL}); declareAttribute("interval","_get_interval","_set_interval"); //virtual attribute declareAttribute("quotes","_get_quotes","_set_quotes"); _syms = new Hashtable(); _cl = new MaxClock(this); } private void _set_interval(int i) { interval = i * 1000; } private Atom[] _get_interval() { return new Atom[]{Atom.newAtom((float)interval / 1000)}; } private void _set_quotes(Atom[] args) { _syms.clear(); for(int i = 0; i < args.length; i++) { if(args[i].isString()) _add_quote(args[i].toString()); else System.out.println("Invalid Symbol: "+args[i].toString()); } } private Atom[] _get_quotes() { Enumeration e = _syms.keys(); Vector tmp = new Vector(); Atom[] ret = null; while(e.hasMoreElements()) tmp.addElement(Atom.newAtom((String)e.nextElement())); ret = new Atom[tmp.size()]; for(int i = 0; i < tmp.size();i++) ret[i] = (Atom)tmp.elementAt(i); return ret; } public void bang() { _cl.delay(0); } public void stop() { _cl.unset(); } public void clear() { _syms.clear(); } public void addQuote(String quote) { _add_quote(quote); } public void removeQuote(String quote) { quote = quote.toUpperCase(); if(_syms.containsKey(quote)) _syms.remove(quote); } public void execute() { _t = new Thread(this); try{ _t.start(); }catch(Exception e) { e.printStackTrace(); } _cl.delay(interval); } public void run() { _do_lookup(); Enumeration e = _syms.keys(); outlet(0,"BEGIN"); while(e.hasMoreElements()) { String[] nfo = (String[])_syms.get(e.nextElement()); Atom[] list = new Atom[]{Atom.newAtom(nfo[0]),Atom.newAtom(nfo[1]), Atom.newAtom(nfo[2]),Atom.newAtom(nfo[3]), Atom.newAtom(nfo[4])}; outlet(0,list); } outlet(0,"END"); } private void _add_quote(String sym) { sym = sym.toUpperCase(); if(!_syms.containsKey(sym)) { _syms.put(sym, new String[5]); } } private void _do_lookup() { try{ String url = genURL(); int c; URL u = new URL(url); BufferedInputStream in = new BufferedInputStream(u.openStream()); StringBuffer sb = new StringBuffer(); while((c = in.read()) != -1) { if(c == (int)' ') { _stuff_into_hash(sb.toString()); sb.setLength(0); continue; } sb.append((char)c); } in.close(); }catch(Exception e) { e.printStackTrace(); } } private String genURL() { Enumeration e = _syms.keys(); int cnt = 0; StringBuffer ret = new StringBuffer(_base_url); while(e.hasMoreElements()) { if(cnt == 0) ret.append(_sym_string+(String)e.nextElement()); else ret.append("+"+(String)e.nextElement()); cnt++; } return ret.toString(); } //indexOf(StringB str, intB fromIndex); private void _stuff_into_hash(String line) { byte[] b = line.getBytes(); StringBuffer word = new StringBuffer(); int idx = 0; String key = null; for(int i = 0; i < b.length;i++) { if(idx >= 5) break; if(b[i] == (byte)'"') continue; //skip quotes else if(b[i] == (byte)',' && idx == 0) //first word { key = word.toString(); ((String[])(_syms.get(key)))[idx] = word.toString(); idx++; word.setLength(0); continue; } else if(b[i] == (byte)',') { ((String[])(_syms.get(key)))[idx] = word.toString(); idx++; word.setLength(0); continue; } word.append((char)b[i]); } } protected void notifyDeleted() { _cl.release(); } } From topher at topher.com Mon Oct 22 12:49:10 2007 From: topher at topher.com (topher lafata) Date: Mon Oct 22 12:49:03 2007 Subject: [java-dev] Re: experience with stockwatch anyone? In-Reply-To: <1d025.471b4849@www.cycling74.com> References: <1d025.471b4849@www.cycling74.com> Message-ID: <5E1BF12B-C7F2-40F5-A972-31103D775321@topher.com> declareOutlets(new int[]{DataTypes.ALL,DataTypes.INT}); t On Oct 21, 2007, at 05:38 AM, Samuel Van Ransbeeck wrote: > > Ok, so i managed to do the first part (getting more info from the > SE) myself (however, still have to compile it) but another problem > is, I want to get the numbers hat i get in number boxes to use > those numbers as a source for my composition. Apparently you have > to create an outlet for that, but what should i write > declareOutlets(new int[]{DataTypes.ALL}); > this is alrteady there, but i now i only get in a message > box. What do I have to write to get a separate outlet for numbers? > Thanks in advance > amuel > > btw, here is the full code as it appears in the java folder of max > > import com.cycling74.max.*; > import java.net.*; > import java.io.*; > import java.util.Hashtable; > import java.util.Vector; > import java.util.Enumeration; > > //finance.yahoo.com/d/quotes.csv?f=sl1d1t1c1ohgv&e=.csv&s=INTC+SUNW > > public class StockWatch extends MaxObject implements Runnable, > Executable > { > //Attributes > double interval = 30 * 1000; //30 seconds > > static final int SYM = 0; > static final int LAST_TRADE = 1; > static final int DAY = 2; > static final int TIME = 3; > static final int CHANGE = 4; > > private String _base_url = "http://finance.yahoo.com/d/ > quotes.csv?f=sl1d1t1c1ohgv&e=.csv"; > private String _sym_string = "&s="; > private Hashtable _syms; > private boolean _first_sym = true; > private Thread _t; > private MaxClock _cl; > > > public StockWatch(Atom[] args) > { > declareInlets(new int[]{DataTypes.ALL}); > declareOutlets(new int[]{DataTypes.ALL}); > declareAttribute("interval","_get_interval","_set_interval"); > //virtual attribute > declareAttribute("quotes","_get_quotes","_set_quotes"); > > _syms = new Hashtable(); > _cl = new MaxClock(this); > } > > private void _set_interval(int i) > { > interval = i * 1000; > } > > private Atom[] _get_interval() > { > return new Atom[]{Atom.newAtom((float)interval / 1000)}; > } > > private void _set_quotes(Atom[] args) > { > _syms.clear(); > for(int i = 0; i < args.length; i++) > { > if(args[i].isString()) > _add_quote(args[i].toString()); > else > System.out.println("Invalid Symbol: "+args[i].toString()); > } > } > > private Atom[] _get_quotes() > { > Enumeration e = _syms.keys(); > Vector tmp = new Vector(); > Atom[] ret = null; > while(e.hasMoreElements()) > tmp.addElement(Atom.newAtom((String)e.nextElement())); > > ret = new Atom[tmp.size()]; > for(int i = 0; i < tmp.size();i++) > ret[i] = (Atom)tmp.elementAt(i); > > return ret; > } > > > public void bang() > { > _cl.delay(0); > } > > public void stop() > { > _cl.unset(); > } > > public void clear() > { > _syms.clear(); > } > > > public void addQuote(String quote) > { > _add_quote(quote); > } > > public void removeQuote(String quote) > { > quote = quote.toUpperCase(); > if(_syms.containsKey(quote)) > _syms.remove(quote); > } > > > public void execute() > { > > _t = new Thread(this); > try{ > _t.start(); > }catch(Exception e) > { > e.printStackTrace(); > } > > _cl.delay(interval); > } > > public void run() > { > _do_lookup(); > Enumeration e = _syms.keys(); > outlet(0,"BEGIN"); > while(e.hasMoreElements()) > { > String[] nfo = (String[])_syms.get(e.nextElement()); > Atom[] list = new Atom[]{Atom.newAtom(nfo[0]),Atom.newAtom(nfo[1]), > Atom.newAtom(nfo[2]),Atom.newAtom(nfo[3]), > Atom.newAtom(nfo[4])}; > outlet(0,list); > } > outlet(0,"END"); > > } > > private void _add_quote(String sym) > { > sym = sym.toUpperCase(); > if(!_syms.containsKey(sym)) > { > _syms.put(sym, new String[5]); > } > } > > private void _do_lookup() > { > try{ > String url = genURL(); > int c; > URL u = new URL(url); > BufferedInputStream in = new BufferedInputStream(u.openStream()); > StringBuffer sb = new StringBuffer(); > while((c = in.read()) != -1) > { > if(c == (int)' > ') > { > _stuff_into_hash(sb.toString()); > sb.setLength(0); > continue; > } > sb.append((char)c); > } > > in.close(); > }catch(Exception e) > { > e.printStackTrace(); > } > } > > private String genURL() > { > Enumeration e = _syms.keys(); > int cnt = 0; > StringBuffer ret = new StringBuffer(_base_url); > while(e.hasMoreElements()) > { > if(cnt == 0) > ret.append(_sym_string+(String)e.nextElement()); > else > ret.append("+"+(String)e.nextElement()); > cnt++; > } > return ret.toString(); > } > > //indexOf(StringB str, intB fromIndex); > private void _stuff_into_hash(String line) > { > byte[] b = line.getBytes(); > StringBuffer word = new StringBuffer(); > int idx = 0; > String key = null; > > for(int i = 0; i < b.length;i++) > { > if(idx >= 5) > break; > if(b[i] == (byte)'"') > continue; //skip quotes > else if(b[i] == (byte)',' && idx == 0) //first word > { > key = word.toString(); > ((String[])(_syms.get(key)))[idx] = word.toString(); > idx++; > word.setLength(0); > continue; > } > else if(b[i] == (byte)',') > { > ((String[])(_syms.get(key)))[idx] = word.toString(); > idx++; > word.setLength(0); > continue; > } > word.append((char)b[i]); > } > } > > protected void notifyDeleted() { > _cl.release(); > } > > > } > > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev From jmail at nospaces.net Tue Oct 23 04:41:13 2007 From: jmail at nospaces.net (Jonny) Date: Tue Oct 23 04:41:15 2007 Subject: [java-dev] Re: Re: experience with stockwatch anyone? In-Reply-To: <5E1BF12B-C7F2-40F5-A972-31103D775321@topher.com> Message-ID: <1d0be.471dcfc7@www.cycling74.com> Hi - sorry to come in a bit late on this thread, but i've been doing a lot of this for a new project recently and have written an mxj object that does all this quite nicely, if you know regular expressions (totally didn't spot the StockWatch example - could have saved myself lots of grief!). Actually it's a general "screen scraper" object that will go and get a list of strings and/or numbers from any web page at regular intervals, so it'll do weather monitoring, random words - you name it). I intend to release it in some sort of Open way at some point, but i need to get a lot of other stuff working before i get time to tidy up the code and look into licenses, documentation etc. In the mean time if it'll help i can mail you an example (but it looks like this thing is doing what you want anyway) Just thought i'd mention it, jonny B From jmail at nospaces.net Tue Oct 23 05:03:53 2007 From: jmail at nospaces.net (Jonny) Date: Tue Oct 23 05:03:54 2007 Subject: [java-dev] Re: Mxj don't like accents In-Reply-To: <1c20c.46e9a063@www.cycling74.com> Message-ID: <1d0c1.471dd519@www.cycling74.com> I take that as a "no" then? (as in, "no support for accented characters in or out of mxj for Max 4.x apart from posting to the Max window" - long filename support should be in a different thread, imho) Seems odd for such an international application... jb From leopold.frey at free.fr Tue Oct 23 06:15:35 2007 From: leopold.frey at free.fr (Léopold Frey) Date: Tue Oct 23 06:15:36 2007 Subject: [java-dev] Re: Mxj don't like accents In-Reply-To: <1d0c1.471dd519@www.cycling74.com> Message-ID: <1d0c8.471de5e7@www.cycling74.com> As Topher didn't post anything new on this subject I suppose he's busy with something else. IMHO don't expect a solution before Max 5, unless... leo From Thinksamuel at yahoo.com Tue Oct 23 11:52:59 2007 From: Thinksamuel at yahoo.com (Samuel Van Ransbeeck) Date: Tue Oct 23 11:53:00 2007 Subject: [java-dev] Re: experience with stockwatch anyone? In-Reply-To: <1c736.46fd5153@www.cycling74.com> Message-ID: <1d0e0.471e34fa@www.cycling74.com> Another question (i am really sorrry but java is quite difficult to learn in shorttime). Is there a way to split all the numbers in different number boxes, I mean, one numberbox for the last trade, one for the change in value of the stock and so on? And this should happen for all stockzs separately. I want to get all the information for each stock and then make a markov patch using the numbers. THe polyphony increases as you add stock to be sonified. Again, sorry for asking so much but I just got to know java so it's still difficult. Thanks a lot Samuel From tarikbarri at hotmail.com Wed Oct 24 07:19:02 2007 From: tarikbarri at hotmail.com (Tarik) Date: Wed Oct 24 07:19:09 2007 Subject: [java-dev] noobie noob-question Message-ID: <1d120.471f4645@www.cycling74.com> Hi, I'm starting to use jitter objects within my Java code and I'm having some problems starting up. Now I've made a JitterObject which refers to a jit.qt.movie. I can get this object to read the movie I want, but I can't send a bang to this object. Max tells me: 'error: jit_qt_movie: doesn't understand "bang" ' So then I try setting the frame numbers manually and performing a matrixCalc("bang", outputMatrix) operation. This gives me the first frame of the movie, no matter what kind of "frame" message I sent to this movie. Oh yeah, and it does exactly the same when I use matrixCalc("blahblahblah", outputMatrix)... instead of an error what I would expect. I realize that these are very basic concepts and unfortunately I'm not grasping them yet. Can anybody pretty please tell me what it is about bangs and matrixCalc etc. that I'm not understanding here? From adam.stark at elec.qmul.ac.uk Wed Oct 24 08:54:12 2007 From: adam.stark at elec.qmul.ac.uk (Adam Stark) Date: Wed Oct 24 08:54:14 2007 Subject: [java-dev] How efficient is coding objects using Java? Message-ID: <1d127.471f5c93@www.cycling74.com> Hi, I have just written an MSP pitch detector object in java. It works perfectly but has a very high load on the CPU. In fact, if I use a signal vector size of more than 256 it causes clicking artefacts in the audio. The code isn't really that big and I am using a brand new intel mac book 2.2 GHz machine. Is this because of some speed limitation of using mxj quickie to build java objects? How could I improve the speed? I am normally a C programmer and have coded much much larger things that run in real-time as VST plug-ins for example - and they generally are not that much of a burden on the CPU. I know Java is slower than C but I didn't expect it to be quite so limiting, is there something I am doing wrong? Alternatively, if anyone could point me to a good introduction to programming Max/MSP objects in C I would be very grateful (apologies as this question prob should go in the other forum but the first question should be here...). I'd be very happy if someone could point me in the right direction, Many thanks, Adam From topher at topher.com Wed Oct 24 11:16:06 2007 From: topher at topher.com (topher lafata) Date: Wed Oct 24 11:15:55 2007 Subject: [java-dev] How efficient is coding objects using Java? In-Reply-To: <1d127.471f5c93@www.cycling74.com> References: <1d127.471f5c93@www.cycling74.com> Message-ID: <0938B570-2645-43F8-BCD6-8D6A1DA3AB9B@topher.com> Java is definitely slower than C but it is possible with some care to get it running pretty efficiently. I could take a look at your code if you want. Things to avoid are unnecessary object allocation, method call overhead, etc. Generally having a knowledge of what the JVM will do when it executes certain instructions. I generally tend to think as if I am writing C code when writing mxj~ stuff and stay as much as possible with the primitive constructs of the java language. Hope this is helpful. Topher On Oct 24, 2007, at 07:54 AM, Adam Stark wrote: > > Hi, > > I have just written an MSP pitch detector object in java. It works > perfectly but has a very high load on the CPU. In fact, if I use a > signal vector size of more than 256 it causes clicking artefacts in > the audio. The code isn't really that big and I am using a brand > new intel mac book 2.2 GHz machine. > > Is this because of some speed limitation of using mxj quickie to > build java objects? How could I improve the speed? > > I am normally a C programmer and have coded much much larger things > that run in real-time as VST plug-ins for example - and they > generally are not that much of a burden on the CPU. I know Java is > slower than C but I didn't expect it to be quite so limiting, is > there something I am doing wrong? > > Alternatively, if anyone could point me to a good introduction to > programming Max/MSP objects in C I would be very grateful > (apologies as this question prob should go in the other forum but > the first question should be here...). > > I'd be very happy if someone could point me in the right direction, > > Many thanks, > > Adam > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev From topher at topher.com Wed Oct 24 11:23:43 2007 From: topher at topher.com (topher lafata) Date: Wed Oct 24 11:23:33 2007 Subject: [java-dev] How efficient is coding objects using Java? In-Reply-To: <1d127.471f5c93@www.cycling74.com> References: <1d127.471f5c93@www.cycling74.com> Message-ID: also... Using the benchmark message allows you to quantify any optimizations that you might be making and could be helpful if you are not aware of it. See the mxj~ examples for use of the benchmark message. T On Oct 24, 2007, at 07:54 AM, Adam Stark wrote: > > Hi, > > I have just written an MSP pitch detector object in java. It works > perfectly but has a very high load on the CPU. In fact, if I use a > signal vector size of more than 256 it causes clicking artefacts in > the audio. The code isn't really that big and I am using a brand > new intel mac book 2.2 GHz machine. > > Is this because of some speed limitation of using mxj quickie to > build java objects? How could I improve the speed? > > I am normally a C programmer and have coded much much larger things > that run in real-time as VST plug-ins for example - and they > generally are not that much of a burden on the CPU. I know Java is > slower than C but I didn't expect it to be quite so limiting, is > there something I am doing wrong? > > Alternatively, if anyone could point me to a good introduction to > programming Max/MSP objects in C I would be very grateful > (apologies as this question prob should go in the other forum but > the first question should be here...). > > I'd be very happy if someone could point me in the right direction, > > Many thanks, > > Adam > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev From adam.stark at elec.qmul.ac.uk Thu Oct 25 07:19:11 2007 From: adam.stark at elec.qmul.ac.uk (Adam Stark) Date: Thu Oct 25 07:19:37 2007 Subject: [java-dev] Re: How efficient is coding objects using Java? In-Reply-To: <0938B570-2645-43F8-BCD6-8D6A1DA3AB9B@topher.com> Message-ID: <1d194.472097cd@www.cycling74.com> Hi Topher, Thanks for your replies. It would be great if you could have a look at my code. I have attached the java file. The function causing the problems is the pitch_YIN function. I also have one more question which is about C coding Max/MSP objects - so far, all the examples I have seen so far in C have been massively complex, uncommented and unexplained. The Java equivalent is so simple. Is there a simple C example somewhere or a good guide? Or is it generally complicated? I'm very very appreciative of your help, Thanks Adam -------------- next part -------------- A non-text attachment was scrubbed... Name: pitch_YIN.java Type: application/octet-stream Size: 4723 bytes Desc: not available Url : http://www.cycling74.com/pipermail/java-dev/attachments/20071025/6be344db/pitch_YIN.obj From topher at topher.com Thu Oct 25 07:45:31 2007 From: topher at topher.com (topher lafata) Date: Thu Oct 25 07:45:36 2007 Subject: [java-dev] Re: How efficient is coding objects using Java? In-Reply-To: <1d194.472097cd@www.cycling74.com> References: <1d194.472097cd@www.cycling74.com> Message-ID: <1193319934.2017E421@bf12.dngr.org> Hola I am about to get on a plane here but will check the code in the next day or so. The c external api is covered in writing max/msp externals by david zicarelli. It is not overly complicated. Just a little different. I agree that there could be a higher level c api for externs. I was working on a similar object to mxj called cfunk that addresses these issues by allowing you to write in a similar way but in c instead of java .I have stopped development of cfunk but perhaps I will finish it up someday or someone else is interested in taking it over. From tarikbarri at hotmail.com Fri Oct 26 08:19:50 2007 From: tarikbarri at hotmail.com (Tarik) Date: Fri Oct 26 08:19:56 2007 Subject: [java-dev] Re: noobie noob-question In-Reply-To: <1d120.471f4645@www.cycling74.com> Message-ID: <1d1ce.4721f785@www.cycling74.com> ...and now I'm wondering why it would take such a time for my question to be answered. Some possibilities are: 1. my question is not specific enough. 2. my question is really too stupid to be taken seriously. 3. my question is just too hard to answer. 4. I'm just being too impatient. From vboehm at gmx.ch Fri Oct 26 09:45:06 2007 From: vboehm at gmx.ch (=?ISO-8859-1?Q?volker_b=F6hm?=) Date: Fri Oct 26 09:44:44 2007 Subject: [java-dev] Re: How efficient is coding objects using Java? In-Reply-To: <1d194.472097cd@www.cycling74.com> References: <1d194.472097cd@www.cycling74.com> Message-ID: hi adam, the reason why your code is slow is not due to the language (at least not entirely), but to the fact that you try to calculate the square difference function in the time domain. in the nested for- loops you are doing a lot of calculations... this wouldn't be efficient in C either. but using FFT you can easily calculate the auto-correlation much quicker. i believe that's the trick other yin-pitchtrackers use. volker. On 25 Oct 2007, at 15:19, Adam Stark wrote: > Hi Topher, > > Thanks for your replies. It would be great if you could have a look > at my code. I have attached the java file. The function causing the > problems is the pitch_YIN function. > > I also have one more question which is about C coding Max/MSP > objects - so far, all the examples I have seen so far in C have > been massively complex, uncommented and unexplained. The Java > equivalent is so simple. Is there a simple C example somewhere or a > good guide? Or is it generally complicated? > > I'm very very appreciative of your help, > > Thanks > > Adam > > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev From adam.stark at elec.qmul.ac.uk Fri Oct 26 10:02:16 2007 From: adam.stark at elec.qmul.ac.uk (Adam Stark) Date: Fri Oct 26 10:02:18 2007 Subject: [java-dev] Re: Re: How efficient is coding objects using Java? In-Reply-To: Message-ID: <1d1d7.47220f87@www.cycling74.com> Hi volker, Yes, that is a good suggestion and would make it run much faster. I also found another problem. This is maybe very obvious to more experienced Java users but I am new to using Java for signal processing: I found that, in my loop, when I calculated the square of a number using: Math.pow(x,2); my function took 19ms to do it's calculations. However, when I used: x*x the processing time was reduced to just 3ms. Anyway, thank you everyone for your help, Adam From jkc at musork.com Fri Oct 26 10:19:33 2007 From: jkc at musork.com (Joshua Kit Clayton) Date: Fri Oct 26 10:19:46 2007 Subject: [java-dev] Re: How efficient is coding objects using Java? In-Reply-To: References: <1d194.472097cd@www.cycling74.com> Message-ID: <76376DB4-74EB-4ACE-BFBF-155AC1047C83@musork.com> On Oct 26, 2007, at 8:45 AM, volker b?hm wrote: > hi adam, > the reason why your code is slow is not due to the language (at > least not entirely), but to the fact that you try to calculate > the square difference function in the time domain. in the nested > for-loops you are doing a lot of calculations... > this wouldn't be efficient in C either. > but using FFT you can easily calculate the auto-correlation much > quicker. > i believe that's the trick other yin-pitchtrackers use. If for some reason you need to stay in the time domain, however, there are some way that you can optimize this code considerably. Here's a few things that stood out on quick glance. 0. if you use a smaller window size (n), your nested loop of "for (int t = 1;t < n;t++) { ... for (int i=0;i < (n-t);i++) { ...} }" will be much faster. 1. Math.pow(x,2) is equivalent to (x*x), which will be *much* faster. Always avoid pow() and sqrt() whenever you can. 2. Division is *much* more expensive than multiplication. Things like x/(1/y) are mathematically equivalent to x*y. And if you are doing something like the following iterative division: for (i=0;i References: <1d1d7.47220f87@www.cycling74.com> Message-ID: <1193416505.2889A3A5@dj11.dngr.org> I still haven't found a spot to view your attachment but that makes sense. Method call overhead in tight loops adds up and the java Math library is typicaly slow on top of that. In the mxj~ noise examples you wil see I opted to write my own random fucntion instead of using Math.nextfloat. It seems like you are able to make use of the benchmarking stuff as well. Kudos. From Thinksamuel at yahoo.com Mon Oct 29 12:19:17 2007 From: Thinksamuel at yahoo.com (Samuel Van Ransbeeck) Date: Mon Oct 29 12:19:19 2007 Subject: [java-dev] Re: experience with stockwatch anyone? In-Reply-To: <1c736.46fd5153@www.cycling74.com> Message-ID: <1d2cb.47262424@www.cycling74.com> It doesn't work :( I added the int and a float outlet and i don't get any numbers out of there, even not in the max window. I really don't know what to do more. In the meantime i discovered the Javatutorials of max, i didn't know there were and the compilation is really simple but still, I don't book any results. What should I do. I am already happy if I can get just 1 stock giing information, if necessary I just make this a subpatch and let for every stock this subpatch be used, with each stock a specific name. From topher at topher.com Mon Oct 29 12:37:30 2007 From: topher at topher.com (topher lafata) Date: Mon Oct 29 12:37:35 2007 Subject: [java-dev] Re: experience with stockwatch anyone? In-Reply-To: <1d2cb.47262424@www.cycling74.com> References: <1d2cb.47262424@www.cycling74.com> Message-ID: <85EEE748-F2F6-42F8-821D-0A9AD0CA28BE@topher.com> if you post your code perhaps someone could help with what is going wrong. t On Oct 29, 2007, at 11:19 AM, Samuel Van Ransbeeck wrote: > > It doesn't work :( > I added the int and a float outlet and i don't get any numbers out > of there, even not in the max window. I really don't know what to > do more. In the meantime i discovered the Javatutorials of max, i > didn't know there were and the compilation is really simple but > still, I don't book any results. What should I do. I am already > happy if I can get just 1 stock giing information, if necessary I > just make this a subpatch and let for every stock this subpatch be > used, with each stock a specific name. > > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev From Thinksamuel at yahoo.com Mon Oct 29 12:43:45 2007 From: Thinksamuel at yahoo.com (Samuel Van Ransbeeck) Date: Mon Oct 29 12:43:47 2007 Subject: [java-dev] Re: experience with stockwatch anyone? In-Reply-To: <1c736.46fd5153@www.cycling74.com> Message-ID: <1d2d9.472629e1@www.cycling74.com> here you go -------------- next part -------------- A non-text attachment was scrubbed... Name: StockWatch.java Type: application/octet-stream Size: 4689 bytes Desc: not available Url : http://www.cycling74.com/pipermail/java-dev/attachments/20071029/9b2391fb/StockWatch.obj From topher at topher.com Mon Oct 29 14:45:43 2007 From: topher at topher.com (topher lafata) Date: Mon Oct 29 14:45:50 2007 Subject: [java-dev] Re: experience with stockwatch anyone? In-Reply-To: <1d2cb.47262424@www.cycling74.com> References: <1d2cb.47262424@www.cycling74.com> Message-ID: I dont really understand totally what you are trying to do but to send something out the FLOAT outlet you created you need to use: outlet(1,floatdata) t On Oct 29, 2007, at 11:19 AM, Samuel Van Ransbeeck wrote: > > It doesn't work :( > I added the int and a float outlet and i don't get any numbers out > of there, even not in the max window. I really don't know what to > do more. In the meantime i discovered the Javatutorials of max, i > didn't know there were and the compilation is really simple but > still, I don't book any results. What should I do. I am already > happy if I can get just 1 stock giing information, if necessary I > just make this a subpatch and let for every stock this subpatch be > used, with each stock a specific name. > > _______________________________________________ > java-dev mailing list > java-dev@cycling74.com > http://www.cycling74.com/mailman/listinfo/java-dev From Thinksamuel at yahoo.com Tue Oct 30 03:16:44 2007 From: Thinksamuel at yahoo.com (Samuel Van Ransbeeck) Date: Tue Oct 30 03:16:46 2007 Subject: [java-dev] Re: experience with stockwatch anyone? In-Reply-To: <1c736.46fd5153@www.cycling74.com> Message-ID: <1d2f5.4726f67c@www.cycling74.com> Ok, I will check how to implement that. This is what I want to do. The java object is collecting stock excgange data. This data I want to use as a source for pitch information and velocity (and then manipulate them further in Max). For this I need to get the numbers out some way. From mattijs at smadsteck.nl Tue Oct 30 10:32:51 2007 From: mattijs at smadsteck.nl (Mattijs Kneppers) Date: Tue Oct 30 10:32:54 2007 Subject: [java-dev] Re: noobie noob-question In-Reply-To: <1d1ce.4721f785@www.cycling74.com> Message-ID: <1d315.47275cb3@www.cycling74.com> Quote: Tarik wrote on Fri, 26 October 2007 16:19 ---------------------------------------------------- > ...and now I'm wondering why it would take such a time for my question to be answered. Some possibilities are: > > 1. my question is not specific enough. > 2. my question is really too stupid to be taken seriously. > 3. my question is just too hard to answer. > 4. I'm just being too impatient. ---------------------------------------------------- None of the above. You didn't provide example code. Mattijs -- SmadSteck - http://www.smadsteck.nl Hard- and software for interactive audiovisual sampling From tmd4u at virginia.edu Tue Oct 30 14:40:54 2007 From: tmd4u at virginia.edu (Timothy Dalbey) Date: Tue Oct 30 14:40:55 2007 Subject: [java-dev] Trying to create a mxj socket listener Message-ID: <1d32a.472796d5@www.cycling74.com> First the SBOD then crash. Is this because of a threading issue? I basically created a while(true){listen to the socket} method. Any advice? Anywhere I should look in particular? From nick at cassiel.com Tue Oct 30 14:53:20 2007 From: nick at cassiel.com (Nick Rothwell) Date: Tue Oct 30 14:53:31 2007 Subject: [java-dev] Trying to create a mxj socket listener In-Reply-To: <1d32a.472796d5@www.cycling74.com> References: <1d32a.472796d5@www.cycling74.com> Message-ID: On 30 Oct 2007, at 20:40, Timothy Dalbey wrote: > First the SBOD then crash. Is this because of a threading issue? Probably: I've written socket listeners for MXJ without any problems. Here's a hack to an O'Reilly demo I did some years ago to demo how to build a TCP/IP server for MXJ. (Apologies to everyone else for the noise...) --- // This example is from _Java Examples in a Nutshell_. (http:// www.oreilly.com) // Copyright (c) 1997 by David Flanagan // This example is provided WITHOUT ANY WARRANTY either expressed or implied. // You may study, use, modify, and distribute it for non-commercial purposes. // For any commercial use, see http://www.davidflanagan.com/javaexamples package net.loadbang.mxj.demo; import java.io.*; import java.net.*; import java.util.*; import com.cycling74.max.*; /** * This class is a generic framework for a flexible, multi-threaded server. * It listens on any number of specified ports, and, when it receives a * connection on a port, passes input and output streams to a specified Service * object which provides the actual service. It can limit the number of * concurrent connections, and logs activity to a specified stream. **/ public class Server extends MaxObject { /** * A main() method for running the server as a standalone program. * The command-line arguments to the program should be pairs of servicenames * and port numbers. For each pair, the program will dynamically load the * named Service class, instantiate it, and tell the server to provide that * Service on the specified port. The special -control argument should be * followed by a password and port, and will start special server control * service running on the specified port, protected by the specified * password. **/ /* public static void main(String[] args) { try { if (args.length < 2) // Check number of arguments throw new IllegalArgumentException("Must start at least one service"); // Create a Server object that uses standard out as its log and // has a limit of ten concurrent connections at once. Server s = new Server(System.out, 10); // Parse the argument list int i = 0; while(i < args.length) { if (args[i].equals("-control")) { // Handle the -control argument i++; String password = args[i++]; int port = Integer.parseInt(args[i++]); s.addService(new Control(s, password), port); // add control service } else { // Otherwise start a named service on the specified port. // Dynamically load and instantiate a class that implements Service. String serviceName = args[i++]; Class serviceClass = Class.forName(serviceName); // dynamic load Service service = (Service)serviceClass.newInstance(); // instantiate int port = Integer.parseInt(args[i++]); s.addService(service, port); } } } catch (Exception e) { // Display a message if anything goes wrong System.err.println("Server: " + e); System.err.println("Usage: java Server [-control ] " + "[ ... ]"); System.exit(1); } }*/ public Server() { createInfoOutlet(false); declareTypedIO("A","M"); init(null, 10); } public void serve(String name, int port) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException { Class serviceClass = Class.forName(name); // dynamic load Service service = (Service) serviceClass.newInstance(); // instantiate addService(service, port); } // This is the state for the server ConnectionManager connectionManager; // The ConnectionManager object Hashtable services; // The current services and their ports ThreadGroup threadGroup; // The threadgroup for all our threads PrintWriter logStream; // Where we send our logging output to /** * This is the Server() constructor. It must be passed a stream * to send log output to (may be null), and the limit on the number of * concurrent connections. It creates and starts a ConnectionManager * thread which enforces this limit on connections. **/ private void init(OutputStream logStream, int maxConnections) { log("Starting server"); threadGroup = new ThreadGroup("Server"); connectionManager = new ConnectionManager(threadGroup, maxConnections); connectionManager.start(); services = new Hashtable(); } /** Write the specified string to the log */ protected synchronized void log(String s) { outlet(0, "[" + s + "]"); } /** Write the specified object to the log */ protected void log(Object o) { log(o.toString()); } /** * This method makes the server start providing a new service. * It runs the specified Service object on the specified port. **/ public void addService(Service service, int port) throws IOException { Integer key = new Integer(port); // the hashtable key // Check whether a service is already on that port if (services.get(key) != null) throw new IllegalArgumentException("Port " + port + " already in use."); // Create a Listener object to listen for connections on the port Listener listener = new Listener(threadGroup, port, service); // Store it in the hashtable services.put(key, listener); // Log it log("Starting service " + service.getClass().getName() + " on port " + port); // Start the listener running. listener.start(); } /** * This method makes the server stop providing a service on a port. * It does not terminate any pending connections to that service, merely * causes the server to stop accepting new connections **/ public void removeService(int port) { Integer key = new Integer(port); // hashtable key // Look up the Listener object for the port in the hashtable of services final Listener listener = (Listener) services.get(key); if (listener == null) return; // Ask the listener to stop listener.pleaseStop(); // Remove it from the hashtable services.remove(key); // And log it. log("Stopping service " + listener.service.getClass().getName() + " on port " + port); } /** * This nested Thread subclass is a "listener". It listens for connections * on a specified port (using a ServerSocket) and when it gets a connection * request, it calls a method of the ConnectionManager to accept (or reject) * the connection. There is one Listener for each Service being provided * by the Server. The Listener passes the Server object to the * ConnectionManager, but doesn't do anything with it itself. */ public class Listener extends Thread { ServerSocket listen_socket; // The socket we listen for connections on int port; // The port we're listening on Service service; // The service to provide on that port boolean stop = false; // Whether we've been asked to stop /** * The Listener constructor creates a thread for itself in the specified * threadgroup. It creates a ServerSocket to listen for connections * on the specified port. It arranges for the ServerSocket to be * interruptible, so that services can be removed from the server. **/ public Listener(ThreadGroup group, int port, Service service) throws IOException { super(group, "Listener:" + port); listen_socket = new ServerSocket(port); // give the socket a non-zero timeout so accept() can be interrupted listen_socket.setSoTimeout(600000); this.port = port; this.service = service; } /** This is the nice way to get a Listener to stop accepting connections */ public void pleaseStop() { this.stop = true; // set the stop flag this.interrupt(); // and make the accept() call stop blocking } /** * A Listener is a Thread, and this is its body. * Wait for connection requests, accept them, and pass the socket on * to the ConnectionManager object of this server **/ @Override public void run() { while(!stop) { // loop until we're asked to stop. try { Socket client = listen_socket.accept(); connectionManager.addConnection(client, service); } catch (InterruptedIOException e) {} catch (IOException e) {log(e);} } } } /** * This nested class manages client connections for the server. * It maintains a list of current connections and enforces the * maximum connection limit. It creates a separate thread (one per * server) that sits around and wait()s to be notify()'d that a connection * has terminated. When this happens, it updates the list of connections. **/ public class ConnectionManager extends Thread { int maxConnections; // The maximum number of allowed connections Vector connections; // The current list of connections /** * Create a ConnectionManager in the specified thread group to enforce * the specified maximum connection limit. Make it a daemon thread so * the interpreter won't wait around for it to exit. **/ public ConnectionManager(ThreadGroup group, int maxConnections) { super(group, "ConnectionManager"); this.setDaemon(true); this.maxConnections = maxConnections; connections = new Vector(maxConnections); log("Starting connection manager. Max connections: " + maxConnections); } /** * This is the method that Listener objects call when they accept a * connection from a client. It either creates a Connection object * for the connection and adds it to the list of current connections, * or, if the limit on connections has been reached, it closes the * connection. **/ synchronized void addConnection(Socket s, Service service) { // If the connection limit has been reached if (connections.size() >= maxConnections) { try { PrintWriter out = new PrintWriter(s.getOutputStream()); // Then tell the client it is being rejected. out.println("Connection refused; " + "server has reached maximum number of clients."); out.flush(); // And close the connection to the rejected client. s.close(); // And log it, of course log("Connection refused to " + s.getInetAddress ().getHostAddress() + ":" + s.getPort() + ": max connections reached."); } catch (IOException e) {log(e);} } else { // Otherwise, if the limit has not been reached // Create a Connection thread to handle this connection Connection c = new Connection(s, service); // Add it to the list of current connections connections.addElement(c); // Log this new connection log("Connected to " + s.getInetAddress().getHostAddress() + ":" + s.getPort() + " on port " + s.getLocalPort() + " for service " + service.getClass().getName()); // And start the Connection thread running to provide the service c.start(); } } /** * A Connection object calls this method just before it exits. * This method uses notify() to tell the ConnectionManager thread * to wake up and delete the thread that has exited. **/ public synchronized void endConnection() { this.notify(); } /** Change the current connection limit */ public synchronized void setMaxConnections(int max) { maxConnections=max; } /** * Output the current list of connections to the specified stream. * This method is used by the Control service defined below. **/ public synchronized void printConnections(PrintWriter out) { for(int i = 0; i < connections.size(); i++) { Connection c = (Connection)connections.elementAt(i); out.println("CONNECTED TO " + c.client.getInetAddress().getHostAddress() + ":" + c.client.getPort() + " ON PORT " + c.client.getLocalPort()+ " FOR SERVICE " + c.service.getClass().getName()); } } /** * The ConnectionManager is a thread, and this is the body of that * thread. While the ConnectionManager methods above are called by other * threads, this method is run in its own thread. The job of this thread * is to keep the list of connections up to date by removing connections * that are no longer alive. It uses wait() to block until notify()'d by * the endConnection() method. **/ @Override public void run() { while(true) { // infinite loop // Check through the list of connections, removing dead ones for(int i = 0; i < connections.size(); i++) { Connection c = (Connection)connections.elementAt(i); if (!c.isAlive()) { connections.removeElementAt(i); log("Connection to " + c.client.getInetAddress ().getHostAddress() + ":" + c.client.getPort() + " closed."); } } // Now wait to be notify()'d that a connection has exited // When we wake up we'll check the list of connections again. try { synchronized(this) { this.wait(); } } catch(InterruptedException e) {} } } } /** * This class is a subclass of Thread that handles an individual connection * between a client and a Service provided by this server. Because each * such connection has a thread of its own, each Service can have multiple * connections pending at once. Despite all the other threads in use, this * is the key feature that makes this a multi-threaded server implementation. **/ public class Connection extends Thread { Socket client; // The socket to talk to the client through Service service; // The service being provided to that client /** * This constructor just saves some state and calls the superclass * constructor to create a thread to handle the connection. Connection * objects are created by Listener threads. These threads are part of * the server's ThreadGroup, so all Connection threads are part of that * group, too. **/ public Connection(Socket client, Service service) { super("Server.Connection:" + client.getInetAddress ().getHostAddress() + ":" + client.getPort()); this.client = client; this.service = service; } /** * This is the body of each and every Connection thread. * All it does is pass the client input and output streams to the * serve() method of the specified Service object. That method * is responsible for reading from and writing to those streams to * provide the actual service. Recall that the Service object has been * passed from the Server.addService() method to a Listener object * to the ConnectionManager.addConnection() to this Connection object, * and is now finally getting used to provide the service. * Note that just before this thread exits it calls the * ConnectionManager.endConnection() method to wake up the * ConnectionManager thread so that it can remove this Connection * from its list of active connections. **/ @Override public void run() { try { InputStream in = client.getInputStream(); OutputStream out = client.getOutputStream(); service.serve(in, out, itsLogger); } catch (IOException e) {log(e);} finally { connectionManager.endConnection(); } } } /** A logging (outlet) interface. */ public interface Logger { public void log(String line); } /** * Here is the Service interface that we have seen so much of. * It defines only a single method which is invoked to provide the service. * serve() will be passed an input stream and an output stream to the client. * It should do whatever it wants with them, and should close them before * returning. * * All connections through the same port to this service share a single * Service object. Thus, any state local to an individual connection must * be stored in local variables within the serve() method. State that should * be global to all connections on the same port should be stored in * instance variables of the Service class. If the same Service is running * on more than one port, there will typically be different Service instances * for each port. Data that should be global to all connections on any port * should be stored in static variables. * * Note that implementations of this interface must have a no- argument * constructor if they are to be dynamically instantiated by the main() * method of the Server class. **/ public interface Service { public void serve(InputStream in, OutputStream out, Logger logger) throws IOException; } private Logger itsLogger = new Logger() { public void log(String line) { outlet(0, line); } }; /** * This service is an HTTP mirror, just like the HttpMirror class * implemented earlier in this chapter. It echos back the client's * HTTP request **/ public static class HTTPMirror implements Service { public void serve(InputStream i, OutputStream o, Logger logger) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(i)); PrintWriter out = new PrintWriter(new OutputStreamWriter(o)); out.println("HTTP/1.0 200 "); out.println("Content-Type: text/plain"); out.println(); String line; while((line = in.readLine()) != null) { if (line.length() == 0) break; out.println(line); } out.close(); in.close(); } } /** * This service demonstrates how to maintain state across connections * by saving it in instance variables and using synchronized access to * those variables. It maintains a count of how many clients have connected * and tells each client what number it is **/ public static class UniqueID implements Service { public int id=0; public synchronized int nextId() { return id++; } public void serve(InputStream i, OutputStream o, Logger logger) throws IOException { PrintWriter out = new PrintWriter(new OutputStreamWriter(o)); out.println("You are client #: " + nextId()); out.close(); i.close(); } } /** * This is a non-trivial service. It implements a command-based protocol * that gives password-protected runtime control over the operation of the * server. See the main() method of the Server class to see how this * service is started. * * The recognized commands are: * password: give password; authorization is required for most commands * add: dynamically add a named service on a specified port * remove: dynamically remove the service running on a specified port * max: change the current maximum connection limit. * status: display current services, connections, and connection limit * help: display a help message * quit: disconnect * * This service displays a prompt, and sends all of its output to the user * in capital letters. Only one client is allowed to connect to this service * at a time. **/ public static class Control implements Service { Server server; // The server we control String password; // The password we require boolean connected = false; // Whether a client is already connected to us /** * Create a new Control service. It will control the specified Server * object, and will require the specified password for authorization * Note that this Service does not have a no argument constructor, which * means that it cannot be dynamically instantiated and added as the other, * generic services above can be. **/ public Control(Server server, String password) { this.server = server; this.password = password; } /** * This is the serve method that provides the service. It reads a line * the client, and uses java.util.StringTokenizer to parse it into * commands and arguments. It does various things depending on the * command. **/ public void serve(InputStream i, OutputStream o, Logger logger) throws IOException { // Setup the streams BufferedReader in = new BufferedReader(new InputStreamReader(i)); PrintWriter out = new PrintWriter(new OutputStreamWriter(o)); String line; boolean authorized = false; // Has the user has given the password yet? // If there is already a client connected to this service, display a // message to this client and close the connection. We use a // synchronized block to prevent a race condition. synchronized(this) { if (connected) { out.println("ONLY ONE CONTROL CONNECTION ALLOWED AT A TIME."); out.close(); return; } else connected = true; } for(;;) { // infinite loop out.print("> "); // Display a prompt out.flush(); // Make it appear right away line = in.readLine(); // Get the user's input if (line == null) break; // Quit if we get EOF. try { // Use a StringTokenizer to parse the user's command StringTokenizer t = new StringTokenizer(line); if (!t.hasMoreTokens()) continue; // if input was blank line // Get the first word of the input and convert to lower case String command = t.nextToken().toLowerCase(); // Now compare it to each of the possible commands, doing the // appropriate thing for each command if (command.equals("password")) { // Password command String p = t.nextToken(); // Get the next word of input if (p.equals(this.password)) { // Does it equal the password out.println("OK"); // Say so authorized = true; // Grant authorization } else out.println("INVALID PASSWORD"); // Otherwise fail } else if (command.equals("add")) { // Add Service command // Check whether password has been given if (!authorized) out.println("PASSWORD REQUIRED"); else { // Get the name of the service and try to dynamically load // and instantiate it. Exceptions will be handled below String serviceName = t.nextToken(); Class serviceClass = Class.forName(serviceName); Service service; try { service = (Service) serviceClass.newInstance(); } catch (NoSuchMethodError e) { throw new IllegalArgumentException("Service must have a " + "no-argument constructor"); } int port = Integer.parseInt(t.nextToken()); // If no exceptions occurred, add the service server.addService(service, port); out.println("SERVICE ADDED"); // acknowledge } } else if (command.equals("remove")) { // Remove service command if (!authorized) out.println("PASSWORD REQUIRED"); else { int port = Integer.parseInt(t.nextToken()); // get port server.removeService(port); // remove the service on it out.println("SERVICE REMOVED"); // acknowledge } } else if (command.equals("max")) { // Set max connection limit if (!authorized) out.println("PASSWORD REQUIRED"); else { int max = Integer.parseInt(t.nextToken()); // get limit server.connectionManager.setMaxConnections(max); // set limit out.println("MAX CONNECTIONS CHANGED"); // acknowledge } } else if (command.equals("status")) { // Status Display command if (!authorized) out.println("PASSWORD REQUIRED"); else { // Display a list of all services currently running Enumeration keys = server.services.keys(); while(keys.hasMoreElements()) { Integer port = (Integer) keys.nextElement(); Listener listener = (Listener)server.services.get (port); out.println("SERVICE " + listener.service.getClass ().getName()+ " ON PORT " + port); } // Display a list of all current connections server.connectionManager.printConnections(out); // Display the current connection limit out.println("MAX CONNECTIONS: " + server.connectionManager.maxConnections); } } else if (command.equals("help")) { // Help command // Display command syntax. Password not required out.println("COMMANDS:\n" + "\tpassword \n" + "\tadd \n" + "\tremove \n" + "\tmax \n" + "\tstatus\n" + "\thelp\n" + "\tquit"); } else if (command.equals("quit")) break; // Quit command. Exit. else out.println("UNRECOGNIZED COMMAND"); // Unknown command error } catch (Exception e) { // If an exception occurred during the command, print an error // message, then output details of the exception. out.println("EXCEPTION WHILE PARSING OR EXECUTING COMMAND:"); out.println(e); } } // Finally, when the loop command loop ends, close the streams // and set our connected flag to false so that other clients can // now connect. out.close(); in.close(); connected = false; } } } Nick Rothwell / Cassiel.com Limited www.cassiel.com www.myspace.com/cassieldotcom www.last.fm/music/cassiel www.loadbang.net