|
Displaywall Toolkit
Original Documentation 1997-2000
For current contacts and details for making and showing images, see the other
links on the main page
Updated Feb 21, 2004 Ben Shedd
General Information
Most software is available from two locations on the Display Wall file
folder, which is located at \\newfs\ShrimpNT\DisplayWall.
This folder can be accessible only within the domain of the Computer Science departmental
network. Please contact CSSTAFF for information regarding how to access a network file
system from your Windows workstation. The executable files (i.e., .EXE) and Windows
scripts (.BAT) are kept in the bin subfolder. The library files are kept in the lib
sub folder, the corresponding include header files in the include/dwall subfolder.
In most cases, you are required to start an application server on each
workstation that is driving the projectors P projector servers. A utility program
SETOPT.EXE is provided for starting these servers from a remote PC P a control station.
There are several PCs in the Display Wall lab for you to use as a control station. People
usually create Windows batch files to issue the SETOPT command to ALL projector servers.
You can find some batch files in the \\newfs\ShrimpNT\DisplayWall\bin
folder.
Due to Microsoft's lock on the LOGON screen, we have not able to start a
Graphics program that replaces the default LOGON screen, although we hope to solve this
problem by the end of 1998. (Volunteers!) For now, we require that a LOGON to be performed
on each projector server. The LOGON account name is vmmc. The
password is Vmmc2Rocks. You can check the LOGON status by using a keyboard
monitor switch that is located near the front-left corner of the Display Wall.
Still Image Viewer
Generating High-Resolution Images
The still image viewer displays JPEG images on the wall, the desired
resolution of the image is 3850x1470.You can have your materials scanned at MECA or PLACE
and use image processing software to convert the images to the desired format and size,
there is (will be) PhotoShop installed in the displaywall lab.
Making PowerPoint slides
Your can also using PowerPoint to prepare slides, here is an example of
how to convert PowerPoint slides to JPEG and show them on the wall.
- Open a your slide in PowerPoint;
- Goto "File|Page Setup", change the page size to 40''x15'';
- PowerPoint will automatically stretch the text and pictures in your
slide, if they are not in the correct aspect ration, do adjustment;
- Goto "File|Save as", save the slide as JPEG files.
One thing needs to pay some attention is that PowerPoint doesn't do a
good job at exporting background images, so instead of setting a background images, it's
better to insert the images as an picture object.
Showing Single Images
The still image viewer source code is in \\newfs\ShrimptNT\Displaywall\ImageViewer.
There are three script files: startviewer.bat, showimg.bat and stopviewer.bat, all are in \\newfs\ShrimpNT\Displaywall\bin directory.
Before showing any images, you need to start a still image server on each of the
projector machines. The server will get command from the control machine, retrieve the
image file and then show the its proper portion of the image on the screen.
Here is an example to show the course poster image on the display wall:
- Goto \\newfs\ShrimpNT\Displaywall\bin (normally mounted to the control machine as drive
s:);
- Run startviewer script to start the still image servers: startviewer
- Copy course poster file cs495.jpg to the image directory \\newfs\ShrimpNT\Displaywall\images\cs495;
- Run showimg script to show the image: showimg cs495\cs495.jpg 0 0 0 0
(by default, showimg will go to \\newfs\ShrimpNT\Displaywall\images\
directory to look for images).
- After showing the images, run stopviewer script to stop the viewers: stopviewer
Showing Slides
There is a small tool for showing a series of slides, it's? \\newfs\ShrimpNT\Displaywall\bin\showjpgs.
What you need to do is:
- Build a slide list file, for example, jlist.txt;
- Start still images servers using startviewer script;
- Run GyroMouse server(see below);
- Run showjpgs jlist.txt. Left click move to next slide, right click move back to
previous slide.
- After showing the slides, run stopviewer to stop the servers.
If you have any further question or demand for the still image viewer,
please contact: yuqun@cs neilshah@cs
zjn@cs
NDSoundServer - A
Distributed Multi-Channel Sound Server
Multi-channel audio reproduction beyond stereo is an area of active
research. We wrote a multi-channel sound server software which allows to control the
playback of multi-channel sounds on large scale multi-channel systems over a simple
network interface.
Introduction
The NDSoundServer is TCP/IP server-software running under Windows95 that provides
flexible control over multi-speaker arrays.
In the current implementation we use a SoundBlaster-compatible sound card and two
8-channel Darla boards by Echo yielding a total of 18 mono-channels. The two
SoundBlaster-channels are typically used to drive two sub-woofers, because of the lack of
synchronization between the SoundBlaster- and Darla-drivers. The Darla-drivers synchronize
all open channels if wanted.
The NDS sound file format
The NDS sound file used by the server follows the format of the standard Sun/NeXT snd
file format, except, that all the data is stored using little endian instead of big
endian. This spares the server from byte-swapping buffers for streaming sound files.
Sun/NeXT snd-files can be converted to nds-files using the snd2nds-tool. There is a MS-Dos
based version available on the server machine and the Unix source is available on request.
The NDSoundServerStub client interface
The purpose of the NDSoundServerStub-class is to provide an easy to use RPC-like client
interface to the sound server which spares sound server users from implementing the
communication protocol. These are the methods provided by the class:
* NDSoundServer()
* Default constructor. Opens the connection to the default NDSoundServer(). Later
* versions of this class will provide a constructor which allows to specify the
* hostname and port number.
* [Possibly this should be changed to having a separate method to initialize connection
* to allow returning errors and the like. For now NDSoundServer() will exit on errors.]
* The current default server is "malleus.cs.princeton.edu".
*
* ~NDSoundServer()
* Default destructor. Closes the connection to the default NDSoundServer if open.
*
* int connectServer()
* Opens the connection to the default NDSoundServer. If a connection is already open
* it should be closed first with closeServer().
*
* int closeServer()
* Closes the connection to the default NDSoundServer if open.
*
* int load(char* lname, int& tag, int& srcs)
* Loads a file from the sound servers file-directory into the pool of activated
* sound sources. Active sound sources can be addressed using the "tag" which is
* return by this function (similar to a file-descriptor). "srcs" is the number
* of channels which are provided by the opened sound source.
*
* int free(int tag)
* Frees a previously opened active source "tag". NOTE: Every load()'d "tag" has to
* be free()'d by its opener!
*
* int map(int tag, int src, int speaker)
* Maps (i.e. virtually connects) a mono sound source stream "src" from the active
* source "tag" to the speaker with number "speaker". "src" must be less than the
* number of sources returned by load().
*
* int play(int tag)
* Starts the playback of all mono sound sources provided by the active source "tag".
* If paused it will resume play. Newly loaded sources are paused by default.
* If already playing, it is ignored. If it stopped at the end of a source stream
* it will resume playing at the beginning.
*
* int pause(int tag)
* Pauses the playback of all mono sound sources provided by the active source "tag".
* If already paused, nothing happens. Newly loaded sources are paused by default.
*
* int reset(int tag)
* Resets the position of the playback of all mono sound sources provided by the
* active source "tag" to the beginning if possible for the given source.
*
* int loop(int tag, int flag)
* All mono sound sources of the active source "tag" will be looped if "flag" is non-zero.
* Otherwise it won't be looped. Some sources may not support this feature. The default
* is no looping.
*
* int atEnd(int tag, int& flag)
* Sets "flag" to non-zero value if playback reached end. Otherwise it sets "flag" to zero.
* Please keep in mind, that repeatingly calling this function might put heavy load in the
* server.
*
* int gain_speaker(int speaker, float gain)
* Sets the gain of a speaker to "gain". "gain" should be between 2.0 and 0.0.
* (very loud to muted). 1.0 is the default gain for all speakers.
*
* int gain_channel(int tag, float gain)
* Sets the gain of the active source "tag" to "gain". "gain" should be between 2.0
* and 0.0. (very loud to muted). 1.0 is the default gain for all channels.
*
* int gain_all_speakers(float gain)
* Sets the gain of all speakers to "gain". "gain" should be between 2.0 and 0.0.
* (very loud to muted). 1.0 is the default gain for all speakers.
*
* int fade_speaker(int speaker, float time, float start_gain, float end_gain)
* Fades the gain of "speaker" uniformly from "start_gain" to "end_gain" in "time" seconds.
* To be implemented.
*
* int fade_all_speakers(float time, float start_gain, float end_gain)
* Fades the gain of all speakers uniformly from "start_gain" to "end_gain" in "time" seconds.
* To be implemented.
*
* int fade_channel(int tag, float time, float start_gain, float end_gain)
* Fades the gain of sound source "tag" uniformly from "start_gain" to "end_gain" in "time" seconds.
* To be implemented.
*
* int getNrChannels(int tag, int& srcs)
* Returns the number of mono sound sources provided by the active source "tag". This
* should always be the same numbers as initially returned by load().
*
* int getNrSpeakers(int& srcs)
* Returns the number of speakers handled by the NDSoundServer. This number should be constant
* during one session with the server.
The NDSoundServer
This is the structure of the sound server:

