Issue 3-16, April 22, 1998

Be Engineering Insights: A BView In An Add-on

By Cyril Meurillon

A few months ago, I wrote an article on how to export C++ code from an add-on ("Writing add-ons in C++", www.be.com/aboutbe/benewsletter/Issue102.html#Insight). The article described the fundamental issues of name mangling and object instantiation. There was also some sample code, but it was fairly abstract. With this article, I'd like to show you some code that's a more practical demonstration of C++ add-ons.

The code I'll be playing with is a modified version of HelloWorld (/optional/sample-code/HelloWorld on the Release 3 CD). I won't show the entire project here—we'll just be looking at the modifications—so you may want to open up the status quo project on your local machine.

In our modified HelloWorld, the app's BView object (HelloView) is loaded from an add-on file (which we'll call HelloViewAddon). Because the HelloView code lives in an add-on, we don't need the HelloView.cpp and HelloView.h files, so they're removed from the project. The only change we make in the remaining code (i.e. in HelloApplication.cpp/.h and HelloWindow.cpp/.h) is to change the HelloWindow constructor so that it loads the add-on and instantiates the HelloView object:

#include <stdio.h>
#include <image.h>
#include <Application.h>
#include "HelloWindow.h"

const char AddonName[] = "HelloViewAddon";

// name of the routine exported from the add-on that
// instantiates an object of our BView class
const char InstantiatorName[] = "instantiate_view";

HelloWindow::HelloWindow(BRect frame)
             : BWindow(frame, "Hello", B_TITLED_WINDOW,
                       B_NOT_RESIZABLE | B_NOT_ZOOMABLE )
{
  BView     *aView;
  image_id  add_on_id;

  // notice the prototype of the view instantiation
  // function
  BView    *(*instantiate)(BRect, const char *);

  // set up a rectangle
  BRect aRect( Bounds() );

  // load the add-on.
  add_on_id = load_add_on(AddonName);
  if (add_on_id  <= 0) {
    printf("cannot load addon\n");
    return;
  }

  // get a pointer to the instantiation routine
  // in the add-on
  if (get_image_symbol(aid, InstantiatorName,
        B_SYMBOL_TYPE_ANY, &instantiate) != B_OK) {
    printf("cannot find function in add-on\n");
    return;
  }

  // invoke the instantiation routine to create a new view
  aView = (*instantiate)(aRect, "HelloView");

  // add the view to the window
  AddChild(aView);
}

bool HelloWindow::QuitRequested()
{
  be_app->PostMessage(B_QUIT_REQUESTED);
  return(true);
}

The add-on consists of its own project that contains the HelloView.cpp/.h files, somewhat modified, that we removed from the HelloWorld project. HelloView draws a line of text but it doesn't respond to user actions, so we only have to rewrite the Draw() function.

#include "HelloView.h"

// the text to draw
static const char  gText[] = "Hello";

// The constructor simply sets up the font drawing
// environment.
HelloView::HelloView(BRect bounds, const char *name)
  : BView(bounds, name, B_FOLLOW_ALL, B_WILL_DRAW)
{
  SetFont(be_bold_font);
  SetFontSize(24);
}

// The destructor does not do anything
HelloView::~HelloView()
{
}

// The Draw function draws the text. For that it has to
// get some font information and position the pen
// appropriately.
void HelloView::Draw(BRect)
{
  BRect       bounds = Bounds();
  BFont       font;
  font_height fheight;
  edge_info   eInfo;
  BPoint      loc;

  GetFontHeight(&fheight);
  GetFont(&font);
  font.GetEdges(gText, 1, &eInfo);
  loc.x = bounds.left + (2 - eInfo.left);
  loc.y = bounds.bottom - (1 + fheight.descent);
  MovePenTo(loc);
  DrawString(gText);
}

// The instantiation function returns a new HelloView
// object. It has to be exported and unmangled, as described
// in the previous article.

extern "C" __declspec(dllexport) HelloView *
instantiate_view(BRect bounds, const char *name);

HelloView *
instantiate_view(BRect bounds, const char *name)
{
  return new HelloView(bounds, name);
}

