Table of Contents
BE EUROPE: CeBIT '99 Be Europe will be exhibiting at the CeBIT '99 show in Hannover, Germany from March 18 through March 24 1999 <http://www.messe.de/cb99/index_e.html>. To give you an idea of the size of this event, there were 7,508 exhibitors and 678,560 visitors in 1998 from all over the world. At the 40-50 sqm (15x30 ft.) booth we will obviously demonstrate the latest release of the BeOS, but this is also a great opportunity to show off your applications. This can be done in several ways:
Whatever your choice is, please contact Christophe Droulers <droulers@beeurope.com> for further details about this event. BeDC: Programming the Media Kit This spring we will be hosting a Be Developer Conference devoted to the new Media Kit. Developers wishing to attend should be versed in the basics of programming the BeOS; there will be no introductory sessions. The conference will be held April 9th and 10th at the Crowne Plaza Cabana Hotel in Palo Alto, California. Look for announcements soon about session topics and registration procedures.
BE ENGINEERING INSIGHTS: An Amusing Diversion, or How to Make Magnify Suck Up even More CPU Cycles By Robert Chin - rudeboy@be.com
A while ago we received a bug report that included scanned-in polaroids of an engineer's BIOS screen and serial card. Pretty twisted -- but we had fun using Magnify to examine the pictures. The only problem was that the image that Magnify showed was pixelated. The solution: Magnify filter add-ons. This article shows you how to add add-on functionality to Magnify. It should also work as a tutorial for adding similar functionality to your own app. Add-on recognition is simple to incorporate, and it's a great way to extend, or have others extend, the functionality of an application. To follow this article, open the sample source for Magnify and copy and paste. Note that all of the image-manipulation work is done in the add-ons themselves; Magnify just calls the add-on's functions to process the image. We start by adding a couple of global variables to the app.
The variables point to the filter's entry point function
( void (*gFilterFunc)(BBitmap*); image_id gAddOnImageID; We initialize the variables in the TWindow::TWindow(int32 pixelCount) : BWindow( BRect(0,0,0,0), "Magnify", B_TITLED_WINDOW, B_OUTLINE_RESIZE) { gFilterFunc = 0; gAddOnImageID = 0; ... } We also create a global function that examines Magnify's add-on directory (a subdirectory of the default add-on directory). We create a menu item for each file we find (each file is assumed to be a Magnify filter): static void AddFilters(BMenu *menu) { BPath path; find_directory (B_USER_ADDONS_DIRECTORY, &path); path.Append ("Magnify"); BDirectory dir(path.Path()); // only add the rest of the menu if filters exist if (dir.CountEntries() <= 0) return; menu->AddSeparatorItem(); BMessage* msg = new BMessage('filt'); msg->AddString("filter", "disable"); BMenuItem* menuItem = new BMenuItem("Disable Current Filter", msg); menu->AddItem(menuItem); int32 index=1; entry_ref ref; while (true) { status_t err = dir.GetNextRef(&ref); if (err == B_ENTRY_NOT_FOUND) break; else { msg = new BMessage('filt'); msg->AddString("filter", ref.name); menuItem = new BMenuItem(ref.name, msg); menu->AddItem(menuItem); index++; } } }
void TInfoView::AddMenu() { fMenu = new TMenu(dynamic_cast When the user selects a filter from the menu,
void TWindow::MessageReceived(BMessage* m) { ... case 'filt': LoadFilter(m); break; ... } In void TWindow::LoadFilter(BMessage* m) { char* fname; m->FindString("filter", (const char**)&fname); if (fname) { if (strcmp(fname, "disable") == 0) { gFilterFunc = 0; gAddOnImageID = 0; return; } // unload the previous add-on, free its memory, etc. if (gFilterFunc) unload_add_on(gAddOnImageID); BPath path; find_directory (B_USER_ADDONS_DIRECTORY, &path, true); path.Append ("Magnify"); path.Append(fname); // load the add-on gAddOnImageID = load_add_on(path.Path()); if (gAddOnImageID < 0) { printf("ERROR: can't load addon\n"); return; } // get the filter function symbol int result = get_image_symbol(gAddOnImageID, "filter", B_SYMBOL_TYPE_TEXT,(void**)&gFilterFunc); if (result < 0) { printf("ERROR: can't get image symbol\n"); return; } } } The filter code is now loaded, and bool TOSMagnify::CreateImage(BPoint mouseLoc, bool force) { ... if (gFilterFunc) (*gFilterFunc)(fBitmap); DrawBitmap(fBitmap, srcRect, destRect); ... } What would add-on support be without some sample add-ons. Here is some sample source for a couple filters (thanks to Victor Tsou for coming up with this idea and creating both of these filters). This first filter (continuously) rotates the Magnify image. #include <math.h> #include <stdio.h> #include <Bitmap.h> extern "C" _EXPORT void filter(BBitmap* image); BRect bounds; uint32 *bits = NULL; int *xcosT, *xsinT; int frame = 30; #define max(a,b) (((a)>(b))?(a):(b)) #define PI 3.14159265 #define SCALE 1 void filter(BBitmap* image) { frame = (system_time() / 200000) % 360; if (bits && (bounds != image->Bounds())) { delete bits; bits = NULL; delete xcosT; xcosT = NULL; delete xsinT; xsinT = NULL; } if (!bits) { int32 m; bounds = image->Bounds(); bits = new uint32[(image->BytesPerRow() / 4) * (bounds.Height() + 1)]; m = max((int32)bounds.Width(), (int32)bounds.Height()); xcosT = new int[m]; xsinT = new int[m]; } // prepare for 27.5 fixed point float sinT = 32*sin(frame*PI/180*SCALE), cosT = 32*cos(frame*PI/180*SCALE); int center_x = image->BytesPerRow()/8, center_y = (int32)bounds.Height()/2; int shiftx = (int)(-center_x*cosT - center_y*sinT + center_x*32), shifty = (int)(center_x*sinT - center_y*cosT + center_y*32); int newx, newy; int32 *dest_int32 = (int32 *)bits, *bitmap_bits_int32 = (int32*)image->Bits(); int width = image->BytesPerRow() / 4, height = (int)image->Bounds().Height() + 1; for (int z=((width > height)?width:height)-1;z>-1;z--) { xcosT[z] = (int)(z*cosT); xsinT[z] = (int)(z*sinT); } for (int y=0;y<height;y++) { int ysinT = (int)(y*sinT), ycosT = (int)(y*cosT); int basex = ysinT + shiftx + (3*width << 5), basey = ycosT + shifty + (3*height << 5); for (int x=0;x The second filter makes the image wave. Just build and run it, the visual is better than a description. #include <math.h> #include <stdio.h> #include <Bitmap.h> extern "C" _EXPORT void filter(BBitmap* image); BRect bounds; uchar *tbits; int32 bpr; #define PI 3.14159265 void filter(BBitmap* image) { int32 w, h, x, y; uchar *bits; int32 bpp; int frame = (system_time() / 20000) % 360; if (tbits && ((bounds != image->Bounds()) || (bpr != image->BytesPerRow()))) { delete tbits; tbits = NULL; } if (!tbits) { bounds = image->Bounds(); tbits = new uchar[image->BytesPerRow()]; bpr = image->BytesPerRow(); } w = (int32)bounds.Width() + 1; h = (int32)bounds.Height() + 1; bits = (uchar *)image->Bits(); switch (image->ColorSpace()) { case B_RGB32 : case B_RGB32_BIG : bpp = 4; break; case B_RGB16 : case B_RGB16_BIG : case B_RGB15 : case B_RGB15_BIG : bpp = 2; break; case B_CMAP8 : bpp = 1; break; default : printf("Unknown color space (%x)\n", image->ColorSpace()); return; } for (y=0;y<h;y++) { int32 delta = (int32) (30 * sin((10 * frame + y) * PI/180) + 15 * sin(( 7 * frame + 3 * y) * PI/180)); uchar *s; s = bits + y * image->BytesPerRow(); if (delta < 0) { delta = -delta; memcpy(tbits, s, bpp * delta); memcpy(s, s + bpp * delta, bpp * (w - delta)); memcpy(s + bpp * (w - delta), tbits, bpp * delta); } else if (delta > 0) { memcpy(tbits, s, bpp * (w - delta)); memcpy(s, s + bpp * (w - delta), bpp * delta); memcpy(s + bpp * delta, tbits, bpp * (w - delta)); } } } To build these filters, create a BeIDE " What's next? How about combining filters and adding a game to Magnify. BE ENGINEERING INSIGHTS: Useful Applications of BeOS Scripting By Jeff Bush - jeff@be.com
Contrary to its name, BeOS message scripting doesn't refer to a scripting language such a Perl or Awk. BeOS scripting is a format for passing messages between applications. Your programs already support scripting as many classes in the Interface Kit have it built in. The really interesting aspect of scripting is that applications can inter-operate without necessarily having to be specially designed to work together. The sample app, Thesaurus demonstrates this principle. You can download it from here: <ftp://ftp.be.com/pub/samples/application_kit/Thesaurus.zip>Thesaurus lets you scan through text that's displayed by some other application, and replace words with their synonyms. Ok, it's not totally useful (unless you're writing a college paper maybe!), but it is mildly entertaining, and the code could easily be adapted to work as a spelling checker or similar application. The synonyms are taken from a file that's included in the optional/goodies folder on the R4 CD. The basic operation of this application is relatively
simple. One problem I ran into was how to find out which application
Thesaurus should talk to. An easy way to do it was to allow
the user to drag an icon onto the app. The message that is
dragged is just bogus. When the view in question receives
it, it won't know how to handle it and will reply with
Thesaurus --app StyledEdit --window 0 --view text The meat and potatoes of Thesaurus is in the
BMessage textRequestMessage(B_GET_PROPERTY); textRequestMessage.AddSpecifier("Text", fTextBufferOffset, TEXT_BUFFER_SIZE); fTextViewMessenger.SendMessage(&textRequestMessage, &reply); if (reply.FindString("result", &text) == B_OK) strncpy(fTextBuffer, text, TEXT_BUFFER_SIZE); That's it. Replacing the targeted word is almost as easy. In
this case, we change the verb to // Erase the word that is going to be replaced BMessage reply; BMessage textDelMessage(B_SET_PROPERTY); textDelMessage.AddSpecifier("Text", fCurrentWordOffset, fCurrentWord.Length()); fTextViewMessenger.SendMessage(&textDelMessage, &reply); // Now insert the new word beginning at the same location BMessage textSetMessage(B_SET_PROPERTY); textSetMessage.AddString("data", newWord); textSetMessage.AddSpecifier("Text", fCurrentWordOffset, strlen(newWord)); fTextViewMessenger.SendMessage(&textSetMessage, &reply); The Luckily, the text view also has a property called
There's quite a bit of room for improvement in this
application: You could modify it to work within a selection
by getting the selection property from the text view before
starting, or improve the UTF8 support ( I hope this gets your creative juices flowing in thinking of ways to make applications more scriptable. The scripting mechanism is still evolving, so if you have ideas for new properties or suites, you can submit requests using the bug database. DEVELOPERS' WORKSHOP: A Stitch in MIME By Eric Shepherd - sheppy@be.com "Developers' Workshop" is a weekly feature that provides
answers to our developers' questions, or topic requests.
To submit a question, visit
<http://www.be.com/developers/suggestion_box.html>.
Sometimes when you're writing an application that reads data
files, it makes a difference what type of data the file
contains. The BeOS uses MIME types to describe the type of
data contained in files. For example, ASCII text files are
type text/plain, and HTML files are text/html. Sometimes applications try to read these files but the type
information isn't correct. The most common case of this
occurs when a file has been archived using the "tar"
utility, then unarchived. This utility doesn't preserve
attributes such as the file's type, so the file is untyped. If an application is trying to read the file and interpret
its contents, this can complicate matters. For example, a
web server application (such as, say, the PoorMan web server
that comes with the BeOS) needs to be able to tell the web
browser receiving a file what type of file it is. Here's some code that looks up the MIME type of a file whose
name is given by filename: This code just uses the You could write code to look at the file's extension and/or
contents and figure out what type of data it contains, but
this isn't an optimal solution because your application
shouldn't have to be aware of every possible type of data
the file might contain. The BeOS provides a function, Here's an altered version of the example code that uses
This version, if Let's look at update_mime_info() in more depth. Here's the
prototype: The path argument indicates the pathname of the file to
update. The recursive argument indicates that if pathname indicates
a directory, whether or not the entire directory tree at
that point should be traversed, updating every file in the
tree. If this value is 1, the tree is traversed recursively;
if it's 0, only the indicated file is updated. To ask If the force argument is 1, files are updated even if they
already have type information specified. If it's 0, files
with types assigned already are skipped. If you haven't guessed already, this one function does at
least 50% of the work of the mimeset utility. Most of the
other 50% of the work is done by This may be helpful if you run into situations in which your
application is trying to read files and is being confused by
nonexistent type information.
On April 9 and 10, we'll hold our next Be Developer
Conference in Palo Alto. Last year, the event spotlighted
the first release of the BeOS for Intel-based PCs. This year
we're on to our third Intel-based release (or fourth or
fifth, depending on how you count 3.1, 3.2, 4.0 and the
upcoming 4.1) and, indeed, we'll be happy to chat about the
progress we've made in our UI, the kernel, the file system,
etc. But at the April conference we're going to focus on the
Media Kit, one of Release 4's most notable additions to the
BeOS. Given our Media OS banner, and our plans for a media-rich
future for the Be commonwealth, this topic is clearly rich
enough for several Developer Conferences. Using the Media
Kit, and using it well, is essential to apps that want to be
fast and flexible. So, does this mean Be is only interested in Media Kit-based
applications? I'll just summarize earlier statements made in
this space: Media applications are the ones that are most
likely to help distinguish the BeOS from its venerable
elders. But drawn by media, BeOS users need to be delighted
enough with our "everyday" apps -- e-mail, Web browsing,
word processing, spreadsheet -- that they'll find no reason
to leave. Prior to the April BeDC we'll promote the BeOS Media Kit at
events such as the NAMM Music Market in Los Angeles, January
28-31, the Frankfurt Musikmesse, March 3-7, and the CeBIT
show in Hannover, March 18-24. Tim Self and his team expect
a number of announcements for these events; these
announcements will provide good technical (and business)
cases, which we'll use to encourage more developers to
embrace our technology. In June we're off to PC Expo. Last year was the first time
Be took part in a PC-centric trade show. This year we'll
return with a proof of the concept that we demonstrated in
1998. This represents a lot of work -- but this is fun work,
and it's paying off. The Release 4 sales results so far are
a gentle but firm tug that indicates traction: Distributors
are paying their bills and ordering more. This motivates all
of us for the next milestones and we all look forward to a
fun and productive BeDC.
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. |