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> classApp
:publicBApplication
{ public:App
(status_t*); voidArgvReceived
(int32,char**); voidMessageReceived
(BMessage
*); };App
::App
(status_t*r
) :BApplication
("application/x-vnd.be.mul2",r
) {} int32DoSomething
(const char*c
) { return 2*strtol(c
,NULL
,0); } voidApp
::ArgvReceived
(int32argc
,char**argv
) { if (IsLaunching()
) { printf("%ld\n",DoSomething
(argv
[1]));Quit()
; } } voidApp
::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(intargc
, char**argv
) { status_tret
;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.
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)
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.