Here's HelloView.h:

#ifndef _HELLO_VIEW_H
#define _HELLO_VIEW_H

#include <BeBuild.h>
#include <InterfaceDefs.h>
#include <View.h>

class HelloView : public BView
{

public:
    HelloView(BRect bounds, const char *name);
virtual ~HelloView();

virtual void Draw(BRect bounds);
};

#endif /* _HELLO_VIEW_H */

Don't forget:

This simple example shows how to make a program modular and extendible. Instead of loading a fixed add-on, the application could look in a directory for all available add-ons. Almost anything can be imported as an add-on: views, windows, menus, young Swedish women. What's important is to take care in designing the interface between your application and the add-ons that it imports.


Be Engineering Insights: Multiculturalism, Be, and You

By Andrew Kimpton

Originally, this article was written in the immediate aftermath of the BeDC. But schedules change (even at Be), so I apologize if some of the highlights of the developer conference have already receded into the mists of memory—although I hope that isn't the case.

The BeDC offered a number of opportunities for everyone involved—some obvious, some not so obvious. We all trust that you felt you benefited from the sessions, and from meeting with the Be Team and with your fellow developers.

As I stood on the stage in the closing session and looked out on all of you, I realized another part of the Be "magic." Not only do I work with a group of talented people, I also work with a *multinational* group of talented people (a French CEO, and an English VP of Marketing only begins to give the game away). Be has 15 (or so) nationalities/ethnic backgrounds represented in its work force, and, although it is a small company, it is very aware of its place in the world.

As you read this I'll have travelled to (and returned from) our Paris office, which handles our European business (and most significantly) our European developers. Do you care that I spent Easter in Paris (no probably not, and since the trip included a visit to Euro Disney in the *snow*, do not feel too envious!)? However, our small band of merry men and women in Paris (and our slightly larger band in Menlo Park) present some interesting opportunities to our developers. How so?

Right now Be conforms to previous historical examples of new operating system companies. We have a small (but loyal and growing) band of small (but very talented) developers, all of whom see the advantages and opportunities of our new operating system. However, one advantage you may have missed—perhaps because it's not technical (no brilliant soaring through the galaxy demonstrations)—is that we quite firmly grasp the opportunities, and complications, of a world market. We should do, after all, since we are from all over the world.

Christophe Droulers from Be Europe mentioned this briefly in his BeDC session, but I'm here to give it a louder airing right now: Let those of us in Be Europe help all the North American developers find markets in Europe for their products. And, since the Atlantic Ocean is a two-way street, let those of us at Be Inc. help all the European developers find markets in North America for their products.

My colleagues in Paris and the rest of us on Frank Boosman's Developer Relations staff communicate regularly, and enjoy sharing our experiences of new software from our developers. Furthermore, we enjoy demonstrating that software wherever we can, be it at a large exhibition or to a small user group.

However, our assistance can go much further than simply being demonstrators-at-large for your product. Given its small size, Be already makes use of third-party companies to assist in customer support and also distribution. In Europe SITEL performs these roles for us with a talented and Be-aware staff (who are just as multilingual as many of us at Be).

For those of you thinking about porting or creating a piece of software for the BeOS, Europe also has an enviable pool of development talent. A quick glance down the BeWare submissions list, and a glance at recent winners of the Be Masters awards, shows just how many talented individuals there are in Europe. Telecommuting is just one way to make use of such talent in far off places.

The world is a large place and I'm proud to work in a company which seems to gather a fair-sized chunk of it in a single office. It's also a large market and we can help all of you find a place in it. I hope you enjoyed the BeDC and I hope to see you and those who couldn't make it this time at the next one in the Autumn (Fall for those of you from the left-hand side of the Atlantic).


Developers' Workshop: Script the Vote!

By Stephen Beaulieu

A Yahoo Online survey became quite a topic of interest and discussion here at Be last Thursday. Our friends at Yahoo posted a survey asking readers to vote for their favorite operating system from the following choices: Windows, Mac OS, Unix, BeOS, PalmPilot, and Nintendo 64. As a company we were gratified that our OS was listed specifically, especially when other popular choices were stuffed into a generic Unix category. We were a bit puzzled, though, with the results that first appeared.

