Be Newsletter
Issue 99, November 12, 1997
Table of Contents
The BeOS at Comdex, in Lake Charles, LA, Austin and Dallas, Texas
- Be at Comdex
Monday, November 17 to Friday, November 21
The BeOS will be demoed by the Be Team on the Umax booth.
Where:
Las Vegas Convention Center
Umax Booth, Number L516B
- Be Demo Tour
Hosted by the Be User Group in Lake Charles
Wednesday, November 12, 1997
7:00 p.m.
Where:
Lake Charles, LA
McNeese State University
Drew Hall, Room 117
Lake Charles, LA
- Be Demo Tour
Hosted by the Be User Group in Austin
Thursday, November 13, 1997
7:00pm
Where:
Austin, Texas
University of Texas at Austin
Taylor Hall
Rm 2.106
- Be Demo Tour
Hosted by Apple Corps Group
Saturday, November 15, 1997
10:00am
Where:
Dallas, Texas
INFOMART
1950 Stemmons Freeway (I-35E) at the Oak Lawn Exit Room 1060
Dallas, TX
Information: infomartusa.com
BE ENGINEERING INSIGHTS: YABSA -- Yet Another Byte-swapping Article
By Bradley Taylor
I really didn't want to write another byte-swapping article.
But I had to. You see, every night I wake up from a
recurring nightmare that some poor BeOS user will be unable
to interoperate their BeOS app between Intel and PowerPC
machines. I toss and turn, gripped with worry and unable to
fall back asleep. Then I think of the public flogging the
guilty application writer will get for this terrible deed,
and I drift back into a pleasant slumber.
The truth is that PR2 has some new byte-swapping macros to
prepare you for our Release 3 Intel release and I wanted to tell
you about them. Judicious use of these macros *now* will
mean that in most cases your application will recompile and
interoperate when Release 3 rolls around later.
The new stuff in PR2 is contained in the file byteorder.h .
The macros can be summarized as follows:
B_LENDIAN_TO_HOST_XXX()
convert from little-endian to host format
B_BENDIAN_TO_HOST_XXX()
convert from big-endian to host format
B_HOST_TO_LENDIAN_XXX()
convert from host to little-endian format
B_HOST_TO_BENDIAN_XXX()
convert from host to big-endian format
Where XXX equals one of the following types: INT16 , INT32 ,
INT64 , FLOAT or DOUBLE . These macros swap in the case where
the host format doesn't match the desired format (big or
little endian), but are no-ops in the case where the host
format matches the desired format.
Additionally, byteorder.h contains two identifiers that will
tell you the host endianness:
B_HOST_IS_LENDIAN
1 on Intel, 0 on PowerPC
B_HOST_IS_BENDIAN
0 on Intel, 1 on PowerPC
Here is a simple example demonstrating usage of these new
macros. If you read something from a device register
(typically little-endian), you might write some code like
this to read the data out into a useful form:
count = B_LENDIAN_TO_HOST_INT32(device_registers->count)
On Intel, this macro does nothing, but on PowerPC it will
swap the data for you. It's much easier to read code like
this than code that contains a lot of #ifdef s to deal with
byte-order issues. #ifdef s are generally frowned upon, and
you should be ashamed of yourself if you use them.
The following sample program further demonstrates the usage
of these new macros:
#include <stdio.h>
#include <stdlib.h>
#include <byteorder.h>
/*
* Simple employee record
*/
typedef struct {
char first_name[16]; /* First name */
char last_name[16]; /* Last name */
float salary; /* Salary */
int16 number; /* Employee number */
char lendian; /* Is record in little-endian format? */
char padding; /* Padding, to float boundary (4-bytes) */
} employee_t;
/*
* Convert an employee record to host format
*/
static void
convert_to_host_format(employee_t *emp)
{
if (emp->lendian) {
/*
* Little-endian to host conversion
*/
emp->number = B_LENDIAN_TO_HOST_INT16(emp->number);
emp->salary = B_LENDIAN_TO_HOST_FLOAT(emp->salary);
} else {
/*
* Big-endian to host conversion
*/
emp->number = B_BENDIAN_TO_HOST_INT16(emp->number);
emp->salary = B_BENDIAN_TO_HOST_FLOAT(emp->salary);
}
}
main(int argc, char **argv)
{
employee_t emp;
switch (argc) {
case 1:
/*
* Read an employee record from standard input
* and print it
*/
if (fread(&emp, 1, sizeof(emp), stdin) != sizeof(emp)) {
fprintf(stderr, "Error reading employee record\n");
exit(1);
}
convert_to_host_format(&emp);
printf("Name: %s %s, #%d, $%8.2f\n",
emp.first_name,
emp.last_name,
emp.number,
emp.salary);
break;
case 5:
/*
* Use the command-line arguments to create an
* employee record
* and write it to standard output.
*/
memset(&emp, 0, sizeof(emp));
strcpy(emp.first_name, argv[1]);
strcpy(emp.last_name, argv[2]);
emp.number = atoi(argv[3]);
emp.salary = atof(argv[4]);
/*
* Note endian-ness for reading later
*/
emp.lendian = B_HOST_IS_LENDIAN;
if (fwrite(&emp, 1, sizeof(emp), stdout) != sizeof(emp))
{
fprintf(stderr, "Error writing employee record\n");
exit(1);
}
break;
default:
fprintf(stderr, "incorrect number of arguments\n");
exit(1);
}
exit(0);
}
This program reads and writes employee records. The records
can be written on Intel and read by PowerPC or vice-versa.
The program is written in a style I prefer, which is to
never swap when writing data, as long as there is an extra
field to indicate the endianness of the data when written.
Then when reading, you swap the data only if necessary. The
advantages of this style are the following:
- You don't swap when exchanging data between
like-minded machines, like Intel to Intel or PowerPC
to PowerPC. This is the common case, after all.
- The code is easier to understand, because there is only
swapping code for one direction (reading). The write case
looks pretty much like it would if you didn't have to
worry about these things (but unfortunately, you do).
Sometimes you don't have the liberty to define your own data
format because you are dealing with some standard format,
such as JPEG or device registers. The macros will still be
helpful to you in this case, and I recommend using them.
These macros won't solve all of your interoperability
problems. You still need to worry about alignment issues.
The employee record in this sample program was carefully
laid out to be interoperable using natural alignment
techniques. Natural alignment is the subject of a previous
Newsletter article...
http://www.be.com/aboutbe/benewsletter/Issue63.html#Insight
...and won't be discussed further here.
So, that's all I have to say. There is now plenty of
information available to you on how to prepare for Intel. If
you design your PR2 application right, it is possible to
just recompile it for Release 3/Intel and have it interoperate with
PowerPC. If you can do this, pour yourself a drink and enjoy
it. You deserve it.
How to Make a Million Dollars Developing for the BeOS (No Kidding)
By Dave Johnson
In the short time I've been at Be I've been getting in touch
with as many of our developers as I can. I hear a lot of
developers say, "I don't want to risk doing apps for the
BeOS until there are lots of apps out for it."
To address this I have here a somewhat edited version of an
e-mail exchange I had with a developer. (I rewrote it to
make me look good.) Reading this just might make you a
million dollars.
ME: Hi, I'm Dave Johnson, new Developer Evangelist at Be,
Inc. I'm going through the database becoming familiar with
all the developers, etc.
DEVELOPER: Dave, as much as I love the BeOS, I have to hold
off developing for it until we see Premiere, Photoshop, or
After Effects running on it. Until there are big-name
applications I don't think you'll have the customer base to
support my product.
ME: You already know the BeOS is a powerful tool that
enables you to write applications with significantly
superior performance -- RIGHT NOW -- so you CAN solve
specific problems for specific customers. The fact is that
there are customers out there who want that performance
because it will save them time and money. So for them the
argument about whether there are "enough applications" is
irrelevant. Service bureaus, video editors, graphic design
houses don't CARE if Quicken is on the BeOS yet! They care
if you can help them save or make money.
Developers who worry about the size of the existing customer
base believe that you write a generic application and just
sort of put it out there and wait for customers to come to
you. In fact this is already happening. We're doing
everything we can to get the BeOS into the hands of lots and
lots of computer users. But there's also another way to look
at this situation.
DEVELOPER: What's that? If you're telling me not to worry
about your existing customer base, how are you proposing I
can make money now?
ME: By solving specific problems for specific customers --
that's how people get rich. If you solve one problem in a
compelling way for customers they'll pay you for doing it.
Developers who write products that solve specific problems
will do well. The BeOS exists, developers understand what
it's good at, and you're going to see very good products
with vastly superior performance running on it. So why don't
YOU do one? Why don't YOU get there first and establish your
specific area of problem solving? How often do opportunities
like that come up?
DEVELOPER: I don't do one, because I really don't want to
reinvent the wheel.
ME: DUDE! Reinventing the wheel on a multi-threaded
symmetric multiprocessing OS means that you'll have
something to show that blows the customers away! You'll
either make a mint selling to those customers, or Adobe will
BUY IT from you when they decide it's time to be on the
BeOS. You want to be there first.
DEVELOPER: Well. . .
ME: Name one other OS that gives you superior performance on
the same hardware. Be is going to do well because it is a
compelling solution. Developers know that as soon as they
see and use the BeOS. And YOU will win by writing
applications that take advantage of the BeOS's performance
to solve problems for customers.
DEVELOPER: Yes, the BeOS is a compelling solution, and yes,
the geeks get it. But it does no good if the geeks aren't
_allowed_ to develop for it. Adobe isn't going to port until
they know that Be's "viable," financially. I think you guys
are doing a great job, and the BeOS is coming right along.
PR2 is great! The real truth is that you guys have
absolutely no competition. You blow NT out of the water, and
make the Mac OS look like a hack.
BUT I still think your main goal should be getting as many
apps, and the sexiest apps on board. Get Adobe to sign on.
No one wants to spend money on a set of apps that are all
1.0 versions, from tiny three-person startup companies!
ME: Leading edge developers think that entering an arena
where there is limited competition is a GREAT idea! They see
it as a huge opportunity. How often do you get opportunities
like this?
DEVELOPER: But why would a customer buy my product -- even
one tailored to solve a specific problem -- to run on an OS
that he isn't already using?
ME: Because applications running on the BeOS demonstrate
significant performance improvements that translate into
MONEY for the customer. Visit some of those customers and
learn their needs. Take a multiprocessor computer with you
and show a finished app that uses threaded multiprocessing
and does one thing for them in a third of the time it takes
them now. Just ONE thing. You can do that with the BeOS.
Think about all those service bureaus, all the
Kinkos, graphic designers, photo processors, video editors,
musicians, you name it...
Time is money, and speeding things up saves money for those
businesses. Lots of businesses are performing some task on a
computer that operates inefficiently. Apps running on the
BeOS will outperform apps running on Mac or Windows or NT.
Period.
DEVELOPER: Gosh. I'm glad I listened to you. I AM going to
go out and develop a BeOS application and make a million
dollars!
SUMMARY: Hey you developers, listen up, it's opportunity
knocking! What I'm suggesting is that you locate key target
business segments and find out specifically where in their
business the benefits of BeOS will make them money. Find out
where they are bogged down by slow programs, which programs,
etc... Then YOU develop a product that takes advantage of
the BeOS to solve that performance problem. Customers will
PAY YOU to do that! The developers that write those
applications for those customers are going to make a lot of
money.
Go out there and DO IT.
DEVELOPERS' WORKSHOP: Sounds That Go Bump In the Night
By Eric Shepherd
"Developers' Workshop" is a new weekly feature that
provides answers to our developers' questions. Each week, a
Be technical support or documentation professional will
choose a question (or two) sent in by an actual developer
and provide an answer.
We've created a new section on our website. Please send us
your Newsletter topic suggestions by visiting the website
at: http://www.be.com/developers/suggestion_box.html.
So I'm sitting here at my desk, minding my own business and
writing lovely new documentation for the Media Kit, when all
of a sudden the powers that be decide to have the new guy
start writing articles for the Newsletter. After momentarily
thinking that was a pretty good joke, I realize they're
actually serious.
As this slowly sinks in, I'm staring at my screen, where
pages and pages of sample code and half-written Media Kit
documentation are mocking me. Slowly it dawns on me that I
can impress everyone with my speedy article writing by
ripping out a piece of one of these sample programs I've
been working on and writing an article about it.
After perusing my source code, I realize that what I have in
my hands is nothing less than the answer to the age-old
question: "How do I take an arbitrarily formatted sound and
stuff it into that 16-bit stereo sound stream?"
What I'll present here is a C function that can mix any
sound format into a stream buffer. Ideally, you'll take this
code and convert it into a member function in your sound
output class.
The BeOS audio streams (both input and output) are 16-bit
stereo. Once you've subscribed to the output stream (by
creating a BDACStream object and subscribing to it with a
BSubscriber ), you can enter the stream and start receiving
buffers of audio data that you can alter to your heart's
content.
This is great when the sound you want to play is in 16-bit
stereo form. But things get ugly when it's 8-bit mono or
some other format. Then you have to manually fix things like
sample size and endianness, and mix the sound into the
stream, preferably without destroying whatever sound is
already in the buffers you receive.
Since you always know what format the output stream is going
to be, you can make your life easier by defining a structure
I call standard_frame , which defines the format of a single
frame of audio data in 16-bit stereo format:
struct standard_frame {
int16 left; // Left channel's sample
int16 right; // Right channel's sample
};
typedef struct standard_frame standard_frame;
Now you can create the MixStandardFrames() function. It
accepts a lot of parameters. When you add this function to
your audio output class, you can probably eliminate a lot of
these parameters by referencing member variables of your
class instead.
status_t MixStandardFrames(char *soundData, int32 index,
int32 count, standard_frame *out, int32 fileFormat,
int32 byteOrder, int32 sampleSize, int32 channelCount) {
soundData is a pointer to a buffer containing the sound data
to mix into the output buffer. To make your life really
easy, it takes a pointer to the beginning of the complete
sound. The index parameter is the frame number of the sound
to start playing at. So if you want to play starting at the
5,000th frame of the sound, you'd pass a pointer to the 0th
frame in soundData and the number 5,000 for index.
The count parameter is the number of frames you want to mix,
and out is a pointer to a 16-bit stereo sound buffer into
which those frames will be mixed. The remaining parameters
specify the file format (B_WAVE_FILE , B_AIFF_FILE , etc),
byte order (B_BIG_ENDIAN or B_LITTLE_ENDIAN ), sample size (1
or 2 bytes), and channel count (1 or 2 channels, for mono
and stereo). These parameters allow MixStandardFrames to
interpret the incoming data correctly.
MixStandardFrames has lots of local variables. The shortIn ,
byteIn , and ubyteIn pointers will be used for type-casted
pointers to the sound data. The other parameters are used,
as you'll see later, by the code that does the actual mixing
of the sound data.
register short *shortIn; // Used for 16-bit samples
register char *byteIn; // For 8-bit signed samples
register uchar *ubyteIn; // For 8-bit unsigned samples
register int32 sample0, sample1; // Mixed left and right samples
register int32 temp0, temp1; // Used in clipping computation
register int32 stereo; // Stereo or not?
register int32 frame; // The frame offset being processed
The first thing to do is verify that the input pointers
aren't null. That would be a bad thing, and as good
programmers we fear bad things, so check for that straight
off.
if (!soundData || !out) {
return B_ERROR;
}
Then set the stereo variable to 1 if the sound you're
playing is in stereo format, or 0 if the sound is mono. This
will be used as a multiplier as you make your way through
the input sound data.
if (channelCount == 1) {
stereo = 0;
}
else {
stereo = 1;
}
Now it's time to prepare for the real work. Set up byte,
unsigned byte, and short pointers to the first frame of the
sound data to be played. When you actually start processing
the data, you'll use the pointer appropriate to the type of
input data you have. The pointer is cast to the appropriate
type and you add the offset to the specified first frame.
The offset is either index or index *2, depending on whether
or not the sound is stereo or not. So you multiply index by
stereo +1, which will either be index *1 or index *2. The
result is a pointer to the first frame to be processed.
Then you initialize the frame counter to zero.
byteIn = ((char *) soundData)+(index*(stereo+1));
ubyteIn = ((uchar *) soundData)+(index*(stereo+1));
shortIn = ((short *) soundData)+(index*(stereo+1));
frame = 0; // Start at the very beginning
// (a very good place to start)
Now it's time to process the actual sound. Start by dealing
with 8-bit sounds, which have a sample size of one byte.
Loop through each frame, from 0 to count, using the frame
variable as a counter.
if (sampleSize == 1) {
while (frame < count) {
if (fileFormat == B_WAVE_FILE) {
sample0 = out->left + (int32) (int8)
(*ubyteIn - 128) << 8;
ubyteIn += stereo;
sample1 = out->right + (int32) (int8)
(*ubyteIn - 128) << 8;
ubyteIn++;
}
else {
sample0 = out->left + (int32) (int8) (*byteIn) << 8;
byteIn += stereo;
sample1 = out->right + (int32) (int8) (*byteIn) << 8;
byteIn++;
}
The above code computes one frame of mixed sound data. Note
that 8-bit WAVE files get special treatment. That's because
8-bit WAVE format samples are unsigned, rather than signed.
So you have to convert the data into signed format by
subtracting 128 from the samples.
sample0 is the left channel's sample. Grab the next sample
from the buffer containing the sound you're playing (pointed
to by either ubyteIn or byteIn), shift it left eight bits to
convert it into a 16-bit number, and add it to out->left ,
which is the existing sample in the output buffer.
Now add the value of the stereo flag to the input pointer.
This will only increment the input pointer if the sound is
in stereo format (remember that stereo is 0 for mono and 1
for stereo). That way, when you read the right channel, if
the sound is stereo, you'll get the right channel's sample,
but if the sound is mono, the left channel will be
duplicated into the right.
Process the right channel's sample, sample1 , the same way.
Now you have to deal with possible clipping problems.
Clipping occurs when the value of the mixed samples is
outside the range that can be represented by a 16-bit
number. This is why you mix the sounds in 32-bit variables:
You can detect overflow and compensate for it.
First, add $8000 to the left and right samples we've mixed,
then mask off the low word. This value, stored in temp0 for
the left channel and temp1 for the right, is non-zero if the
sample overflowed.
Now store the sample into the output buffer. If temp0 (for
the left channel) or temp1 (for the right channel) is
non-zero, replace the output sample with $7FFF if the sample
is positive (this is the maximum possible sample value) or
$8000 if the sample is negative (this is the minimum
possible sample value). This clips the sample to the range
of valid 16-bit integers without accidentally wrapping
around and sounding *really* strange.
Finally, increment the out pointer to point to the next
frame of audio in the output buffer, and increment frame ,
which is the number of frames you've processed so far, and
continue looping until the desired number of frames have
been mixed into the output buffer.
temp0 = (sample0 + 0x8000) & 0xFFFF0000;
temp1 = (sample1 + 0x8000) & 0xFFFF0000;
out->left = sample0;
if (temp0) {
out->left = (sample0 > 0 ? 0x7FFF : 0x8000);
}
out->right = sample1;
if (temp1) {
out->right = (sample1 > 0 ? 0x7FFF : 0x8000);
}
out++; // Next slot in the output buffer
frame++; // Next frame of input
}
}
16-bit input data is handled almost exactly the same way,
with two significant differences: WAVE files don't need
special consideration, and you have to deal with both
big-endian and little-endian input.
Since BeOS is natively big-endian, you have to use the
read_16_swap() function to read little-endian data. This
function returns, byte-swapped, the 16-bit value located at
a given address. The input data is pointed to here by
shortIn, which represents the 16-bit input data. Otherwise,
this code is exactly the same as the 8-bit code above.
else {
while (frame < count) {
if (byteOrder == B_LITTLE_ENDIAN) {
sample0 = out->left + (int32) read_16_swap(shortIn);
shortIn += stereo;
sample1 = out->right + (int32) read_16_swap(shortIn);
shortIn++;
}
else {
sample0 = out->left + (int32) *shortIn;
shortIn += stereo;
sample1 = out->right + (int32) *shortIn;
shortIn++;
}
temp0 = (sample0 + 0x8000) & 0xFFFF0000;
temp1 = (sample1 + 0x8000) & 0xFFFF0000;
out->left = sample0;
if (temp0) {
out->left = (sample0 > 0 ? 0x7FFF : 0x8000);
}
out->right = sample1;
if (temp1) {
out->right = (sample1 > 0 ? 0x7FFF: 0x8000);
}
out++; // Next slot in the output buffer
frame++; // Next frame of input
}
}
Finally, return B_OK to indicate that, as far as this code
can tell, nothing went too terribly wrong while mixing the
sound data:
return B_OK;
}
This code can be called easily from your stream function to
mix any kind of sound data into the output stream. The
following sample hook function assumes the existence of
certain variables. Normally you'll have these within the
class containing the hook function, but space doesn't permit
me to show the entire class. These variables are:
playFrameNumber: Specifies the frame number of the first
frame of audio data to play.
soundLength: Specifies the length, in frames, of the sound
being played.
soundData: Pointer to the sound data to play.
fileFormat , byteOrder , sampleSize , and channelCount specify
the file format, byte ordering, sample size, and number of
channels in the sound. These are passed straight through to
MixStandardFrame() .
static bool OutStreamHook(void *userData, char *buffer,
size_t count, void *header) {
int32 frameCount;
// If the sound is done playing, exit the stream
if (playFrameNumber >= soundLength) {
return false;
}
// Compute the number of frames to copy
frameCount = count/4; // Compute buffer size in frames
if ((soundLength-playFrameNumber) < frameCount) {
frameCount = soundLength-playFrameNumber;
if (!frameCount) {
return false; // No more data!
}
}
// Mix ourselves into the buffer.
MixStandardFrames(soundData, playFrameNumber, frameCount,
(standard_frame *) buffer, fileFormat, byteOrder,
sampleSize, channelCount);
playFrameNumber += frameCount;
return true;
}
This hook function starts by looking to see if the sound has
finished playing (the frame to be played is greater than or
equal to the number of frames in the sound); if so, it
returns false, which tells the BSubscriber to remove us from
the stream.
Now compute the number of frames to copy into the buffer, by
dividing the size of the file in bytes by four and storing
that result in frameCount . Each frame of 16-bit stereo sound
is four bytes long.
If the number of frames left to play in the sound
(soundLength - playFrameNumber ) is less than the number of
frames in the buffer, change frameCount to that value. This
can happen when you are approaching the end of the sound,
and there are fewer frames of sound left to play than there
are in the buffer you've received.
Once that's all done, call MixStandardFrames() to mix the
sound into the buffer, then add frameCount to
playFrameNumber to keep track of the next frame to be
played. Finally, return true, which tells the BSubscriber
that you're not done playing yet.
BeOS on the Web
By Jean-Louis Gassée
Perhaps this isn't the best of weeks to discuss e-commerce,
right in the wake of an ambitious announcement from one of
our noble and worthy elders, but we just made the BeOS
available for Web download (visit
http://www.be.com/products/beos_download/.
From one angle, this isn't news, we said we'd do it, we're
doing it, a little late, we're just doing our job and, in
any case, doesn't everyone promote and deliver their
software on the Web? True. But, from another angle, our
latest move raises a few questions. The hardest one stems
from the "free trial" status of our product. If we start on
that slope, some critics say, how are we going to make
money, how are we going to wean users from the "free BeOS
habit"?
Here is our perspective: The world isn't waiting for us,
we've got to earn the trust and the commitment of developers
and customers. The BeOS is an unproven platform within a
context where one company, Microsoft, is enormously
successful, and other operating systems have slowed down, in
the best of cases, or failed. Of course, in order to make
our case, we can write columns, go to industry conferences
and give speeches, or go to trade shows and run
demonstrations. This is good, necessary perhaps, but not
sufficient.
Clearly positioning the product is good, comparing the
benefits of a specialized Media OS versus the comforts and
limits of a general-purpose platform is commendable
marketing hygiene. Opposing IBM's strategy with OS/2 (better
DOS than DOS, better Windows than Windows) to our goal of
coexisting with Windows is a useful disclaimer.
But, in the end, the most potent marketing weapon in our
business still is word-of-mouth. If users and developers say
good things about the BeOS and our company, its business
practices and its people, this is much more credible than
any commercial. If, on the contrary, our product is
perceived as poorly designed, our staff as unresponsive, no
amount of advertising will correct the problem.
This is well and good, but it doesn't quite address the
"freebie habit" problem. Why don't we charge for PR2
downloads? After all, it's nice, stable and usable, right?
Right now, our view is we need to develop the installed base
of BeOS users more than we need the revenue. We'd rather
make this investment as soon as possible, learn what users
like and dislike and maximize the installed based BeOS
developers can count on.
And, as we plan to enter the Intel space, we want to gather
as much momentum and experience as possible, while keeping
in mind that this new field isn't the PowerPC market, only
bigger. Mac developers have discovered that fact when they
moved to Windows. The context, the competition, the belief
systems, the purchasing habits are all different. Which puts
us in the slightly paradoxical situation of wanting to gain
experience quickly while realizing that the knowledge gained
must be applied selectively.
Back to the main issue, our current plan is to let the trial
version, free, and the paid for product coexist. Many
companies do that today, and rather successfully. You can
use Eudora Lite or pay for Eudora Pro, your choice. You can
use QuickView, or pay for the QuickView Plus version, both
very nice products. And there are many, many more such
examples.
These companies obviously want to make it easy for the
prospective paying customer to make up his or her mind, and
they have faith in the statistical outcome of the trial.
Qualcomm, for instance, knows some people will keep using
the "free" Eudora Lite instead of forking the $50 or so
required for the Pro version. But, as long as the "Lite"
users are happy, they contribute to the positive buzz about
Eudora. This, I hasten to say, doesn't mean to represent our
detailed calculus of possibilities for the free vs. paid for
versions of the BeOS, these examples merely intend to show
it can work and that users are willing to move from free to
"commercial."
We'll keep in mind that history repeats itself in mysterious
way as we happily add bandwidth for the demand created by
the Web availability of our product -- and as we are chasing
freshly discovered bugs.
BeDevTalk Summary
BeDevTalk is an unmoderated discussion group that's a forum
for the exchange of technical information, suggestions,
questions, mythology, and suspicions. In this column, we
summarize some of the active threads, listed by their
subject lines as they appear, verbatim, in the group.
To subscribe to BeDevTalk, visit the mailing list page on
our Web site: http://www.be.com/aboutbe/mailinglists.html.
-
Subject: Workspace dragging
The drag-a-window-between-workspaces feature was a new found
source of amusement for one of our listeners. Although
initially offered as an off-topic thread, others joined in
to offer window management suggestions:
- Hot-key window delivery: Bucky bit-click on a window to
send it to some other workspace.
- Workspace scrolling.
- Multiple graphics card support, with separate workspaces
running on each.
- Spatial arrangement of workspaces to support multi-headed
setups.
- Smarter desktop layout when switching from a big to a small
workspace.
The spatial arrangement/multi-headed question generated the
most debate: Should individual workspaces be views into a
single universal workspace area? Should each monitor have
its own list of workspaces that it can switch to, exclusive
of all other monitors? And so on.
- Subject: Web Browser
Jerome Chan is curious:
"How hard is it to write a web browser? I mean, if the Linux
people can write an entire OS why can't we write a web
browser ourselves?"
Craig Longman suggests looking at the HTML spec to get an
idea of the task's complexity. And then move on to Java, and
JavaScript, and CSS... Pierre-Emmanuel Chaut pointed out
that many of the elements of a good browser are already
available (through Kftp, rRaster, Felix, and so on). It's
(ahem) simply a matter of putting the pieces together.
Various members of the BeDevTalk community offered their
services for a international group effort.
The thread then veered into a discussion of XML ("Extensible
Markup Language") vs HTML. Is XML the Web language of the
future?
- Subject: VirtualMemory Swap on Alternate Drive
Swap file questions:
- How about providing a "remote" swap file feature, in which
the swap file is on a different drive?
- How about a swap file on a separate partition?
- Can the kernel handle multiple swap files?
The swap-file-across-a-wire idea was generally accepted as
an obviously beneficial improvement. But does it make sense
to dedicate a partition as a swap file? Jake Hamby points
out that the BeOS is quite efficient when handling VM I/O,
so assigning a partition might not gain anything. Osma
Ahvenlampi offered this: If you can physically place the
partition on the outer cylinders, you can take advantage of
the cylinders' naturally heightened speed.
THE BE LINE: (From Dominic Giampaolo) Although the kernel
can handle "remote" swap files, there's currently no way to
tell it to do so. We'll consider it, but it's not likely to
happen in the next release.
- Subject: Opera
John Tegen sent a well-reasoned description of the necessity
of and requirements for an intelligent open system. But
where to go from here, wherever "here" is?
Somehow, the thread immediately skidded into a discussion of
the "Project Magic" Opera browser. A number of listeners
have pledged their money to this port; others question the
wisdom of buying a product before it exists.
More interestingly (and generally), the notion of
"nativeness" was scrutinized. Is moving code from one
platform to another and stitching up the loose ends enough
to deem the result "native"? Many folks don't think so. A
native app should take advantage of an OS's features, which
implies a significant amount of rewriting. In the case of
the BeOS, according to Jon Watte, a primary feature that
should be taken advantage of is the multi-threaded
environment:
"There is no shame in having written code that does not port
cleanly to the BeOS, because you couldn't know that we would
come along and suddenly do everything so much better.
However, what we do is make sure that there is glory in
writing code that DOES work in a multi-threaded
environment."
- Subject: Compile with which headers? And the
subscription model
Which headers should an app developer use when compiling?
Are older headers (where PR1 is oldest) better because of
the larger customer base? Or, given the subscription model,
will all/most users be automatically "on the bus"?
Relatedly, it was suggested that the compiler should note
the version of the OS that an app is compiled under. If the
app is launched on a newer version, a "renew your OS
subscription" Alert could pop up.
THE BE LINE: You should compile against the headers of the
oldest OS version that you want to run on. This means, of
course, that you can't take advantage of newer features.
|