The Sound Core is the interface of the server to the hardware drivers. It
handles both the playback of samples as well as the collection of data via input channels
like microphones. The Mixer combines the mono sound streams to create the sound
streams for the individual speakers and controls the gain of the speakers. The Mapper
is responsible for separating multiple channel streams (e.g. stereo) from a source into
mono sound streams and is also responsible to keep the multi-channel source synchronized
with respect to the mono streams it provides. The Sound Source Handler manages
open sound sources and assigns them universal tags which are used throughout the system to
identify open sources and their channels. Each Sound Source like the File
Sound Source or the Microphone Source provides the interface to embed the
characteristics of the particular source stream with the system. The Socket Server
provides the TCP/IP network interface. It implements the protocol and converts protocol
commands into the respective interface calls of the other modules.
Sound Core
The sound core contains the interface between the NDSoundServer and the sound drivers
of the used sound cards. It contains functions to start and stop the playback to speakers
and the recording from microphones or other inputs. In general, all used sound devices are
opened and playback and recording is constantly running. Whether or not actual sound will
be heard, i.e. the playback buffers are not zero will be handled at higher level. The link
to the higher levels in the server architecture are provided in the callbacks of the sound
devices when a sound buffer has been played. At this point the sound core will request the
next data block for a speaker channel from the mixer. Also the callback will initiate
synchronization of sources through the mapper.
The MicSoundSource is closely linked to the callback of the recording device. The buffers
used in the sound core for this purpose are directly used by the MicSoundSource to avoid
unnecessary copying. Not, that there is no synchronization guarantee between recording and
playback.
Mixer
The mixer handles three tasks. It handles links of mono sound sources to the speakers.
Any number of mono sound sources can be connected with any number of speakers allowing any
possible mapping of sources into the virtual room. It provides gain control for the
individual speakers, which is mainly important for master gain control. Finally it mixes
the mono sound streams to a speaker channel on request from the sound core. The mixing and
gain control is implemented using long integers for performance reasons and to allow
future porting to MMX.
Mapper
The mapper maintains the logical connection from virtual mono sound sources to physical
sound sources which may provide multiple channels. This means, that given a virtual mono
sound source, the mapper is able to locate the appropriate sound source and request the
correct channel buffer from that source. As the mapper is also aware of all active
physical sources, it is responsible to advance the sources input buffers on a
synchronization event triggered by the sound core.
Sound Source Handler (SoundSourcePool)
The sound source handler assigns newly opened physical sound sources a virtual tag,
which is used throughout the server to uniquely identify this sound source. The sound
source handler can identify if a provided tag is valid and if so, it can provide the
physical sound source for this tag.
Conceptually effects are treated like a sound source by the handler and active effects are
also addressed by a unique tag.
Generic Sound Source
Every sound source has to provide an implementation of a specified set of operations.
This includes providing a specific current mono block in the source stream and preparation
of the next blocks of data in the stream. The outgoing mono sources can be amplified by a
gain which is valid for the physical sources (i.e. for all channels the same gain). The
playback can be paused, started and if applicable for the stream type, it can be checked
if the end of the stream has been reached. If the sound source permits, a toggle for loops
is provided. The start position and the end position for playback/loops in the sound
stream can be specified.
File Sound Source
The file sound source implements all generic operations as intuitively expected. The
end of the stream can only be checked if the file sound source is not set to loop.
Microphone Sound Source
The microphone sound source, due to its inherent properties, does not provide some of
the generic features of a sound source. First of all, loops are not possible and the
position cannot be reset to the beginning of the stream. The effect of pause and play are
somewhat different from the file sound source, in that the input from the mic is muted,
but, as is to be expected, resumes playback at the current moment in time and not at the
moment it was paused.
Socket Server
Incoming TCP/IP requests on port 5180 are handled by the socket
server. The socket server has to maintain a link between an open socket connection and
active sound sources which were loaded by this connection. In case that the connection is
closed by the client and not all active sources have been closed, the sound server has to
close all those "zombie" sources.
The ND-Sound Protocol (NDSP) implemented by both the Socket Server and the
NDSoundServerStub is a simple text-based protocol. The server only responses to request
from the client. A client request consist of one text line of specified protocol commands
and the server responds either with "NO" if the request failed, or with either
"OK" or a specific response depending on the request.
Valid NDSP requests with responses are:
| Request |
Response |
Remarks |
| LOAD <sourcename> |
<tag> <nrchannels> |
If sourcename is __MIC, __DI1 or __DI1, the microphone, DarlaIn1 or DarlaIn2 channel
will be opened if possible, otherwise the server will be looking for an NDS sound file in
its directory. <tag> is the virtual tag for the opened sound source.
<nrchannels> is the number of mono channels provided by the sound source. |
| GETCH <tag> |
<nrchannels> |
Returns the number of mono channels of a sound source. |
| GETSP |
<nrspeakers> |
Returns the number of speakers handled by the sound server. |
| GAINCH <tag> <gain> |
OK |
Sets the gain of a sound source to the float value <gain>. Should be between 2.0
and 0.0. |
| GAINSP <speaker> <gain> |
OK |
Sets the gain of a speaker to the float value <gain>. Should be between 2.0 and
0.0. |
| PLAY <tag> |
OK |
|
| PAUSE <tag> |
OK |
|
| RESET <tag> |
OK |
|
| LOOP <tag> <loop> |
OK |
If <loop> is 0, the sound source will not loop otherwise it will. |
| START <tag> <pos> |
OK |
Set start of playback/loops to sample-position <pos>. Default is 0. |
| END <tag> <pos> |
OK |
Set end of playback/loops to sample-position <pos>. Default is the end of the
stream. |
| ATEND <tag> |
OK/NO |
|
| FREE <tag> |
OK |
|
| MAP <tag> <channel> <speaker> |
OK |
Maps the mono source channel <channel> of source <tag> to <speaker>. |
| MAPALL <tag> <channel> |
OK |
Maps to all speakers. |
| UNMAP <tag> <channel> <speaker> |
OK |
|
| UNMAPALL <tag> <channel> |
OK |
|
OpenGL Server
Running an OpenGL program on the Wall
- Run (using the command line or the Windows Explorer) s:\DisplayWall\Rudro\StartGL.BAT
(This starts the GL servers on the wall)
- Run all the programs you like
- Run (using the command line or the Windows Explorer) s:\DisplayWall\Rudro\StopGL.BAT
(This stops the servers you have started)
Compiling a program to run on the wall
- Write an OpenGL program that runs on windows. It is highly recommendedthat you use the
"aux" library (it's standard with Visual C++) for all user interface. At least
for the initial projects.
- Now copy the file s:\DisplayWall\Rudro\Demos\opengl32.dll to the same directory
that the
executable (.EXE file) for your program resides in.
- That should be it ! Now when you run your program (using the steps above) it will use the
"special" OpenGL driver that will send the graphics to the wall.
An OpenGL example program
- Create a new "Console appplication" in Visual C++.
- Add a single .cpp file to this project (name it whatever you like)
- Cut and paste the code below to that .cpp file. - Compile the project and follow the
steps above.
EXAMPLE CODE :
- #include <GL/gl.h>
- #include <GL/glaux.h>
- #include <stdlib.h>
- int main(int argc, char** argv)
- {
- auxInitDisplayMode (AUX_DOUBLE | AUX_RGB);
- auxInitPosition (0, 0, 500, 500);
- auxInitWindow ("Simple OpengGL Sample");
- glClearColor (0.0, 0.0, 1.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
- glMatrixMode (GL_PROJECTION);
- glLoadIdentity (); glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
- glColor3f(1.0, 1.0, 1.0);
- glBegin(GL_POLYGON);
- glVertex2f(-0.5, -0.5);
- glVertex2f(-0.5, 0.5);
- glVertex2f(0.5, 0.5);
- glVertex2f(0.5, -0.5);
- glEnd();
- glFlush();
- auxSwapBuffers();
- _sleep (10000);
- return(0);
}
User Interface
Gyro mouse
GyroMouse is the point input device we are using for the wall demos. We have one
GyroMouse linked to the machine NTTEST1 now.
To use the GyroMouse, a GryoMouse tracking program must be started on NTTEST1. The
program listen to? the GyroMouse events, such as mouse move, left-button click, ..., and
broadcast those events to the wall control and the viewer machines. The default port
number is? 4979, which is defined in \\newfs\shrimpNT\DisplayWall\include\dwall\control.h.
On the client side, there is a GyroMouse class which can be used to check mouse event,
its definition is:
- class GyroMouse
{
public:
??? GyroMouse();
??? GyroMouse(struct sockaddr_in &in_addr, int flag = 1);
??? ~GyroMouse(){};
??? int Read();
??? const int X();
??? const int Y();
??? const int Event();
???
??? void SetCursor(int x, int y);
private:
??? InitSocket(struct sockaddr_in &socketaddr, int flag);
??? void sock_close();
??? int x,y;
??? int event;
??? int flag;
??? int socketid;
};
which can be found in \\newfs\shrimpNT\DisplayWall\include\dwall\GMouse.h,
the according library is in \\newfs\shrimpNT\DisplayWall\libs.
Here is an example of how to use the GyroMouse class.
Wand
Wand was used as a point input device before GyroMouse. It needs two
tracking cameras and two machines linked to them. In the lab, machine NTTEST2 is used to
control the master camera; NTTEST1 is used for the slave camera, both machines are on the
lefthand bench. To use the wand, wand tracking program must be started on those machines,
you may find the icon for the tracking program on those machines desktop.
Wand shares the same programming interface as GyroMouse, except that
wand doesn't support button-click..?
Hand
Not available now.
Virtual Display Driver
???? ? ? Not Available now
Contact
If you have further questions, feel free to contact us.
|