With roughly 50,000 votes cast the Mac OS was leading the pack by a large margin. The breakdown was Mac OS 62%, Unix 19%, BeOS 9%, Windows 7%, Nintendo 64 2%, and PalmPilot 0%. This seemed odd, given market realities.

On closer examination we discovered that there was no limit to the number of times that a given person or machine could vote in the poll. Yahoo had no "One Person, One Vote" security in place. In short, stuffing the ballot box was, if not legal, certainly possible.

Since the policy seemed to be "Vote Early, Vote Often," and the Mac Evangelists had more than a three-day head start in stuffing the ballot box, we decided to take drastic action. The "Script the Vote" campaign was born.

Early in the campaign we got tired of the "Tally My Vote" --> "Back Button" --> "Tally My Vote" strategy. At least, we got tired of doing this by hand. But since the BeOS in general, and NetPositive in particular, is highly scriptable, we soon gave our mouse fingers a break.

Here is the original script submitted by the engineer in charge of scripting:

"Try this script: (It's more complex than hoped because of some goofy behavior in the "Back" button of NetPositive). This assumes that the window in question is the first NP window and that the radio_button for the BeOS is already selected."

i=0
while true
do
  i=`expr $i + 1`
  echo "iteration $i"
  doo NetPositive set Value of View 6 of View 0 View 4 of
    View 1 of Window 0 to 1 > /dev/null
  sleep 6
  doo NetPositive set Value of View "back" of Window 0 to
    $i > /dev/null
  sleep 4
done

This significantly improved our voting rate, and freed our engineers to deal with other, possibly more important, issues. But it didn't seem to satisfy the more rabid ballot stuffers on staff. Further investigation revealed that the survey itself was managed through an HTTP GET request. In other words, all the voting information was contained in the URL itself. Simply scripting NetPositive to constantly hit the Reload button increased speed dramatically.

But it *still* wasn't good enough for some of us. If it was just a matter of submitting a URL, why not write a full-fledged voting application? So, while I started working on the VoteBe app, Ficus Kirkpatrick took another crack at a scripting solution. He wrote a bash script that launched multiple copies of lynx, the text-only browser, and submitted requests.

Those of you in the know might realize that there is no port of lynx for the BeOS. We must in all honesty reveal that at this stage of the game much of our voting came from five or so Linux boxes floating around the company. The same script would have worked wonders on the BeOS, if a version of lynx had been available.

At this point we were, through our various enterprises, submitting BeOS votes at a rate of 60-70 a second. Needless to say, our percentage of the pie increased greatly (just over 20% at its peak).

But all good things must end, and as is often the case, our VP of Sales and Marketing, Alex Osadzinski—ever the voice of maturity and reason at Be—was the killjoy. (Hi, Alex 8^) He noted with some unease that "Le Grand Fromage" would probably be displeased with our morning's efforts, and that perhaps our energies would be better spent elsewhere. We assented, and turned our attention to voting for Nintendo 64 (still a measly 2% of the vote at this time). This was not exactly what Alex had in mind, but nobody gets their way all the time.

So now Nintendo 64 picked up quite a bit of momentum. After an hour of voting it had about 17% of the pie. Then disaster struck: Yahoo's voting server became unresponsive. Connections had slowed down as time went on, but now we could get nothing. Fearful that we had crashed Yahoo's server, we pulled our voters away from the ballot boxes and went back to work.

An hour or so later we happened to check the site again and discovered to our surprise that others had also championed the cause of Nintendo 64. The N64 vote was at 30%, with the Mac OS down to 31%. N64 was so close to becoming the Internet OS of choice that we mobilized the voters again to push it over the top.

We did end up pushing the Nintendo 64 platform to 38%, ahead of the Mac OS, but it appears that Yahoo has adjusted their figures to compensate for our ballot stuffing. You can view the final results here:

http://features1.yahoo.com/survey/tally?Dir=survey&Tmpl=19980413.html&Id=199804 13&Count=5&MaxWidth=100&Strip=1

