Issue 4-9, March 3, 1999

Be Engineering Insights: NetPositive Q&A

By Scott Barta

Whenever I make an appearance on one of the Be user mailing lists, I usually get peppered with questions from the curious about NetPositive. Many of these questions have common themes, so I thought I'd answer a number of them here.

Q:

When is JavaScript going to be implemented?

A:

JavaScript support is my main project right now (aside from getting R4.1 out the door, of course). You can get a very early developer release of JavaScript- capable NetPositive right now at http://www.be.com/support/updates/r4_netpositive_3.html. The mainline browser in R4.1 will not be JavaScript-enabled, though a 3.0 developmental version will likely ship in the experimental folder on the CD.

For those who downloaded 3.0d1 and were less than impressed, a much- improved 3.0d2 is now available at the URL above. JavaScript will be shaping up over the next few months, and we'll continue to release new versions as it makes sense to do so.

Q:

How about Java?

A:

First, please understand that JavaScript has nothing at all to do with Java, despite the similarity of names. For more details, please see the ReadMe that installs with the developer release at the URL above. For Java to work in the browser, there needs to be a Java VM and AWT implementation for the BeOS; none currently exist.

We've looked into bringing Java into the fold, and at various times there has been rudimentary Java support for the BeOS, but never anything that was very useful.

Unfortunately, getting a decent Java implementation on the BeOS requires a lot of engineering resources that we don't have, so there isn't anything on the drawing board yet. A number of third parties are working on Java for the BeOS, but I don't know the exact status of any of those projects. It's my general understanding that getting the VM working isn't the hard part; the AWT and class libraries are extremely tough, especially if you're independent from Sun.

Q:

Will NetPositive allow plug-ins?

A:

NetPositive has a decreased reliance on plug-ins compared to other browsers, because a lot of the technologies that other browsers implement this way can be done with more BeOS-specific paradigms. For example, R4.1 will add PNG image support, courtesy of the Translation Kit and the new PNG add-on; and in the future, as streaming media nodes are written, the addition of Media Kit support to NetPositive will bring in those data types "for free." With that said, though, there are still a lot of situations which call for plug-ins, and I'm hoping to add plug-in support in cooperation with the folks working on Opera and BeZilla. One of my goals is to expand plug-in support beyond the simple model that Netscape and Internet Explorer use, and to allow new kinds of plug-ins to interact with the browser in new and mysterious ways.

Q:

What's up with the haiku error messages?

A:

The haiku error messages are responsible for a surprising amount of user feedback, which has been overwhelmingly (but not entirely) positive. I think it has to do with the fact that despite their fancy GUIs, computers have lately become somewhat impersonal, with their interfaces endlessly focus-grouped and graphic-designer-polished, and users are grasping at anything that adds a human touch, if a somewhat quirky one. Like many human touches, though, the haiku tend to anger some, particularly those who have seen NetPositive spectacularly fail to deal with yet another site. For that reason, and also for the non-native speakers of English, there will be a preference in R4.1 to turn the haiku off. There's a secret preference to do this in R4; see the BeOS Tip Server at http://www.birdhouse.org/beos/tips/archive/tip235.html for details.

Be warned, though—if you're expecting to get more informative error messages with the haiku turned off, you're going to be disappointed, because the messages that the haiku replace are (and always were) rather bland. There are very few kinds of errors that NetPositive displays in an error dialog, and for all of those, there is little information that NetPositive could possibly give that would be of any help. In virtually all cases, the haiku that you see replace one of two error messages, the first being "The web server www.blah.com could not be found" and the second, "The web server www.blah.com is temporarily down. Please try again later." The distinction between these two errors is important, because it will tell you if you've mistyped the hostname (unless you've mistyped the name of a popular site like www.yahoo.com, whereupon you're likely to come across one of the Net's several "adult" sites), or if the server is dead. Actually, NetPositive chooses from different sets of haiku for each type of error, and if you interpret the poem, you'll figure out what happened.

For nearly every other type of error condition, the error message you see is actually an error page that is sent back from the server which NetPositive has no control over and displays as-is regardless of the haiku setting. So, the addition of haiku does not significantly mask information that other browsers would give you; if you like them, leave them turned on.

