<br><font size=3>I have create a small bit of code which adds functionality
to app_meetme.c -- it runs fine for me in test, compiles without
warnings, and does not interfere with anything else. </font>
<br>
<br><font size=3>Is there enough general interest in the feature to make
it worthwhile for me to submit this code as a patch or addin via the specifed
process given that I have zero karma on that site and am not a member of
any team?</font>
<br><font size=3>-------------------------------------</font>
<br><font size=3>The rest of this note is in the following order:</font>
<br>
<br><font size=3>1. An explanation of the goal of this addition.</font>
<br><font size=3>2. How I've implemented this in code.</font>
<br><font size=3>3. How I make use of the features for my own use</font>
<br><font size=3>4. My answers to anticipated questions.</font>
<br><font size=3>5. Code Status -- testing, etc.</font>
<br><font size=3>6. Request for feedback.</font>
<br><font size=3>-------------------------------------</font>
<br>
<br><font size=3>1. An explanation of the goal of this addition:</font>
<br>
<br><font size=3>One of the things I need to do for a is record a conference
in 'time compressed' mode -- meaning that any spaces where people are not
speaking are left out. This is useful for what I call "catch-up mode".
It has particular importance for me, but I wanted to ask if it has importance
to anyone else.</font>
<br>
<br><font size=3>I am aware that this would appear to make recordings hard
to follow. After all, why not just speed up playback via some algorithm?
Please think for a moment of a conference call in a somewhat more
asynchronous way. A motion activated video camera recording system, for
example, ads no value to feature length movies. If you need to know who
went through the door in the last 20 minutes however, looking at that output
from that motion activated camera will save you the time form 20 minutes
to about 20 seconds. </font>
<br>
<br><font size=3>2. How I've implemented this in code:</font>
<br>
<br><font size=3>First, I've added an optional "R" flag to the
"app_meetme.c" application -- so far used it must be used in
addition to the regular "r" flag but that seems redundant to
me. This flag turns the basic mode of the feature "on".
When this is set, any time there is no user currently in the conference
marked as "talking" -- which means the user is making noise,
and the user was marked when he entered the conference as someone who is
being monitored for talking -- the stream of recording data simply does
not get written to the file. Everything else works as you would expect
of the current MeetMe application, and all the flags are set as if the
recording is happening normally.<br>
<br>
Second, An optional channel variable ${MEETME_LIVECATCHUPDIR} performs
a new bit of magic, let me 'splain. Normally, it doesn't work out
well if you try to play a file while it is being recorded in another thread.
I suppose you could do some kind of buffering but its an ugly hack at best.
I know, I've tried. For catch up mode to work properly, you need to be
able to play the audio that's transpired up to this point before putting
the user in the conference. If set, this variable will mean that
every time recording "pauses" for silence it the code quickly
closes the current recording file and renames it to the specified directory
and gives it a numeric prefix indicating the counter of how many of these
'sub files' have been created. It also resets the flags in the recording
thread so that the very next thing that thread does is open a new file
with the originally requested name as if it were just starting up from
scratch. When someone talks, the code just allows recording to continue
as normal, and the streaming data is written to the new file just as if
it had always been open.<br>
</font>
<br><font size=3>3. How I make use of the features for my own use</font>
<br>
<br><font size=3>For me, the conference in question tends to be open ended
and permanent. Its more like a party line than a conference call
-- but has a business focus. When a user is on the way to the conference,
I use a quick AGI script (mine is a bash shell script) which reads the
contents of that directory and queues up the list of files in order --
going back however many minutes of real-time recording I want -- and sends
them to the Playback or Background commands. I also have a web-accessible
page that uses AJAX style functionality to play the recordings as they
get added to the directory, meaning web based users can easily follow along.
Another script running through cron cleans up the directory on a
regular basis.</font>
<br>
<br><font size=3>4. My answers to anticipated questions.</font>
<br><font size=3><br>
1) Why not concatenate the files right inside the thread, then you only
need one additional file name? Because that would be potentially
slow, as it moves lots of bytes. Simply closing and renaming a file is
a very minimal system impact AND HAPPENS WHEN THERE IS NOBODY TALKING.
The cleanup, if you need it, should be done at a time you specify and out
of the thread loop of the meetme application -- which is already rushing
to keep up with all it has to do.<br>
<br>
2) Won't looping through all those users for each frame to see who's talking
slow down the recording thread? 99% of the time the same person is
talking that was talking the last time. For this reason, a pointer to the
last user who was talking is kept locally. Before looking to see who may
be talking, the code checks the last user who was talking to see if they
still are. This then, is a single integer comparison. If that person is
not talking, then a loop through the users happens -- however even then
we're talking about a single comparison of integer values for each user
in the conference. Even at a thousand users in conference, this would be
an eye-blink on most machines, and again, should happen only when there
is a pause in the talking. It also takes no i/o operation.<br>
<br>
3) How do you tell if a user is talking? I cheated -- I'm using the
routines already in app_meetme.c which call other places to figure it out.
I figure its best to use the standard way of doing this when at all possible.
It looks like the existing code takes into account a minimum silence duration
and the other kinds of things which should be considered.<br>
</font>
<br><font size=3>5. Code Status -- testing, etc.</font>
<br>
<br><font size=3>It's like Steve Martin said, "Everyone thinks they
have a sense of humor." Like everyone else, I believe my code
to be of a high quality. Although I must admit has been something
like fifteen years since I've done and serious programming in C or C++,
I do write code for a living and have my own business and a product or
two out there written in various other languages. Once you can write
in two or three languages, much of the rest is just getting used to differences
in syntax and "style" from language to language. I believe
what I've written will fit right in here without issue -- even if I did
write it using a text editor in an ssh session.</font>
<br>
<br><font size=3>To do what I needed, two areas in the app_meetme.c code
needed changing. It was necessary to make two additions the entry
point code. First, to process the new "R" option -- something
which pretty much anyone should be able to do easily enough -- the only
potential issue is if I've chosen to use a bit mask someone else is already
using for a patch, and that is easily resolved by simply picking another.
The second was to read the channel variable and store its contents
along with a flag indicating that the feature is active into the user structure
so that it could be accessed by the recordingthread. All other changes
are in the reasonably self contained "recordingthread" function.
Here, a block of code was inserted which checks to see if its quiet
or not quiet and based on that toggles a flag. If the extended feature
that handles file renaming is active, at the moment we flag from "not
quiet" to "quiet" the current stream is closed, that file
is renamed, and the flags indicating that the stream was ever opened at
all are reset. As a result, the very next code block encountered
is the existing check to see if the stream is open and if it is not, to
open in. This operates normally. Finally, a simple condition
branch happens at the line which does the write to the recording stream.
If the flag is currently set to indicate it is quiet right now, instead
of writing to the stream the result variable is set to indicate a successful
write occurred and the code goes on unaware.</font>
<br>
<br><font size=3>I have commented and tested this code on my own environment.
The compile is done without warning, the application works as expected,
and the audio is processed as expected. I have a little cleanup
to do so that as few changes show up in a diff file as possible. In
all other respects, I'm now using it live.</font>
<br>
<br><font size=3>6. Request for feedback.</font>
<br>
<br><font size=3>Your turn. First, does anyone else want this?
Second, is it worth me going to the trouble of submitting it or should
I just post it to my own website? Third, anyone have any other ideas?</font>
<br>
<br><font size=2 face="sans-serif">---<br>
Andrew Pollack<br>
Northern Collaborative Technologies<br>
207-221-2547<br>
</font>