So, where was I during all of this? After the initial shutdown of the Yahoo server, I stopped doing real work on my VoteBe application. I had a very primitive version that submitted votes to the PoorMan server running on my BeBox. It worked. When we started up the voting again I used it for awhile, but it was never distributed to the company as a whole.

But, with my Newsletter article deadline looming, I decided that this was a fun story to tell and that, after beefing it up a bit, my voter application would make a fine bit of basic sample networking code. So, point your favorite ftp client to...

ftp://ftp.be.com/pub/samples/network_kit/VoteOften.zip

...and download this example of how to write a simple, threaded BeOS networking application. (Note that the use of this program and its derivatives should be reserved for special voting occasions. It is very uncool to use software like this to pound a server that has not asked for it. Be kind and don't try this one at home.)

On an entirely different subject, I want to remind you that Be is still looking for qualified engineers to fill many different positions. A full listing of available jobs can be found at http://www.be.com/aboutbe/jobs/index.html.

Note especially that we are still looking to fill a DTS Engineering position. As you can guess from the vote-o-rama story, this is a very serious place to work.

I'll be back in four to six weeks with more sample code. In the meantime, enjoy our regularly scheduled Developer Workshops, and look for the first article from our newest DTS Engineer, Michael Morrissey, sometime very soon.


What Do We Do, What Do We Say About Windows 98?

By Jean-Louis Gassée

A number of betas for Windows 98 have been circulating for a while. As a registered Microsoft developer, I got the Release Candidate 0 in the latest shipment of my MSDN subscription and installed it on one of my PCs in the office.

The procedure is painless and very automated. It appears to faithfully keep old Windows 95 settings and shows pleasant attention to details. For instance, the installation program asks you to restart your computer, then offers to do it for you after 15 seconds, assuming you're bored or on a coffee break.

The only glitch I encountered was that the system didn't respond to my shared (via a switchbox) keyboard and mouse when Windows 98 first started "for good" after completing the updating process. Mysteriously, the problem disappeared after I hit reset and rebooted.

Windows 98 doesn't behave very differently from Windows 95, unlike the bumpy transition one experienced when moving from 3.1 to the modern 95 version. The user interface is smoother: nice gradients on some windows' top bars, animations with menus. Perhaps more important, Windows 98 now supports multiple monitors without the need to resort to high-wire tricks, something the Macintosh has done for awhile—and something we plan to do for R5.

Does Windows 98 make a big difference? As many industry observers have already explained, one can get most of the Win98 feature set in the latest '95 service release, a few additions available on the Web, and Internet Explorer 4.0. Put another way, Windows 98 provides a nicer integration (a questionable word in some locales) of already available features. By now, the integrated browser with e-mail client and news reader is a non-event.

More interesting is the use of an Internet connection to keep your system updated. Before, one could do this by hand; now it is automated, or semi-automated. Your permission is required to inspect your system, and download and install the new and improved application and drivers.

This is nice. It is likely to make customers happy and configurations easier to maintain. It might even lower the cost of supporting these more stable configurations. This is a more gratifying aspect of Web integration than the desktop channels most Explorer 4 customers turn off or never look at. Oops, I just read in news.com, honest, Microsoft will let OEMs ship Windows 98 with the channel bar hidden.

On the Be side, if you look at BeDepot and Software Valet, you can see the implementation of a similar concept. It will be interesting to watch the large-scale Windows 98 implementation for good and bad ideas to stimulate our own thinking. Of course, the higher degree of semi-automated intimacy between Microsoft and its customers will raise questions. Is this another case of leveraging the knowledge and control of the platform into an unfair or unbreakable advantage?

Still on the topic of better integration, the Universal Serial Bus is now even more "official" than in the latest Windows 95 OSR2.1 "with USB support." USB devices have been slow to come to market, probably as a reaction to the delays with Windows 97. No one wants an unsupported product clogging the distribution channels. Hopefully, with Windows 98, USB devices will become a market reality.

This, in turn, will help us: configurations with richer I/O will be easier to put together, something we'll enjoy as we develop our specialized audio-video platform. With a little bit of luck, the broad deployment of USB will kill off the pesky ISA bus.

On the performance side, we heard Windows 98 was going to speed things up. This appears to be true: on two identical systems, Eudora, Explorer, and Outlook Express do appear to launch faster. Booting the system, on the other hand, doesn't appear to have gained anything. And when it comes to video performance, Windows 98 doesn't show much improvement when compared to Windows 95, or to the BeOS.

Running Windows and BeOS systems side by side shows the advantage we enjoy in A/V applications when capturing, mixing, and rendering several streams. It is this kind of side by side demonstration that makes the simplest case for the BeOS: a specialized OS coexisting with the general-purpose Windows, complementing it in A/V applications where its general nature and its Office Automation roots put it at a disadvantage.

At an investor meeting this week-end, one participant who saw our demonstration, stated that this was well and good but, doesn't Microsoft have a successful history of fixing their problems and catching up with the innovators? See fourteen years of Microsoft eating into the lead Apple used to enjoy with the Macintosh.

That is very much on our mind—and was when we started our company. Operating system go through life phases. They improve very quickly during their youth, they mature, get comfortable, and start aging. Depending upon their genes, their parents, they age at different speeds, with more or less grace—but they all age.

Microsoft has stated Windows 98 is the last Windows "classic." For a while, Windows NT has been positioned as the "professional" Windows for robust, enterprise applications. The party line is that the version of Windows after 98 will be a "consumer" version of NT 5.0. This is entirely possible, and it probably won't change the complementary relationship between the general-purpose Windows and the specialized BeOS.

According to Microsoft officials quoted in Information Week a few months ago, NT 5.0 sports more than 25 million lines of source code. For reference purposes, with the usual caveats associated with such comparisons, the BeOS still weighs in well below a million lines. If the NT 5.0 stats are accurate, we are more than one order of magnitude apart.

We won't do what they do best in enterprise and office automation applications. Conversely, the maturing 98 and the robust NT may not axiomatically catch up with us in a few areas where we perform rather nimbly. Of course, we realize we have much to do and much to prove in order to convert our potential advantage into a successful market reality.


BeDevTalk Summary

BeDevTalk is an unmonitored discussion group in which technical information is shared by Be developers and interested parties. In this column, we summarize some of the active threads, listed by their subject lines as they appear, verbatim, in the mail.

To subscribe to BeDevTalk, visit the mailing list page on our web site: http://www.be.com/aboutbe/mailinglists.html.

NEW

Subject: [ANN] SigWorld

AKA: Signal handlers

An initial application announcement was rescinded when it was pointed out that the implementation may not be signal-handler safe. Be should publish a list of functions that *are* handler-safe (suggests Chris Herborth). Olaf Seibert claims that...

According to the C standard, the only thing that you are allowed to do in a signal handler is change global variables of type volatile sig_atomic_t and return.

Popping up a bit, Gerardo Diaz Cuellar asked a few questions:

Q:

What's a signal?

A:

It's an asynchronous 'message' that's handled by your app through the invocation of an (app-designated) "signal handler" function.

Q:

How are signals sent to an app?

A:

Whenever your code returns from a system call, and every time the scheduler considers your thread for execution, a check is made whether there are any signals pending.

Q:

What happens if an app doesn't designate a signal handler for a particular signal?

A:

The system defines default behavior for all signals; for most signals, the default behavior is to simply kill the app.

Q:

So what sort of apps need to handle signals?

A:

In general, only apps that have "special needs." But Chris Herborth suggests that it might not be a bad idea to include signal handling as idiot protection:

Imagine a situation like this:...user has focus-follows-mouse turned on,...starts app from Terminal...bumps mouse [so it's] over Terminal [but] doesn't notice that top window doesn't have focus...whacks ^C intending for some keyboard shortcut to go off, and the program instead vanishes (due to an uncaught SIGINT...)

Mr. Herborth's suggestion launched a mini-controversy about what an app should do when handed a SIGINT. He later added this:

I'm not suggesting that 'real' BeOS applications should ignore SIGINT (or other deadly signals), I'm suggesting that they should quit gracefully

Subject: Attribute storage requirements

Chris Tate wants to know how to calculate the disk storage for a set of attributes. Dominic Giampaolo responds:

In general if your attributes are small and there aren't lots of other attributes associated with the file (i.e. besides BEOS:TYPE) then there is zero extra storage used because you attributes will wind up in the fast-attribute area. The fast attribute area is slightly over 700 bytes in size. The size needed for an attribute is the size of the name of the attribute, the size of the data and 8 bytes for overhead.

If your attributes do not fit into this fast attribute area then they will require 1 disk block for the i-node of the attribute and at least 1 more disk block for the data. At some point in the future I may store the data of an attribute in the attribute i-node if it is small enough although that's a far-off kind of thing.

And just in case anyone is thinking about it, there is not, nor will there be a way, to request that attributes go into the fast attribute area as doing that would expose too many details of the implementation of BFS in the higher level API which is a bad thing.

Mr. Tate asks: Does the 1+1 disk block business really mean (at least) 2 blocks for *each* attribute that doesn't fit in the fast area?

Dominic answers: Yes (with a concession that this isn't great, but...)

Mr. Tate asks: [Does the] attributes' indexed/non-indexed state...affect this?

Dominic answers: No.

Kenneth Flaxman asks: Aside from using extra storage, are there reasons to try not to exceed the 700 byte fast-attribute area?

Dominic answers: No. Whether an attribute uses the fast attribute area or not is _completely_ transparent to application programs. There are no other differences.

David Evans asks: Can an attribute be split between the i-node "cache" and other blocks?

Dominic answers: C'mon, I'm crazy but not _that_ crazy :-)

Subject: BeOS On FTP !!!!!! NOT GOOD!

Patrick Lantz wants to squash the OS pirates that sail the FTP seas:

If Be Inc, added a BAD Sector or a unstable 0/1 on a sector on the CD, and the installer checked for the bad Sector / Unstable Sector when installing most of the illegal copies will disapper.” [sic]

Marco Nelissen thinks the check would be futile:

...some guy with too much time on his hands would spend an hour disabling the check. Copy protection doesn't work.

Angus Mackay finds solace in disinformation:

...the solution is to covertly get someone else to do an equal crack that sometimes does something bad. 1 time in 10 nuke all the data on the disk it's being run on or something. Then people will fear the crack and only the die hard crackers will use it.

Yeah, well, uhm...okay. Oh gosh, look at the time, I really have to go.

Subject: Realtime priority idea

Chris Russo has a solution to the runaway realtime thread problem:

How about a 'Allow real-time processes?' checkbox in some control panel? Then, the user could decide whether to allow the machine to be taken over.

But, Jon Watte points out, the priority isn't the problem:

B_REAL_TIME priority is there for a reason, and if you only use it when you should, you won't hog anyone's machine. It's all these compute bound threads with high priority that slow the machine down. Even high non- real-time priorities suck away responsiveness.

Mr. Watte also pointed out a little known fact:

With the CURRENT scheduler, if a thread has a priority that is 16 or more higher than the others available, that thread will always be scheduled, and will thus in effect act like a realtime thread... This behaviour may change later. Or it may not. Stay in the 5-20 range for best effect.

Subject: Proposed UI feature request:

How about double-clicking an app icon (in Deskbar) to unhide the app's hidden windows (suggests Roberto JP)? Jon Watte thinks the current "Show All" in the Deskbar app menu is good enough (and avoids the "it's a single-click, oops, nope, it's a double-click" problem).

Same topic, different angle, from Hanan Y Jacob:

...perhaps u only want it to show the windows that were open in the current workspace... otherwise were u to open four tracker windows in four diff. workspaces then hit show-all you would be spun round through 4 workspaces which i dew find irritating.

(Actually, u don't spin round all those workspaces.)

Other feature requests:

  • a key-combo that hides the active window

  • keyboard-only file copy/move

  • visual clipboard

  • full, global keymapping

  • spring-loaded folders (ala Mac 8)

Creative Commons License
Legal Notice
This work is licensed under a Creative Commons Attribution-Non commercial-No Derivative Works 3.0 License.