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


bulletGeneral Information
bulletStill Image Viewer
bulletGenerating High-Resolution Images
bulletMaking Slides using PowerPoint
bulletShowing Single Images
bulletShowing Slides
bulletMulti-channel Sound Server
bulletIntroduction
bulletThe NDS sound file format
bulletThe NDSoundServerStub client interface
bulletThe NDSoundServer
bulletThe Sound Server FAQ
bulletOpenGL Server
bulletRunning an OpenGL program
bulletCompiling a program
bulletAn OpenGL example program
bulletUser Interface Devices
bulletWand
bulletGyro Mouse
bulletHand
bulletVirtual Display Driver
bulletWallThumbs (thumbnail image generator)
bulletContacts

 

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.

  1. Open a your slide in PowerPoint;
  2. Goto "File|Page Setup", change the page size to 40''x15'';
  3. PowerPoint will automatically stretch the text and pictures in your slide, if they are not in the correct aspect ration, do adjustment;
  4. 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:

  1. Goto \\newfs\ShrimpNT\Displaywall\bin (normally mounted to the control machine as drive s:);
  2. Run startviewer script to start the still image servers: startviewer
  3. Copy course poster file cs495.jpg to the image directory \\newfs\ShrimpNT\Displaywall\images\cs495;
  4. 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).
  5. 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:

  1. Build a slide list file, for example, jlist.txt;
  2. Start still images servers using startviewer script;
  3. Run GyroMouse server(see below);
  4. Run showjpgs jlist.txt. Left click move to next slide, right click move back to previous slide.
  5. 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.


NDSoundServerSetup


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:


Structure of the NDSoundServer


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

  1. Run (using the command line or the Windows Explorer) s:\DisplayWall\Rudro\StartGL.BAT (This starts the GL servers on the wall)
  2. Run all the programs you like
  3. 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

  1. 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.
  2. Now copy the file s:\DisplayWall\Rudro\Demos\opengl32.dll to the same directory that the executable (.EXE file) for your program resides in.
  3. 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

  1. Create a new "Console appplication" in Visual C++.
  2. Add a single .cpp file to this project (name it whatever you like)
  3. 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.
bulletStill Image Viewer: yuqun@cs neilshah@cs zjn@cs
bulletSound Server: prc@cs gessl@cs
bulletInterface: yuqun@cs emilp@cs zjn@cs
bulletOpenGL server: rudro@cs

 

 

 

last edited 04/28/2008