Table of Contents
Be Team at PC EXPO 1998
Be will be demonstrating the BeOS in our brand new exhibit booth. Come check it out! Where:
For more information see: http://www.pcexpo.com/
BE ENGINEERING INSIGHTS: Writing A Sound Card Driver A number of people have expressed interest in writing sound card drivers for BeOS. This article describes the interface used by the current audio server to communicate with sound card drivers. Note that this interface is for the current audio server, and that the current audio server will be replaced with something better in a future release. But if you want to write a sound card driver and test it with the current audio server, this is what you will have to support. These are the ioctl codes used by the audio server: #include <Drivers.h> enum { SOUND_GET_PARAMS = B_DEVICE_OP_CODES_END, SOUND_SET_PARAMS, SOUND_SET_PLAYBACK_COMPLETION_SEM, SOUND_SET_CAPTURE_COMPLETION_SEM, SOUND_RESERVED_1, /* unused */ SOUND_RESERVED_2, /* unused */ SOUND_DEBUG_ON, /* unused */ SOUND_DEBUG_OFF, /* unused */ SOUND_WRITE_BUFFER, SOUND_READ_BUFFER, SOUND_LOCK_FOR_DMA }; The
The typedef struct audio_buffer_header { int32 buffer_number; int32 subscriber_count; bigtime_t time; int32 reserved_1; int32 reserved_2; int32 reserved_3; int32 reserved_4; } audio_buffer_header; The audio data immediately follows the audio_buffer_header in memory and is in stereo signed 16-bit linear native-endian format. The size in bytes of the audio data plus the audio_buffer_header is stored in the "reserved_1" slot of the audio_buffer_header (the audio server was written before the size argument to the ioctl call was implemented). The size and address of the audio data can be derived this way: audio_buffer_header* header = (audio_buffer_header*) ioctl_arg; int32 bytes_of_data = header->reserved_1 - sizeof(*header); int16* addr_of_data = (int16*) (header + 1); The driver can ignore the "buffer_number" and "subscriber_count" slots of the buffer header and should store an estimate of the system_time() corresponding to the beginning of the buffer in the "time" slot of the buffer header. The The The enum adc_source { line = 0, cd, mic, loopback }; enum sample_rate { kHz_8_0 = 0, kHz_5_51, kHz_16_0, kHz_11_025, kHz_27_42, kHz_18_9, kHz_32_0, kHz_22_05, kHz_37_8 = 9, kHz_44_1 = 11, kHz_48_0, kHz_33_075, kHz_9_6, kHz_6_62 }; enum sample_format {}; /* obsolete */ struct channel { enum adc_source adc_source; /* adc input source */ char adc_gain; /* 0..15 adc gain, in 1.5 dB steps */ char mic_gain_enable; /* non-zero enables 20 dB MIC input gain */ char cd_mix_gain; /* 0..31 cd mix to output gain in -1.5dB steps */ char cd_mix_mute; /* non-zero mutes cd mix */ char aux2_mix_gain; /* unused */ char aux2_mix_mute; /* unused */ char line_mix_gain; /* 0..31 line mix to output gain in -1.5dB steps */ char line_mix_mute; /* non-zero mutes line mix */ char dac_attn; /* 0..61 dac attenuation, in -1.5 dB steps */ char dac_mute; /* non-zero mutes dac output */ }; typedef struct sound_setup { struct channel left; /* left channel setup */ struct channel right; /* right channel setup */ enum sample_rate sample_rate; /* sample rate */ enum sample_format playback_format; /* ignore (always 16bit-linear) */ enum sample_format capture_format; /* ignore (always 16bit-linear) */ char dither_enable; /* non-zero enables dither on 16 => 8 bit */ char mic_attn; /* 0..64 mic input level */ char mic_enable; /* non-zero enables mic input */ char output_boost; /* ignore (always on) */ char highpass_enable; /* ignore (always on) */ char mono_gain; /* 0..64 mono speaker gain */ char mono_mute; /* non-zero mutes speaker */ } sound_setup; On PPC systems the "mic_attn" and "mic_enable" parameters are used to control the amount of adc to dac "loopback" instead of the microphone input level. The The audio server opens the driver named "/dev/old/sound". So when you have implemented these ioctl calls and you want to test your driver with the audio server, you can either name it "/dev/old/sound" or name it something like "/dev/old/mydriver" and create a symbolic link in your UserBootscript file: ln -s /dev/old/mydriver /dev/old/sound The "old" in this path name is to remind you that this is an interface which will be deprecated in the future.
DEVELOPERS' WORKSHOP: DynaDraw, Part Two "Developers' Workshop" is a new weekly feature that provides answers to our developers' questions. Each week, a Be technical support or documentation professional will choose a question (or two) sent in by an actual developer and provide an answer. We've created a new section on our web site. Please send us your Newsletter topic suggestions by visiting the web site at: http://www.be.com/developers/suggestion_box.html.
In the previous article on DynaDraw, we built a no-frills app -- a basic window and a view, and our drawing algorithm. In this article, we get to the fun part -- adding lots of controls which modify how the calligraphy strokes are drawn. Download the code from: ftp://ftp.be.com/pub/samples/interface_kit/obsolete/dynadraw2.zip, compile it, and see how the new features work before getting into the details of this article. I especially dig wireframe mode, which calls StrokePolygon instead of FillPolygon. Let's start out the way we did last time, looking at what we'd like to do, and what we'll need to do it: First, we'd like a menu bar across the top of the window. Under it, we'll put two menus: "File" and "Controls". Under File, we'll have the items "About", which brings up an About Box, and Quit, which, well, quits. Under "Controls", we'll have three items: "Tweakables", which brings up a panel for controlling the mass, drag, and other parameters; "Color", which allows us to change the color of the pen; and "Clear Screen", which clears our drawing. The Tweakables panel and the Color panel will each have
their own windows. R3 introduces a new window type,
The next question is: which object should be responsible for managing these control windows? It's possible to add these duties to the DDWindow class, but if our application grows to include more windows, this approach will be cumbersome. A better solution is to subclass BApplication in an object which manages the creation and destruction of the control windows. Here's our object list now:
Messaging Good object layout is half the battle, and the other half is good messaging. The heart of this entire application lies in the MessageReceived() functions in each of the classes listed above. Reading those functions will tell you what duties those objects perform, so let's go over them now. Our application object handles ColorWin has only one specific message to deal with:
case COLOR_CHG: /* get the current color settings, */ /* attach to the message */ /* and pass it along to the handler */ rgb_color clr = cc->ValueAsColor(); swatch->SetViewColor(clr); swatch->Invalidate(); msg->AddInt16("red", clr.red); msg->AddInt16("green", clr.green); msg->AddInt16("blue", clr.blue); handler->PostMessage(msg); break; So our message is really getting double-duty: it serves as a command from the BColorControl object to ColorWin indicating a color change, and it serves as a message (with the RGB value as data) from ColorWin to DDWindow. TweakWin's M TweakWin also generates fill = new BCheckBox(BRect(25,320,135,340), "fill", "Wireframe", new BMessage(FILL_CHG)); fill->SetTarget(handler); /* send FILL_CHG directly to handler */ SetTarget() is a function defined in BInvoker, which is a subclass of BCheckBox. This technique is also used in the menus of DDWindow. Since
we want BMenu* menu = new BMenu("File"); menu->AddItem(new BMenuItem("About", new BMessage(B_ABOUT_REQUESTED))); menu->AddItem(new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED))); /* Both the About and Quit messages should be directed to be_app */ menu->SetTargetForItems(be_app); mb->AddItem(menu); In the Controls menu, although we want menu = new BMenu("Controls"); BMenuItem* tmpItem = new BMenuItem("Tweakables", new BMessage(TWEAK_REQ)); tmpItem->SetTarget(be_app); menu->AddItem(tmpItem); tmpItem = new BMenuItem("Color", new BMessage(COLOR_REQ)); tmpItem->SetTarget(be_app); menu->AddItem(tmpItem); menu->AddSeparatorItem(); menu->AddItem(new BMenuItem("Clear Screen", new BMessage(CLEAR_SCREEN))); /* Target not specified for Clear, so the target will be DDWindow */ mb->AddItem(menu); AddChild(mb); Notice that in case COLOR_CHG: int16 red, green, blue; msg->FindInt16("red", &red); msg->FindInt16("green", &green); msg->FindInt16("blue", &blue); SetHighColor(red,green,blue); break;
BSliders R3 introduces the BSlider class, an incredibly useful control device. It's really flexible too, allowing you to customize the look of the thumb, the tick marks, the track, and more. Since BSlider only deals with integers, you may need to do some small tricks to get the value you want, such as setting up a slider with a range of values between 0 and 100, and using this as a percentage of your maximum value. This is what we're doing with Mass, Drag, and Width. Also, BSliders are set up to have the left hand side be the minimum value, and the right hand side as the maximum value. Sometimes this isn't what you want to do: in the case of "Sleepage", it seemed more natural to me to "sleep less" towards the right of the control, and "sleep more" towards the left. In this case, just set the slider up to go from your minimum
to your maximum, and when reading that value, subtract it
>from your maximum, and add that value to your minimum. In
the sleep case, I set up the slider to go from 3000
microseconds to 30000 microseconds, and then (in
Future Enhancements This program can be extended in a variety of ways, and I encourage you to do so. Some small projects might include letting the user control the background color of the FilterView, and dynamic updating of the color swatch. Larger projects include saving the drawing to disk, printing, and letting the user undo brush strokes. Experiment and enjoy!
You're Contradicting Yourself!We've "heard" this on e-mail and from newsgroups. We're likely to hear it again at PC Expo, so I thought I'd take a few minutes to clarify our position. The contradiction astute observers point out is this: On the one hand we present ourselves as a media OS, a specialized platform for audio and video applications. We sometimes use the "A/V Linux" sound byte -- and then proceed to show off "non-A/V" applications on our site and, soon, at our booth. Come on, they say, you're really trying to be a general purpose OS -- you're competing with Microsoft, you just don't want to admit it! Let's address the "non-A/V" applications first. We believe the "tractor apps" will come from the field of audio and video activities -- editing, synthesizing, producing, and mangling digital media. However, this belief doesn't imply that the BeOS can't or shouldn't be put to other uses. Imagine for a moment that you're a software developer and all you care about is word processing. Your mother said you shouldn't, but you do, either to aggravate her or just because it's in your soul. Let's further assume you want to make money at it, presumably to show dear old mom who's right. Are you going to try writing a Windows word processor? Of course not. Microsoft Office is the monarch and you'll never impress your mother. On the BeOS though, the adventure might look risky, but not suicidal. And you can allay family scepticism by telling them about the advantages of Electronic Software Distribution (ESD) and how BeDepot.com is for software authors without knee pads. "Non-A/V" applications for BeOS have another advantage: users will be happier with their BeOS system, even if their primary use is the "official" media driven one. They still want word processing and e-mail. Further, imagine a page layout program on the BeOS. It's likely to be livelier, faster, more reactive, and more available to the user than its venerable elders are on the Mac or Windows now. The better feel of the program, its real-time WYSIWYG behavior comes from the programmer, of course. But it also makes a good case for what the BeOS platform has to offer: a good combination of multithreading and -- on the right hardware -- multiprocessing, fast graphics, and good APIs. But, keen observers will insist, this makes you a general-purpose OS, non? Therefore, you're competing with Microsoft and, therefore, you're dead -- you just don't realize it yet. Ah, but this is sophistry. Yes, computers are programmable, in fact they can all be simulated by a simple Turing machine. As a result, all hardware and all system software can do anything. All true enough, if we don't consider how much time, aggravation, or money is involved. So, in the general-purpose office productivity field, I don't believe anyone can beat Microsoft for the time being. Windows, with or without Internet Explorer, Office, Money... your everyday needs are well covered and OEM relationships are such that no new entrants can survive. But, if Windows can "do" audio and video, it doesn't do it very well. And Windows 98 shows little sign of anything but marginal improvements on what Windows 95 offered. That's where we complement Windows, and the fact that Be developers offer a broader range of applications doesn't make us a competitor to Microsoft Office. In other words, just as Windows can "do" audio and video but doesn't shine there, we can "do" more than A/V, but that's not where we will win. So, our priority continues to be the A/V domain, where we are most useful. And, when we like a page layout program or an e-mail client on the BeOS, that sentiment doesn't change the nature of our platform.
BeDevTalk SummaryBeDevTalk is a discussion group that's a forum for the exchange of technical information, suggestions, questions, mythology, and suspicions. In this column, we summarize some of the active threads, listed by their subject lines as they appear, verbatim, in the group. To subscribe to BeDevTalk, visit the mailing list page on our Web site: http://www.be.com/aboutbe/mailinglists.html
Subject:BLooper/multiple inheritance: is this a bug? AK A:BLooper and multiple inheritance?? Multiple inheritance questions: Q:Given... class C : public A, public B {...} ...why does the A destructor not get called when a C object is deleted? A:Most likely because the A destructor probably isn't declared virtual. The same problem holds for single inheritance: If you use a base class pointer (A) to point to a derived instance (C) and then delete A, the C destructor will only be called if the A destructor is virtual. (And note that virtual destructor declaration is inherited; if 'virtual ~A();' then the destructors of all classes that inherit from A will be virtual.)
Q:What's the trick to getting the "diamond" problem (D derives from B and C; B and C both derive from A) to compile properly? A. B and C derivation (from A) must be virtual: class B : virtual public A { ... } class C : virtual public A { ... } Otherwise, D will end up with two A instances.
Subject:BTextControl cannot be made uneditable Wendell Beckwith has noticed that you can't set a BTextControl's text view object to be uneditable until after the control has been added to its window. In other words, this is no good: control->TextView()->MakeEditable(false); window->AddChild(control); /* The text view is still edible. */ Why should this be? Peter Potrebic suggests that instead of setting the text view's editable state, you should simply set the control to be disabled. But, responded Mr. Beckwith, disabling the control affects the control's label (it turns gray). Why should the two states (text editability and label appearance) be tied together?
Subject:Shared libs on Intel From Sander Stoks, a question and a plea: "I searched the FAQ, searched BeGeek.com, tried everything. How does one make (use of) a shared lib on R3/Intel? [And] _please_ don't tell me that I will have to add __declspec() stuff to all that code..." Jon Watte responded to Mr. Stoks question, but couldn't satisfy the no-declspec request: "The easiest fix is to have a file Exports.h which __declspec()-s all your classes, and include this file first in each and every one of your header files. You also need to __declspec(dllimport) the same entities that you previously exported when you get around to using the shared library. Also, you need to include the init_term_dyn.o file among your libraries for static initialization to happen correctly." Chris Herborth seconded the spirit of Mr. Stoks' letter: "Just fix the damn development tools. >}:-( There should be NO DIFFERENCE when building an app/library/shared library for BeOS, whether you're on PowerPC or x86." There was a groundswell of support for the position, which is, in essence, that Be should concentrate more on the performance, robustness, and portability of the development tools. Fred Fish gave a reasoned response to the escalating criticism: "Although I'm not thrilled about the current tools situation with all the 'windows cruft', I've learned to hold my nose and just get on with work... I'm still hoping that someday we will have the opportunity to either hide this stuff better or dump it entirely. Whether that point is months from now or a few years down the road, I think it will eventually happen." So how should Be go about "transitioning" to new tools? Wendell Beckwith says drop the hammer: "If Be ... should redraw the line for backwards compatibility and adopt a single object/executable file format that works across all of their architectures, then I believe the users/developers would rather bite the bullet now than wait until later when Be software is more numerous and doing something like this will be much harder to pull off." The thread concentrated, thereafter, on itchy symbol exportation/library inclusion details. For more info on the topic, see "Project Libraries" and "Building a Library" in http://www.be.com/documentation/rel_notes/R3DevLayout.html
Subject:Wizards Does the BeOS have any "Wizard" API? (According to Mark B. Elrod, a Wizard is a "dialog which guides you through a process...It is most often used for installers and things that need to gather info.") You can, of course, build a Wizard-like UI yourself from windows, textviews, buttons and bows. But should there be a specialized panel class that knows how to draw and apply back/forward labels to successive "slides"? Factotum Jon Watte rushed out and wrote one, damn it: ftp://ftp.b500.com/pub/BeOS/wizard.zip
Subject:What happened to the inherited keyword? It's dead. But, as Jon Watte pointed out: "You can use templates for the same effect. Or just make the rule that every class...should have a private typedef of inherited: "Making it private means it won't clash with further subclasses of MyClass."class MyClass : public BView { public: private: typedef BView inherited; };
1997 Be Newsletters | 1995 & 1996 Be Newsletters Copyright ©1998 Be, Inc. Be is a registered trademark, and BeOS, BeBox, BeWare, GeekPort, the Be logo and the BeOS logo are trademarks of Be, Inc. All other trademarks mentioned are the property of their respective owners. Comments about this site? Please write us at webmaster@be.com. |