Issue 5-7, February 16, 2000

Be Engineering Insights: B_MULTIPLE_LAUNCH and the Command Line

By Jean-Baptiste Queru

Think about it: the day before the newsletter comes out, you get an e-mail that says, "Please write an article, I need it last week." There's only one solution—write about what I'm currently doing. OK, I exaggerate. Michelle isn't the slave driver I've depicted her as, and I'm actually happy to write an article. Also, the article isn't about what I'm doing right now, but about something I did last week.

There's a small detail in the application kit that's a useful feature but also something that you often have to work around—the "single launch" launch mode.

When you try to launch a second copy of a B_SINGLE_LAUNCH application that's already running, constructing the BApplication object for the second copy fails, and the first copy gets notified (see your favorite BeBook for details on that notification mechanism). The problem is that the second copy you try to launch gets terminated instantly, which can be annoying if you launched it from a shell script (or, for that matter, any environment where the termination of an application and/or its return code has a meaning, such as a makefile or a perforce command (check perforce at http://www.perforce.com/ they have a BeOS client).

There's a reasonably easy solution that doesn't involve using a separate binary (Hi, Pavel!), but detects that another copy is already running, sends this other copy a message, and waits for a synchronous reply. Here's a code snippet that shows how to do it:

#include <Application.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

class App:public BApplication {
public:
    App(status_t*);
    void ArgvReceived(int32,char**);
    void MessageReceived(BMessage*);
};

App::App(status_t*r)
    :BApplication("application/x-vnd.be.mul2",r) {}

int32 DoSomething(const char*c) {
    return 2*strtol(c,NULL,0);
}

void App::ArgvReceived(int32 argc,char**argv) {
    if (IsLaunching()) {
        printf("%ld\n",DoSomething(argv[1]));
        Quit();
    }
}

void App::MessageReceived(BMessage*m) {
    switch(m->what) {
        case ' mul' : {
            BMessage r;
            r.AddInt32("result",
                    DoSomething(m->FindString("data")));
            m->SendReply(&r);
        }
        default : {
            BApplication::MessageReceived(m);
            break;
        }
    }
}

int main(int argc, char** argv) {
    status_t ret;
    App app(&ret);
    if (ret==B_ALREADY_RUNNING) {
        if (argc>1) {
            BMessenger msgr("application/x-vnd.be.mul2");
            BMessage m(' mul');
            BMessage r;
            m.AddString("data",argv[1]);
            msgr.SendMessage(&m,&r);
            printf("%ld\n",r.FindInt32("result"));
        }
    } else {
        app.Run();
    }
    exit(0);
}

The core of this technique is to check whether there's already another app with the same signature. The best way is to try to create a BApplication, and check whether it fails. That avoids a number of race conditions. When it fails, get a BMessenger to the existing application and use it to communicate with the application that's already running.


Developers' Workshop: Previewing Audio Files

By Todd Thomas

Here's a quick little sample code ditty about bending a BFilePanel to suit your (I hope not evil) needs. We've covered this subject in past articles, but never in combination with (drum roll, please) The Game Kit!

Get the thrilling sample code for this article at <ftp://ftp.be.com/pub/samples/game_kit/SndFilePanel.zip>.

I've tried to comment the source extensively, but feel free to e-mail me if you have any questions.

Submitted for your approval is the SndFilePanel class, which lets you peruse your file system for sound files as well as preview them, using the super-easy BFileGameSound class. BFileGameSound is the ticket if you need to play a sound file quickly and painlessly. I've also provided a simple BApplication-based test harness to let you try out SndFilePanel.

Class SndFilePanel is mostly a standard derivation of BFilePanel. I've mixed in BHandler via multiple inheritance so I can implement MessageReceived(). In MessageReceived, I handle events generated by the BButton added to the file panel to allow playing and stopping the BFileGameSound. For more info on fiddling with BFilePanel derivatives, consult Developers' Workshop: Translation Kit Part 1: File Panel Fun.

Using BFileGameSound is easy, as I hope you can see from the source. A BFileGameSound instance is created in SndFilePanel::SelectionChanged(), upon finding a suitable file to preview. Playing and stopping the sound is handled in response to the appropriate message in SndFilePanel::MessageReceived(). For more info on using BFileGameSound, consult Be Engineering Insights: Farewell BSound and BSoundFile (All Hail BGameSound and BMediaFile)


An Exemplary Appliance Application

By Jean-Louis Gassée

This is the column I wanted to write before we went to Palm Springs for Demo 2000. Demo is an industry conference with the theme of "more demo, less talk." This could be a reaction to the talking heads and PowerPoint slides of other venues, or it may be just marketing 101: distinguish yourself from the pack. In any event, we were allotted eight minutes of fame to demonstrate four appliances. Two of them, the Clipper and the WebPad, are in imminent danger of shipping in the short term. The other two, the music center and the touch pad kitchen appliance, represent the more distant future. Our eight minutes stretched to ten, as the producers must have foreseen, but the audience didn't object to the overtime and rewarded us with warm applause. I should mention that a major theme of the conference was the emergence of appliances, evidence that the Internet is no longer viewed solely through the lens of the PC.

That was last week. This week, I'll sketch out a home entertainment application developed by Steve Sakoman, one of our founders, for his family's use. It begins with a DSL connection and a wireless home network based on Proxim devices. Using a 2.4 GHz carrier, one gets a wireless Ethernet at 1.6 Mbits/s. One PC on the network acts as a dedicated device, taking tracks from CDs to make a compilation of 5,000 songs stored as MP3 files. Then, any client on the network, wireless in this case, can stream songs from the server, anywhere in the house. This sounds fairly simple and in fact it is. The reward is music on demand -- no more fiddling with CDs or losing them.

One interesting point is that you can do this with PCs and only PCs on the network, or you can do it without any PC at all. You could do it with WebPads and Clippers, or a mixture of both, and be able to browse the Web to your heart's content, do your e-mail, while playing your favorite songs or downloading new ones. In other words, this isn't an either/or situation.

I won't play the "peaceful coexistence" song again but the question of whether a PC or an appliance better suits your needs has only one clear, unambiguous answer: it depends. It depends who's using it and for what. The PC offers the charm of "everything on it" generality, with the attending burdens of complexity and fragility. The appliance does fewer things, but in a better, simpler, more agile, and often less expensive way. These days, when I see a receiver on the shelves at Fry's, I imagine the next generation model, with an Ethernet connector in the back and a small touch screen in front.