|Issue 47, 17 Aug 2003
Howdy, everyone, from your friendly neighbourhood newsletter editor. If you haven't heard from me in awhile, it's because I've been working behind the scenes for awhile ever since I became editor. I'd just like to say a few things.
First of all, welcome back, Michael! Your dedication to the project through thick and even thicker is inspiring to say the least. Now get back to work! ;) I was also glad to hear of... well, you'll have to read his editorial for the gem.
Next I'd like to apologize for the missing newsletter edition. If anything could've gone wrong, it did. Mishaps and crossed schedules cancelled the last edition, and when we finally geared up for this one, out went the lights. Anyway, I hope it was worth the wait, and we should be back into the swing of things now.
Lastly, I'd like to call on the community once again. Newsletter articles are sparse nowadays, so if you've written before and would like to do a sequel, you have a new perspective on OBOS, you want to advertise your BeOS software, you have some programming wisdom to share, or you feel like making a compilation of interesting goings-on within the OBOS project like Niels does, please, drop us a line. Just think of the fame and glory you'll have with your name and writing forever immortalized in the OBOS Newsletter Archive. We also offer free digital donuts to whoever shows up.
Thanks for coming out! Enjoy...
"Replicants are like any other machine; they're a benefit or a hazard."
Many people have heard that sentence from the good old movie Blade Runner by Ridley Scott, but only BeOS-geeks actually saw the world full of replicants living their life. Sure, it's not the same: On the movie side, a replicant is a machine that looks like and acts like a human, while on the BeOS side, it's...hmm...yeah, what is it?
That's where this article comes in: What's a replicant? What do I do if I want to code one?
I - The Concept
As I said, a replicant is a BeOS unique feature which could be described as follows: "A replicant is a piece of a program that is plugged into another application." Where can I see an example? Well, everywhere: All the tiny logos in the Taskbar of your Deskbar are replicants. Net+ and SoundPlay can be dragged 'n' dropped onto the desktop, so they're replicants as well. But there are some others that are interesting to use, like some apps that can ask others to give them a certain replicant. For instance, let's say someday we have a BeOS-native Web-browser. (Yeah, I know--no comment!) To display a movie in a web page, the browser could ask the BeOS media player to give it a replicant. The media player would give the browser the view that can handle and display the movie. The same thing could work for any other app. For instance, BeHappy is an app that calls a NetPositive replicant. No need for plug-ins and things, just replicants. Moreover replicants are cheap code: Only a few lines are needed to make them happen.
II - Code, always code...
Technically, a replicant is an archivable
BView, archivable in the sense of the BeOS API (that is, it can be described by the fields of a
BArchivable for details). So here is the idea: Say you wanted a Deskbar replicant. On your app side, you pack up the
BView you want the Deskbar to use into a
BMessage. The Deskbar then calls a certain function to get the
BMessage, unpacks the
BMessage, rebuilds your
BView and adds it to its view hierarchy at the correct place. Simple. Let's see some already working code. I chose the code of Space (click to download it on BeBits) for its simplicity and clarity. Let's follow the code step by step.
Brian Matzon, the author, creates the class SpaceView, deriving from the BView class and overloading the
Instantiate() functions to make its SpaceView archivable (see the Archiving tutorial). Once this is done, he just creates a
BView *instantiate_deskbar_item() function which he doesn't forget to export with the following line:
extern "C" _EXPORT BView* instantiate_deskbar_item();.
This function will be called by the Deskbar. Indeed, if you look into our beloved BeBook, you will see that the function which adds a replicant onto the Deskbar (
AddItem()) asks for an entry_ref parameter (the other version of
AddItem() being deprecated as noted in the Annotated BeBook!).
Now that everything is in place, you just have to ask the Deskbar to add your replicant: See the
main() function. Get the entry_ref of your app and pass it to a BDeskbar object's
AddItem(). This last one will call
instantiate_deskbar_item() to get a SpaceView object which will then be archived through
Archive() into a
BMessage, which will be sent to the Deskbar to be unpacked and reconstructed with
Instantiate() , and then finally added to the Deskbar's shelf at the end of the list!
III - The traps
The track looks simple but is filled with traps which you must be careful not to fall into. Here is a list of the most important ones:
- Do not forget to add your app signature to the
BMessage archive! (Line 54 in SpaceView.cpp.) Easy to forget and needed for the process (if it lacks this, nothing will happen.)
- If you have any object to build which needs a
BApplication object, do not do it in the constructor, but instead in the
AttachedToWindow() method. Indeed, if you do it in the constructor it will fail as the object is not yet attached to the Deskbar. For instance, for Space, Brian builds there a
- Take care of the internal messages you send and where they are handled. For instance, let's say your replicant contains a BButton. Such a thing sends BMessages. If the app that you attach the replicant to understands such a message, it's fine, but if it's not, you might not get what you expected. For instance, if your BButton sends B_QUIT_REQUESTED messages, that's OK and the app will understand, but if you send MY_FANCY_ID messages, you'll have to put the code to handle such a message into your replicant because the Deskbar (or the app that you plugged your replicant into) may not handle them.
- The size of a Deskbar replicant is at max 16x16 pixels so it gets a BRect(0,0,15,15) at most.
IV - Communication
Here is a last thing I would like to tell you about, as it shows an interesting feature of BMessenger.
Let's say we are doing an app which, besides its main interface, uses a Deskbar replicant to quickly report its actions to the user. The first example that comes to my mind is a download manager. You have the main window showing you the files you are downloading and their status. A Deskbar replicant can be useful here when this main window is minimized or in another workspace: you click on it and you get a list of the downloads with the percentage of data downloaded. Neat. For this kind of use, the replicant doesn't work on its own like Space does: It needs to contact the main BApplication object to get a report of the downloads and their additional data.
Sending a message from the Deskbar replicant to a BApplication is simple, like all BeOS messaging is. You just build a BMessenger with your app's signature or team_id and away you go, sending the messages without any problem. To go the other way, from the app to the replicant, is not that simple. You have no direct way to send a BMessage to the replicant or build a BMessenger to do so. So here is the trick: BMessenger has a nice feature which I call "They work from anywhere to anywhere," and which I'm sure the coder of the OBOS BMessenger took great care to reproduce. Practically, you just have to create a method in your replicant BView which is as followed:
status_t MyReplicantView::SendMessageToMyApp(BMessage *message)
status_t error = B_OK;
BMessenger app (MY_APP_SIGNATURE,-1,&error);
if (error == B_OK)
As you can see, we build a BMessenger that points to the replicant itself. This we then add to the message we want to send. So in the app's MessageReceived() all you'll have to do is to retrieve that BMessenger and use it to send the reply:
void MyApp::MessageReceived(BMessage *message)
BMessenger *messenger = NULL;
//Add the lists of downloads and the additional data to 'answer'.
Isn't that nice?
First of all, sorry that the last issue was somewhat late. It first was a problem
with my timing (a mini-break messed up my personal schedule), and it was delayed
even more by Michael Phipps' unfortunate accident. I want to wish him the best,
and I hope he will continue his work on the vm soon! The past two weeks were
marked with somewhat less commits than in previous weeks, mainly due to vacation
period (some prominent names are missing from the statistics list).
Ingo Weinhold continued on his disk device implementation. Andrew Bachman worked
on the posix headers. Gabe Yoder did a whole bunch of GCC fixes.
| CVS statistics
||# of Changes
||Lines per Change
||% of Changed Lines
Most frequently modified file:
Most frequent committer:
|| Andrew Bachman(145)
| CVS statistics generated by cvstat
These statistics are provided purely for interested developers, and
are not intended to reflect quality or quality of work done by any
given developer in CVS, merely to show activity of operations in the
CVS repository performed by all developers. If you want to use them
to motivate yourself, that's fine, but keep in mind that a bit of
useful work is more meaningful than a lot of useless work.
Created by Juli Mallett
Bits 'n' Pieces
Stephano Ceccherini continued his efforts on the interface kit and implemented
a BScreen. On the 28th of July, he committed:
Added BScreen implementation, which uses BPrivateScreen (not yet implemented)
Darkwyrm continued his work on the app_server with improvements to the pattern
passing code. On the 28th of July:
AccelerantDriver.cpp AccelerantDriver.h BitmapDriver.cpp
BitmapDriver.h DefaultDecorator.cpp DisplayDriver.cpp
PatternHandler.cpp PicturePlayer.cpp PicturePlayer.h
RootLayer.cpp ScreenDriver.cpp ScreenDriver.h ViewDriver.cpp
Retooled pattern passing - much neater now. :)
On the 28th of July, Michael Phipps checked in the code for the new VM on a
separate branch in the repository:
area.cpp area.h areaManager.cpp areaManager.h diskBlock.cpp
diskBlock.h diskBlockManager.cpp diskBlockManager.h error.cpp
error.h hashTable.h internalList.h list.h lockedList.h mman.h
olist.h pageManager.cpp pageManager.h pool.cpp pool.h
swapFileManager.cpp swapFileManager.h vm2.h vmHeaderBlock.h
vmInterface.cpp vmInterface.h vm_arch.h
Andrew Bachman was working on his text-encoding library, and he started using
iconv for that. This led to a large discussion on how this had to be done in
the release. On the 31st of July he committed:
written to use iconv.h
Darkwyrm added some quality fonts to the repository, that will be used by our
first release. On the first of August, he added:
Directory /cvsroot/open-beos/./current/src/servers/app/server/fonts added to the repository
Michael Wilber worked on his ShowImage implementation. On the first of August,
he added a feature to save images in different formats.
ShowImageConstants.h ShowImageView.h ShowImageWindow.h
Changed Save As sub menu to only show the available destination types
for bitmap images, implemented Save As feature
Philippe Houdoin worked on his new stack. He added attributes to it, to make
it work in a more BeOS-like way. On the second of August, he added:
Start to use new buffer attributes feature.
Andrew Bachman felt like doing stuff, and he started on the Scrollbar preflet.
On the sixth of August:
added font sensitivity and resources
He also added UNIX linefeeds ('\n') to the BTextView widget:
LineBuffer.cpp LineBuffer.h StyleBuffer.h TextGapBuffer.h
He also posted a lot of updates to the Terminal and StyledEdit applications.
This has been the digestible status report for the last two weeks. As always, comments, omissions, questions, and liquor are welcome at email@example.com.
I spent a good portion of a recent (pre-accident) Saturday at Harborfest. As we were walking in, I heard the delicious strains of The Eagles classic hits. I honestly had to look at the stage to realize that it wasn't the real deal, but instead, a cover band. After a few more songs, the band took a break; in announcing the break, they pointed out that if people liked the music, there were T-shirts, CDs and hats available. As I stood in line, I thought about freedom--free software, free music, and free speech.
The word "free", in the typical sense, means "without restraint". As in "I am not in jail--I am free" or "free kittens". The part of free that interests me for the moment is "without cost". People like free. They are often suspicious of free, as it often has been used by con artists to separate people and their money, but when they realize that free is really free, they like it. They like it a lot. The question becomes, "How can I supply free stuff and still feed my family?"
Free "stuff", though, often comes with a price. Sometimes people are willing to pay that price. One example is radio. With the recent exception of XM Radio, people have "always" accepted the concept that radio stations need to advertise to pay the bills. Likewise, up until about 20-30 years ago, TV was "free" with commercials. Cable TV is a fairly new innovation. So providing the service for free with commercials is one way to make money while supplying free stuff. This model has been tried with some level of success on computers, too--Opera's browser, web sites with banner ads, and Prodigy are good examples. This methodology, though, is somewhat inelastic in much the same way that hydroelectric power is inelastic: The places in which you can place promotional materials are limited, and the more of them you use, the less valuable your product is to the general public.
The second way to be reimbursed for free stuff is through donations. This counts on the goodwill and charity of the recipients of your product (or even people who believe in your mission). PBS, GNU, and EFF are all examples of organizations that acquire funds this way. Donations can be a very positive way to measure the public's pleasure with your organization.
A third way to raise money is to sell "brand" merchandise. A jacket with the band's logo, a Linux T-shirt, or a "Think Different" mouse pad are all examples. Take a low priced item, add "branding" information and sell it at a dramatic profit margin. One thing that is interesting about this concept, from a freedom standpoint, is that it utilizes the same artificial scarcity that proponents of free intellectual property resent: trademark instead of copyright. Without that trademark protection, anyone could make that T-shirt and sell it.
The last way to bring in revenue is to sell your product. This may sound counter-intuitive when talking about free software, but it is really not. You can sell a nice package, maybe a hard cover book and a number of CDs that saves downloading time. Services (tech support, for example) or non-free software, for example, the Mac OS X GUI with the open source Darwin core, can also provide incentive to buy.
To state the obvious: Getting money involves enticing someone to give it to you. In case number one, above, advertisers are enticed to give away money in exchange for some of the limited space/time available within your product. In case number two, you provide a good or service to people and count on their appreciation. In case three, you build a brand by giving away your goods and/or services and charge people for the ability to associate themselves with you. In the final case, you are actually providing more than just the free product, so one could argue that the free product is not really bringing in the money.
As a provider of free software, OBOS needs to seriously consider the above models as ways to fund development. Furthermore, being in a pre-release state seriously limits our options. It is hard to have a brand that represents a product that doesn't quite exist for most people. Likewise, it is tough to sell a nice box that doesn't contain software. Banner ads on the web site won't really work all that well, either. That leaves us donations.
The last stage of the non-profit organization paperwork is in process right now. The New York State approval is complete. The first portion of the IRS paperwork is complete. The last stage is in progress. When it is complete, the new name can be released, the new web site revealed and donations can be accepted. That money will go directly toward finishing OBOS. My ideal would be to hire full time developers to work on it. There is certainly a glut of qualified people in the marketplace right now and good people can be found for reasonable prices. Now is the perfect time to hire people. Unfortunately, it is also the *worst* time to ask for donations.
The BeOS community has been asked many times to donate for many things. Hardware for driver writers, funds to keep web sites going and much more. I believe that people want to see OBOS finished soon. I certainly do. We all know that we cannot ask more of the volunteers that we have (how many times can we tie Axel up?) It is obvious that the BeOS community doesn't have any more developers who are willing and able to work on OBOS. That really means going outside of the community. Many open source projects hire people. From the BSDs to Gnome, there are people being paid to work on OSS projects. I think that many people want to work on projects where their work will be given away. It is just a matter of being funded.