Be Newsletter
Volume II, Issue 2, January 14,
1998
Table of Contents
BeOS Demos: SD'98 in San Francisco; Be Developer
Conference in Santa Clara
- Be at SD'98
Monday, February 9 to Friday, February 13, 1998
Where:
Moscone Convention Center
North Hall
Booth #454
San Francisco, California
For more information, see: http://www.sd98.com/
- Be Developer Conference
Thursday, March 19 to Friday, March 20, 1998
Where:
Westin Hotel
Santa Clara Convention Center
Santa Clara, California
All software developers are invited to join us for two days of in-depth
technical presentations, demonstrations, and discussion by the Be team.
For more information, see:
http://www.be.com/developers/BeDC_info.html
Be Developer Classifieds
Be Developer Classified are an opportunity for Be developers
to tell each other about projects they're working on, are
thinking about working on, or would like to work on. Here's
your chance to request assistance on a project, or make your
talents available for other projects.
(For more information, check out the Classified Ads section in
the Registered Be Developer Area.)
Help Wanted: Contract Programmer
We're looking for an experienced C/C++ developer who is
familiar with the BeOS and web technologies to help us
create a Live Web Video application on the BeOS. The
contract rate is negotiable.
Contact Bill Dunning at wdunning@envision-inc.com. No
replies after 1/31/98, please.
BE ENGINEERING INSIGHTS: Workspace Workout
By Robert Polic
Workspaces are an illusion that allow users to organize
their applications and documents into different virtual
screens. By default, application windows open in the current
workspace and live solely in a single workspace (though the
user, through the Workspaces preference panel, can later
position the window in any of the available workspaces).
If the default behavior satisfies the needs of your
application, you don't need to add any workspace- specific
code. However, if your application supports multiple
windows, gratuitous animation, or other processing tasks
that can stop when its workspace is deactivated and continue
when it is reactivated, there area handful of BWindow and
global functions to assist you.
In most cases the user should determine which workspace a
given window exists in (use B_CURRENT_WORKSPACE in the
BWindow constructor), though there may be cases were it
makes sense for the application to set the workspace for a
window. To create a window in a specific workspace (or
workspaces) the BWindow constructor takes an unsigned int32
bit field. A "1" in any bit position indicates the window
should exist in that workspace (with bit 0 corresponding to
the first workspace). Using B_ALL_WORKSPACES forces the
window to exist in all workspaces. Most applications should
not use B_ALL_WORKSPACES since this would rapidly defeat the
purpose of workspaces.
To change the current workspace (or workspaces) for a window
after construction, there is a BWindow method,
SetWorkspaces() , that takes the same bit field parameter. An
example of an application that may need to do this is a
paint program with an editing window and separate tool
palette windows. When the user moves the editing window to
another workspace, the palette windows should follow. To do
this, override the edit window's WorkspaceChanged() method
and call the palette window's SetWorkspaces() function:
void TEditWindow::WorkspacesChanges(uint32 old_ws,
uint32 new_ws)
{
fPaletteWindow->SetWorkspaces(new_ws);
}
NOTE: Before creating or moving a window to a given
workspace you should first determine that the workspace is
valid (the user can set between 1 and 32 workspaces). There
is a global function, count_workspaces() , that can be used
to determine the number of workspaces.
Some applications may wish to create follow-on windows in
the same workspace that the main window resides in. To
determine which workspace (or workspaces) the main window is
in, use the window's Workspaces() method. An application
example might be a compiler that creates a status window:
void TCompilerWindow::ShowStatus(...)
{
BWindow* status = new BWindow(rect, title, type, flags,
Workspaces());
}
An application that can curtail processing when its window's
workspace becomes inactive should do so. Obviously, a web
browser should not stop a download, but it could stop all
animated GIFs. To do this, override the BWindow's
WorkspaceActivated() method and stop or start processing
tasks according to the state variable:
EyeCandy::WorkspaceActivated(int32 ws, bool active)
{
(active) ?
release_sem(process_sem) :
acquire_sem(process_sem);
}
Applications with windows that live in more than one
workspace can do this a bit more efficiently by ignoring the
ws variable and instead using the global function
current_workspace() to determine if the window lives in the
current workspace:
EyeCandy::WorkspaceActivated(int32 ws, bool active)
{
(Workspaces() & (1 << current_workspace())) ?
release_sem(process_sem) :
acquire_sem(process_sem);
}
DEVELOPERS' WORKSHOP: Proper Attribution
By Stephen Beaulieu
"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.
As you know, the Developer's Workshop is all about answering
questions and providing sample code to developers. We get a
list of topics and questions developers send in. We look
them over and provide the sample code that we think will
solve the problem. Well, being the new kid on the block, I
brought a question with me.
"When is it appropriate to use attributes to store
information for your program?"
Making the most of my direct access to the Be engineers, I
wandered around asking my question until I got some answers.
The quick and dirty answer is that attributes are
appropriate for storing extra information that is
inappropriate or impossible to store in the file itself.
This information may change frequently, or can be done
without if it doesn't exist.
As always, the quick and dirty answer isn't the full story.
But the full story needs a little background information.
Attributes are arbitrary name/value pairs associated with a
file, which can be indexed by the file system for querying.
Attribute names can be up to 255 characters in length, and
their values can be of any size. Attribute names and values
are stored together, and a file can only have a single value
for a given attribute name. Attributes are stored in the
order they are added to the file. Queries are limited to
indexed attributes whose values are strings, floats, or one
of the various integer types.
Some implementation details suggest ways to optimize
attribute storage. These details are subject to change, but
the suggestions I'll make shouldn't negatively affect future
performance. In any case, these details will be completely
invisible to users.
While attributes can store any amount of information, each
file has a small "fast attribute" area that is accessible at
little cost whenever the file is referenced. This "fast
attribute" area is about 700 bytes in size, and is the first
place attribute information is stored. As soon as it fills
up, the file system creates additional areas to store
attributes. The additional areas impose some file system
access costs, making them considerably slower than the
"fast" area.
So, what can a developer do to maximize the performance of
retrieving attribute information? Try and get as much
information into the "fast" attribute area as possible.
Although there are no specific methods to guarantee that an
attribute exists inside of the fast attribute area, we can
suggest guidelines that should increase the likelihood of
having your attributes accessed in the fastest method
possible:
- Keep attribute names short, but descriptive. Remember to
avoid namespace conflicts.
- Create all of your smallest attributes first, leaving
larger ones for the end.
With these optimization guidelines in mind, let's look to
the BeOS for some appropriate uses for attributes. Perhaps
the best overall example is using attributes to store
information about e-mail files. The mail_daemon saves each
message to a file and adds the following attribute
information:
Information Attribute Name
----------- --------------
Name MAIL:name
Subject MAIL:subject
To MAIL:to
From MAIL:from
ReplyTo MAIL:reply
Status MAIL:status
Priority MAIL:priority
When MAIL:when
Header Length MAIL:header_length
Content Length MAIL:content_length
Most of these are self explanatory, and are simply the
record of information contained in the file in the attribute
system for querying purposes.
The header_length attribute, however, is worthy of special
note, as it shows an efficient use of attributes. Header
information is not normally needed when displaying a message
to the user, but since it's at the beginning of the file
it's important to know its length to make it easier to jump
to the real contents of the file. Similarly, when the
headers are specifically requested, having the length
available makes it easy to read that amount of data from the
file. This makes parsing the file to get to the end of the
headers every time the file is accessed unnecessary.
Other BeOS uses of attributes can be found in StyledEdit and
the Tracker. StyledEdit stores all of its style information
in attributes. This allows the actual data of the file to be
stored as plain text, making it easy to read the file in
applications that don't care about the styled information.
The Tracker uses attributes to store icon and position
information for files and folders.
The People app also uses attributes for information storage.
Person files contain only attributes; there is no other data
in the file itself. This raises the question of whether it
is appropriate to use attributes as a kind of built-in
database. The answer is that it really depends on the type
of information you want to store. The drawback of such a
system is that it is inefficient in terms of storage. Every
record would exist as an individual file, taking up a
minimum of a block on the drive. Each file must live in some
directory somewhere.
While in theory this method should work for nearly any
amount of information, as a practical matter a "database"
with hundreds of thousands of records would be inefficient
both in terms of storage space and speed of accessing
information. On the other hand, it can be useful for storing
contact information in a place where it's easily accessed by
any application.
There are many uses for attributes in addition to those
we've touched on in this article. Attributes could be used
to store the URL of a downloaded document; the last backup
date for a file; the keywords of a document; or gamma
correction, color depth and dimensions of an image. We'd
like to hear about the uses that developers are putting
attributes to. If you have an interesting use, drop us a
line at the online support form in the Registered Developers Area.
We're curious.
Finally, there are a few things to be aware of when dealing
with attributes. Currently, only direct Tracker copying to
another Be File System disk or archiving your files with zip
preserves attribute information. Most of the other common
storage and transfer formats do not save that information
(including tar, cp, ftp and mail attachments.) This means
that you need to take extra care when transferring files
that contain attributes. Also, applications should be aware
that a file might not contain the attributes they expect,
and be prepared to rebuild them, if possible.
Well, I've gone over many things to consider when using
attributes, but I've not touched on how to actually use
them. I'll cover that in four weeks, along with some sample
code that shows how to read and write files in the BeOS.
CES Snapshot
By Jean-Louis Gassée
Last week, Steve Sakoman and I took time off MacWorld to go
to Las Vegas. This wasn't a desperation financing trip, but
an attempt to survey the scene at the Consumer Electronics
Show. It didn't start well. Steve tried to register
electronically and the server promptly got stuck leaving him
in registration limbo for a while.
We went in looking for signs of the convergence between
consumer electronics and computing. We saw black boxes and
silver boxes and titanium colored boxes, but not much
convergence. Still, WebTV Plus, the latest version, is
really good, TV and the Web coexist nicely, even if they
don't merge yet and this product will make Microsoft look
very smart.
Smart is an adjective that becomes harder to place when
contemplating the latest TCI machinations. John Malone gives
a layer of the mille-feuilles to Scott McNealy's Personal
Java and another one to Windows CE. But the hardware layer
is still to be defined, the microprocessor is to be anointed
in the Spring, all the while NextLevel nee and born again
General Instruments (the NextLevel name didn't work) claims
billions in orders for their next generation set-top boxes.
I guess John Malone is the smartest right now for wringing
money out of Sun and Microsoft. Sun is rumored to provide
about $10 per box to "compensate" for the hardware penalty
required to run Personal Java and Microsoft is rumored to
have made similar concessions in excess of the WinCE
royalty, while pointing out Java, unlike Win CE, won't run
on all boxes, only higher-end ones. The "happy" processor
manufacturer knows what to expect.
Will this yield a nice product? The developments will be
interesting to watch with each player bringing up hardware
or debugging code while watching the other guys trying to
create some kind of toll gate in order to recoup their
"advance payment" and, at the same time, rereading the legal
paperwork looking for loopholes in the contracts.
With this in mind, the un-second-guessed approach pursued by
WebTV looks even more attractive, in a different domain for
the time being.
We watched with great interest the PalmPC demos (I'm a Palm
Pilot user and a director of 3Com, the owner of Palm
Computing -- so you know the possible biases in my
opinions). Same physical size as the Pilot, and running a
version of Windows CE, with Microsoft's might, it could
become tough competition.
The PalmPC demo involved a man and a woman. The woman played
the role of the "conventional" user of paper organizers, big
purse, you see the picture, and the man inside the little
demo booth was the more enlightened user of a PDA.
On top of the booth, a big screen reproduced the small
PalmPC screen for a large audience -- I thought, until Steve
Sakoman's sharper eyes and elbow brought me back to reality.
"They're running a tape," said Steve. Indeed, this was a
karaoke demo, the two actors were saying their lines as the
video tape of the demo ran. I went around the booth, the
male "demonstrator" followed the tape on a small screen and
kept flipping his neat little cue cards with yellow
highlights as he went along.
Just to acquire more data about WinCE, I bought a Sharp 2.0
device, grayscale display, 12MB of RAM, integrated (soft)
modem, and took it on an overseas trip along with my Hitachi
portable, my Pilot, my Swiss-Army knife, my screw-pull
(don't want to face a bottle of fine Bordeaux without it)
and other unmentionables. Without getting into a detailed
review of the Sharp hardware nor of Windows CE 2.0, the
whole system looks to me as too big, too slow, too
unreliable and too battery-hungry (one set of two AAs per
day) to compete in the smaller, lighter, more nimble Pilot
category.
HDTV was everywhere and looked pretty real. Yes, the sets
are horribly expensive. But imagine the following situation:
two sports bars in town, one shows football and basketball
on HDTV, one on a current set. The beer costs 50 cents more,
which bar will get more volume and better margins? Joe,
where did you get that set? Sports sells ads, somehow a way
will be found to prime this better pump for commercials.
For the rest, wireless devices continue to proliferate
happily, GPS devices can now be had for less than $100 and
slightly more expensive ones acquire better displays, store
maps -- they'll be and take us everywhere.
The rest was either unmentionable or too hilarious for this
family newsletter, or too sad. In this latter case, I'm
referring to the "very high-end" audio with Russian mil-spec
12AX7 triodes, gold-plated everything and oxygen-free copper
crystal cables.
We grabbed a cab, ran through the airport, caught a
just-boarding Southwest flight to San Jose. The peanuts and
the diet coke never tasted better. Comdex looks even better
now.
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: B_PAGE_SIZE
If you malloc() a single page (4096 bytes), does the system
actually reserve another page for bookkeeping overhead?
Should you be wary as your malloc() request approaches a
page size boundary? Should you use areas instead?
THE BE LINE: A malloc() smaller than 2048 bytes rounds up to
the next power of two. Greater than 2048 rounds up to the
next multiple of 4096. The bookkeeping overhead needn't be a
concern; for example, the overhead won't push a malloc(4096)
call into an 8k allocation. Note that the 2048/4096 numbers
are NOT related to the page size (which, coincidentally, is
also 4096 bytes); these numbers could change in a later
release.
As many readers pointed out, you shouldn't blithely swap
create_area() for malloc() . Areas are useful when you need
to lock or share a chunk of data; they aren't meant to be
fast.
- Subject: Mouse Position
AKA: Mouse Position Again
AKA: Pointers.
Should Be allow programmatic mouse positioning? The "all
things are possible" camp thinks a modern OS should allow
this sort of manipulation.
From Marco Nelissen:
"SetMousePosition is *good*. For one thing, it allows you to
plug in all kinds of funky hardware to control the mouse
cursor with, and you don't even have to write a fake mouse
driver for it. It also allows for stand-alone recorded
demo's to play..."
UI wonks fear that this ability will corrupt interface
consistency and confuse users. Many of our listeners adopted
a laissez-faire, natural selection position:
"Is SetMousePosition() so bad an idea that we can't let
programmers do what they will and let Darwin sort them out?"
(Trey Boudreau)
"Sure, it could be abused, but software that abuses this
feature will annoy users, and thereby die a quiet death."
(Marco Nelissen)
Wholesale mouse repositioning was a pretty hot issue, with
little room for compromise. But what about mouse constraint?
Should a developer be allowed to declare a rectangle that
restricts the mouse's movement? Ross A. Knepper thinks this
is antisocial...
"...remember that the user might have other things going on
at the same time. While you're constraining the mouse, the
user might be desperately trying to click cancel on the
requester that says "melt down the processor in 3 seconds"
And Trey Boudreau responded...
"Constraining the mouse motion is likely to be done ... only
while a specific set of modifiers are being held down.
Programs that do otherwise will likely be un-installed
pretty quickly."
- Subject: Shutdown message?
When the computer is shutdown, the BeOS doesn't send a
"shutdown pending" message, it simply sends a "quit
requested" to all applications. Would it be worthwhile to
send a special "shutdown" message? Most folks can't see the
harm in it; the idea is fine-tuned thus:
- Broadcast a
B_SYSTEM_SHUTDOWN to all applications and then
launch all apps [that are] in a special shutdown folder.
(Dirk Steins)
- Let individual apps (or the entire system) set an
"interaction at shutdown" level. An unattended server
machine (for example) wouldn't want any interaction.
Scott Lindsey took this last point further, applying it
interaction at any time:
"...there's nothing special about user interaction on quit.
It's not reasonable to define an alternative message for
every message type that might interact with the user. Seems
to me there's two ways of handling it. Either build an
interaction level into the messaging system, or attach an
optional parameter to the message (where the absence of the
parameter is the same as full interaction)."
Jon Watte modified the idea to fit the "save changes"
situation:
"I would prefer a boolean [message field] named 'saving'
that tells you whether to save changes or not... The cool
thing is that a scripting language might use the same
[field] to quit just one application:
tell SomeApp quit saving:true"
And Osma Ahvenlampi suggested a couple more fields:
"Okay, I suggest two modifiers for all standard system
messages:
'unattended':bool -- don't pop up any dialogs,
take the default action.
'force':bool -- message demands immediate action"
- Subject: Using
RefsReceived
Some BMessage thoughts, concentrating on 'what ' types. Is 32
bits enough to encode a message's 'what ' constant? Marco
Nelissen wishes that the 'what ' field were 64 bits, thus
making vendor /what encoding simple. Should developers adopt
a separate 'owner ' field convention? As suggested by Wendell
Beckwith:
"We simply need to define a convention that all foreign
messages (i.e. messages traveling outside of your app's
address space) contain a int32 named 'owner' and then add
your own data to it. Be could fix the BMessage constructor
to automatically do this and define a default 'owner' field
to be 0/-1 or whatever. This would indicate that the message
was generated by an unknown entity."
But what about forwarded messages? Is the original sender
always the owner, or should it be the app that last touched
the message?
- Subject: Control locking
This discussion about provable programs concentrated on what
happens when a (non-virtual) function is invoked on an
invalid object, where "invalid" can mean deleted or reused.
The practical answer: BLooper 's Lock() function doesn't
throw an exception when invoked on a NULL pointer. The
theoretical question (does it make sense to strive for
provability?) faded away without resolution.
- Subject:
dynamic_cast
Is it possible to "cross cast" an object, changing its
flavor from one branch of a multiple inheritance to another
branch? For example, should this excerpt, submitted by Marco
Nelissen, do anything other than what it does do, which is
crash:
class MyButton: public BButton, public MyBase;
MyBase *thing=new MyButton();
...
dynamic_cast<MyBase*>((BButton*)thing);
According to Jon Watte, it should, indeed, crash. This foils
Mr. Nelissen's attempt to create a varargs function that
does its own casting of its semi-anonymous arguments. The
desired casting can't be done because the function doesn't
know the exact class of the argument.
- Subject: text/weird, and other strange mime types
Olaf Seibert was seeing odd file types when he noticed that
the problem stemmed from a confusion between app signatures
and an app's file type/supported types. Mr. Seibert's
testimony was seconded by other listeners; it seems that
many folks regularly (or, worse, irregularly) experience
messed-up file types. The answer? Check with us next week.
- Subject: BeOS "face"
Customizable user interface talk. Nothing much new, here,
except for this observation by Jeff A. Campbell:
"As a support tech, I KNOW how hard it can be to talk a user
over the phone through a process and not know where
everything is. I personally want as customizable an
interface as humanly possible, but I also want this: The
ability to switch back to a non-editable 'interface' with
VERY little effort, and no restart."
|