Q:

Can you add the XYZ feature to help page designers author better pages?

A:

I think some of the flap over haiku comes from people who would like to use NetPositive to help them author web sites, and would like to get more detailed error information when something goes wrong. They think that NetPositive is ignoring error information it could be giving and is deciding to be cute instead.

The error information that page designers want would take the form of detailed, verbose error reporting from the HTTP level (which would be very helpful in diagnosing a variety of redirection and cookie problems), as well as some sort of "strict" HTML parsing mode that would reject illegal HTML with an error message.

Unfortunately, this sort of error information usually isn't available in great detail from any browser, and in most cases isn't appropriate or interesting for the general browser user. While site designers are very interested in knowing what went wrong in the delicate interaction of CGIs, redirection, caching, proxies, cookies, frames, HTML, and JavaScript that made their site not work, most users don't want to be bothered with the gory details. Since it would require so much work to implement well and would only benefit a small fraction of users, it isn't something that makes sense to do in NetPositive in the near future. It's unfortunate, though, because this is an important if small market that isn't being served well by any tools that I'm aware of.

There is one small diagnostic tool you can use, though; if you run NetPositive from the command line and give it the --dump option, it will dump the contents of all net transactions to the terminal. This isn't a supported feature of the browser, so please don't rely on its being there or write up bugs against it (particularly since it doesn't work perfectly), but you may find it useful. Also, please be aware that it will dump the data from SSL connections in the clear (though the network connection itself is still of course encrypted), so there is a slight security risk involved.

Q:

How can I tell a NetPositive window to open a URL?

A:

/boot/develop/headers/be/be_apps/NetPositive/NetPositive.h describes a set of BMessages that you can send to NetPositive windows or Replicant views to have them load URLs. You can obtain a reference to a window in a running instance of NetPositive through the normal scripting mechanisms. In the future, NetPositive will have a more complete scripting solution, but for now, this should satisfy the needs of many developers. Keep an eye on this file; it will describe any public APIs that are added to NetPositive in the future.

Q:

What is the NetPositive Replicant format?

A:

The best way to figure it out is to create a BShelf in your application, drag a NetPositive Replicant into it, and dump out the resulting archive message. If you hand-craft your own NetPositive Replicant archive, you can instantiate NetPositive Replicants in your application to do in-line HTML viewing. Since the NetPositive-specific message fields aren't documented anywhere else, here they are:

  • url (string)
    The fully-qualified URL to open.

  • encoding (int32)
    The character encoding to use; see UTF8.h for a list of constants.

  • openAsText (bool)
    true if NetPositive should open the URL as a plain text file.

  • showToolbars (bool)
    true if NetPositive should show the location field, navigation buttons, and status bar.

The other fields in the BMessage are inherited from BView; disassemble the Replicant archive to find out more.

Q:

Can I launch my own application when the user clicks a telnet:// URL?

A:

This capability will be added for R4.1. It will be done through a set of MIME types that your application may register itself as a handler of to receive notification when the user clicks on a specific type of URL. NetPositive will look for handlers for these MIME types for all kinds of URLs that it doesn't insist on handling internally; these include, telnet, news, NNTP, ftp, and more.

To help prevent user confusion, NetPositive will always handle http, file, javascript, and netpositive URLs internally (when they are clicked in NetPositive, that is) and won't defer to external handlers. In addition, if you're writing your own application that needs to deal with URLs (such as an e-mail program or word processor), you can use this mechanism to launch the appropriate external handler for a URL. See the TypeConstants.h file in the R4.1 headers for more information.

Q:

Will you implement a "WWW Kit" for developers to use in their apps?

A:

This is a frequent and very reasonable request from developers. It would be very handy if NetPositive exported its various functions into a public Kit API so developers could do things like instantiate (or subclass) a BHTMLView in their application to show HTML or allow in-place browsing, get files via HTTP, and more. Some of these can be accomplished now through the use of NetPositive Replicants, but the mechanism is clunky and the result difficult to control.

The browser components need to be worked into a stable public API for developers to be able to do these sorts of things better. While this is a long-term goal for NetPositive, there is an awful lot of heavy lifting in the architecture that needs to happen for this to work well, or at all.

This is more than a convenient excuse: NetPositive does indeed have an HTMLView class, but trust me, you don't want to try to use it the way it is now, because it is too inbred with the HTML parser and HTTP engine to be usable to anyone else. The good news is that the architectural work needed to make this a clean reality makes sense in many ways beyond a public API, so things are moving in the right direction. However, it will be a while before we'll see the "WWW Kit" in the BeOS.


Developers' Workshop: ParameterWebs and Nodes and Controls, Oh My!

By Christopher Tate

I'm sure you've all noticed a certain emphasis on the Media Kit in Developer Workshop columns over the last few months. So far we've talked a lot about nodes, but not much about how to control their behavior from the application level. Many commonplace nodes that media applications will deal with on a regular basis have various parameters that can be adjusted at run time. This week I'll show you how to present a user interface for dynamically controlling a node.

But...before you run off to try the techniques I'll demonstrate here, I must warn you that like so many of our new Media Kit tools, today's code will only work under Release 4.1, not under Release 4. Feel free to follow along at home, though, and as soon as you get your hands on Release 4.1 you can see the glorious results in living color!

Right—the code. You can find the ParameterSample application right here:

ftp://ftp.be.com/pub/samples/media_kit/ParameterSample.zip

This little application displays a pair of windows. One is a duplicate of the Audio preferences panel's Mixer tab, and the other contains a single slider control for adjusting the master gain of the system mixer. All the controls are "live"; adjusting the sliders while sounds are playing adjusts the volume in real time. And the secret to all this live instrumentation is the magic of BParameters.

What a Tangled Web We Weave

Any Media Kit node that has an adjustable configuration can express that configuration in terms of BParameters, objects which each describe a single variable parameter. The set of all BParameters that a node supports is called its "parameter web," and (sensibly enough) is published via a class called BParameterWeb. Each BControllable node in the system has exactly one BParameterWeb; if a node is not configurable, its BParameterWeb will contain no BParameters. You can see whether a given node is controllable by checking (media_node::kind & B_CONTROLLABLE), which will be non-zero if the node is controllable.

The BParameterWeb is not simply a list of BParameters. Because some parameters are linked -- for example, the gain and mute controls for a particular audio channel -- the BParameterWeb class uses a hierarchical organization in which BParameters are contained by BParameterGroups, which themselves can contain other BParameterGroups; the end result is rather like an organization of files into a directory structure. This organization of parameters into groups is intended as a "hint" to the user interface to guide the presentation of related parameters.

Ready-Made User Interface: Media Themes

The Media Kit also supports standardized presentations of media-related controls. This ensures that all media-related instrumentation the user sees will have a consistent look and feel. The Kit uses an object called a BMediaTheme to manage the creation of appropriate BControl objects for configuring nodes. The design of BMediaThemes is a topic for the future; for today, we'll just use the default theme to get the controls for our node.

Oh—our node? That's true, we need to pick a node to control, preferably one that does something noticeable. The ParameterSample app manipulates the global system mixer's node, just like the Audio preferences panel.

BParameters the Easy Way

The easiest way to present a UI for a node's parameter web is to ask a BMediaTheme to build one for you. This is the approach implemented in the EasySampleWin class. Let's look at the relevant code, all of which is in the window's constructor.

media_node mixerNode;
BMediaRoster* roster = BMediaRoster::Roster();
roster->GetAudioMixer(&mixerNode);
roster->GetParameterWebFor(mixerNode, &mParamWeb);

This is straightforward: We look up the global BMediaRoster object, ask it for a reference to the global system mixer's node, then get a copy of the node's BParameterWeb.

BMediaTheme* theme = BMediaTheme::PreferredTheme();
BView* paramView = theme->ViewFor(mParamWeb);
AddChild(paramView);

That's it! We ask for the preferred theme, then request a BView from the BMediaTheme that can manage the full BParameterWeb. Once this view is added to the window, your application needn't do anything with it -- all messages and parameter updating are handled internally to the BView. As a user, you'll see that this window contains a clone of the Audio preferences panel's mixer controls. This is because—surprise!—the Audio preferences panel uses exactly this technique to build its BViews.

Finer Control—the Hard Way

But what if you don't want to instrument the entire BParameterWeb? What if you only want to present a UI for a single BParameter? Well, life gets a bit more complex in that case. Instead of creating a BView to handle a single parameter, a BMediaTheme will create a single BControl. The responsibility for handling that BControl's placement belongs to your application. More significantly, handling that control's *semantics* is also the app's responsibility—the app must respond to and interpret the BControl's messages, and change the BParameter's value in response to those messages.

The HarderSampleWin class displays a window containing just the master gain slider. Let's look at the differences from the easy case. The constructor begins the same way, by looking up the mixer's BParameterWeb, but then things get complicated:

int32 numParams = mParamWeb->CountParameters();
BParameter* param = NULL;
for (int32 i = 0; i < numParams; i++) {
  BParameter* p = mParamWeb->ParameterAt(i);
  if (!strcmp(p->Kind(), B_MASTER_GAIN)) {
    param = p;
    break;
  }
}

if (param->Type() == BParameter::B_CONTINUOUS_PARAMETER) {
  mGainParam = dynamic_cast<BContinuousParameter*>(param);
}

This searches the BParameterWeb for a specific BParameter; in this case, the master gain parameter. This is easy because there is only one such parameter in the mixer's web. If you're looking for a particular BParameter from a given parameter web, there are other mechanisms you can use to locate the one you're interested in, such as looking at BParameter::ID() and matching that against the source or destination ID supplied with your connection to the node.

Note the dynamic_cast. In general, you won't know the derived type of the BParameter that the web returns to you. The BParameter::Type() method gives you the information you need to determine which derived class the object really is, and, therefore, how to manipulate it. Our example is simplified by knowing that the system mixer's master gain control is always a BContinuousParameter, but it would be a straightforward matter to write code to handle any of the BParameter subclasses appropriately.

Once we've found the right BParameter, we need a control that is appropriate for manipulating it:

BMediaTheme* theme = BMediaTheme::PreferredTheme();
BControl* control = theme->MakeControlFor(mGainParam);
mGainControl = dynamic_cast<BMultiChannelControl*>(control);
mGainControl->SetMessage(new BMessage(gControlMessage));

That gives us the control, and ensures that its value-changed messages have a known "what" code for our message handler to recognize. Note that the control is of type BMultiChannelControl. This class is new in R4.1. As its name suggests, it provides an interface for controlling arbitrarily many "channels" of data from within a single BControl. In our case, it will hold two channels of data, because the system mixer is stereo. Controls derived from BContinuousParameter will generally be derived from either BSlider or BMultiChannelControl—a general-purpose application will need to be able to handle all possibilities—but for purposes of the example we assume that the control is a BMultiChannelControl, because the system mixer is stereo.

Now, before we're done constructing the view, a little math:

float paramMin = mGainParam->MinValue();
float paramMax = mGainParam->MaxValue();
int32 controlMin, controlMax;
mGainControl->GetLimitsFor(0, &controlMin, &controlMax);
mScale = (paramMax - paramMin) / (controlMax - controlMin);
mOffset = paramMax - mScale * controlMax;

The BControl's range and the BParameter's are not necessarily the same, but they *are* guaranteed to map linearly. This formula is the result of a little linear algebra that lets us express the parameter's min and max values as a linear function of the control's min and max values.

That's it for setting up the window; the rest of the magic happens in the window's MessageReceived() method. When the slider is moved, the window receives messages with our designated "what" code indicating the new value of all channels of data managed by that BMultiChannelControl. The channel values are passed in an array of int32s called be:channel_value. If the parameter is single-valued, then there may only be the standard BControl data, under the name be:value. A well-behaved application should be prepared to handle either case:

int32 chan1, chan2;
status_t err =
  msg->FindInt32("be:channel_value", 0, &chan1);

if (!err)
  err = msg->FindInt32("be:channel_value", 1, &chan2);
else {
  err = msg->FindInt32("be:value", &chan1);
  chan2 = chan1;
}

Next, we use the scaling factors that we calculated earlier to transform the slider's values to the BParameter's expected range. BParameters take floating point values, by the way!

float chanData[2];
chanData[0] = mScale * chan1 + mOffset;
chanData[1] = mScale * chan2 + mOffset;

Finally, we're ready to set the parameter's new value. Like so many other things in the Media Kit, setting a BParameter's value takes a performance time at which to apply the change. We want the change to be immediate, so we look up the current time according to the node's time source, and set the parameter:

BTimeSource* timeSource;
BMediaRoster* roster = BMediaRoster::Roster();
timeSource = roster->MakeTimeSourceFor(mParamWeb->Node());
bigtime_t now = timeSource->Now();
mGainParam->SetValue(&chanData, sizeof(chanData), now);

Voilà! An active, effective slider controlling the master system gain without benefit of the Audio preferences panel!

What Now?

Well, okay, it's not the world's most practical application (although a pop-up Replicant to tweak the master volume would be pretty handy), but of course it's just a convenient controllable node to illustrate the principles. Other nodes that media applications will find themselves presenting interfaces for with may include video compression, audio devices including multichannel cards, video capture, and so forth. Now as soon as you get Release 4.1 you'll be all set to build the UI of everyone's dreams!

There's more that could be done with these implementations, too. Neither one of them watches the BParameterWeb to see if it changes, and so the dynamic updates that you see in the Audio preferences panel won't appear in these sample windows. Also, none of these views are "aware" of parameter value changes that are made in other views—so if you adjust the master gain in the Audio preferences panel, you won't see the sliders move in the sample windows. Perhaps a future Developer Workshop will address these additional features...


Is the Customer King?

By Jean-Louis Gassée

One would hope to answer this question in the affirmative, but before I elaborate, some follow-up to last week's column, "A Crack in the Wall," along with our thanks.

Our offer of free copies of the BeOS to OEMs willing to load our OS "at the factory," on the hard disk of PCs they sell, got a tremendous response. We appreciate the interest in our product and we intend to do our best to honor the hospitality extended to us. Watch this space or, more generally, www.be.com, for more details. For a number of contractual reasons, this offer applies only in the US and Canada, not to other countries in the Americas or in Asia. For Europe, please contact our VP Europe, Jean Calmon, jcalmon@beeurope.com, for country-by- country details.

As we collect data from the flow of responses, an interesting but not unexpected picture emerges. The OEMs expressing interest are the ones who cannot realistically be "fined" by Microsoft—that is, lose their Windows rebate. If you pay the maximum OEM price for Windows, or close to it, you won't be afraid to load Linux or the BeOS on your customers' hard drives, especially if you don't have to account to Wall Street for your actions.

If, on the other hand, your exposure is measured in millions of dollars per quarter, and you are the CEO of a publicly traded company, you'll load Windows and nothing but Windows on the PCs you sell. More precisely, you might load Linux as the OS engine on hardware other than PC servers. In any event, this represents only a preliminary look at the returns -- it's too early to draw definite conclusions.

Now, let's turn to the customer in the title of this column. We hear that the Windows monopoly is good for customers—it's a standard, there's no confusion, users can rely on a trusted foundation for their work, and so on. But how can this be if there are so many obstacles placed in the way of a customer's even seeing that (s)he has some (limited) choices?

I'll take one example of what I mean by choices. One overseas OEM announced with great fanfare that it would offer some configurations in its PC line with a dual-boot arrangement: Windows 98 for mainstream applications and the BeOS for its natural media uses. Great—exactly what we wanted—the specialized media OS peacefully coexisting with the mainstream platform.

Well, not exactly. If you take the machine out of the box and boot it, the BeOS is nowhere to be seen—the computer boots only Windows 98. If you read the documentation carefully, you'll find out how to "unhide" the BeOS. Then, through a complicated sequence, you'll finally get to the dual-boot situation. Should the OEM be criticized for this state of affairs? Again, not exactly. It appears that the fear of losing Windows rebates intervened to prevent the customer from being offered a genuine dual-boot system. In fact, as we verified for ourselves, the steps the customer must perform are so complicated that it's much easier just to do the simple partition and BeOS installation possible with our retail product, complete with a BeOS Launcher icon on the Windows desktop.

Wouldn't one think that Microsoft behaves, in effect, as if the PC belonged to it, rather than to the OEM or to the customer? It's is hard to see how the customer and, more generally, the industry, benefit if one company decides what's good for all, and what the customer should see or not see.

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