<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://sessrumnir.net/fernseher/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=129.42.161.36</id>
	<title>Fernseher - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="http://sessrumnir.net/fernseher/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=129.42.161.36"/>
	<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Special:Contributions/129.42.161.36"/>
	<updated>2026-07-01T06:59:30Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Theoretical_Pipe_Variations&amp;diff=2137</id>
		<title>Theoretical Pipe Variations</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Theoretical_Pipe_Variations&amp;diff=2137"/>
		<updated>2009-03-30T23:02:53Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: A set of characteristics of pipe spectra, useful in categorizing actual pipe sounds as well as synthesizing them.  ===Frequency Variations=== *Typical large organ range is from 32&amp;#039; to 2&amp;#039; s...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A set of characteristics of pipe spectra, useful in categorizing actual pipe sounds as well as synthesizing them.&lt;br /&gt;
&lt;br /&gt;
===Frequency Variations===&lt;br /&gt;
*Typical large organ range is from 32&amp;#039; to 2&amp;#039; stops, which puts us around C0 up through C9, or 9 octaves and a note.  This is 109 notes. (N)&lt;br /&gt;
*For a given note, there are several possible mutation frequencies that pipes could have that would not fall on perfect equal temperament notes: (M)&lt;br /&gt;
**Harmonic 1: Unison (that is, no mutation)  (N+0.00)&lt;br /&gt;
**Harmonic 3: Twelfth (N+19.02)&lt;br /&gt;
**Harmonic 5: Seventeenth (N+27.86)&lt;br /&gt;
**Harmonic 6: Nineteenth (N+31.02)&lt;br /&gt;
**Harmonic 7: Twentieth (N+33.69)&lt;br /&gt;
**Harmonic 9: Twenty-third (N+38.04)&lt;br /&gt;
*For each mutation of each note, we could be slightly detuned below, perfect, or slightly detuned above, yielding 3 tunings.  This will allow things like Voix Celeste, etc.  In reality, the detuned mutations would only be used for certain ranks, against certain standard string-like ranks.  Most Mixtures would never be detuned, etc.  But, the variations could exist.  The detuned pipes will probably just be by a couple of cents from the mutated frequency. (D)&lt;br /&gt;
&lt;br /&gt;
These combinations yield 1962 fundamental frequencies that we have to generate pipes for, possibly a handful more for multiple octave mutations that wouldn&amp;#039;t normally fall in the C0-C9 range (meaning we&amp;#039;d need unmutated notes up to C12, which at 67kHz is well outside human hearing...)&lt;br /&gt;
&lt;br /&gt;
===Spectrum Characteristics===&lt;br /&gt;
*A given pipe can be open (all harmonics present), stopped perfectly (no even harmonics), or stopped imperfectly (even harmonics severely diminished, say at 1/4 of what it would be if open) (U, Sp, Si)&lt;br /&gt;
*A given pipe can be normally blown (all harmonics present), perfectly overblown (fundamental completely missing), or imperfectly overblown (fundamental diminished, say at 1/4 of what it would be if normally blown) (B, Op, Oi)&lt;br /&gt;
*A given pipe can be coherent, or have rotating phase shifts (each harmonics is 90 degrees out of phase with previous and next harmonic in the series, so 0, 90, 180, 270, 0..., like a triangle wave) (C, A)&lt;br /&gt;
*A given pipe can have harmonic decay in one of multiple modes, where the relative strength of the kth harmonics is k^(-d), where d is one of (Xd):&lt;br /&gt;
**00, or 0: uniform all the way to the cutoff frequency... not very realistic...&lt;br /&gt;
**05, or 1/2: subharmonic, slower than a perfect harmonic series&lt;br /&gt;
**10, or 1: harmonic, a perfect harmonic series.  Sawtooth and square waves fall here.&lt;br /&gt;
**15, or 3/2: subsuperharmonic, slightly faster than a perfect harmonic series&lt;br /&gt;
**20, or 2: superharmonic, faster than a perfect harmonic series.  Like a triangle wave.&lt;br /&gt;
&lt;br /&gt;
===Bandwidth Limitations===&lt;br /&gt;
The spectrum for a pipe can be bandwidth limited as well.  All synthesized waveforms for sound should be limited to 22050Hz at a maximum.  Cutoff harmonics worth trying are:&lt;br /&gt;
*Pure (n=0, perfect).  No real transition zone here. Fundamental only, everything else is nonexistant. L0p is just notational convenience.&lt;br /&gt;
*n=3. Normal strength fundamental, then diminishing begins.&lt;br /&gt;
*n=5&lt;br /&gt;
*n=13&lt;br /&gt;
*n=37&lt;br /&gt;
*None (n=0, imperfect).  No cutoff here, all harmonics are full strength, up to the 22050Hz cutoff that everything has.  L0i is just notational conveneience.&lt;br /&gt;
&lt;br /&gt;
A bandwidth limitation can be perfect or imperfect (Lnp, Lni).  A perfect limitation has a three harmonic transition zone, where the strength of the harmonic before the cutoff is 85% what it would have been, unlimited, the strength of the harmonic at the cutoff is 50%, and the strength of the harmonic after the cutoff is 15%.  All harmonics below these are at 100%, and all harmonics above these are at 0%.  An imperfect limitation also has a three harmonic transition zone, where strength well before cutoff is 100%, right before cutoff is 81.25%, at cutoff is 62.5%, right after cutoff is 43.75%, and  everything above that is at 25%.&lt;br /&gt;
&lt;br /&gt;
===Conclusions===&lt;br /&gt;
Given all that, we have:&lt;br /&gt;
*N+M+D determine fundamental frequency, of which there appear to be just under 2000 reasonable ones.&lt;br /&gt;
*Xd + U/Sp/Si + B/Op/Oi + C/A determine pipe family, of which there appear to be about 90.&lt;br /&gt;
*Lnp/Lni determine pipe color, of which there are 10.&lt;br /&gt;
&lt;br /&gt;
90*10 yeilds 900 rank classes.&lt;br /&gt;
If each fundamental frequency is represented in each rank class, we would have about 1.8 million different theoretical pipes.&lt;br /&gt;
&lt;br /&gt;
For convenience sake, these theoretical ranks will be named as follows:&lt;br /&gt;
 XddxxyyzLnq_Mht&lt;br /&gt;
&lt;br /&gt;
*Xdd is one of the decay modes, X00, X05, X10, X15, or X20.&lt;br /&gt;
*xx is U, Sp, or Si to indicate any stoppage&lt;br /&gt;
*yy is B, Op, or Oi to indicate any overblowing&lt;br /&gt;
*z is C or A to indicate phasing&lt;br /&gt;
*Lnq indicates color, where n is the cutoff indicator, or 0, and q is either p or i to indicate perfect or imperfect limitation&lt;br /&gt;
*Mht indicates that the rank is of mutation harmonic h (1, 3, 5, 6, 7, 9 (possibly 2, 4, or 8 for high notes)), and t indicates either u for under, p for perfect, or o for over to refer to any detuning.&lt;br /&gt;
&lt;br /&gt;
Each pipe file or dft will have the actual fundamental frequency in cents included in the name after another underscore.  This will take into account the mutation or detuning.  Its the actual frequency of harmonic gap in the spectrum.&lt;br /&gt;
&lt;br /&gt;
So, an example might be:&lt;br /&gt;
 X10SiOiAL37i_M1p.rank&lt;br /&gt;
&lt;br /&gt;
This indicates a harmonically decaying, imperfectly stopped, imperfectly overblown rank of pipes with alternating phasing, being imperfectly limited above the 37th harmonic, perfectly tuned at unison.&lt;br /&gt;
&lt;br /&gt;
We will likely have 16,200 basic ranks of pipes.  Each pipe of mixtures would count as a different rank here.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MIDI_and_the_organ_project&amp;diff=2136</id>
		<title>MIDI and the organ project</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MIDI_and_the_organ_project&amp;diff=2136"/>
		<updated>2009-03-30T21:53:12Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[http://sessrumnir.net/organs/trunk/ SVN trunk for organ code]&lt;br /&gt;
*[http://www.die-orgelseite.de/pfeifenarten_e.htm Interesting site for pipe shapes and sounds]&lt;br /&gt;
&lt;br /&gt;
*[[Pipe creation workflow]]&lt;br /&gt;
*[[Theoretical Pipe Variations]]&lt;br /&gt;
&lt;br /&gt;
====MIDI and the organ====&lt;br /&gt;
MIDI standard is out there. Also good is the RTP-MIDI RFC, for putting MIDI data into a stream and whatnot.&lt;br /&gt;
&lt;br /&gt;
The basics, as I think we will be using them:&lt;br /&gt;
&lt;br /&gt;
Packet basics (we&amp;#039;ll only be using 3 byte packet forms):&lt;br /&gt;
&lt;br /&gt;
 1 &amp;lt;3: opcode&amp;gt; &amp;lt;4: channel&amp;gt; 0 &amp;lt;7: arg1&amp;gt; 0 &amp;lt;7: arg2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Essentially, a status byte, with the high bit on (0x80-0xFF), and two argument bytes, with the high bit off (0x00-0x7F).&lt;br /&gt;
&lt;br /&gt;
opcodes of relevance:&lt;br /&gt;
*0x0: key off.  arg1 is the key number, arg2 is the velocity.  We will always use velocity of 0x40.&lt;br /&gt;
*0x1: key on. arg1 is the key number, arg2 is the velocity.  We will always use the velocity of 0x40.&lt;br /&gt;
*0x3: control change.  arg1 is the control number (0x01 is modulation wheel, 0x0B is the expression pedal), arg2 is the new control value, from 0x00 - 0x7F (Note:  If we need more than 127 steps, add 0x20 to the control number, and thats the control number to use to send the least significant 7-bits of the value.  The value sent with the base control number is considered to be the most significant 7-bits of the value.  This ensures that if just read the base control number, you set the control to approximately the correct percentage of fully off/fully on.)&lt;br /&gt;
&lt;br /&gt;
For channels, we will use:&lt;br /&gt;
*0x0: Great (Solo) Manual&lt;br /&gt;
*0x1: Swell (Accompaniment) Manual&lt;br /&gt;
*0x2: Choir (below Great) Manual, if present&lt;br /&gt;
*0x3: Solo (above Swell) Manual, if present&lt;br /&gt;
*0x4: Echo (above Solo) Manual, if present&lt;br /&gt;
*0x5: Third Pedalboard, if present, or the auxilary stop channel, covering additional stops for all manuals and pedals.&lt;br /&gt;
*0x6: Second Pedalboard, if present, or the main stop channel, covering all stops for all manuals and pedals.&lt;br /&gt;
*0x7: Main Pedalboard&lt;br /&gt;
*0x8: Great stops only&lt;br /&gt;
*0x9: Swell stops only&lt;br /&gt;
*0xA: Choir stops only&lt;br /&gt;
*0xB: Solo stops only&lt;br /&gt;
*0xC: Echo stops only&lt;br /&gt;
*0xD: Third Pedalboard stops only&lt;br /&gt;
*0xE: Second Pedalboard stops only&lt;br /&gt;
*0xF: Main Pedalboard stops only&lt;br /&gt;
&lt;br /&gt;
Our initial organ will only use channels 0x0-0x1, 0x6-0x7.&lt;br /&gt;
&lt;br /&gt;
Each keyboard channel (0x0-0x7) gets its own control set.  For our organ, where the modulation wheel and expression pedal control all divisions equally, each control change gets sent for each active channel... or maybe just for great, and the software will figure out that they control all the stuff.  Note, we may not hook up the modulation wheel when we begin.  It&amp;#039;d be kinda a lot harder to make work right, I think.&lt;br /&gt;
&lt;br /&gt;
We will be building channel combination boards, that take an enable and a sub-channel address, and read back the contents of the addressed buffer.  4 bits of address gets 16 buffers.  At 8 bits per buffer, thats 128 inputs for each channel.  That matches with midi&amp;#039;s numbering scheme.  Alternatively, if you take the LSB of the true channel, and feed it to the 4th address bit of the channel board, and only decode the top 3 bits of the channel to determine channel board enable, you can duplex your channel boards, since we will only be using under 64 inputs per channel.  The AVR firmware will have an MIDI offset value for each channel to add to the number received from the board before sending as part of a MIDI command. For most subchannels, this will be 36.  Will probably just use an offset of 0 for the stop channels.&lt;br /&gt;
&lt;br /&gt;
Using the split channel board design, we only need two channel boards for our organ.  The main board will be designed to use the channel boards in split mode, and will never probably use the split-mode stop channels (0x8-0xF), so it will only have 4 plugs for channel boards, 0x0-0x1, 0x2-0x3, 0x4-0x5, and 0x6-0x7.  The initial organ will only use the first and last of these plugs, so we don&amp;#039;t even need to populate the board positions for the other channel boards.&lt;br /&gt;
&lt;br /&gt;
Also, I think we might want to put all the switch pull-up resistors on the manuals themselves, soldered to the key tabs.  This will eliminate a lot of crap on the boards, and keep the board design uniform, since the different keys will need different pull-ups.  The manuals, with their 5k internal resistance, will need 50k (or so) pull-ups to 5V, and the pedals and stops, with no internal resistance, will need just 10k (or so) pull-ups to 5V.  Each manual will get a separate power and ground plug for the pull-ups and grounds, so the connectors for the keys don&amp;#039;t need a pin for ground or power, I don&amp;#039;t think... Though if there is room, I guess we could send it along there, too.  Can&amp;#039;t hurt anything, provided the wires support enough current for the crazy case of all the stop pulled or keys pressed or something.  Given a max of 64 inputs to a half-channel, and only 61 keys on a full manual, we can use 2x36 pin connectors for the manuals, and 1x36 pin connector for the pedalboards, and 1x36 pin connector for the stop boards.  Thats 6 total 36 pin connectors, male and female, solder cup and through-hole.&lt;br /&gt;
&lt;br /&gt;
Channel board to main board connectors will have an 8-bit data bus, 4-bit address bus, a power, ground, enable, and identify(?) pins (16 total).  Should be able to use IDC connectors and ribbon cable here.&lt;br /&gt;
&lt;br /&gt;
===Simple algorithm for key change detection===&lt;br /&gt;
After reading a byte from the buffers, we xor it with the copy of the byte from last time, then store the new version in the copy location.  We then start looking at the lsb of the xor&amp;#039;ed byte.  If its a 1, we send a key on if the lsb of the read byte is a 1, and a key off if the lsb of the read byte is a 0.  We then shift right and do that again.  We do that 8 times, once for each bit in that byte.  Then we can move on to the next valid address for that channel, write out the address, read back the buffer value, xor, store, analyze, etc.  Note, we can speed this up by checking if the xor byte is identically 0x00, in which case we don&amp;#039;t have to analyze it, it hasn&amp;#039;t changed.  This will be the usual case!  Only occasionally (in sample time), will things change, and usually only on one bit, and thus one buffer, amongst all the channels and buffers.  This should help us keep up to speed.&lt;br /&gt;
&lt;br /&gt;
Once we are done reading all the channel board buffers, we can check the expression pedals and other variable controls for new values, and possibly send control change events.  After all this, we actually send the MIDI bytes as we have determined them to need to be for this time around, and go to sleep until our next sample time.&lt;br /&gt;
&lt;br /&gt;
Not sure what the latency of the serial to USB conversion is in FTDI, but it could be as bad as a single byte in a single USB message....  Anyway, we want to build a buffer of bytes that need to get send over each sample time, with the RTP-MIDI spec used to make it a stream type thing.  This means: packet length, &amp;quot;timestamp&amp;quot;, first MIDI event, relative timestamps (should all be zero), subsequent MIDI events.&lt;br /&gt;
&lt;br /&gt;
===Chips to use===&lt;br /&gt;
*16x? 74HCT540  for the octal tri-state buffers, inverting (0.54, 20 pin dip)&lt;br /&gt;
*1x? 74HCT138  for 1 to 8 decoder (0.40, 16 pin dip)&lt;br /&gt;
*1x? 74HCT154  for 1 to 16 decoder (0.80, 24 pin dip)&lt;br /&gt;
*1x ATMega164P-20P for AVR controller, 20MHz, (4.82, 40 pin dip)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Pipe_creation_workflow&amp;diff=2132</id>
		<title>Pipe creation workflow</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Pipe_creation_workflow&amp;diff=2132"/>
		<updated>2009-03-03T22:55:00Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Creating a pipe and rank has several steps and possible intermediate file formats and editing tools.&lt;br /&gt;
&lt;br /&gt;
===1: Create the spectrum for a pipe===&lt;br /&gt;
The spectrum needs to be created for a pipe.  This can be done in octave, and then viewed in gnuplot.  It could be created with a C program.  It would be nice to have a javascript editor to create these a bit more dynamically so you can see what the spectrum will look like, and also to see what the the resulting pipe would sound like.&lt;br /&gt;
&lt;br /&gt;
The file format for the spectrum is nice and simple, to aid in creation and use by the various tools.  There is no header, just a list of records, each one holding a complex value associated with a given frequency in the response.  It&amp;#039;s likely that all frequencies from 0 up to 22050 would be present at uniform spacing, but this wouldn&amp;#039;t be necessarily the case.&lt;br /&gt;
Format for each record is:&lt;br /&gt;
 float float float&lt;br /&gt;
First float is the frequency in hertz, second is the real part of the DFT value at that frequency, and third is the imaginary part of the DFT value at that frequency.&lt;br /&gt;
&lt;br /&gt;
All frequencies above 22050 should be chopped to prevent aliasing.  File should be named as:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;fundamental frequency&amp;gt;.dft&lt;br /&gt;
&lt;br /&gt;
Gnuplot can easily read this format for plotting, as can C files for later conversion.  C files and octave can write this format easily.&lt;br /&gt;
&lt;br /&gt;
Tools:&lt;br /&gt;
*octave(existing) - to create a spectrum from scratch and known theoretical concepts&lt;br /&gt;
*gnuplot(existing) - to display the spectrum for analysis&lt;br /&gt;
*nameless javascript tool - to interactively edit the spectrum&lt;br /&gt;
*wavdft - to convert a recording of a pipe to a spectrum file for clean up and re-dissection.&lt;br /&gt;
&lt;br /&gt;
===2: Convert from spectrum to pipe waveform===&lt;br /&gt;
Once the spectrum is created, the pipe waveform data can be created by using FFT on the data in the spectrum file, or the slow sinusoid summation manually.  Once the waveform data is generated, its normalized and using input parameters to specify envelope characteristics, appropriate subsets are taken of the waveform and placed into a pipe file, named:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;fundamental frequency&amp;gt;.pipe&lt;br /&gt;
&lt;br /&gt;
The format of that file is a pipe header, specifying the fundamental frequency, the lengths of each portion of the waveform data, and arrays of floats for the sustain, attack, and release portions, is from rankfile.H&lt;br /&gt;
&lt;br /&gt;
The tool that will be used to do this processing is &amp;quot;pipegen&amp;quot; which will take the .dft and some envelope parameters, and generate a .pipe file.&lt;br /&gt;
&lt;br /&gt;
This pipe file can then be played back using the &amp;quot;playpipe&amp;quot; utility.  Also, a &amp;quot;playset&amp;quot; utility can be used to play multiple pipes at once, for testing how a pipe set sounds together, to see how a chord in a given rank will sound, or to see how a note or chord sounds when played with multiple stops pulled.&lt;br /&gt;
&lt;br /&gt;
Tools:&lt;br /&gt;
*pipegen - to generate a pipe file from a spectrum file&lt;br /&gt;
*playpipe - to listen to the pipe to make sure it sounds as expected&lt;br /&gt;
*playset - to listen to a set of pipes to make sure they sound good together&lt;br /&gt;
&lt;br /&gt;
===3: Combine pipe files into a rank file===&lt;br /&gt;
The rank file will be created according to rankfile.H, consisting of a rank header, an index to find each pipe data section, and the data from each pipe data file, all combined into one rank file, with a name of form:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;pitch length in rounded feet&amp;gt;.rank&lt;br /&gt;
&lt;br /&gt;
This file will be generated by &amp;quot;rankgen&amp;quot;, which will take parameters to specify the name and length of this rank, as well as how many pipes are in each set, and a list of all the pipes to add to the rank, in the order to put them into the file, with each set preceded by the written note that will cause this rank to play that set of pipes.&lt;br /&gt;
&lt;br /&gt;
A rankfile can be played using the &amp;quot;playrank&amp;quot; tool, which will cause each pipe set in the rank to play, one after the other.  All pipes in a given set will sound simultaneously here, to get an accurate affect of what this rank will sound like when played on the organ.  A &amp;quot;playbar&amp;quot; tool will take a set of ranks that should be un-stopped, and a sequence of midi notes to play using those ranks.  All the notes will use the ranks specified.&lt;br /&gt;
&lt;br /&gt;
Tools:&lt;br /&gt;
*rankgen - to generate the rank file from the given sets of pipes&lt;br /&gt;
*playrank - to listen to all the pipes of a rank to verify they all sound alike and of similar volumes and timbres.&lt;br /&gt;
*playbar - to listen to a simple midi sequence on a given set of ranks to make sure we are interpreting notes correctly.&lt;br /&gt;
&lt;br /&gt;
===4: Play the organ===&lt;br /&gt;
Once all the ranks are complete, &amp;quot;organ-emu&amp;quot; would listen for midi events from the organ and play the right pipes from the right ranks for each division.    &amp;quot;midi-test&amp;quot; just listens for midi events from the organ and displays them on screen, or records them to a file.  &amp;quot;organ-midi&amp;quot; is similar to &amp;quot;playbar&amp;quot; in that it takes in a midi file, but this will interpret stop keys correctly, and set the proper ranks on for each manual/pedal, and interpret the midi channels correctly to play back the song using the full organ abilities.&lt;br /&gt;
&lt;br /&gt;
Tools:&lt;br /&gt;
*midi-test - to listen to midi events from the organ and display or record them&lt;br /&gt;
*organ-midi - to playback a recorded stream of midi events for the organ, including stops and multiple divisions&lt;br /&gt;
*organ-emu - to listen for midi events and play the resulting ranks and pipes in real-time.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Pipe_creation_workflow&amp;diff=2131</id>
		<title>Pipe creation workflow</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Pipe_creation_workflow&amp;diff=2131"/>
		<updated>2009-03-03T22:54:08Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Creating a pipe and rank has several steps and possible intermediate file formats and editing tools.&lt;br /&gt;
&lt;br /&gt;
===1: Create the spectrum for a pipe===&lt;br /&gt;
The spectrum needs to be created for a pipe.  This can be done in octave, and then viewed in gnuplot.  It could be created with a C program.  It would be nice to have a javascript editor to create these a bit more dynamically so you can see what the spectrum will look like, and also to see what the the resulting pipe would sound like.&lt;br /&gt;
&lt;br /&gt;
The file format for the spectrum is nice and simple, to aid in creation and use by the various tools.  There is no header, just a list of records, each one holding a complex value associated with a given frequency in the response.  It&amp;#039;s likely that all frequencies from 0 up to 22050 would be present at uniform spacing, but this wouldn&amp;#039;t be necessarily the case.&lt;br /&gt;
Format for each record is:&lt;br /&gt;
 float float float&lt;br /&gt;
First float is the frequency in hertz, second is the real part of the DFT value at that frequency, and third is the imaginary part of the DFT value at that frequency.&lt;br /&gt;
&lt;br /&gt;
All frequencies above 22050 should be chopped to prevent aliasing.  File should be named as:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;fundamental frequency&amp;gt;.dft&lt;br /&gt;
&lt;br /&gt;
Gnuplot can easily read this format for plotting, as can C files for later conversion.  C files and octave can write this format easily.&lt;br /&gt;
&lt;br /&gt;
Tools:&lt;br /&gt;
*octave - to create a spectrum from scratch and known theoretical concepts&lt;br /&gt;
*nameless javascript tool - to interactively edit the spectrum&lt;br /&gt;
*gnuplot - to display the spectrum for analysis&lt;br /&gt;
*wavdft - to convert a recording of a pipe to a spectrum file for clean up and re-dissection.&lt;br /&gt;
&lt;br /&gt;
===2: Convert from spectrum to pipe waveform===&lt;br /&gt;
Once the spectrum is created, the pipe waveform data can be created by using FFT on the data in the spectrum file, or the slow sinusoid summation manually.  Once the waveform data is generated, its normalized and using input parameters to specify envelope characteristics, appropriate subsets are taken of the waveform and placed into a pipe file, named:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;fundamental frequency&amp;gt;.pipe&lt;br /&gt;
&lt;br /&gt;
The format of that file is a pipe header, specifying the fundamental frequency, the lengths of each portion of the waveform data, and arrays of floats for the sustain, attack, and release portions, is from rankfile.H&lt;br /&gt;
&lt;br /&gt;
The tool that will be used to do this processing is &amp;quot;pipegen&amp;quot; which will take the .dft and some envelope parameters, and generate a .pipe file.&lt;br /&gt;
&lt;br /&gt;
This pipe file can then be played back using the &amp;quot;playpipe&amp;quot; utility.  Also, a &amp;quot;playset&amp;quot; utility can be used to play multiple pipes at once, for testing how a pipe set sounds together, to see how a chord in a given rank will sound, or to see how a note or chord sounds when played with multiple stops pulled.&lt;br /&gt;
&lt;br /&gt;
Tools:&lt;br /&gt;
*pipegen - to generate a pipe file from a spectrum file&lt;br /&gt;
*playpipe - to listen to the pipe to make sure it sounds as expected&lt;br /&gt;
*playset - to listen to a set of pipes to make sure they sound good together&lt;br /&gt;
&lt;br /&gt;
===3: Combine pipe files into a rank file===&lt;br /&gt;
The rank file will be created according to rankfile.H, consisting of a rank header, an index to find each pipe data section, and the data from each pipe data file, all combined into one rank file, with a name of form:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;pitch length in rounded feet&amp;gt;.rank&lt;br /&gt;
&lt;br /&gt;
This file will be generated by &amp;quot;rankgen&amp;quot;, which will take parameters to specify the name and length of this rank, as well as how many pipes are in each set, and a list of all the pipes to add to the rank, in the order to put them into the file, with each set preceded by the written note that will cause this rank to play that set of pipes.&lt;br /&gt;
&lt;br /&gt;
A rankfile can be played using the &amp;quot;playrank&amp;quot; tool, which will cause each pipe set in the rank to play, one after the other.  All pipes in a given set will sound simultaneously here, to get an accurate affect of what this rank will sound like when played on the organ.  A &amp;quot;playbar&amp;quot; tool will take a set of ranks that should be un-stopped, and a sequence of midi notes to play using those ranks.  All the notes will use the ranks specified.&lt;br /&gt;
&lt;br /&gt;
Tools:&lt;br /&gt;
*rankgen - to generate the rank file from the given sets of pipes&lt;br /&gt;
*playrank - to listen to all the pipes of a rank to verify they all sound alike and of similar volumes and timbres.&lt;br /&gt;
*playbar - to listen to a simple midi sequence on a given set of ranks to make sure we are interpreting notes correctly.&lt;br /&gt;
&lt;br /&gt;
===4: Play the organ===&lt;br /&gt;
Once all the ranks are complete, &amp;quot;organ-emu&amp;quot; would listen for midi events from the organ and play the right pipes from the right ranks for each division.    &amp;quot;midi-test&amp;quot; just listens for midi events from the organ and displays them on screen, or records them to a file.  &amp;quot;organ-midi&amp;quot; is similar to &amp;quot;playbar&amp;quot; in that it takes in a midi file, but this will interpret stop keys correctly, and set the proper ranks on for each manual/pedal, and interpret the midi channels correctly to play back the song using the full organ abilities.&lt;br /&gt;
&lt;br /&gt;
Tools:&lt;br /&gt;
*midi-test - to listen to midi events from the organ and display or record them&lt;br /&gt;
*organ-midi - to playback a recorded stream of midi events for the organ, including stops and multiple divisions&lt;br /&gt;
*organ-emu - to listen for midi events and play the resulting ranks and pipes in real-time.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Pipe_creation_workflow&amp;diff=2130</id>
		<title>Pipe creation workflow</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Pipe_creation_workflow&amp;diff=2130"/>
		<updated>2009-03-03T22:48:08Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Creating a pipe and rank has several steps and possible intermediate file formats and editing tools.&lt;br /&gt;
&lt;br /&gt;
===1: Create the spectrum for a pipe===&lt;br /&gt;
The spectrum needs to be created for a pipe.  This can be done in octave, and then viewed in gnuplot.  It could be created with a C program.  It would be nice to have a javascript editor to create these a bit more dynamically so you can see what the spectrum will look like, and also to see what the the resulting pipe would sound like.&lt;br /&gt;
&lt;br /&gt;
The file format for the spectrum is nice and simple, to aid in creation and use by the various tools.  There is no header, just a list of records, each one holding a complex value associated with a given frequency in the response.  It&amp;#039;s likely that all frequencies from 0 up to 22050 would be present at uniform spacing, but this wouldn&amp;#039;t be necessarily the case.&lt;br /&gt;
Format for each record is:&lt;br /&gt;
 float float float&lt;br /&gt;
First float is the frequency in hertz, second is the real part of the DFT value at that frequency, and third is the imaginary part of the DFT value at that frequency.&lt;br /&gt;
&lt;br /&gt;
All frequencies above 22050 should be chopped to prevent aliasing.  File should be named as:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;fundamental frequency&amp;gt;.dft&lt;br /&gt;
&lt;br /&gt;
Gnuplot can easily read this format for plotting, as can C files for later conversion.  C files and octave can write this format easily.&lt;br /&gt;
&lt;br /&gt;
===2: Convert from spectrum to pipe waveform===&lt;br /&gt;
Once the spectrum is created, the pipe waveform data can be created by using FFT on the data in the spectrum file, or the slow sinusoid summation manually.  Once the waveform data is generated, its normalized and using input parameters to specify envelope characteristics, appropriate subsets are taken of the waveform and placed into a pipe file, named:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;fundamental frequency&amp;gt;.pipe&lt;br /&gt;
&lt;br /&gt;
The format of that file is a pipe header, specifying the fundamental frequency, the lengths of each portion of the waveform data, and arrays of floats for the sustain, attack, and release portions, is from rankfile.H&lt;br /&gt;
&lt;br /&gt;
The tool that will be used to do this processing is &amp;quot;pipegen&amp;quot; which will take the .dft and some envelope parameters, and generate a .pipe file.&lt;br /&gt;
&lt;br /&gt;
This pipe file can then be played back using the &amp;quot;playpipe&amp;quot; utility.  Also, a &amp;quot;playset&amp;quot; utility can be used to play multiple pipes at once, for testing how a pipe set sounds together, to see how a chord in a given rank will sound, or to see how a note or chord sounds when played with multiple stops pulled.&lt;br /&gt;
&lt;br /&gt;
===3: Combine pipe files into a rank file===&lt;br /&gt;
The rank file will be created according to rankfile.H, consisting of a rank header, an index to find each pipe data section, and the data from each pipe data file, all combined into one rank file, with a name of form:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;pitch length in rounded feet&amp;gt;.rank&lt;br /&gt;
&lt;br /&gt;
This file will be generated by &amp;quot;rankgen&amp;quot;, which will take parameters to specify the name and length of this rank, as well as how many pipes are in each set, and a list of all the pipes to add to the rank, in the order to put them into the file, with each set preceded by the written note that will cause this rank to play that set of pipes.&lt;br /&gt;
&lt;br /&gt;
A rankfile can be played using the &amp;quot;playrank&amp;quot; tool, which will cause each pipe set in the rank to play, one after the other.  All pipes in a given set will sound simultaneously here, to get an accurate affect of what this rank will sound like when played on the organ.  A &amp;quot;playbar&amp;quot; tool will take a set of ranks that should be un-stopped, and a sequence of midi notes to play using those ranks.  All the notes will use the ranks specified.&lt;br /&gt;
&lt;br /&gt;
===4: Play the organ===&lt;br /&gt;
Once all the ranks are complete, &amp;quot;organ-emu&amp;quot; would listen for midi events from the organ and play the right pipes from the right ranks for each division.    &amp;quot;midi-test&amp;quot; just listens for midi events from the organ and displays them on screen, or records them to a file.  &amp;quot;organ-midi&amp;quot; is similar to &amp;quot;playbar&amp;quot; in that it takes in a midi file, but this will interpret stop keys correctly, and set the proper ranks on for each manual/pedal, and interpret the midi channels correctly to play back the song using the full organ abilities.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Pipe_creation_workflow&amp;diff=2129</id>
		<title>Pipe creation workflow</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Pipe_creation_workflow&amp;diff=2129"/>
		<updated>2009-03-03T22:47:26Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: Creating a pipe and rank has several steps and possible intermediate file formats and editing tools.  ===1: Create the spectrum for a pipe=== The spectrum needs to be created for a pipe.  ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Creating a pipe and rank has several steps and possible intermediate file formats and editing tools.&lt;br /&gt;
&lt;br /&gt;
===1: Create the spectrum for a pipe===&lt;br /&gt;
The spectrum needs to be created for a pipe.  This can be done in octave, and then viewed in gnuplot.  It could be created with a C program.  It would be nice to have a javascript editor to create these a bit more dynamically so you can see what the spectrum will look like, and also to see what the the resulting pipe would sound like.&lt;br /&gt;
&lt;br /&gt;
The file format for the spectrum is nice and simple, to aid in creation and use by the various tools.  There is no header, just a list of records, each one holding a complex value associated with a given frequency in the response.  It&amp;#039;s likely that all frequencies from 0 up to 22050 would be present at uniform spacing, but this wouldn&amp;#039;t be necessarily the case.&lt;br /&gt;
Format for each record is:&lt;br /&gt;
 float float float&lt;br /&gt;
First float is the frequency in hertz, second is the real part of the DFT value at that frequency, and third is the imaginary part of the DFT value at that frequency.&lt;br /&gt;
&lt;br /&gt;
All frequencies above 22050 should be chopped to prevent aliasing.  File should be named as:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;fundamental frequency&amp;gt;.dft&lt;br /&gt;
&lt;br /&gt;
Gnuplot can easily read this format for plotting, as can C files for later conversion.  C files and octave can write this format easily.&lt;br /&gt;
&lt;br /&gt;
===2: Convert from spectrum to pipe waveform===&lt;br /&gt;
Once the spectrum is created, the pipe waveform data can be created by using FFT on the data in the spectrum file, or the slow sinusoid summation manually.  Once the waveform data is generated, its normalized and using input parameters to specify envelope characteristics, appropriate subsets are taken of the waveform and placed into a pipe file, named:&lt;br /&gt;
 &amp;lt;rank name&amp;gt;_&amp;lt;fundamental frequency&amp;gt;.pipe&lt;br /&gt;
&lt;br /&gt;
The format of that file is a pipe header, specifying the fundamental frequency, the lengths of each portion of the waveform data, and arrays of floats for the sustain, attack, and release portions, is from rankfile.H&lt;br /&gt;
&lt;br /&gt;
The tool that will be used to do this processing is &amp;quot;pipegen&amp;quot; which will take the .dft and some envelope parameters, and generate a .pipe file.&lt;br /&gt;
&lt;br /&gt;
This pipe file can then be played back using the &amp;quot;playpipe&amp;quot; utility.  Also, a &amp;quot;playset&amp;quot; utility can be used to play multiple pipes at once, for testing how a pipe set sounds together, to see how a chord in a given rank will sound, or to see how a note or chord sounds when played with multiple stops pulled.&lt;br /&gt;
&lt;br /&gt;
===3: Combine pipe files into a rank file===&lt;br /&gt;
The rank file will be created according to rankfile.H, consisting of a rank header, an index to find each pipe data section, and the data from each pipe data file, all combined into one rank file.&lt;br /&gt;
&lt;br /&gt;
This file will be generated by &amp;quot;rankgen&amp;quot;, which will take parameters to specify the name and length of this rank, as well as how many pipes are in each set, and a list of all the pipes to add to the rank, in the order to put them into the file, with each set preceded by the written note that will cause this rank to play that set of pipes.&lt;br /&gt;
&lt;br /&gt;
A rankfile can be played using the &amp;quot;playrank&amp;quot; tool, which will cause each pipe set in the rank to play, one after the other.  All pipes in a given set will sound simultaneously here, to get an accurate affect of what this rank will sound like when played on the organ.  A &amp;quot;playbar&amp;quot; tool will take a set of ranks that should be un-stopped, and a sequence of midi notes to play using those ranks.  All the notes will use the ranks specified.&lt;br /&gt;
&lt;br /&gt;
===4: Play the organ===&lt;br /&gt;
Once all the ranks are complete, &amp;quot;organ-emu&amp;quot; would listen for midi events from the organ and play the right pipes from the right ranks for each division.    &amp;quot;midi-test&amp;quot; just listens for midi events from the organ and displays them on screen, or records them to a file.  &amp;quot;organ-midi&amp;quot; is similar to &amp;quot;playbar&amp;quot; in that it takes in a midi file, but this will interpret stop keys correctly, and set the proper ranks on for each manual/pedal, and interpret the midi channels correctly to play back the song using the full organ abilities.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MIDI_and_the_organ_project&amp;diff=2128</id>
		<title>MIDI and the organ project</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MIDI_and_the_organ_project&amp;diff=2128"/>
		<updated>2009-03-03T19:49:57Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[http://sessrumnir.net/organs/trunk/ SVN trunk for organ code]&lt;br /&gt;
*[http://www.die-orgelseite.de/pfeifenarten_e.htm Interesting site for pipe shapes and sounds]&lt;br /&gt;
&lt;br /&gt;
*[[Pipe creation workflow]]&lt;br /&gt;
&lt;br /&gt;
====MIDI and the organ====&lt;br /&gt;
MIDI standard is out there. Also good is the RTP-MIDI RFC, for putting MIDI data into a stream and whatnot.&lt;br /&gt;
&lt;br /&gt;
The basics, as I think we will be using them:&lt;br /&gt;
&lt;br /&gt;
Packet basics (we&amp;#039;ll only be using 3 byte packet forms):&lt;br /&gt;
&lt;br /&gt;
 1 &amp;lt;3: opcode&amp;gt; &amp;lt;4: channel&amp;gt; 0 &amp;lt;7: arg1&amp;gt; 0 &amp;lt;7: arg2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Essentially, a status byte, with the high bit on (0x80-0xFF), and two argument bytes, with the high bit off (0x00-0x7F).&lt;br /&gt;
&lt;br /&gt;
opcodes of relevance:&lt;br /&gt;
*0x0: key off.  arg1 is the key number, arg2 is the velocity.  We will always use velocity of 0x40.&lt;br /&gt;
*0x1: key on. arg1 is the key number, arg2 is the velocity.  We will always use the velocity of 0x40.&lt;br /&gt;
*0x3: control change.  arg1 is the control number (0x01 is modulation wheel, 0x0B is the expression pedal), arg2 is the new control value, from 0x00 - 0x7F (Note:  If we need more than 127 steps, add 0x20 to the control number, and thats the control number to use to send the least significant 7-bits of the value.  The value sent with the base control number is considered to be the most significant 7-bits of the value.  This ensures that if just read the base control number, you set the control to approximately the correct percentage of fully off/fully on.)&lt;br /&gt;
&lt;br /&gt;
For channels, we will use:&lt;br /&gt;
*0x0: Great (Solo) Manual&lt;br /&gt;
*0x1: Swell (Accompaniment) Manual&lt;br /&gt;
*0x2: Choir (below Great) Manual, if present&lt;br /&gt;
*0x3: Solo (above Swell) Manual, if present&lt;br /&gt;
*0x4: Echo (above Solo) Manual, if present&lt;br /&gt;
*0x5: Third Pedalboard, if present, or the auxilary stop channel, covering additional stops for all manuals and pedals.&lt;br /&gt;
*0x6: Second Pedalboard, if present, or the main stop channel, covering all stops for all manuals and pedals.&lt;br /&gt;
*0x7: Main Pedalboard&lt;br /&gt;
*0x8: Great stops only&lt;br /&gt;
*0x9: Swell stops only&lt;br /&gt;
*0xA: Choir stops only&lt;br /&gt;
*0xB: Solo stops only&lt;br /&gt;
*0xC: Echo stops only&lt;br /&gt;
*0xD: Third Pedalboard stops only&lt;br /&gt;
*0xE: Second Pedalboard stops only&lt;br /&gt;
*0xF: Main Pedalboard stops only&lt;br /&gt;
&lt;br /&gt;
Our initial organ will only use channels 0x0-0x1, 0x6-0x7.&lt;br /&gt;
&lt;br /&gt;
Each keyboard channel (0x0-0x7) gets its own control set.  For our organ, where the modulation wheel and expression pedal control all divisions equally, each control change gets sent for each active channel... or maybe just for great, and the software will figure out that they control all the stuff.  Note, we may not hook up the modulation wheel when we begin.  It&amp;#039;d be kinda a lot harder to make work right, I think.&lt;br /&gt;
&lt;br /&gt;
We will be building channel combination boards, that take an enable and a sub-channel address, and read back the contents of the addressed buffer.  4 bits of address gets 16 buffers.  At 8 bits per buffer, thats 128 inputs for each channel.  That matches with midi&amp;#039;s numbering scheme.  Alternatively, if you take the LSB of the true channel, and feed it to the 4th address bit of the channel board, and only decode the top 3 bits of the channel to determine channel board enable, you can duplex your channel boards, since we will only be using under 64 inputs per channel.  The AVR firmware will have an MIDI offset value for each channel to add to the number received from the board before sending as part of a MIDI command. For most subchannels, this will be 36.  Will probably just use an offset of 0 for the stop channels.&lt;br /&gt;
&lt;br /&gt;
Using the split channel board design, we only need two channel boards for our organ.  The main board will be designed to use the channel boards in split mode, and will never probably use the split-mode stop channels (0x8-0xF), so it will only have 4 plugs for channel boards, 0x0-0x1, 0x2-0x3, 0x4-0x5, and 0x6-0x7.  The initial organ will only use the first and last of these plugs, so we don&amp;#039;t even need to populate the board positions for the other channel boards.&lt;br /&gt;
&lt;br /&gt;
Also, I think we might want to put all the switch pull-up resistors on the manuals themselves, soldered to the key tabs.  This will eliminate a lot of crap on the boards, and keep the board design uniform, since the different keys will need different pull-ups.  The manuals, with their 5k internal resistance, will need 50k (or so) pull-ups to 5V, and the pedals and stops, with no internal resistance, will need just 10k (or so) pull-ups to 5V.  Each manual will get a separate power and ground plug for the pull-ups and grounds, so the connectors for the keys don&amp;#039;t need a pin for ground or power, I don&amp;#039;t think... Though if there is room, I guess we could send it along there, too.  Can&amp;#039;t hurt anything, provided the wires support enough current for the crazy case of all the stop pulled or keys pressed or something.  Given a max of 64 inputs to a half-channel, and only 61 keys on a full manual, we can use 2x36 pin connectors for the manuals, and 1x36 pin connector for the pedalboards, and 1x36 pin connector for the stop boards.  Thats 6 total 36 pin connectors, male and female, solder cup and through-hole.&lt;br /&gt;
&lt;br /&gt;
Channel board to main board connectors will have an 8-bit data bus, 4-bit address bus, a power, ground, enable, and identify(?) pins (16 total).  Should be able to use IDC connectors and ribbon cable here.&lt;br /&gt;
&lt;br /&gt;
===Simple algorithm for key change detection===&lt;br /&gt;
After reading a byte from the buffers, we xor it with the copy of the byte from last time, then store the new version in the copy location.  We then start looking at the lsb of the xor&amp;#039;ed byte.  If its a 1, we send a key on if the lsb of the read byte is a 1, and a key off if the lsb of the read byte is a 0.  We then shift right and do that again.  We do that 8 times, once for each bit in that byte.  Then we can move on to the next valid address for that channel, write out the address, read back the buffer value, xor, store, analyze, etc.  Note, we can speed this up by checking if the xor byte is identically 0x00, in which case we don&amp;#039;t have to analyze it, it hasn&amp;#039;t changed.  This will be the usual case!  Only occasionally (in sample time), will things change, and usually only on one bit, and thus one buffer, amongst all the channels and buffers.  This should help us keep up to speed.&lt;br /&gt;
&lt;br /&gt;
Once we are done reading all the channel board buffers, we can check the expression pedals and other variable controls for new values, and possibly send control change events.  After all this, we actually send the MIDI bytes as we have determined them to need to be for this time around, and go to sleep until our next sample time.&lt;br /&gt;
&lt;br /&gt;
Not sure what the latency of the serial to USB conversion is in FTDI, but it could be as bad as a single byte in a single USB message....  Anyway, we want to build a buffer of bytes that need to get send over each sample time, with the RTP-MIDI spec used to make it a stream type thing.  This means: packet length, &amp;quot;timestamp&amp;quot;, first MIDI event, relative timestamps (should all be zero), subsequent MIDI events.&lt;br /&gt;
&lt;br /&gt;
===Chips to use===&lt;br /&gt;
*16x? 74HCT540  for the octal tri-state buffers, inverting (0.54, 20 pin dip)&lt;br /&gt;
*1x? 74HCT138  for 1 to 8 decoder (0.40, 16 pin dip)&lt;br /&gt;
*1x? 74HCT154  for 1 to 16 decoder (0.80, 24 pin dip)&lt;br /&gt;
*1x ATMega164P-20P for AVR controller, 20MHz, (4.82, 40 pin dip)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MIDI_and_the_organ_project&amp;diff=2127</id>
		<title>MIDI and the organ project</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MIDI_and_the_organ_project&amp;diff=2127"/>
		<updated>2009-03-02T17:58:25Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[http://sessrumnir.net/organs/trunk/ SVN trunk for organ code]&lt;br /&gt;
*[http://www.die-orgelseite.de/pfeifenarten_e.htm Interesting site for pipe shapes and sounds]&lt;br /&gt;
&lt;br /&gt;
====MIDI and the organ====&lt;br /&gt;
MIDI standard is out there. Also good is the RTP-MIDI RFC, for putting MIDI data into a stream and whatnot.&lt;br /&gt;
&lt;br /&gt;
The basics, as I think we will be using them:&lt;br /&gt;
&lt;br /&gt;
Packet basics (we&amp;#039;ll only be using 3 byte packet forms):&lt;br /&gt;
&lt;br /&gt;
 1 &amp;lt;3: opcode&amp;gt; &amp;lt;4: channel&amp;gt; 0 &amp;lt;7: arg1&amp;gt; 0 &amp;lt;7: arg2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Essentially, a status byte, with the high bit on (0x80-0xFF), and two argument bytes, with the high bit off (0x00-0x7F).&lt;br /&gt;
&lt;br /&gt;
opcodes of relevance:&lt;br /&gt;
*0x0: key off.  arg1 is the key number, arg2 is the velocity.  We will always use velocity of 0x40.&lt;br /&gt;
*0x1: key on. arg1 is the key number, arg2 is the velocity.  We will always use the velocity of 0x40.&lt;br /&gt;
*0x3: control change.  arg1 is the control number (0x01 is modulation wheel, 0x0B is the expression pedal), arg2 is the new control value, from 0x00 - 0x7F (Note:  If we need more than 127 steps, add 0x20 to the control number, and thats the control number to use to send the least significant 7-bits of the value.  The value sent with the base control number is considered to be the most significant 7-bits of the value.  This ensures that if just read the base control number, you set the control to approximately the correct percentage of fully off/fully on.)&lt;br /&gt;
&lt;br /&gt;
For channels, we will use:&lt;br /&gt;
*0x0: Great (Solo) Manual&lt;br /&gt;
*0x1: Swell (Accompaniment) Manual&lt;br /&gt;
*0x2: Choir (below Great) Manual, if present&lt;br /&gt;
*0x3: Solo (above Swell) Manual, if present&lt;br /&gt;
*0x4: Echo (above Solo) Manual, if present&lt;br /&gt;
*0x5: Third Pedalboard, if present, or the auxilary stop channel, covering additional stops for all manuals and pedals.&lt;br /&gt;
*0x6: Second Pedalboard, if present, or the main stop channel, covering all stops for all manuals and pedals.&lt;br /&gt;
*0x7: Main Pedalboard&lt;br /&gt;
*0x8: Great stops only&lt;br /&gt;
*0x9: Swell stops only&lt;br /&gt;
*0xA: Choir stops only&lt;br /&gt;
*0xB: Solo stops only&lt;br /&gt;
*0xC: Echo stops only&lt;br /&gt;
*0xD: Third Pedalboard stops only&lt;br /&gt;
*0xE: Second Pedalboard stops only&lt;br /&gt;
*0xF: Main Pedalboard stops only&lt;br /&gt;
&lt;br /&gt;
Our initial organ will only use channels 0x0-0x1, 0x6-0x7.&lt;br /&gt;
&lt;br /&gt;
Each keyboard channel (0x0-0x7) gets its own control set.  For our organ, where the modulation wheel and expression pedal control all divisions equally, each control change gets sent for each active channel... or maybe just for great, and the software will figure out that they control all the stuff.  Note, we may not hook up the modulation wheel when we begin.  It&amp;#039;d be kinda a lot harder to make work right, I think.&lt;br /&gt;
&lt;br /&gt;
We will be building channel combination boards, that take an enable and a sub-channel address, and read back the contents of the addressed buffer.  4 bits of address gets 16 buffers.  At 8 bits per buffer, thats 128 inputs for each channel.  That matches with midi&amp;#039;s numbering scheme.  Alternatively, if you take the LSB of the true channel, and feed it to the 4th address bit of the channel board, and only decode the top 3 bits of the channel to determine channel board enable, you can duplex your channel boards, since we will only be using under 64 inputs per channel.  The AVR firmware will have an MIDI offset value for each channel to add to the number received from the board before sending as part of a MIDI command. For most subchannels, this will be 36.  Will probably just use an offset of 0 for the stop channels.&lt;br /&gt;
&lt;br /&gt;
Using the split channel board design, we only need two channel boards for our organ.  The main board will be designed to use the channel boards in split mode, and will never probably use the split-mode stop channels (0x8-0xF), so it will only have 4 plugs for channel boards, 0x0-0x1, 0x2-0x3, 0x4-0x5, and 0x6-0x7.  The initial organ will only use the first and last of these plugs, so we don&amp;#039;t even need to populate the board positions for the other channel boards.&lt;br /&gt;
&lt;br /&gt;
Also, I think we might want to put all the switch pull-up resistors on the manuals themselves, soldered to the key tabs.  This will eliminate a lot of crap on the boards, and keep the board design uniform, since the different keys will need different pull-ups.  The manuals, with their 5k internal resistance, will need 50k (or so) pull-ups to 5V, and the pedals and stops, with no internal resistance, will need just 10k (or so) pull-ups to 5V.  Each manual will get a separate power and ground plug for the pull-ups and grounds, so the connectors for the keys don&amp;#039;t need a pin for ground or power, I don&amp;#039;t think... Though if there is room, I guess we could send it along there, too.  Can&amp;#039;t hurt anything, provided the wires support enough current for the crazy case of all the stop pulled or keys pressed or something.  Given a max of 64 inputs to a half-channel, and only 61 keys on a full manual, we can use 2x36 pin connectors for the manuals, and 1x36 pin connector for the pedalboards, and 1x36 pin connector for the stop boards.  Thats 6 total 36 pin connectors, male and female, solder cup and through-hole.&lt;br /&gt;
&lt;br /&gt;
Channel board to main board connectors will have an 8-bit data bus, 4-bit address bus, a power, ground, enable, and identify(?) pins (16 total).  Should be able to use IDC connectors and ribbon cable here.&lt;br /&gt;
&lt;br /&gt;
===Simple algorithm for key change detection===&lt;br /&gt;
After reading a byte from the buffers, we xor it with the copy of the byte from last time, then store the new version in the copy location.  We then start looking at the lsb of the xor&amp;#039;ed byte.  If its a 1, we send a key on if the lsb of the read byte is a 1, and a key off if the lsb of the read byte is a 0.  We then shift right and do that again.  We do that 8 times, once for each bit in that byte.  Then we can move on to the next valid address for that channel, write out the address, read back the buffer value, xor, store, analyze, etc.  Note, we can speed this up by checking if the xor byte is identically 0x00, in which case we don&amp;#039;t have to analyze it, it hasn&amp;#039;t changed.  This will be the usual case!  Only occasionally (in sample time), will things change, and usually only on one bit, and thus one buffer, amongst all the channels and buffers.  This should help us keep up to speed.&lt;br /&gt;
&lt;br /&gt;
Once we are done reading all the channel board buffers, we can check the expression pedals and other variable controls for new values, and possibly send control change events.  After all this, we actually send the MIDI bytes as we have determined them to need to be for this time around, and go to sleep until our next sample time.&lt;br /&gt;
&lt;br /&gt;
Not sure what the latency of the serial to USB conversion is in FTDI, but it could be as bad as a single byte in a single USB message....  Anyway, we want to build a buffer of bytes that need to get send over each sample time, with the RTP-MIDI spec used to make it a stream type thing.  This means: packet length, &amp;quot;timestamp&amp;quot;, first MIDI event, relative timestamps (should all be zero), subsequent MIDI events.&lt;br /&gt;
&lt;br /&gt;
===Chips to use===&lt;br /&gt;
*16x? 74HCT540  for the octal tri-state buffers, inverting (0.54, 20 pin dip)&lt;br /&gt;
*1x? 74HCT138  for 1 to 8 decoder (0.40, 16 pin dip)&lt;br /&gt;
*1x? 74HCT154  for 1 to 16 decoder (0.80, 24 pin dip)&lt;br /&gt;
*1x ATMega164P-20P for AVR controller, 20MHz, (4.82, 40 pin dip)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MIDI_and_the_organ_project&amp;diff=2124</id>
		<title>MIDI and the organ project</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MIDI_and_the_organ_project&amp;diff=2124"/>
		<updated>2009-02-23T19:34:56Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MIDI standard is out there. Also good is the RTP-MIDI RFC, for putting MIDI data into a stream and whatnot.&lt;br /&gt;
&lt;br /&gt;
The basics, as I think we will be using them:&lt;br /&gt;
&lt;br /&gt;
Packet basics (we&amp;#039;ll only be using 3 byte packet forms):&lt;br /&gt;
&lt;br /&gt;
 1 &amp;lt;3: opcode&amp;gt; &amp;lt;4: channel&amp;gt; 0 &amp;lt;7: arg1&amp;gt; 0 &amp;lt;7: arg2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Essentially, a status byte, with the high bit on (0x80-0xFF), and two argument bytes, with the high bit off (0x00-0x7F).&lt;br /&gt;
&lt;br /&gt;
opcodes of relevance:&lt;br /&gt;
*0x0: key off.  arg1 is the key number, arg2 is the velocity.  We will always use velocity of 0x40.&lt;br /&gt;
*0x1: key on. arg1 is the key number, arg2 is the velocity.  We will always use the velocity of 0x40.&lt;br /&gt;
*0x3: control change.  arg1 is the control number (0x01 is modulation wheel, 0x0B is the expression pedal), arg2 is the new control value, from 0x00 - 0x7F (Note:  If we need more than 127 steps, add 0x20 to the control number, and thats the control number to use to send the least significant 7-bits of the value.  The value sent with the base control number is considered to be the most significant 7-bits of the value.  This ensures that if just read the base control number, you set the control to approximately the correct percentage of fully off/fully on.)&lt;br /&gt;
&lt;br /&gt;
For channels, we will use:&lt;br /&gt;
*0x0: Great (Solo) Manual&lt;br /&gt;
*0x1: Swell (Accompaniment) Manual&lt;br /&gt;
*0x2: Choir (below Great) Manual, if present&lt;br /&gt;
*0x3: Solo (above Swell) Manual, if present&lt;br /&gt;
*0x4: Echo (above Solo) Manual, if present&lt;br /&gt;
*0x5: Third Pedalboard, if present, or the auxilary stop channel, covering additional stops for all manuals and pedals.&lt;br /&gt;
*0x6: Second Pedalboard, if present, or the main stop channel, covering all stops for all manuals and pedals.&lt;br /&gt;
*0x7: Main Pedalboard&lt;br /&gt;
*0x8: Great stops only&lt;br /&gt;
*0x9: Swell stops only&lt;br /&gt;
*0xA: Choir stops only&lt;br /&gt;
*0xB: Solo stops only&lt;br /&gt;
*0xC: Echo stops only&lt;br /&gt;
*0xD: Third Pedalboard stops only&lt;br /&gt;
*0xE: Second Pedalboard stops only&lt;br /&gt;
*0xF: Main Pedalboard stops only&lt;br /&gt;
&lt;br /&gt;
Our initial organ will only use channels 0x0-0x1, 0x6-0x7.&lt;br /&gt;
&lt;br /&gt;
Each keyboard channel (0x0-0x7) gets its own control set.  For our organ, where the modulation wheel and expression pedal control all divisions equally, each control change gets sent for each active channel... or maybe just for great, and the software will figure out that they control all the stuff.  Note, we may not hook up the modulation wheel when we begin.  It&amp;#039;d be kinda a lot harder to make work right, I think.&lt;br /&gt;
&lt;br /&gt;
We will be building channel combination boards, that take an enable and a sub-channel address, and read back the contents of the addressed buffer.  4 bits of address gets 16 buffers.  At 8 bits per buffer, thats 128 inputs for each channel.  That matches with midi&amp;#039;s numbering scheme.  Alternatively, if you take the LSB of the true channel, and feed it to the 4th address bit of the channel board, and only decode the top 3 bits of the channel to determine channel board enable, you can duplex your channel boards, since we will only be using under 64 inputs per channel.  The AVR firmware will have an MIDI offset value for each channel to add to the number received from the board before sending as part of a MIDI command. For most subchannels, this will be 36.  Will probably just use an offset of 0 for the stop channels.&lt;br /&gt;
&lt;br /&gt;
Using the split channel board design, we only need two channel boards for our organ.  The main board will be designed to use the channel boards in split mode, and will never probably use the split-mode stop channels (0x8-0xF), so it will only have 4 plugs for channel boards, 0x0-0x1, 0x2-0x3, 0x4-0x5, and 0x6-0x7.  The initial organ will only use the first and last of these plugs, so we don&amp;#039;t even need to populate the board positions for the other channel boards.&lt;br /&gt;
&lt;br /&gt;
Also, I think we might want to put all the switch pull-up resistors on the manuals themselves, soldered to the key tabs.  This will eliminate a lot of crap on the boards, and keep the board design uniform, since the different keys will need different pull-ups.  The manuals, with their 5k internal resistance, will need 50k (or so) pull-ups to 5V, and the pedals and stops, with no internal resistance, will need just 10k (or so) pull-ups to 5V.  Each manual will get a separate power and ground plug for the pull-ups and grounds, so the connectors for the keys don&amp;#039;t need a pin for ground or power, I don&amp;#039;t think... Though if there is room, I guess we could send it along there, too.  Can&amp;#039;t hurt anything, provided the wires support enough current for the crazy case of all the stop pulled or keys pressed or something.  Given a max of 64 inputs to a half-channel, and only 61 keys on a full manual, we can use 2x36 pin connectors for the manuals, and 1x36 pin connector for the pedalboards, and 1x36 pin connector for the stop boards.  Thats 6 total 36 pin connectors, male and female, solder cup and through-hole.&lt;br /&gt;
&lt;br /&gt;
Channel board to main board connectors will have an 8-bit data bus, 4-bit address bus, a power, ground, enable, and identify(?) pins (16 total).  Should be able to use IDC connectors and ribbon cable here.&lt;br /&gt;
&lt;br /&gt;
===Simple algorithm for key change detection===&lt;br /&gt;
After reading a byte from the buffers, we xor it with the copy of the byte from last time, then store the new version in the copy location.  We then start looking at the lsb of the xor&amp;#039;ed byte.  If its a 1, we send a key on if the lsb of the read byte is a 1, and a key off if the lsb of the read byte is a 0.  We then shift right and do that again.  We do that 8 times, once for each bit in that byte.  Then we can move on to the next valid address for that channel, write out the address, read back the buffer value, xor, store, analyze, etc.  Note, we can speed this up by checking if the xor byte is identically 0x00, in which case we don&amp;#039;t have to analyze it, it hasn&amp;#039;t changed.  This will be the usual case!  Only occasionally (in sample time), will things change, and usually only on one bit, and thus one buffer, amongst all the channels and buffers.  This should help us keep up to speed.&lt;br /&gt;
&lt;br /&gt;
Once we are done reading all the channel board buffers, we can check the expression pedals and other variable controls for new values, and possibly send control change events.  After all this, we actually send the MIDI bytes as we have determined them to need to be for this time around, and go to sleep until our next sample time.&lt;br /&gt;
&lt;br /&gt;
Not sure what the latency of the serial to USB conversion is in FTDI, but it could be as bad as a single byte in a single USB message....  Anyway, we want to build a buffer of bytes that need to get send over each sample time, with the RTP-MIDI spec used to make it a stream type thing.  This means: packet length, &amp;quot;timestamp&amp;quot;, first MIDI event, relative timestamps (should all be zero), subsequent MIDI events.&lt;br /&gt;
&lt;br /&gt;
===Chips to use===&lt;br /&gt;
*16x? 74HCT541  for the octal tri-state buffers (0.40, 20 pin dip)&lt;br /&gt;
*1x? 74HCT138  for 1 to 8 decoder (0.40, 16 pin dip)&lt;br /&gt;
*1x? 74HCT154  for 1 to 16 decoder (0.80, 24 pin dip)&lt;br /&gt;
*1x ATMega164P-20P for AVR controller, 20MHz, (4.82, 40 pin dip)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Thoughts_on_avr_event_scheduling&amp;diff=2114</id>
		<title>Thoughts on avr event scheduling</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Thoughts_on_avr_event_scheduling&amp;diff=2114"/>
		<updated>2009-01-30T00:35:56Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;For my reprap playground firmware, I need a better way to schedule events.  This will enable me to do g-code shorthand movement calls.  The general form will be&lt;br /&gt;
 int moveVect(dx, dy, dz, rampUpTime, initialSpeed, finalSpeed, rampDownTime)&lt;br /&gt;
dx, dy, dz is the motion vector relative to current position, given in mm.  rampUpTime and rampDownTime are given in seconds, and initialSpeed/finalSpeed are given in mm/s.  moveVect returns 0 if we were able to move all the way to the target location.  It returns 1 if we could not move all the way there because we hit an endstop.  It returns 2 if we could not move all the way there because we think we would have hit another edge (no endstop).&lt;br /&gt;
&lt;br /&gt;
To help us, we need to have steps per mm numbers for each axis (qx, qy, qz).  We also should have a stepping interval time (qt).  This is how long to actually have the motor coil energized.  This should either be small enough to run during the event, or large enough that a new event to de-energize can be scheduled and run.&lt;br /&gt;
&lt;br /&gt;
As we run through the moveVect() we determine a current speed by linearizing from 0 to initialSpeed over the rampUpTime interval, then linearizing to the finalSpeed over a calculated time it will take us to move in toto (could be tough..??), and finally linearizing back down to 0 over rampDownTime.  After getting the current speed (s), we find out velocity vector (v) by normalizing the motion vector and multiplying it by the speed.&lt;br /&gt;
 dh = sqrt(dx^2 + dy^2 + dz^2)&lt;br /&gt;
 v = (dx*s/dh, dy*s/dh, dz*s/dh)&lt;br /&gt;
&lt;br /&gt;
The next step events should be scheduled then at times in the future given by&lt;br /&gt;
 1/(vi*qi) - qt&lt;br /&gt;
for each axis.  This event simply steps the given axis by toggling the step line for qt seconds.&lt;br /&gt;
&lt;br /&gt;
Each step event needs an axis and a direction.  Associated with each move is a move control block, containing velocity vector information, acceleration vector information, and target location data, as well as info about if we stopped, and why.&lt;br /&gt;
At each event, we check endstops and position to determine if we have to stop, otherwise, we step, adjust that axis&amp;#039;s velecity information using the acceleration information for that axis, and schedule the next event for that axis.&lt;br /&gt;
&lt;br /&gt;
We can chain moves together in a list, and when one move is finished (all axis event chains have ceased, or we are on the last one), we pull up the next move control block and trigger its event chains for each axis.&lt;br /&gt;
&lt;br /&gt;
We&amp;#039;ll need to use one of the chip&amp;#039;s timers for our interrupt, and the interrupt should look at the next event in the event list, and if its timer has expired or will expire, we execute it and remove it from the list.  We then look at the next event in the list.  If its timer has now expired, we execute that one too. We keep doing this until we have no more events or we find one that needs to execute in the future.  We set our interrupt for that future time and exit.&lt;br /&gt;
&lt;br /&gt;
When somebody schedules a new event, we determine if the new event should fire after or before the first one in our current list.  If before, we put it in the list before the first item and reset the interrupt trigger time to our new event&amp;#039;s time.  If after, we put it in the list in the right spot and call it good.&lt;br /&gt;
&lt;br /&gt;
Scheduling an event and the checking to see if we need to run an event need to occur under an event list lock, so we don&amp;#039;t mess up our event list or the timer.  Just use a spin lock probably, and enable/disable interrupts around our check and set.&lt;br /&gt;
&lt;br /&gt;
== Move List ==&lt;br /&gt;
move list lock, next move ptr, next available id, plus list of move control blocks, each containing:&lt;br /&gt;
 type = 1(move)&lt;br /&gt;
 id&lt;br /&gt;
 status 0 not yet active, 1 in progress, 2 complete, at target, 3 complete, not at target&lt;br /&gt;
 link to next move&lt;br /&gt;
 x,y,z endstop/position status (0, ok, 1 max endstop, 2 min endstop, 3 max steps, 4 min steps)&lt;br /&gt;
 x,y,z target&lt;br /&gt;
 x,y,z velocity (current)&lt;br /&gt;
 x,y,z acceleration&lt;br /&gt;
 link to next move&lt;br /&gt;
&lt;br /&gt;
 type = 2(dwell)&lt;br /&gt;
 id&lt;br /&gt;
 status 0 not yet active, 1 in progress, 2 completed.&lt;br /&gt;
 link to next move&lt;br /&gt;
 dwell time&lt;br /&gt;
&lt;br /&gt;
When a move is completed, the old move control block is left on the list until it is removed (to check status, etc), but the next move in the list is started up immediately.  Some move functions:&lt;br /&gt;
 mid = moveDelta(dx, dy, dz, initial speed, final speed)&lt;br /&gt;
 mid = moveTo(x, y, z, initial speed, final speed)&lt;br /&gt;
 status = cancelMove(mid)&lt;br /&gt;
 mid = moveDwell(dwell time)&lt;br /&gt;
 void genMcb(delta?, x,y,z, ispeed, fspeed, buffer*)&lt;br /&gt;
&lt;br /&gt;
== Event Queue ==&lt;br /&gt;
event queue lock, next event ptr, next available id, plus list of event control blocks currently scheduled&lt;br /&gt;
 type = 0 nop&lt;br /&gt;
 time to fire&lt;br /&gt;
 id&lt;br /&gt;
 link to next event&lt;br /&gt;
 move after?&lt;br /&gt;
&lt;br /&gt;
 type = 1 step&lt;br /&gt;
 time to fire&lt;br /&gt;
 id&lt;br /&gt;
 link to next event&lt;br /&gt;
 axis&lt;br /&gt;
 move control block ptr&lt;br /&gt;
&lt;br /&gt;
 type = 2 run&lt;br /&gt;
 time to fire&lt;br /&gt;
 id&lt;br /&gt;
 link to next event&lt;br /&gt;
 function ptr to call (of type (void)(void*))&lt;br /&gt;
 ptr to pass to function when run&lt;br /&gt;
&lt;br /&gt;
 type = 3 move&lt;br /&gt;
 time to fire&lt;br /&gt;
 id&lt;br /&gt;
 link to next event&lt;br /&gt;
 number of mcbs in this event&lt;br /&gt;
 move control blocks to run in the future&lt;br /&gt;
&lt;br /&gt;
When an event is triggered, the event is discarded after being run.  Some event functions:&lt;br /&gt;
  eid = scheduleEvent(type, delta time, data ptr, data len) (eid = -1 means couldn&amp;#039;t schedule)&lt;br /&gt;
  status = cancelEvent(eid) (status = -1 means no such event)&lt;br /&gt;
  eid = scheduleFunction(delta time, func ptr, data)&lt;br /&gt;
  eid = scheduleMoveSequence(delta time, num moves, mcb*)&lt;br /&gt;
  eid = scheduleNop(delta time, move after?)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Thoughts_on_avr_event_scheduling&amp;diff=2113</id>
		<title>Thoughts on avr event scheduling</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Thoughts_on_avr_event_scheduling&amp;diff=2113"/>
		<updated>2009-01-30T00:23:38Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;For my reprap playground firmware, I need a better way to schedule events.  This will enable me to do g-code shorthand movement calls.  The general form will be&lt;br /&gt;
 int moveVect(dx, dy, dz, rampUpTime, initialSpeed, finalSpeed, rampDownTime)&lt;br /&gt;
dx, dy, dz is the motion vector relative to current position, given in mm.  rampUpTime and rampDownTime are given in seconds, and initialSpeed/finalSpeed are given in mm/s.  moveVect returns 0 if we were able to move all the way to the target location.  It returns 1 if we could not move all the way there because we hit an endstop.  It returns 2 if we could not move all the way there because we think we would have hit another edge (no endstop).&lt;br /&gt;
&lt;br /&gt;
To help us, we need to have steps per mm numbers for each axis (qx, qy, qz).  We also should have a stepping interval time (qt).  This is how long to actually have the motor coil energized.  This should either be small enough to run during the event, or large enough that a new event to de-energize can be scheduled and run.&lt;br /&gt;
&lt;br /&gt;
As we run through the moveVect() we determine a current speed by linearizing from 0 to initialSpeed over the rampUpTime interval, then linearizing to the finalSpeed over a calculated time it will take us to move in toto (could be tough..??), and finally linearizing back down to 0 over rampDownTime.  After getting the current speed (s), we find out velocity vector (v) by normalizing the motion vector and multiplying it by the speed.&lt;br /&gt;
 dh = sqrt(dx^2 + dy^2 + dz^2)&lt;br /&gt;
 v = (dx*s/dh, dy*s/dh, dz*s/dh)&lt;br /&gt;
&lt;br /&gt;
The next step events should be scheduled then at times in the future given by&lt;br /&gt;
 1/(vi*qi) - qt&lt;br /&gt;
for each axis.  This event simply steps the given axis by toggling the step line for qt seconds.&lt;br /&gt;
&lt;br /&gt;
Each step event needs an axis and a direction.  Associated with each move is a move control block, containing velocity vector information, acceleration vector information, and target location data, as well as info about if we stopped, and why.&lt;br /&gt;
At each event, we check endstops and position to determine if we have to stop, otherwise, we step, adjust that axis&amp;#039;s velecity information using the acceleration information for that axis, and schedule the next event for that axis.&lt;br /&gt;
&lt;br /&gt;
We can chain moves together in a list, and when one move is finished (all axis event chains have ceased, or we are on the last one), we pull up the next move control block and trigger its event chains for each axis.&lt;br /&gt;
&lt;br /&gt;
We&amp;#039;ll need to use one of the chip&amp;#039;s timers for our interrupt, and the interrupt should look at the next event in the event list, and if its timer has expired or will expire, we execute it and remove it from the list.  We then look at the next event in the list.  If its timer has now expired, we execute that one too. We keep doing this until we have no more events or we find one that needs to execute in the future.  We set our interrupt for that future time and exit.&lt;br /&gt;
&lt;br /&gt;
When somebody schedules a new event, we determine if the new event should fire after or before the first one in our current list.  If before, we put it in the list before the first item and reset the interrupt trigger time to our new event&amp;#039;s time.  If after, we put it in the list in the right spot and call it good.&lt;br /&gt;
&lt;br /&gt;
Scheduling an event and the checking to see if we need to run an event need to occur under an event list lock, so we don&amp;#039;t mess up our event list or the timer.  Just use a spin lock probably, and enable/disable interrupts around our check and set.&lt;br /&gt;
&lt;br /&gt;
== Move List ==&lt;br /&gt;
move list lock, next move ptr, next available id, plus list of move control blocks, each containing:&lt;br /&gt;
 type = 1(move)&lt;br /&gt;
 id&lt;br /&gt;
 status 0 not yet active, 1 in progress, 2 complete, at target, 3 complete, not at target&lt;br /&gt;
 link to next move&lt;br /&gt;
 x,y,z endstop/position status (0, ok, 1 max endstop, 2 min endstop, 3 max steps, 4 min steps)&lt;br /&gt;
 x,y,z target&lt;br /&gt;
 x,y,z velocity (current)&lt;br /&gt;
 x,y,z acceleration&lt;br /&gt;
 link to next move&lt;br /&gt;
&lt;br /&gt;
 type = 2(dwell)&lt;br /&gt;
 id&lt;br /&gt;
 status 0 not yet active, 1 in progress, 2 completed.&lt;br /&gt;
 link to next move&lt;br /&gt;
 dwell time&lt;br /&gt;
&lt;br /&gt;
== Event Queue ==&lt;br /&gt;
event queue lock, next event ptr, next available id, plus list of event control blocks currently scheduled&lt;br /&gt;
 type = 0 nop&lt;br /&gt;
 time to fire&lt;br /&gt;
 id&lt;br /&gt;
 link to next event&lt;br /&gt;
&lt;br /&gt;
 type = 1 step&lt;br /&gt;
 time to fire&lt;br /&gt;
 id&lt;br /&gt;
 link to next event&lt;br /&gt;
 axis&lt;br /&gt;
 move control block ptr&lt;br /&gt;
&lt;br /&gt;
 type = 2 run&lt;br /&gt;
 time to fire&lt;br /&gt;
 id&lt;br /&gt;
 link to next event&lt;br /&gt;
 function ptr to call (of type (void)(void*))&lt;br /&gt;
 ptr to pass to function when run&lt;br /&gt;
&lt;br /&gt;
 type = 3 move&lt;br /&gt;
 time to fire&lt;br /&gt;
 id&lt;br /&gt;
 link to next event&lt;br /&gt;
 move control block to run execute in the future&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MimeEntity&amp;diff=2095</id>
		<title>MimeEntity</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MimeEntity&amp;diff=2095"/>
		<updated>2009-01-23T00:52:19Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MimeEntity represents a standard [[MIME]]/HTTP entity, including headers and body.  For [[Modjs]], there is a MimeEntity in [[MailMessage]]s, [[HTTPRequest]]s, and [[HTTPResponse]]s, including the request that brought about the modjs script invocation, and the response that will be sent back.&lt;br /&gt;
&lt;br /&gt;
MimeEntitys can be created manually with:&lt;br /&gt;
 entity = new MimeEntity(array of [[MimeHeader]]s, body)&lt;br /&gt;
&lt;br /&gt;
If this doesn&amp;#039;t work for some reason, it could throw&lt;br /&gt;
 MimeEntityException&lt;br /&gt;
&lt;br /&gt;
Each MimeEntity has the following properties, which may be queried, but really shouldn&amp;#039;t be edited directly.&lt;br /&gt;
*headers: the array of [[MimeHeader]]s for this entity&lt;br /&gt;
*body: the raw body of this entity&lt;br /&gt;
*type: the major content type of this entity&lt;br /&gt;
*subtype: the subtype of this entity&lt;br /&gt;
*id: the content-id of this entity, if it has one&lt;br /&gt;
*boundary: the boundary string of this entity&lt;br /&gt;
*children: an array of MimeEntities representing the children of this entity, in the multipart and message types&lt;br /&gt;
*leader: In a multipart or message entity, the part of the body before the first boundary&lt;br /&gt;
*trailer: In a multipart or message entity, the part of the body after the last boundary&lt;br /&gt;
&lt;br /&gt;
The entity also has the following methods, which should be the primary method of modifying the entity if needed.&lt;br /&gt;
 string = entity.toString()&lt;br /&gt;
 string = entity.getContentType()&lt;br /&gt;
 string = entity.getBoundaryString(last?)&lt;br /&gt;
 entity.addHeader([[MimeHeader]] | array of [[MimeHeader]]s)&lt;br /&gt;
 string = entity.getHeader(name)&lt;br /&gt;
 entity.setHeader(name, value)&lt;br /&gt;
 entity.clearBody()&lt;br /&gt;
 entity.setBody(string)&lt;br /&gt;
 entity.addToBody(string)&lt;br /&gt;
 entity.addMessageEntity(MimeEntity)&lt;br /&gt;
 entity.addMultipartEntity(MimeEntity | array of MimeEntitys)&lt;br /&gt;
 MimeEntity = entity.removeChildEntity(index)&lt;br /&gt;
 MimeEntity = entity.getChildEntity(index)&lt;br /&gt;
 MimeEntity = entity.getChildEntityById(id)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MimeEntity&amp;diff=2094</id>
		<title>MimeEntity</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MimeEntity&amp;diff=2094"/>
		<updated>2009-01-23T00:49:36Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MimeEntity represents a standard [[MIME]]/HTTP entity, including headers and body.  For [[Modjs]], there is a MimeEntity in MailMessages, HTTPRequests, and HTTPResponses, including the request that brought about the modjs script invocation, and the response that will be sent back.&lt;br /&gt;
&lt;br /&gt;
MimeEntitys can be created manually with:&lt;br /&gt;
 entity = new MimeEntity(array of MimeHeaders, body)&lt;br /&gt;
&lt;br /&gt;
If this doesn&amp;#039;t work for some reason, it could throw&lt;br /&gt;
 MimeEntityException&lt;br /&gt;
&lt;br /&gt;
Each MimeEntity has the following properties, which may be queried, but really shouldn&amp;#039;t be edited directly.&lt;br /&gt;
*headers: the array of MimeHeaders for this entity&lt;br /&gt;
*body: the raw body of this entity&lt;br /&gt;
*type: the major content type of this entity&lt;br /&gt;
*subtype: the subtype of this entity&lt;br /&gt;
*id: the content-id of this entity, if it has one&lt;br /&gt;
*boundary: the boundary string of this entity&lt;br /&gt;
*children: an array of MimeEntities representing the children of this entity, in the multipart and message types&lt;br /&gt;
*leader: In a multipart or message entity, the part of the body before the first boundary&lt;br /&gt;
*trailer: In a multipart or message entity, the part of the body after the last boundary&lt;br /&gt;
&lt;br /&gt;
The entity also has the following methods, which should be the primary method of modifying the entity if needed.&lt;br /&gt;
 string = entity.toString()&lt;br /&gt;
 string = entity.getContentType()&lt;br /&gt;
 string = entity.getBoundaryString(last?)&lt;br /&gt;
 entity.addHeader(MimeHeader | array of MimeHeader)&lt;br /&gt;
 string = entity.getHeader(name)&lt;br /&gt;
 entity.setHeader(name, value)&lt;br /&gt;
 entity.clearBody()&lt;br /&gt;
 entity.setBody(string)&lt;br /&gt;
 entity.addToBody(string)&lt;br /&gt;
 entity.addMessageEntity(MimeEntity)&lt;br /&gt;
 entity.addMultipartEntity(MimeEntity | array of MimeEntitys)&lt;br /&gt;
 MimeEntity = entity.removeChildEntity(index)&lt;br /&gt;
 MimeEntity = entity.getChildEntity(index)&lt;br /&gt;
 MimeEntity = entity.getChildEntityById(id)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=HTTPRequest&amp;diff=2093</id>
		<title>HTTPRequest</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=HTTPRequest&amp;diff=2093"/>
		<updated>2009-01-23T00:48:23Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: The HTTPRequest class represents an HTTP Request message for my Modjs environment.  It contains a request line and other information about the requestor, and a MIME entity ([[MimeE...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The HTTPRequest class represents an HTTP Request message for my [[Modjs]] environment.  It contains a request line and other information about the requestor, and a [[MIME]] entity ([[MimeEntity]]) for the request headers and data.  Its primary use will be for the script writer to see the request from the browser to the server, and what data they are sending over.  It will do a little bit to parse out cookie variables, query variables, and post data variables to make the script writer&amp;#039;s life easier.  It can also be tied back to a [[HTTPResponse]] object to make inclusion of cookie headers mostly seemless when new cookies are defined and the response is sent back with them.&lt;br /&gt;
&lt;br /&gt;
When a [[Modjs]] script builds a completely new HTTPRequest object in order to send it over a [[TCPConnection]] or the like to a different, remote, server, it will behave a little bit differently, in that, rather than parsing the headers and request data in order to get cookies/queries/posts, it will have the ability to unparse those variables sets back into headers and request data, as needed (and only if requested).  And not cookies.  Just too much work for too little benefit.&lt;br /&gt;
&lt;br /&gt;
Some info on this class was previously described in [[request API]], but that is no longer trustworthy and should get copied over here and corrected.&lt;br /&gt;
&lt;br /&gt;
To create a new HTTPRequest object, the constructor is called:&lt;br /&gt;
 request = new HTTPRequest(host [,method [,path [,query [,version]]]])&lt;br /&gt;
&lt;br /&gt;
Note that except for host, the rest of the arguments could be passed as one string. They are essentially joined and reparsed to verify that the correct syntax is used for the request line.  host sets the required Host: header in the mimeentity on creation.  If the method is POST, the Content-type: header also gets set to the default value of application/form-data.  &lt;br /&gt;
&lt;br /&gt;
This could throw an exception if method or query string are malformed:&lt;br /&gt;
 HTTPRequestException&lt;br /&gt;
&lt;br /&gt;
The object will have these properties:&lt;br /&gt;
*method: the request method&lt;br /&gt;
*path: the request path&lt;br /&gt;
*query: the request query&lt;br /&gt;
*host: the request host&lt;br /&gt;
*version: the request version&lt;br /&gt;
*entity: the [[MimeEntity]] for the data in this request, including headers.&lt;br /&gt;
*queryVars: the query is parsed and proper variables are put in here as name/value pairs.  Last one sticks. If you reuse a name, you&amp;#039;ll have to go to the real query to get both values.  On outgoing requests, this will get slurped up and urlencoded and _added_ to the query property as part of the query string in the request line.  Be aware!&lt;br /&gt;
*cookieVars: the Cookie and Cookie2 headers are parsed and proper variables are put in here as name/value pairs.  If there are duplicate names, the last one sticks. Go to the actual headers if you need more, or property values.  Note that this is not a magic cookie jar.  For the outgoing response, if you need to add new cookies, you must add the cookie using the [[HTTPResponse]] addCookie() method.  For outgoing requests, the cookie variables placed in here do not get magically merged into the appropriate Cookie: header, since it doesn&amp;#039;t have enough information.&lt;br /&gt;
*postVars: If the method is POST and the [[MIME]] entity is correct, posted variables get parsed and put in here as name/value pairs.  If there are dups, again, the last one sticks.  You may have to actually decode the entity if you need more details.  On outgoing requests, this will get slurped up and put as variables in the POST data, in the appropriate section, depending on current content-type and method, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The object has only one method, toString() which essentially converts to a single string, appropriate for sending over a TCPConnection.  This will do queryVars and postVars recombination, if there are any variables there.  Be aware!  It will also use proper CRLF EOLs, for network safety.&lt;br /&gt;
 string = request.toString()&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2092</id>
		<title>Modjs</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2092"/>
		<updated>2009-01-22T17:54:18Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.modjs.org modjs.org] has the rudiments of an apache module to handle server side javascript using SpiderMonkey.&lt;br /&gt;
&lt;br /&gt;
SpiderMonkey [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference APIs] and a [https://developer.mozilla.org/en/SpiderMonkey tutorial].&lt;br /&gt;
Apache Module [http://httpd.apache.org/dev/apidoc/ APIs] and a [http://httpd.apache.org/dev/API.html tutorial].&lt;br /&gt;
&lt;br /&gt;
Would like [[MIME]] support, a global request/response object (both MIME trees I think), SQLite and MySQL support, and File IO Support (if its not already there).  Also should have support for including other javascript sources.  mod_js has an example for includes and some of the request/apache stuff.  SpiderMonkey has an example shell that shows some support for File objects I think.&lt;br /&gt;
&lt;br /&gt;
Would be nice to have libGD and/or ImageMagick support (EXIF too, if possible), as well as some sort of curl library to get to other sites to do stuff.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Things we should have:&lt;br /&gt;
*Class for MIME objects and MIME headers.&lt;br /&gt;
*Object with server info (environment, log functionality)&lt;br /&gt;
*Object with request info (request string (full and broken up), incoming mime object, maybe cookies already broken up, etc.)&lt;br /&gt;
*Object with response info (outgoing mime object, print functionality, obstack stuff, way to set headers, etc)&lt;br /&gt;
*File class extensions, if needed&lt;br /&gt;
*Better include support (add to File)&lt;br /&gt;
*MySQL/SQLite classes and support (new classes probably needed here)&lt;br /&gt;
*system call support (put this on server)&lt;br /&gt;
*image manipulation support (new classes probably needed here)&lt;br /&gt;
*json support (maybe just some quick functions on the response (encode) /request (decode) ? or maybe better as a global)&lt;br /&gt;
*curl support (new class probably, using MIME stuff to send and receive, probably wrapped by request/response like objects.. maybe they should be classes, too.)&lt;br /&gt;
*Instead of bothering with curl, maybe just have a way to open a socket and read/write to it for now.&lt;br /&gt;
&lt;br /&gt;
JS Class APIs:&lt;br /&gt;
*File (see [[File API]])&lt;br /&gt;
*server object (see [[server API]])&lt;br /&gt;
*[[TCPConnection]]&lt;br /&gt;
*[[DbConnection]]&lt;br /&gt;
*DbStatement (see [[DbConnection]])&lt;br /&gt;
*[[ProcessConnection]]&lt;br /&gt;
*[[MimeHeader]]&lt;br /&gt;
*[[MimeEntity]]&lt;br /&gt;
*[[MailMessage]]&lt;br /&gt;
*[[HTTPRequest]] modified [[request API]]&lt;br /&gt;
*[[HTTPResponse]] modified [[response API]]&lt;br /&gt;
*global object (see [[global object extensions]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Things the module should do if it can:&lt;br /&gt;
*Cache compiled javascript code?&lt;br /&gt;
*Stay alive? Might already do this...&lt;br /&gt;
*Cached javascript context? Would this make sense?&lt;br /&gt;
*Cached session stuff? Do I really want/need this?&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MimeEntity&amp;diff=2091</id>
		<title>MimeEntity</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MimeEntity&amp;diff=2091"/>
		<updated>2009-01-22T00:37:36Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: MimeEntity represents a standard MIME/HTTP entity, including headers and body.  For Modjs, there is a MimeEntity in MailMessages, HTTPRequests, and HTTPResponses, including the req...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MimeEntity represents a standard [[MIME]]/HTTP entity, including headers and body.  For [[Modjs]], there is a MimeEntity in MailMessages, HTTPRequests, and HTTPResponses, including the request that brought about the modjs script invocation, and the response that will be sent back.&lt;br /&gt;
&lt;br /&gt;
MimeEntitys can be created manually with:&lt;br /&gt;
 entity = new MimeEntity(array of MimeHeaders, body)&lt;br /&gt;
&lt;br /&gt;
If this doesn&amp;#039;t work for some reason, it could throw&lt;br /&gt;
 MimeEntityException&lt;br /&gt;
&lt;br /&gt;
Each MimeEntity has the following properties, which may be queried, but really shouldn&amp;#039;t be edited directly.&lt;br /&gt;
*headers: the array of MimeHeaders for this entity&lt;br /&gt;
*body: the raw body of this entity&lt;br /&gt;
*type: the major content type of this entity&lt;br /&gt;
*subtype: the subtype of this entity&lt;br /&gt;
*id: the content-id of this entity, if it has one&lt;br /&gt;
*boundary: the boundary string of this entity&lt;br /&gt;
*children: an array of MimeEntities representing the children of this entity, in the multipart and message types&lt;br /&gt;
*leader: In a multipart or message entity, the part of the body before the first boundary&lt;br /&gt;
*trailer: In a multipart or message entity, the part of the body after the last boundary&lt;br /&gt;
&lt;br /&gt;
The entity also has the following methods, which should be the primary method of modifying the entity if needed.&lt;br /&gt;
 string = entity.toString()&lt;br /&gt;
 string = entity.getContentType()&lt;br /&gt;
 string = entity.getBoundaryString(last?)&lt;br /&gt;
 entity.addHeader(MimeHeader | array of MimeHeader)&lt;br /&gt;
 entity.clearBody()&lt;br /&gt;
 entity.setBody(string)&lt;br /&gt;
 entity.addToBody(string)&lt;br /&gt;
 entity.addMessageEntity(MimeEntity)&lt;br /&gt;
 entity.addMultipartEntity(MimeEntity | array of MimeEntitys)&lt;br /&gt;
 MimeEntity = entity.removeChildEntity(index)&lt;br /&gt;
 MimeEntity = entity.getChildEntity(index)&lt;br /&gt;
 MimeEntity = entity.getChildEntityById(id)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MimeHeader&amp;diff=2090</id>
		<title>MimeHeader</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MimeHeader&amp;diff=2090"/>
		<updated>2009-01-22T00:17:27Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A MimeHeader object represents a single header in a MIME or HTTP message in a easier to use format for [[Modjs]] scripts.  Each header can have an array of MimeValue objects, which can have an array of MimeProperties. The true format of these are described in [[MIME]].&lt;br /&gt;
&lt;br /&gt;
To paraphrase, a true MIME header is a name:value[,value...] pair of form:&lt;br /&gt;
 header          := header-name  &amp;#039;:&amp;#039;  header-value  CRLF&lt;br /&gt;
 header-value    := values&lt;br /&gt;
 values          := (value-exp  &amp;#039;,&amp;#039;)*  value-exp&lt;br /&gt;
&lt;br /&gt;
Each value is of form:&lt;br /&gt;
 value-exp       := real-value  (&amp;#039;;&amp;#039;  property-exp)*&lt;br /&gt;
 real-value      := value-key [&amp;#039;=&amp;#039; value-value]&lt;br /&gt;
&lt;br /&gt;
And each property then is of form:&lt;br /&gt;
 property-exp    := property-key  [&amp;#039;=&amp;#039;  property-value]&lt;br /&gt;
&lt;br /&gt;
A new MimeHeader can be created using:&lt;br /&gt;
 header = new MimeHeader(name, array of MimeValue objects)&lt;br /&gt;
 header = new MimeHeader(name, raw value string)&lt;br /&gt;
&lt;br /&gt;
If the header cannot be created (if the objects passed in aren&amp;#039;t duckable to MimeValue, or the string isn&amp;#039;t valid header value formatted), an exception can be thrown:&lt;br /&gt;
 MimeHeaderException&lt;br /&gt;
&lt;br /&gt;
A new MimeValue can be created using:&lt;br /&gt;
 value = new MimeValue(raw value, array of MimeParameters)&lt;br /&gt;
 value = new MimeValue(value name, value content, array of MimeParameters)&lt;br /&gt;
 value = new MimeValue(raw value string)&lt;br /&gt;
&lt;br /&gt;
These could throw:&lt;br /&gt;
 MimeValueException&lt;br /&gt;
&lt;br /&gt;
A new MimeProperty can be created using:&lt;br /&gt;
 property = new MimeProperty(property name, property value)&lt;br /&gt;
&lt;br /&gt;
Once a header is created, it has these properties:&lt;br /&gt;
*name: The header name&lt;br /&gt;
*values: array of MimeValue objects&lt;br /&gt;
&lt;br /&gt;
The header has several methods:&lt;br /&gt;
 string = header.getName()&lt;br /&gt;
 array of MimeValues = header.getValueList()&lt;br /&gt;
 header.addValue(MimeValue)&lt;br /&gt;
 MimeValue = header.removeValue(index)&lt;br /&gt;
 MimeValue = header.getValue(index)&lt;br /&gt;
 string = header.toString()&lt;br /&gt;
 string = header.getValue(value name)&lt;br /&gt;
&lt;br /&gt;
The value has these properties:&lt;br /&gt;
*value: The value name, or &amp;quot;true&amp;quot; value&lt;br /&gt;
*content: the value content&lt;br /&gt;
*properties: array of parameter name/value pairs&lt;br /&gt;
&lt;br /&gt;
And these methods:&lt;br /&gt;
 string = value.getValueName()&lt;br /&gt;
 string = value.getValueContent()&lt;br /&gt;
 string = value.getValue()&lt;br /&gt;
 value.setValueContent(string)&lt;br /&gt;
 array of MimeParameters = value.getPropertyList()&lt;br /&gt;
 value.addParameter(MimeParameter)&lt;br /&gt;
 MimeParameter = value.removeParameter(index)&lt;br /&gt;
 MimeParameter = value.getParameter(index)&lt;br /&gt;
 string = value.toString()&lt;br /&gt;
 string = value.getParameter(parameter name)&lt;br /&gt;
&lt;br /&gt;
MimeParameters have these properties:&lt;br /&gt;
*name: the parameter name&lt;br /&gt;
*value: the parameter value&lt;br /&gt;
&lt;br /&gt;
And these methods:&lt;br /&gt;
 string = parm.getName()&lt;br /&gt;
 string = parm.getValue()&lt;br /&gt;
 parm.setValue(string)&lt;br /&gt;
 string = parm.toString()&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MimeHeader&amp;diff=2089</id>
		<title>MimeHeader</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MimeHeader&amp;diff=2089"/>
		<updated>2009-01-22T00:14:26Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A MimeHeader object represents a single header in a MIME or HTTP message in a easier to use format for [[Modjs]] scripts.  Each header can have an array of MimeValue objects, which can have an array of MimeProperties. The true format of these are described in [[MIME]].&lt;br /&gt;
&lt;br /&gt;
To paraphrase, a true MIME header is a name:value[,value...] pair of form:&lt;br /&gt;
 header          := header-name  &amp;#039;:&amp;#039;  header-value  CRLF&lt;br /&gt;
 header-value    := values&lt;br /&gt;
 values          := (value-exp  &amp;#039;,&amp;#039;)*  value-exp&lt;br /&gt;
&lt;br /&gt;
Each value is of form:&lt;br /&gt;
 value-exp       := real-value  (&amp;#039;;&amp;#039;  property-exp)*&lt;br /&gt;
 real-value      := value-key [&amp;#039;=&amp;#039; value-value]&lt;br /&gt;
&lt;br /&gt;
And each property then is of form:&lt;br /&gt;
 property-exp    := property-key  [&amp;#039;=&amp;#039;  property-value]&lt;br /&gt;
&lt;br /&gt;
A new MimeHeader can be created using:&lt;br /&gt;
 header = new MimeHeader(name, array of MimeValue objects)&lt;br /&gt;
 header = new MimeHeader(name, raw value string)&lt;br /&gt;
&lt;br /&gt;
If the header cannot be created (if the objects passed in aren&amp;#039;t duckable to MimeValue, or the string isn&amp;#039;t valid header value formatted), an exception can be thrown:&lt;br /&gt;
 MimeHeaderException&lt;br /&gt;
&lt;br /&gt;
A new MimeValue can be created using:&lt;br /&gt;
 value = new MimeValue(raw value, array of MimeParameters)&lt;br /&gt;
 value = new MimeValue(value name, value content, array of MimeParameters)&lt;br /&gt;
 value = new MimeValue(raw value string)&lt;br /&gt;
&lt;br /&gt;
These could throw:&lt;br /&gt;
 MimeValueException&lt;br /&gt;
&lt;br /&gt;
A new MimeProperty can be created using:&lt;br /&gt;
 property = new MimeProperty(property name, property value)&lt;br /&gt;
&lt;br /&gt;
Once a header is created, it has these properties:&lt;br /&gt;
*name: The header name&lt;br /&gt;
*values: array of MimeValue objects&lt;br /&gt;
&lt;br /&gt;
The header has several methods:&lt;br /&gt;
 string = header.getName()&lt;br /&gt;
 array of MimeValues = header.getValueList()&lt;br /&gt;
 header.addValue(MimeValue)&lt;br /&gt;
 MimeValue = header.removeValue(index)&lt;br /&gt;
 MimeValue = header.getValue(index)&lt;br /&gt;
 string = header.toString()&lt;br /&gt;
 string = header.getValue(value name)&lt;br /&gt;
&lt;br /&gt;
The value has these properties:&lt;br /&gt;
*value: The value name, or &amp;quot;true&amp;quot; value&lt;br /&gt;
*content: the value content&lt;br /&gt;
*properties: array of parameter name/value pairs&lt;br /&gt;
&lt;br /&gt;
And these methods:&lt;br /&gt;
 string = value.getValueName()&lt;br /&gt;
 string = value.getValueContent()&lt;br /&gt;
 string = value.getValue()&lt;br /&gt;
 value.setValueContent(string)&lt;br /&gt;
 array of MimeParameters = value.getPropertyList()&lt;br /&gt;
 value.addParameter(MimeParameter)&lt;br /&gt;
 MimeParameter = value.removeParameter(index)&lt;br /&gt;
 MimeParameter = value.getParameter(index)&lt;br /&gt;
 string = value.toString()&lt;br /&gt;
 string = value.getParameter(parameter name)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MimeHeader&amp;diff=2088</id>
		<title>MimeHeader</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MimeHeader&amp;diff=2088"/>
		<updated>2009-01-22T00:09:10Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: A MimeHeader object represents a single header in a MIME or HTTP message in a easier to use format for Modjs scripts.  Each header can have an array of MimeValue objects.  The true for...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A MimeHeader object represents a single header in a MIME or HTTP message in a easier to use format for [[Modjs]] scripts.  Each header can have an array of MimeValue objects.  The true format of these are described in [[MIME]].&lt;br /&gt;
&lt;br /&gt;
To paraphrase, a true MIME header is a name:value[,value...] pair of form:&lt;br /&gt;
 header          := header-name  &amp;#039;:&amp;#039;  header-value  CRLF&lt;br /&gt;
 header-value    := values&lt;br /&gt;
 values          := (value-exp  &amp;#039;,&amp;#039;)*  value-exp&lt;br /&gt;
&lt;br /&gt;
Each value is of form:&lt;br /&gt;
 value-exp       := real-value  (&amp;#039;;&amp;#039;  property-exp)*&lt;br /&gt;
 real-value      := value-key [&amp;#039;=&amp;#039; value-value]&lt;br /&gt;
 property-exp    := property-key  [&amp;#039;=&amp;#039;  property-value]&lt;br /&gt;
&lt;br /&gt;
A new MimeHeader can be created using:&lt;br /&gt;
 header = new MimeHeader(name, array of MimeValue objects)&lt;br /&gt;
 header = new MimeHeader(name, raw value string)&lt;br /&gt;
&lt;br /&gt;
If the header cannot be created (if the objects passed in aren&amp;#039;t duckable to MimeValue, or the string isn&amp;#039;t valid header value formatted), an exception can be thrown:&lt;br /&gt;
 MimeHeaderException&lt;br /&gt;
&lt;br /&gt;
A new MimeValue can be created using:&lt;br /&gt;
 value = new MimeValue(value, array of parameter name/value pairs)&lt;br /&gt;
 value = new MimeValue(raw value string)&lt;br /&gt;
&lt;br /&gt;
These could throw:&lt;br /&gt;
 MimeValueException&lt;br /&gt;
&lt;br /&gt;
Once a header is created, it has these properties:&lt;br /&gt;
*name: The header name&lt;br /&gt;
*values: array of MimeValue objects&lt;br /&gt;
&lt;br /&gt;
The header has several methods:&lt;br /&gt;
 string = header.getName()&lt;br /&gt;
 array of value strings = header.getValueList()&lt;br /&gt;
 header.addValue(MimeValue)&lt;br /&gt;
 MimeValue = header.removeValue(index)&lt;br /&gt;
 MimeValue = header.getValue(index)&lt;br /&gt;
 string = header.toString()&lt;br /&gt;
&lt;br /&gt;
The value has these properties:&lt;br /&gt;
*value: The &amp;quot;true&amp;quot; value&lt;br /&gt;
*properties: array of parameter name/value pairs&lt;br /&gt;
&lt;br /&gt;
And these methods:&lt;br /&gt;
 string = value.getValue()&lt;br /&gt;
 array of parameters = value.getPropertyList()&lt;br /&gt;
 value.addParameter(name, value)&lt;br /&gt;
 {name, value} = value.removeParameter(index)&lt;br /&gt;
 {name, value} = value.getParameter(index)&lt;br /&gt;
 string = value.toString()&lt;br /&gt;
 string = value.getParameter(parameter name)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Global_object_extensions&amp;diff=2087</id>
		<title>Global object extensions</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Global_object_extensions&amp;diff=2087"/>
		<updated>2009-01-21T23:50:20Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: A couple functions, I didn&amp;#039;t know where to put, but definitely wanted for my Modjs implementation, so they went onto the global object.  If I can think of a better place for them, they...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A couple functions, I didn&amp;#039;t know where to put, but definitely wanted for my [[Modjs]] implementation, so they went onto the global object.  If I can think of a better place for them, they may move.  This page can also list all the classes I&amp;#039;ve added and that are available and whatnot.&lt;br /&gt;
&lt;br /&gt;
Used to convert an object to a JSON compliant string and back again:&lt;br /&gt;
 string = jsonEncode(object)&lt;br /&gt;
 object = jsonDecode(string)&lt;br /&gt;
&lt;br /&gt;
These could throw exceptions if the object or string cannot be converted or is otherwise malformed:&lt;br /&gt;
 JsonCodingException&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=ProcessConnection&amp;diff=2086</id>
		<title>ProcessConnection</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=ProcessConnection&amp;diff=2086"/>
		<updated>2009-01-21T23:47:38Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ProcessConnection is a class to represent an external process running on the server that is started by this [[Modjs]] script and runs independently.  It can be read and written to as well.&lt;br /&gt;
&lt;br /&gt;
Start the process by creating a new ProcessConnection:&lt;br /&gt;
 process = new ProcessConnection(cmd, args array)&lt;br /&gt;
 process = new ProcessConnection(cmdandargs)&lt;br /&gt;
 process = new ProcessConnection(File, args array)&lt;br /&gt;
&lt;br /&gt;
Read and write just like for TCPConnections:&lt;br /&gt;
 process.send(string | array of strings)&lt;br /&gt;
 string = process.recvAll()&lt;br /&gt;
 string = process.recvLine(chomp?)&lt;br /&gt;
 array of strings = process.recvLines(numlines, chomp?)&lt;br /&gt;
 bool = process.dataAvailable()&lt;br /&gt;
&lt;br /&gt;
Closing the process can be done by garbage collection or explicit close():&lt;br /&gt;
 status = process.close()&lt;br /&gt;
&lt;br /&gt;
Note that close() blocks until the process ends and a status is returned.  Garbage collection will do the same.&lt;br /&gt;
&lt;br /&gt;
To send a signal to the process (and thus possibly killing it earlier, if needed):&lt;br /&gt;
 process.signal(signum)&lt;br /&gt;
&lt;br /&gt;
Exceptions can be thrown:&lt;br /&gt;
 ProcessConnectionOpenError&lt;br /&gt;
 ProcessConnectionChildClosed&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=DbConnection&amp;diff=2085</id>
		<title>DbConnection</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=DbConnection&amp;diff=2085"/>
		<updated>2009-01-21T23:46:53Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DbConnection is used to talk to MySQL (for now) and later SQLite databases from a [[Modjs]] script.&lt;br /&gt;
&lt;br /&gt;
To connect to a database, create a new object:&lt;br /&gt;
 connection = new DbConnection(host, database, username, password, type): type is &amp;quot;mysql&amp;quot; or &amp;quot;sqlite&amp;quot; but defaults to &amp;quot;mysql&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exceptions include:&lt;br /&gt;
 DbConnectionError&lt;br /&gt;
 DbStatementError&lt;br /&gt;
&lt;br /&gt;
To use the connection to the database:&lt;br /&gt;
 connection.close(): closes the database connection explicitly(otherwise garbage collection will do so)&lt;br /&gt;
 statement = connection.prepare(string): creates a new prepared statement based on the passed in string&lt;br /&gt;
 numRowsAffected = connection.execute(string): executes the given statement straight up.  Please don&amp;#039;t use unless you have to. May not be supported.&lt;br /&gt;
 array of result objects = connection.query(string): executes the given statement straight up. Please don&amp;#039;t use unless you have to. May not be supported.&lt;br /&gt;
&lt;br /&gt;
To use DbStatements, you must first get one from the connection by preparing it. Then:&lt;br /&gt;
 numRowsAffected = statement.execute(array of bound arguments)&lt;br /&gt;
 array of result objects = statement.query(array of bound arguments)&lt;br /&gt;
&lt;br /&gt;
Result objects are created by using the field names (or AS marked field names) wherever possible.  If not possible (expression or something), the field will be named &amp;quot;_exp_N&amp;quot; where N goes from 1 on up as needed.  Try to use reasonably AS clauses. it just makes it so much easier.  expressions may not be supported at first.&lt;br /&gt;
&lt;br /&gt;
Statements stick around until they are garbage collected.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=TCPConnection&amp;diff=2084</id>
		<title>TCPConnection</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=TCPConnection&amp;diff=2084"/>
		<updated>2009-01-21T23:46:18Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Wrapper for C socket API.  Only works for now with IPv4 and TCP streams.  Only client support for now as well.  Just simpler.  Why would a user of [[Modjs]] need server support anyway?&lt;br /&gt;
&lt;br /&gt;
Construct with:&lt;br /&gt;
 connection = new TCPConnection(remotehost, remoteport)&lt;br /&gt;
&lt;br /&gt;
Exceptions:&lt;br /&gt;
 TCPConnectionError&lt;br /&gt;
&lt;br /&gt;
Send and receive with:&lt;br /&gt;
 connection.send(string | array of strings)&lt;br /&gt;
 string = connection.recvAll()&lt;br /&gt;
 string = connection.recvLine(chomp?)&lt;br /&gt;
 array of strings = connection.recvLines(numLines, chomp?)&lt;br /&gt;
 boolean = connection.dataAvailable()&lt;br /&gt;
&lt;br /&gt;
Closure is done when garbage collected, or when close() is called directly:&lt;br /&gt;
 connection.close()&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Server_API&amp;diff=2083</id>
		<title>Server API</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Server_API&amp;diff=2083"/>
		<updated>2009-01-21T23:45:46Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The server object is a global object representing the server interfaces for logging and environment and such in my [[Modjs]] implementation.&lt;br /&gt;
&lt;br /&gt;
Data members on the global server object:&lt;br /&gt;
*env: array of environment variables, including standard request headers and server information&lt;br /&gt;
&lt;br /&gt;
Functions on the global server object:&lt;br /&gt;
*logNotice(string|array of strings): function to log a notice (or a list of notices) to the server error log&lt;br /&gt;
*logError(string|array of strings): function to log an error (or a list of errors) to the server error log&lt;br /&gt;
*runCmd(cmdstring): function execute a command on the server (with the httpd daemon&amp;#039;s permissions!) execution of the script will wait until the cmd is finished, and will return the exit status of the command.&lt;br /&gt;
*runCmd(cmd, array of args): same as above, but executes the given command with the arguments given in the array.  arguments will be escaped or quoted as necessary&lt;br /&gt;
*runCmd(File, array of args): same as above, but takes the given command from the File object passed in.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=File_API&amp;diff=2082</id>
		<title>File API</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=File_API&amp;diff=2082"/>
		<updated>2009-01-21T23:44:22Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File is a built in class from SpiderMonkey, but its poorly documented.  Going through the source code, it appears this is what we get for the interface.&lt;br /&gt;
&lt;br /&gt;
Global properties of File:&lt;br /&gt;
*curdir (sp?):&lt;br /&gt;
&lt;br /&gt;
Properties of File objects:&lt;br /&gt;
*length&lt;br /&gt;
*name&lt;br /&gt;
*parent&lt;br /&gt;
*size&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Methods of File objects:&lt;br /&gt;
*new File([path])&lt;br /&gt;
*open()&lt;br /&gt;
*close()&lt;br /&gt;
*flush()&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
I&amp;#039;ve extended File to add an include and require and stuff for my [[Modjs]]:&lt;br /&gt;
*File.prototype.include(): Executes the contents of the File as a javascript script in place.&lt;br /&gt;
*File.prototype.require(): Executes the contents of the File as a javascript script in place, only if it has not already been executed as part of a require().  Keeps track by updating a property in the global File class object (required[])&lt;br /&gt;
*File.required[]: array of filenames that have already been executed by a require() call for the current script.&lt;br /&gt;
*File.prototype.execute(args array): Executes the File as with server.runCmd(File, args array) and returns the exit status&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2081</id>
		<title>Modjs</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2081"/>
		<updated>2009-01-21T23:43:47Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.modjs.org modjs.org] has the rudiments of an apache module to handle server side javascript using SpiderMonkey.&lt;br /&gt;
&lt;br /&gt;
SpiderMonkey [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference APIs] and a [https://developer.mozilla.org/en/SpiderMonkey tutorial].&lt;br /&gt;
Apache Module [http://httpd.apache.org/dev/apidoc/ APIs] and a [http://httpd.apache.org/dev/API.html tutorial].&lt;br /&gt;
&lt;br /&gt;
Would like [[MIME]] support, a global request/response object (both MIME trees I think), SQLite and MySQL support, and File IO Support (if its not already there).  Also should have support for including other javascript sources.  mod_js has an example for includes and some of the request/apache stuff.  SpiderMonkey has an example shell that shows some support for File objects I think.&lt;br /&gt;
&lt;br /&gt;
Would be nice to have libGD and/or ImageMagick support (EXIF too, if possible), as well as some sort of curl library to get to other sites to do stuff.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Things we should have:&lt;br /&gt;
*Class for MIME objects and MIME headers.&lt;br /&gt;
*Object with server info (environment, log functionality)&lt;br /&gt;
*Object with request info (request string (full and broken up), incoming mime object, maybe cookies already broken up, etc.)&lt;br /&gt;
*Object with response info (outgoing mime object, print functionality, obstack stuff, way to set headers, etc)&lt;br /&gt;
*File class extensions, if needed&lt;br /&gt;
*Better include support (add to File)&lt;br /&gt;
*MySQL/SQLite classes and support (new classes probably needed here)&lt;br /&gt;
*system call support (put this on server)&lt;br /&gt;
*image manipulation support (new classes probably needed here)&lt;br /&gt;
*json support (maybe just some quick functions on the response (encode) /request (decode) ? or maybe better as a global)&lt;br /&gt;
*curl support (new class probably, using MIME stuff to send and receive, probably wrapped by request/response like objects.. maybe they should be classes, too.)&lt;br /&gt;
*Instead of bothering with curl, maybe just have a way to open a socket and read/write to it for now.&lt;br /&gt;
&lt;br /&gt;
JS Class APIs:&lt;br /&gt;
*File (see [[File API]])&lt;br /&gt;
*server object (see [[server API]])&lt;br /&gt;
*[[TCPConnection]]&lt;br /&gt;
*[[DbConnection]]&lt;br /&gt;
*DbStatement (see [[DbConnection]])&lt;br /&gt;
*[[ProcessConnection]]&lt;br /&gt;
*[[MimeHeader]]&lt;br /&gt;
*[[MimeEntity]]&lt;br /&gt;
*[[MailMessage]]&lt;br /&gt;
*[[HTTPRequest]]&lt;br /&gt;
*[[HTTPResponse]]&lt;br /&gt;
*global object (see [[global object extensions]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Things the module should do if it can:&lt;br /&gt;
*Cache compiled javascript code?&lt;br /&gt;
*Stay alive? Might already do this...&lt;br /&gt;
*Cached javascript context? Would this make sense?&lt;br /&gt;
*Cached session stuff? Do I really want/need this?&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2080</id>
		<title>Modjs</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2080"/>
		<updated>2009-01-21T23:41:37Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.modjs.org modjs.org] has the rudiments of an apache module to handle server side javascript using SpiderMonkey.&lt;br /&gt;
&lt;br /&gt;
SpiderMonkey [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference APIs] and a [https://developer.mozilla.org/en/SpiderMonkey tutorial].&lt;br /&gt;
Apache Module [http://httpd.apache.org/dev/apidoc/ APIs] and a [http://httpd.apache.org/dev/API.html tutorial].&lt;br /&gt;
&lt;br /&gt;
Would like [[MIME]] support, a global request/response object (both MIME trees I think), SQLite and MySQL support, and File IO Support (if its not already there).  Also should have support for including other javascript sources.  mod_js has an example for includes and some of the request/apache stuff.  SpiderMonkey has an example shell that shows some support for File objects I think.&lt;br /&gt;
&lt;br /&gt;
Would be nice to have libGD and/or ImageMagick support (EXIF too, if possible), as well as some sort of curl library to get to other sites to do stuff.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Things we should have:&lt;br /&gt;
*Class for MIME objects and MIME headers.&lt;br /&gt;
*Object with server info (environment, log functionality)&lt;br /&gt;
*Object with request info (request string (full and broken up), incoming mime object, maybe cookies already broken up, etc.)&lt;br /&gt;
*Object with response info (outgoing mime object, print functionality, obstack stuff, way to set headers, etc)&lt;br /&gt;
*File class extensions, if needed&lt;br /&gt;
*Better include support (add to File)&lt;br /&gt;
*MySQL/SQLite classes and support (new classes probably needed here)&lt;br /&gt;
*system call support (put this on server)&lt;br /&gt;
*image manipulation support (new classes probably needed here)&lt;br /&gt;
*json support (maybe just some quick functions on the response (encode) /request (decode) ? or maybe better as a global)&lt;br /&gt;
*curl support (new class probably, using MIME stuff to send and receive, probably wrapped by request/response like objects.. maybe they should be classes, too.)&lt;br /&gt;
*Instead of bothering with curl, maybe just have a way to open a socket and read/write to it for now.&lt;br /&gt;
&lt;br /&gt;
JS Class APIs:&lt;br /&gt;
*File (see [[File API]])&lt;br /&gt;
*server object (see [[server API]])&lt;br /&gt;
*[[TCPConnection]]&lt;br /&gt;
*[[DbConnection]]&lt;br /&gt;
*DbStatement (see [[DbStatement]])&lt;br /&gt;
*[[ProcessConnection]]&lt;br /&gt;
*[[MimeHeader]]&lt;br /&gt;
*[[MimeEntity]]&lt;br /&gt;
*[[MailMessage]]&lt;br /&gt;
*[[HTTPRequest]]&lt;br /&gt;
*[[HTTPResponse]]&lt;br /&gt;
*global object (see [[global object extensions]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Things the module should do if it can:&lt;br /&gt;
*Cache compiled javascript code?&lt;br /&gt;
*Stay alive? Might already do this...&lt;br /&gt;
*Cached javascript context? Would this make sense?&lt;br /&gt;
*Cached session stuff? Do I really want/need this?&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=DbConnection&amp;diff=2079</id>
		<title>DbConnection</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=DbConnection&amp;diff=2079"/>
		<updated>2009-01-21T00:19:10Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: DbConnection is used to talk to MySQL (for now) and later SQLite databases.  To connect to a database, create a new object:  connection = new DbConnection(host, database, username, passwor...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;DbConnection is used to talk to MySQL (for now) and later SQLite databases.&lt;br /&gt;
&lt;br /&gt;
To connect to a database, create a new object:&lt;br /&gt;
 connection = new DbConnection(host, database, username, password, type): type is &amp;quot;mysql&amp;quot; or &amp;quot;sqlite&amp;quot; but defaults to &amp;quot;mysql&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Exceptions include:&lt;br /&gt;
 DbConnectionError&lt;br /&gt;
 DbStatementError&lt;br /&gt;
&lt;br /&gt;
To use the connection to the database:&lt;br /&gt;
 connection.close(): closes the database connection explicitly(otherwise garbage collection will do so)&lt;br /&gt;
 statement = connection.prepare(string): creates a new prepared statement based on the passed in string&lt;br /&gt;
 numRowsAffected = connection.execute(string): executes the given statement straight up.  Please don&amp;#039;t use unless you have to. May not be supported.&lt;br /&gt;
 array of result objects = connection.query(string): executes the given statement straight up. Please don&amp;#039;t use unless you have to. May not be supported.&lt;br /&gt;
&lt;br /&gt;
To use DbStatements, you must first get one from the connection by preparing it. Then:&lt;br /&gt;
 numRowsAffected = statement.execute(array of bound arguments)&lt;br /&gt;
 array of result objects = statement.query(array of bound arguments)&lt;br /&gt;
&lt;br /&gt;
Result objects are created by using the field names (or AS marked field names) wherever possible.  If not possible (expression or something), the field will be named &amp;quot;_exp_N&amp;quot; where N goes from 1 on up as needed.  Try to use reasonably AS clauses. it just makes it so much easier.  expressions may not be supported at first.&lt;br /&gt;
&lt;br /&gt;
Statements stick around until they are garbage collected.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=File_API&amp;diff=2078</id>
		<title>File API</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=File_API&amp;diff=2078"/>
		<updated>2009-01-21T00:01:27Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File is a built in class from SpiderMonkey, but its poorly documented.  Going through the source code, it appears this is what we get for the interface.&lt;br /&gt;
&lt;br /&gt;
Global properties of File:&lt;br /&gt;
*curdir (sp?):&lt;br /&gt;
&lt;br /&gt;
Properties of File objects:&lt;br /&gt;
*length&lt;br /&gt;
*name&lt;br /&gt;
*parent&lt;br /&gt;
*size&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Methods of File objects:&lt;br /&gt;
*new File([path])&lt;br /&gt;
*open()&lt;br /&gt;
*close()&lt;br /&gt;
*flush()&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
I&amp;#039;ve extended File to add an include and require:&lt;br /&gt;
*File.prototype.include(): Executes the contents of the File as a javascript script in place.&lt;br /&gt;
*File.prototype.require(): Executes the contents of the File as a javascript script in place, only if it has not already been executed as part of a require().  Keeps track by updating a property in the global File class object (required[])&lt;br /&gt;
*File.required[]: array of filenames that have already been executed by a require() call for the current script.&lt;br /&gt;
*File.prototype.execute(args array): Executes the File as with server.runCmd(File, args array) and returns the exit status&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Server_API&amp;diff=2077</id>
		<title>Server API</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Server_API&amp;diff=2077"/>
		<updated>2009-01-21T00:00:20Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Data members on the global server object:&lt;br /&gt;
*env: array of environment variables, including standard request headers and server information&lt;br /&gt;
&lt;br /&gt;
Functions on the global server object:&lt;br /&gt;
*logNotice(string|array of strings): function to log a notice (or a list of notices) to the server error log&lt;br /&gt;
*logError(string|array of strings): function to log an error (or a list of errors) to the server error log&lt;br /&gt;
*runCmd(cmdstring): function execute a command on the server (with the httpd daemon&amp;#039;s permissions!) execution of the script will wait until the cmd is finished, and will return the exit status of the command.&lt;br /&gt;
*runCmd(cmd, array of args): same as above, but executes the given command with the arguments given in the array.  arguments will be escaped or quoted as necessary&lt;br /&gt;
*runCmd(File, array of args): same as above, but takes the given command from the File object passed in.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=ProcessConnection&amp;diff=2076</id>
		<title>ProcessConnection</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=ProcessConnection&amp;diff=2076"/>
		<updated>2009-01-20T23:59:01Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ProcessConnection is a class to represent an external process running on the server that is started by this script and runs independently.  It can be read and written to as well.&lt;br /&gt;
&lt;br /&gt;
Start the process by creating a new ProcessConnection:&lt;br /&gt;
 process = new ProcessConnection(cmd, args array)&lt;br /&gt;
 process = new ProcessConnection(cmdandargs)&lt;br /&gt;
 process = new ProcessConnection(File, args array)&lt;br /&gt;
&lt;br /&gt;
Read and write just like for TCPConnections:&lt;br /&gt;
 process.send(string | array of strings)&lt;br /&gt;
 string = process.recvAll()&lt;br /&gt;
 string = process.recvLine(chomp?)&lt;br /&gt;
 array of strings = process.recvLines(numlines, chomp?)&lt;br /&gt;
 bool = process.dataAvailable()&lt;br /&gt;
&lt;br /&gt;
Closing the process can be done by garbage collection or explicit close():&lt;br /&gt;
 status = process.close()&lt;br /&gt;
&lt;br /&gt;
Note that close() blocks until the process ends and a status is returned.  Garbage collection will do the same.&lt;br /&gt;
&lt;br /&gt;
To send a signal to the process (and thus possibly killing it earlier, if needed):&lt;br /&gt;
 process.signal(signum)&lt;br /&gt;
&lt;br /&gt;
Exceptions can be thrown:&lt;br /&gt;
 ProcessConnectionOpenError&lt;br /&gt;
 ProcessConnectionChildClosed&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=TCPConnection&amp;diff=2075</id>
		<title>TCPConnection</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=TCPConnection&amp;diff=2075"/>
		<updated>2009-01-20T23:57:17Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Wrapper for C socket API.  Only works for now with IPv4 and TCP streams.  Only client support for now as well.  Just simpler.&lt;br /&gt;
&lt;br /&gt;
Construct with:&lt;br /&gt;
 connection = new TCPConnection(remotehost, remoteport)&lt;br /&gt;
&lt;br /&gt;
Exceptions:&lt;br /&gt;
 TCPConnectionError&lt;br /&gt;
&lt;br /&gt;
Send and receive with:&lt;br /&gt;
 connection.send(string | array of strings)&lt;br /&gt;
 string = connection.recvAll()&lt;br /&gt;
 string = connection.recvLine(chomp?)&lt;br /&gt;
 array of strings = connection.recvLines(numLines, chomp?)&lt;br /&gt;
 boolean = connection.dataAvailable()&lt;br /&gt;
&lt;br /&gt;
Closure is done when garbage collected, or when close() is called directly:&lt;br /&gt;
 connection.close()&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=ProcessConnection&amp;diff=2074</id>
		<title>ProcessConnection</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=ProcessConnection&amp;diff=2074"/>
		<updated>2009-01-20T23:56:44Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: ProcessConnection is a class to represent an external process running on the server that is started by this script and runs independently.  It can be read and written to as well.  Start th...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ProcessConnection is a class to represent an external process running on the server that is started by this script and runs independently.  It can be read and written to as well.&lt;br /&gt;
&lt;br /&gt;
Start the process by creating a new ProcessConnection:&lt;br /&gt;
 process = new ProcessConnection(cmd, args array)&lt;br /&gt;
 process = new ProcessConnection(cmdandargs)&lt;br /&gt;
&lt;br /&gt;
Read and write just like for TCPConnections:&lt;br /&gt;
 process.send(string | array of strings)&lt;br /&gt;
 string = process.recvAll()&lt;br /&gt;
 string = process.recvLine(chomp?)&lt;br /&gt;
 array of strings = process.recvLines(numlines, chomp?)&lt;br /&gt;
 bool = process.dataAvailable()&lt;br /&gt;
&lt;br /&gt;
Closing the process can be done by garbage collection or explicit close():&lt;br /&gt;
 status = process.close()&lt;br /&gt;
&lt;br /&gt;
Note that close() blocks until the process ends and a status is returned.  Garbage collection will do the same.&lt;br /&gt;
&lt;br /&gt;
To send a signal to the process (and thus possibly killing it earlier, if needed):&lt;br /&gt;
 process.signal(signum)&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=TCPConnection&amp;diff=2073</id>
		<title>TCPConnection</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=TCPConnection&amp;diff=2073"/>
		<updated>2009-01-20T23:18:46Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: Wrapper for C socket API.  Only works for now with IPv4 and TCP streams.  Only client support for now as well.  Just simpler.  Construct with:  connection = new TCPConnection(remotehost, r...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Wrapper for C socket API.  Only works for now with IPv4 and TCP streams.  Only client support for now as well.  Just simpler.&lt;br /&gt;
&lt;br /&gt;
Construct with:&lt;br /&gt;
 connection = new TCPConnection(remotehost, remoteport)&lt;br /&gt;
&lt;br /&gt;
Exceptions:&lt;br /&gt;
 TCPConnectionError&lt;br /&gt;
&lt;br /&gt;
Send and receive with:&lt;br /&gt;
 connection.send(string | array of strings)&lt;br /&gt;
 string = connection.recvAll()&lt;br /&gt;
 string = connection.recvLine(chomp?)&lt;br /&gt;
 array of strings = connection.recvAllLines(chomp?)&lt;br /&gt;
 boolean = connection.dataAvailable()&lt;br /&gt;
&lt;br /&gt;
Closure is done when garbage collected, or when close() is called directly:&lt;br /&gt;
 connection.close()&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2072</id>
		<title>Modjs</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2072"/>
		<updated>2009-01-20T23:12:25Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.modjs.org modjs.org] has the rudiments of an apache module to handle server side javascript using SpiderMonkey.&lt;br /&gt;
&lt;br /&gt;
SpiderMonkey [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference APIs] and a [https://developer.mozilla.org/en/SpiderMonkey tutorial].&lt;br /&gt;
Apache Module [http://httpd.apache.org/dev/apidoc/ APIs] and a [http://httpd.apache.org/dev/API.html tutorial].&lt;br /&gt;
&lt;br /&gt;
Would like [[MIME]] support, a global request/response object (both MIME trees I think), SQLite and MySQL support, and File IO Support (if its not already there).  Also should have support for including other javascript sources.  mod_js has an example for includes and some of the request/apache stuff.  SpiderMonkey has an example shell that shows some support for File objects I think.&lt;br /&gt;
&lt;br /&gt;
Would be nice to have libGD and/or ImageMagick support (EXIF too, if possible), as well as some sort of curl library to get to other sites to do stuff.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Things we should have:&lt;br /&gt;
*Class for MIME objects and MIME headers.&lt;br /&gt;
*Object with server info (environment, log functionality) [[server API]]&lt;br /&gt;
*Object with request info (request string (full and broken up), incoming mime object, maybe cookies already broken up, etc.) [[request API]]&lt;br /&gt;
*Object with response info (outgoing mime object, print functionality, obstack stuff, way to set headers, etc) [[response API]]&lt;br /&gt;
*File class extensions, if needed [[File API]]&lt;br /&gt;
*Better include support (add to File)&lt;br /&gt;
*MySQL/SQLite classes and support (new classes probably needed here)&lt;br /&gt;
*system call support (put this on server)&lt;br /&gt;
*image manipulation support (new classes probably needed here)&lt;br /&gt;
*json support (maybe just some quick functions on the response (encode) /request (decode) ? or maybe better as a global)&lt;br /&gt;
*curl support (new class probably, using MIME stuff to send and receive, probably wrapped by request/response like objects.. maybe they should be classes, too.)&lt;br /&gt;
*Instead of bothering with curl, maybe just have a way to open a socket and read/write to it for now.&lt;br /&gt;
*Classes: [[HTTPRequest API]], [[HTTPResponse API]], [[MailMessage API]], [[HTTPMessage API]], [[MimeEntity API]], [[MimeHeader API]]&lt;br /&gt;
*Classes: [[Socket API]], [[DbConnection API]], [[DbStatement API]]&lt;br /&gt;
*[[TCPConnection]]&lt;br /&gt;
*[[DbConnection]]&lt;br /&gt;
*[[ProcessConnection]]&lt;br /&gt;
&lt;br /&gt;
Things the module should do if it can:&lt;br /&gt;
*Cache compiled javascript code?&lt;br /&gt;
*Stay alive? Might already do this...&lt;br /&gt;
*Cached javascript context? Would this make sense?&lt;br /&gt;
*Cached session stuff? Do I really want/need this?&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MIME&amp;diff=2070</id>
		<title>MIME</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MIME&amp;diff=2070"/>
		<updated>2009-01-14T00:04:21Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Need to describe MIME headers and body types here, and what types of MIME bodies can be in multiparts/treed stuff, etc.  This is really Entity, probably.  Need to be able to distinguish between HTTP and MIME (mail) type entities.  Also, an indicator as to whether the entity is currently encoded or decoded.  Functions to encode/decode (to MIME transport spec, gzip, compress, etc).  When the entity is encoded, it probably shouldn&amp;#039;t be writable, if we can enforce that.  Should have header access for raw header contents as well as an array of values, with true value, raw value group, and properties array for each value.  Should have raw access to the body (including entity bodies, and multipart bodies), as well as split into the entity tree form.  Preferably things are only added/changed/removed via the methods or non-raw arrays/hashes, and just viewed in the raw views.&lt;br /&gt;
&lt;br /&gt;
 HTTP-Message    := HTTP-Request | HTTP-Response&lt;br /&gt;
 MIME-Message    := entity&lt;br /&gt;
 HTTP-Request    := request-line  CRLF  entity&lt;br /&gt;
 HTTP-Response   := status-line  CRLF  entity&lt;br /&gt;
&lt;br /&gt;
 entity          := header-group  CRLF  entity-body&lt;br /&gt;
 entity-body     := text-body | entity | multipart-group&lt;br /&gt;
 multipart-group := leader  (CRLF  boundary  CRLF  entity)+  CRLF  boundary-end  CRLF  trailer&lt;br /&gt;
&lt;br /&gt;
 text-body       := &amp;lt;true entity content&amp;gt;&lt;br /&gt;
 leader          := &amp;lt;content that is not important and must be discarded when encountered&amp;gt;&lt;br /&gt;
 trailer         := &amp;lt;content that is not important and must be discarded when encountered&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 header-group    := header*&lt;br /&gt;
 header          := header-name  &amp;#039;:&amp;#039;  header-value  CRLF&lt;br /&gt;
 header-value    := values&lt;br /&gt;
 values          := (value-exp  &amp;#039;,&amp;#039;)*  value-exp&lt;br /&gt;
 value-exp       := real-value  (&amp;#039;;&amp;#039;  property-exp)*&lt;br /&gt;
 real-value      := value-key [&amp;#039;=&amp;#039; value-value]&lt;br /&gt;
 property-exp    := property-key  [&amp;#039;=&amp;#039;  property-value]&lt;br /&gt;
&lt;br /&gt;
*Header comments are in &amp;#039;(&amp;#039; &amp;#039;)&amp;#039; and should not be kept except in the raw header value.&lt;br /&gt;
*Header contents can have double quoted strings for atoms.&lt;br /&gt;
*Line folding can happen (header line followed by CRLF LWSP extra line), but should be decoded as soon as possible by the entity (right after receiving the mail message), and encoded only at the last moment (before sending the mail message).  HTTP headers don&amp;#039;t need line folding.&lt;br /&gt;
*Be careful with cookies (usually will have a cookie header that appears as one value with all other values being properties of that value, which is incorrect, they are usually all distinct values. However, value-keys that start with &amp;#039;$&amp;#039; are usually actually properties of the preceding value, and so that&amp;#039;s why we have to store all &amp;quot;properties&amp;quot; as an array, not a hash, since we could have duplicate names, and order matters in that regard.  The HTTP-Request class should properly interpret cookies and store them as a hash at that level, with properties appropriately split out.  That is where they should be accessed.  Similarly, new cookies should be added in the HTTP-Response level cookie jar, where they can be correctly remerged into the proper header format at send time.  Probably both request and response should have a linked cookie jar with better abstraction to properly handle cookie deletion, new cookies, etc., while making cookie actions more transparent to the user (simple access should be possible, while simultaneously encoding and decoding access).&lt;br /&gt;
*Keep in mind that by and large only the top level entity headers &amp;quot;matter&amp;quot; for the given message type.  Deeper entity headers really don&amp;#039;t matter much, except to decode/encode their containing bodies, as with all abstract entities.  For example, Cookie headers deep in multipart entities of request messages aren&amp;#039;t parsed into the request cookie jar.  Similarly, transport limitations of mail messages are enforced at the top level entity, and hopefully any lower level entities get encoded before insertion into the message if they need newline preservation or line length preservation contrary to mail specifications.&lt;br /&gt;
*Request messages will break up the request string, query string, post data, cookie data, etc., as needed.&lt;br /&gt;
*Response messages have to ensure the proper apache request_rec values get set based on header data in the response and the status information, and determining which cookies need to get set.  They also need the obstack support for printing, etc.&lt;br /&gt;
*Mail messages have lots to do in terms of encoding and decoding messages for transport, header folding, newline handling, etc. at send and receive time.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MIME&amp;diff=2069</id>
		<title>MIME</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MIME&amp;diff=2069"/>
		<updated>2009-01-13T22:53:23Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Need to describe MIME headers and body types here, and what types of MIME bodies can be in multiparts/treed stuff, etc.  This is really Entity, probably.  Need to be able to distinguish between HTTP and MIME (mail) type entities.  Also, an indicator as to whether the entity is currently encoded or decoded.  Functions to encode/decode (to MIME transport spec, gzip, compress, etc).  When the entity is encoded, it probably shouldn&amp;#039;t be writable, if we can enforce that.  Should have header access for raw header contents as well as an array of values, with true value, raw value group, and properties array for each value.  Should have raw access to the body (including entity bodies, and multipart bodies), as well as split into the entity tree form.  Preferably things are only added/changed/removed via the methods or non-raw arrays/hashes, and just viewed in the raw views.&lt;br /&gt;
&lt;br /&gt;
 HTTP-Message    := HTTP-Request | HTTP-Response&lt;br /&gt;
 MIME-Message    := entity&lt;br /&gt;
 HTTP-Request    := request-line  CRLF  entity&lt;br /&gt;
 HTTP-Response   := status-line  CRLF  entity&lt;br /&gt;
&lt;br /&gt;
 entity          := header-group  CRLF  entity-body&lt;br /&gt;
 entity-body     := text-body | entity | multipart-group&lt;br /&gt;
 multipart-group := leader  (CRLF boundary  entity)+  boundary-end  trailer&lt;br /&gt;
&lt;br /&gt;
 text-body       := &amp;lt;true entity content&amp;gt;&lt;br /&gt;
 leader          := &amp;lt;content that is not important and must be discarded when encountered&amp;gt;&lt;br /&gt;
 trailer         := &amp;lt;content that is not important and must be discarded when encountered&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 header-group    := header*&lt;br /&gt;
 header          := header-name  &amp;#039;:&amp;#039;  header-value  CRLF&lt;br /&gt;
 header-value    := values&lt;br /&gt;
 values          := (value-exp  &amp;#039;,&amp;#039;)*  value-exp&lt;br /&gt;
 value-exp       := real-value  (&amp;#039;;&amp;#039;  property-exp)*&lt;br /&gt;
 real-value      := value-key [&amp;#039;=&amp;#039; value-value]&lt;br /&gt;
 property-exp    := property-key  [&amp;#039;=&amp;#039;  property-value]&lt;br /&gt;
&lt;br /&gt;
*Header comments are in &amp;#039;(&amp;#039; &amp;#039;)&amp;#039; and should not be kept except in the raw header value.&lt;br /&gt;
*Header contents can have double quoted strings for atoms.&lt;br /&gt;
*Line folding can happen (header line followed by CRLF LWSP extra line), but should be decoded as soon as possible by the entity (right after receiving the mail message), and encoded only at the last moment (before sending the mail message).  HTTP headers don&amp;#039;t need line folding.&lt;br /&gt;
*Be careful with cookies (usually will have a cookie header that appears as one value with all other values being properties of that value, which is incorrect, they are usually all distinct values. However, value-keys that start with &amp;#039;$&amp;#039; are usually actually properties of the preceding value, and so that&amp;#039;s why we have to store all &amp;quot;properties&amp;quot; as an array, not a hash, since we could have duplicate names, and order matters in that regard.  The HTTP-Request class should properly interpret cookies and store them as a hash at that level, with properties appropriately split out.  That is where they should be accessed.  Similarly, new cookies should be added in the HTTP-Response level cookie jar, where they can be correctly remerged into the proper header format at send time.  Probably both request and response should have a linked cookie jar with better abstraction to properly handle cookie deletion, new cookies, etc., while making cookie actions more transparent to the user (simple access should be possible, while simultaneously encoding and decoding access).&lt;br /&gt;
*Keep in mind that by and large only the top level entity headers &amp;quot;matter&amp;quot; for the given message type.  Deeper entity headers really don&amp;#039;t matter much, except to decode/encode their containing bodies, as with all abstract entities.  For example, Cookie headers deep in multipart entities of request messages aren&amp;#039;t parsed into the request cookie jar.  Similarly, transport limitations of mail messages are enforced at the top level entity, and hopefully any lower level entities get encoded before insertion into the message if they need newline preservation or line length preservation contrary to mail specifications.&lt;br /&gt;
*Request messages will break up the request string, query string, post data, cookie data, etc., as needed.&lt;br /&gt;
*Response messages have to ensure the proper apache request_rec values get set based on header data in the response and the status information, and determining which cookies need to get set.  They also need the obstack support for printing, etc.&lt;br /&gt;
*Mail messages have lots to do in terms of encoding and decoding messages for transport, header folding, newline handling, etc. at send and receive time.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MIME&amp;diff=2068</id>
		<title>MIME</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MIME&amp;diff=2068"/>
		<updated>2009-01-13T22:32:11Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Need to describe MIME headers and body types here, and what types of MIME bodies can be in multiparts/treed stuff, etc.  This is really Entity, probably.  Need to be able to distinguish between HTTP and MIME (mail) type entities.  Also, an indicator as to whether the entity is currently encoded or decoded.  Functions to encode/decode (to MIME transport spec, gzip, compress, etc).  When the entity is encoded, it probably shouldn&amp;#039;t be writable, if we can enforce that.  Should have header access for raw header contents as well as an array of values, with true value, raw value group, and properties array for each value.  Should have raw access to the body (including entity bodies, and multipart bodies), as well as split into the entity tree form.  Preferably things are only added/changed/removed via the methods or non-raw arrays/hashes, and just viewed in the raw views.&lt;br /&gt;
&lt;br /&gt;
 HTTP-Message := HTTP-Request | HTTP-Response&lt;br /&gt;
 HTTP-Request := request-line  CRLF  entity&lt;br /&gt;
 HTTP-Response := status-line  CRLF  entity&lt;br /&gt;
 MIME-Message := entity&lt;br /&gt;
&lt;br /&gt;
 entity := headers  CRLF  (body | entity | multipart)&lt;br /&gt;
 multipart := leader  (CRLF boundary  entity)+  boundary-end  trailer&lt;br /&gt;
&lt;br /&gt;
 headers := header*&lt;br /&gt;
 header := header-name  &amp;#039;:&amp;#039;  header-value  CRLF&lt;br /&gt;
 header-value := values&lt;br /&gt;
 values := (value-exp  &amp;#039;,&amp;#039;)*  value-exp&lt;br /&gt;
 value-exp := real-value  (&amp;#039;;&amp;#039;  property-exp)*&lt;br /&gt;
 property-exp := property-key  [&amp;#039;=&amp;#039;  property-value]&lt;br /&gt;
&lt;br /&gt;
*Header comments are in &amp;#039;(&amp;#039; &amp;#039;)&amp;#039; and should not be kept except in the raw header value.&lt;br /&gt;
*Line folding can happen (header line followed by CRLF LWSP extra line).&lt;br /&gt;
*Be careful with cookies.&lt;br /&gt;
*Header contents can have double quoted strings for atoms.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MIME&amp;diff=2067</id>
		<title>MIME</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MIME&amp;diff=2067"/>
		<updated>2009-01-13T18:01:41Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Need to describe MIME headers and body types here, and what types of MIME bodies can be in multiparts/treed stuff, etc.  This is really Entity, probably.  Need to be able to distinguish between HTTP and MIME (mail) type entities.  Also, an indicator as to whether the entity is currently encoded or decoded.  Functions to encode/decode (to MIME transport spec, gzip, compress, etc).  When the entity is encoded, it probably shouldn&amp;#039;t be writable.&lt;br /&gt;
&lt;br /&gt;
 HTTP-Message -&amp;gt; HTTP-Request -&amp;gt; request-line  CRLF  entity&lt;br /&gt;
 HTTP-Message -&amp;gt; HTTP-Response -&amp;gt; status-line  CRLF  entity&lt;br /&gt;
 MIME-Message -&amp;gt; entity&lt;br /&gt;
&lt;br /&gt;
 entity -&amp;gt; headers  CRLF  (body | entity | multipart)&lt;br /&gt;
 multipart -&amp;gt; leader  (CRLF boundary  entity)+  boundary-end  trailer&lt;br /&gt;
&lt;br /&gt;
 headers -&amp;gt; header*&lt;br /&gt;
 header -&amp;gt; header-name  &amp;#039;:&amp;#039;  header-value  CRLF&lt;br /&gt;
 header-value -&amp;gt; values&lt;br /&gt;
 values -&amp;gt; (value-exp  &amp;#039;,&amp;#039;)*  value-exp&lt;br /&gt;
 value-exp -&amp;gt; real-value  (&amp;#039;;&amp;#039;  property-exp)*&lt;br /&gt;
 property-exp -&amp;gt; property-key  [&amp;#039;=&amp;#039;  property-value]&lt;br /&gt;
&lt;br /&gt;
*Header comments are in &amp;#039;(&amp;#039; &amp;#039;)&amp;#039; and should not be kept except in the raw header value.&lt;br /&gt;
*Line folding can happen (header line followed by CRLF LWSP extra line).&lt;br /&gt;
*Be careful with cookies.&lt;br /&gt;
*Header contents can have double quoted strings for atoms.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=MIME&amp;diff=2065</id>
		<title>MIME</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=MIME&amp;diff=2065"/>
		<updated>2009-01-09T23:51:50Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: Need to describe MIME headers and body types here, and what types of MIME bodies can be in multiparts/treed stuff, etc.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Need to describe MIME headers and body types here, and what types of MIME bodies can be in multiparts/treed stuff, etc.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2064</id>
		<title>Modjs</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2064"/>
		<updated>2009-01-09T23:51:14Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.modjs.org modjs.org] has the rudiments of an apache module to handle server side javascript using SpiderMonkey.&lt;br /&gt;
&lt;br /&gt;
SpiderMonkey [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference APIs] and a [https://developer.mozilla.org/en/SpiderMonkey tutorial].&lt;br /&gt;
Apache Module [http://httpd.apache.org/dev/apidoc/ APIs] and a [http://httpd.apache.org/dev/API.html tutorial].&lt;br /&gt;
&lt;br /&gt;
Would like [[MIME]] support, a global request/response object (both MIME trees I think), SQLite and MySQL support, and File IO Support (if its not already there).  Also should have support for including other javascript sources.  mod_js has an example for includes and some of the request/apache stuff.  SpiderMonkey has an example shell that shows some support for File objects I think.&lt;br /&gt;
&lt;br /&gt;
Would be nice to have libGD and/or ImageMagick support (EXIF too, if possible), as well as some sort of curl library to get to other sites to do stuff.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Things we should have:&lt;br /&gt;
*Class for MIME objects and MIME headers. [[MimeObject API]] [[MimeHeader API]]&lt;br /&gt;
*Object with server info (environment, log functionality) [[server API]]&lt;br /&gt;
*Object with request info (request string (full and broken up), incoming mime object, maybe cookies already broken up, etc.) [[request API]]&lt;br /&gt;
*Object with response info (outgoing mime object, print functionality, obstack stuff, way to set headers, etc) [[response API]]&lt;br /&gt;
*File class extensions, if needed [[File API]]&lt;br /&gt;
*Better include support (add to File)&lt;br /&gt;
*MySQL/SQLite classes and support (new classes probably needed here)&lt;br /&gt;
*system call support (put this on server)&lt;br /&gt;
*image manipulation support (new classes probably needed here)&lt;br /&gt;
*json support (maybe just some quick functions on the response (encode) /request (decode) ? or maybe better as a global)&lt;br /&gt;
*curl support (new class probably, using MIME stuff to send and receive, probably wrapped by request/response like objects.. maybe they should be classes, too.)&lt;br /&gt;
&lt;br /&gt;
Things the module should do if it can:&lt;br /&gt;
*Cache compiled javascript code?&lt;br /&gt;
*Stay alive? Might already do this...&lt;br /&gt;
*Cached javascript context? Would this make sense?&lt;br /&gt;
*Cached session stuff? Do I really want/need this?&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=File_API&amp;diff=2061</id>
		<title>File API</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=File_API&amp;diff=2061"/>
		<updated>2009-01-09T20:03:00Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: File is a built in class from SpiderMonkey, but its poorly documented.  Going through the source code, it appears this is what we get for the interface.  Global properties of File: *curdir...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;File is a built in class from SpiderMonkey, but its poorly documented.  Going through the source code, it appears this is what we get for the interface.&lt;br /&gt;
&lt;br /&gt;
Global properties of File:&lt;br /&gt;
*curdir (sp?):&lt;br /&gt;
&lt;br /&gt;
Properties of File objects:&lt;br /&gt;
*length&lt;br /&gt;
*name&lt;br /&gt;
*parent&lt;br /&gt;
*size&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
Methods of File objects:&lt;br /&gt;
*new File([path])&lt;br /&gt;
*open()&lt;br /&gt;
*close()&lt;br /&gt;
*flush()&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
I&amp;#039;ve extended File to add an include and require:&lt;br /&gt;
*File.prototype.include(): Executes the contents of the File as a javascript script in place.&lt;br /&gt;
*File.prototype.require(): Executes the contents of the File as a javascript script in place, only if it has not already been executed as part of a require().  Keeps track by updating a property in the global File class object (required[])&lt;br /&gt;
*File.required[]: array of filenames that have already been executed by a require() call for the current script.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Server_API&amp;diff=2060</id>
		<title>Server API</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Server_API&amp;diff=2060"/>
		<updated>2009-01-09T19:56:47Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Data members on the global server object:&lt;br /&gt;
*env: array of environment variables, including standard request headers and server information&lt;br /&gt;
&lt;br /&gt;
Functions on the global server object:&lt;br /&gt;
*logNotice(string|array of strings): function to log a notice (or a list of notices) to the server error log&lt;br /&gt;
*logError(string|array of strings): function to log an error (or a list of errors) to the server error log&lt;br /&gt;
*runCmd(cmdstring): function execute a command on the server (with the httpd daemon&amp;#039;s permissions!) execution of the script will wait until the cmd is finished, and will return the exit status of the command.&lt;br /&gt;
*runCmd(cmd, array of args): same as above, but executes the given command with the arguments given in the array.  arguments will be escaped or quoted as necessary&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Server_API&amp;diff=2059</id>
		<title>Server API</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Server_API&amp;diff=2059"/>
		<updated>2009-01-09T19:55:47Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: Data members on the global server object: *env: array of environment variables, including standard request headers and server information  Functions on the global server object: *logNotice...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Data members on the global server object:&lt;br /&gt;
*env: array of environment variables, including standard request headers and server information&lt;br /&gt;
&lt;br /&gt;
Functions on the global server object:&lt;br /&gt;
*logNotice(string|array of strings): function to log a notice (or a list of notices) to the server error log&lt;br /&gt;
*logError(string|array of strings): function to log an error (or a list of errors) to the server error log&lt;br /&gt;
*system(cmdstring): function execute a command on the server (with the httpd daemon&amp;#039;s permissions!) execution of the script will wait until the cmd is finished, and will return the exit status of the command.&lt;br /&gt;
*system(cmd, array of args): same as above, but executes the given command with the arguments given in the array.  arguments will be escaped or quoted as necessary&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2058</id>
		<title>Modjs</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2058"/>
		<updated>2009-01-09T19:44:11Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.modjs.org modjs.org] has the rudiments of an apache module to handle server side javascript using SpiderMonkey.&lt;br /&gt;
&lt;br /&gt;
SpiderMonkey [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference APIs] and a [https://developer.mozilla.org/en/SpiderMonkey tutorial].&lt;br /&gt;
Apache Module [http://httpd.apache.org/dev/apidoc/ APIs] and a [http://httpd.apache.org/dev/API.html tutorial].&lt;br /&gt;
&lt;br /&gt;
Would like MIME support, a global request/response object (both MIME trees I think), SQLite and MySQL support, and File IO Support (if its not already there).  Also should have support for including other javascript sources.  mod_js has an example for includes and some of the request/apache stuff.  SpiderMonkey has an example shell that shows some support for File objects I think.&lt;br /&gt;
&lt;br /&gt;
Would be nice to have libGD and/or ImageMagick support (EXIF too, if possible), as well as some sort of curl library to get to other sites to do stuff.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Things we should have:&lt;br /&gt;
*Class for MIME objects and MIME headers. [[MimeObject API]] [[MimeHeader API]]&lt;br /&gt;
*Object with server info (environment, log functionality) [[server API]]&lt;br /&gt;
*Object with request info (request string (full and broken up), incoming mime object, maybe cookies already broken up, etc.) [[request API]]&lt;br /&gt;
*Object with response info (outgoing mime object, print functionality, obstack stuff, way to set headers, etc) [[response API]]&lt;br /&gt;
*File class extensions, if needed [[File API]]&lt;br /&gt;
*Better include support (add to File)&lt;br /&gt;
*MySQL/SQLite classes and support (new classes probably needed here)&lt;br /&gt;
*system call support (put this on server)&lt;br /&gt;
*image manipulation support (new classes probably needed here)&lt;br /&gt;
*json support (maybe just some quick functions on the response (encode) /request (decode) ? or maybe better as a global)&lt;br /&gt;
*curl support (new class probably, using MIME stuff to send and receive, probably wrapped by request/response like objects.. maybe they should be classes, too.)&lt;br /&gt;
&lt;br /&gt;
Things the module should do if it can:&lt;br /&gt;
*Cache compiled javascript code?&lt;br /&gt;
*Stay alive? Might already do this...&lt;br /&gt;
*Cached javascript context? Would this make sense?&lt;br /&gt;
*Cached session stuff? Do I really want/need this?&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2057</id>
		<title>Modjs</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2057"/>
		<updated>2009-01-09T19:42:37Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.modjs.org modjs.org] has the rudiments of an apache module to handle server side javascript using SpiderMonkey.&lt;br /&gt;
&lt;br /&gt;
SpiderMonkey [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference APIs] and a [https://developer.mozilla.org/en/SpiderMonkey tutorial].&lt;br /&gt;
Apache Module [http://httpd.apache.org/dev/apidoc/ APIs] and a [http://httpd.apache.org/dev/API.html tutorial].&lt;br /&gt;
&lt;br /&gt;
Would like MIME support, a global request/response object (both MIME trees I think), SQLite and MySQL support, and File IO Support (if its not already there).  Also should have support for including other javascript sources.  mod_js has an example for includes and some of the request/apache stuff.  SpiderMonkey has an example shell that shows some support for File objects I think.&lt;br /&gt;
&lt;br /&gt;
Would be nice to have libGD and/or ImageMagick support (EXIF too, if possible), as well as some sort of curl library to get to other sites to do stuff.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Things we should have:&lt;br /&gt;
*Class for MIME objects and MIME headers. [MimeObject API] [MimeHeader API]&lt;br /&gt;
*Object with server info (environment, log functionality) [server API]&lt;br /&gt;
*Object with request info (request string (full and broken up), incoming mime object, maybe cookies already broken up, etc.) [request API]&lt;br /&gt;
*Object with response info (outgoing mime object, print functionality, obstack stuff, way to set headers, etc) [response API]&lt;br /&gt;
*File class extensions, if needed [File API]&lt;br /&gt;
*Better include support (add to File)&lt;br /&gt;
*MySQL/SQLite classes and support (new classes probably needed here)&lt;br /&gt;
*system call support (put this on server)&lt;br /&gt;
*image manipulation support (new classes probably needed here)&lt;br /&gt;
*json support (maybe just some quick functions on the response/request ? or maybe better as a global)&lt;br /&gt;
*curl support (new class probably, using MIME stuff to send and receive)&lt;br /&gt;
&lt;br /&gt;
Things the module should do if it can:&lt;br /&gt;
*Cache compiled javascript code?&lt;br /&gt;
*Stay alive? Might already do this...&lt;br /&gt;
*Cached javascript context? Would this make sense?&lt;br /&gt;
*Cached session stuff? Do I really want/need this?&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2056</id>
		<title>Modjs</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Modjs&amp;diff=2056"/>
		<updated>2009-01-07T19:39:59Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.modjs.org modjs.org] has the rudiments of an apache module to handle server side javascript using SpiderMonkey.&lt;br /&gt;
&lt;br /&gt;
SpiderMonkey [https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference APIs] and a [https://developer.mozilla.org/en/SpiderMonkey tutorial].&lt;br /&gt;
Apache Module [http://httpd.apache.org/dev/apidoc/ APIs] and a [http://httpd.apache.org/dev/API.html tutorial].&lt;br /&gt;
&lt;br /&gt;
Would like MIME support, a global request/response object (both MIME trees I think), SQLite and MySQL support, and File IO Support (if its not already there).  Also should have support for including other javascript sources.  mod_js has an example for includes and some of the request/apache stuff.  SpiderMonkey has an example shell that shows some support for File objects I think.&lt;br /&gt;
&lt;br /&gt;
Would be nice to have libGD and/or ImageMagick support (EXIF too, if possible), as well as some sort of curl library to get to other sites to do stuff.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Things we should have:&lt;br /&gt;
*Class for MIME objects and MIME headers.&lt;br /&gt;
*Object with server info (environment, log functionality)&lt;br /&gt;
*Object with request info (request string (full and broken up), incoming mime object, maybe cookies already broken up, etc.)&lt;br /&gt;
*Object with response info (outgoing mime object, print functionality, obstack stuff, way to set headers, etc)&lt;br /&gt;
*File class extensions, if needed&lt;br /&gt;
*Better include support&lt;br /&gt;
*MySQL/SQLite classes and support&lt;br /&gt;
*system call support&lt;br /&gt;
*image manipulation support&lt;br /&gt;
*json support&lt;br /&gt;
*curl support&lt;br /&gt;
&lt;br /&gt;
Things the module should do if it can:&lt;br /&gt;
*Cache compiled javascript code?&lt;br /&gt;
*Stay alive? Might already do this...&lt;br /&gt;
*Cached javascript context? Would this make sense?&lt;br /&gt;
*Cached session stuff? Do I really want/need this?&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Thoughts_on_PWM&amp;diff=1578</id>
		<title>Thoughts on PWM</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Thoughts_on_PWM&amp;diff=1578"/>
		<updated>2008-10-16T16:23:26Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, we turn off outputting automatically, set up interrupts on mid and top.  Set the period to something reasonable, and the resolution to something largish.&lt;br /&gt;
&lt;br /&gt;
There should be a table in RAM, of duty cycles for each chosen output pin.  Should be single (double) byte entries for each pin specifying the fraction of 255 slots that should be ON for that pin.  Each entry should contain:&lt;br /&gt;
*(byte):  next entry in sorted sequence (in entry numbers, so *4 is the offset from start. FF indicates end of list)&lt;br /&gt;
*(byte):  output port for this entry (upper nibble determines which set of 8 pins (PAx=0,PBx=1,PCx=2,PDx=3,PEx=4,PFx=5...), lower nibble determines which pin of the 8 to use)&lt;br /&gt;
*(word):  duty cycle specification (might just be one byte, with a one byte pad)&lt;br /&gt;
&lt;br /&gt;
Before the table should be a dummy entry, stating which entry to start with, how many entries there are, and what the resolution is (maybe?)&lt;br /&gt;
&lt;br /&gt;
When the top interrupt fires, we turn on outputs to all pins, then navigate our sorted table by jumping through the next thingies to find the first pin that will need to be shut off.  We place that pin&amp;#039;s duty cycle value in mid, and return.&lt;br /&gt;
&lt;br /&gt;
When mid fires, we work through our sorted table, turning off all pins until we find a value that exceeds our current mid.  Then we change mid to that new value, and return.&lt;br /&gt;
&lt;br /&gt;
When adding a new entry to the table, turn off interrupts (or at least the top and mid ones), update the total number of entries, place a new entry at the end of the table, then figure out where in the sequence it belongs, and reshuffle next ptrs to include the new entry.  Then turn back on interrupts.  We may have missed one of them, but it should fire at that point, I think?&lt;br /&gt;
&lt;br /&gt;
When removing an entry, turn off interrupts (or at least top and mid), find the old entry for this port, and copy the last entry in the table to that slot.  Have to reshuffle next ptrs for the one that used to point at the deleted entry, and the one that used to point at the last entry.  Then we update the total number of entries, turn off the output to the port, and turn back on interrupts.&lt;br /&gt;
&lt;br /&gt;
Note that to change the duty cycle of a port, it has to be removed and readded.  No need to turn off ints in between the two operations, I don&amp;#039;t think.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Thoughts_on_PWM&amp;diff=1577</id>
		<title>Thoughts on PWM</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Thoughts_on_PWM&amp;diff=1577"/>
		<updated>2008-10-16T16:23:08Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: So, we turn off outputting automatically, set up interrupts on mid and top.  Set the period to something reasonable, and the resolution to something largish.  There should be a table in RA...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;So, we turn off outputting automatically, set up interrupts on mid and top.  Set the period to something reasonable, and the resolution to something largish.&lt;br /&gt;
&lt;br /&gt;
There should be a table in RAM, of duty cycles for each chosen output pin.  Should be single (double) byte entries for each pin specifying the fraction of 255 slots that should be ON for that pin.  Each entry should contain:&lt;br /&gt;
(byte):  next entry in sorted sequence (in entry numbers, so *4 is the offset from start. FF indicates end of list)&lt;br /&gt;
(byte):  output port for this entry (upper nibble determines which set of 8 pins (PAx=0,PBx=1,PCx=2,PDx=3,PEx=4,PFx=5...), lower nibble determines which pin of the 8 to use)&lt;br /&gt;
(word):  duty cycle specification (might just be one byte, with a one byte pad)&lt;br /&gt;
&lt;br /&gt;
Before the table should be a dummy entry, stating which entry to start with, how many entries there are, and what the resolution is (maybe?)&lt;br /&gt;
&lt;br /&gt;
When the top interrupt fires, we turn on outputs to all pins, then navigate our sorted table by jumping through the next thingies to find the first pin that will need to be shut off.  We place that pin&amp;#039;s duty cycle value in mid, and return.&lt;br /&gt;
&lt;br /&gt;
When mid fires, we work through our sorted table, turning off all pins until we find a value that exceeds our current mid.  Then we change mid to that new value, and return.&lt;br /&gt;
&lt;br /&gt;
When adding a new entry to the table, turn off interrupts (or at least the top and mid ones), update the total number of entries, place a new entry at the end of the table, then figure out where in the sequence it belongs, and reshuffle next ptrs to include the new entry.  Then turn back on interrupts.  We may have missed one of them, but it should fire at that point, I think?&lt;br /&gt;
&lt;br /&gt;
When removing an entry, turn off interrupts (or at least top and mid), find the old entry for this port, and copy the last entry in the table to that slot.  Have to reshuffle next ptrs for the one that used to point at the deleted entry, and the one that used to point at the last entry.  Then we update the total number of entries, turn off the output to the port, and turn back on interrupts.&lt;br /&gt;
&lt;br /&gt;
Note that to change the duty cycle of a port, it has to be removed and readded.  No need to turn off ints in between the two operations, I don&amp;#039;t think.&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
	<entry>
		<id>http://sessrumnir.net/fernseher/index.php?title=Some_avr_stuff&amp;diff=1576</id>
		<title>Some avr stuff</title>
		<link rel="alternate" type="text/html" href="http://sessrumnir.net/fernseher/index.php?title=Some_avr_stuff&amp;diff=1576"/>
		<updated>2008-10-16T16:06:22Z</updated>

		<summary type="html">&lt;p&gt;129.42.161.36: New page: *thoughts on PWM&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;*[[thoughts on PWM]]&lt;/div&gt;</summary>
		<author><name>129.42.161.36</name></author>
	</entry>
</feed>