Table of Contents
Be Developer Classified are an opportunity for Be developers
to tell each other about projects they're working on, are
thinking about working on, or would like to work on. Here's
your chance to request assistance on a project, or make your
talents known to other projects.
For more information, check out the Classified Ads section
in the Registered Be Developer area.
Service Available: BeOS Programmer for Contract Work BeOS programmer with shipping applications seeks contract work starting early July. Experienced professional OOP programmer (ex-Apple employee with C++, Unix, Java, SmallTalk and extensive debugging skills), including experience porting between platforms. Be Masters Award (honorable mention). Recent work includes scanner drivers written to the SCSI-2 CAM interface. Information on Crawford Software Consulting and resume is available at: http://www.scruznet.com/~crawford/crawford.html Contact Michael Crawford at crawford@scruznet.com.
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 about PCExpo, see: http://www.pcexpo.com/
BE ENGINEERING INSIGHTS: Getting Mounted By Robert Polic Mounting a volume under the BeOS requires identifying and
passing three parameters to the The second parameter is the mount point -- the location that the newly mounted volume will be referenced from (typically this is at root level but in theory can be anywhere). The last parameter is the device driver used to access the volume. NOTE: I lied, there are actually *six* parameters defined
for the Device drivers for accessing volumes come in two flavors: physical and logical. A physical driver allows complete and total access to all blocks on the device. A physical driver can only be used to mount a device that does not contain a partition map or has multiple sessions. A logical driver allows only indirect access to a range of blocks on the device and is used for mounting individual partitions and sessions. Physical (raw) drivers are installed by the system at boot time for all recognizable devices. To look for and install raw drivers for devices after boot, there are two "rescan" drivers, /dev/disk/scsi/rescan and /dev/disk/ide/rescan... if ((dev = open("/dev/disk/ide/rescan",0)) >=0) { ioctl(dev, B_SCSI_SCAN_FOR_DEVICES); close(dev); } Logical drivers are constructed by creating a new device and using an ioctl to set the range of accessible blocks... char path[256]; char tmp[256]; int32 dev; partition_info partition; strncpy(tmp, DEVICE_PATH, strlen(DEVICE_PATH) - strlen("/raw")); sprintf(path, "%s/%d_%d", tmp, session, partition); if ((dev = create(path, 0666)) >= 0) { partition.offset = offset; /* offset from start of physical device in bytes */ partition.size = size; /* length of partition in bytes */ partition.logical_block_size = block_size; /* physical block size*/ partition.session = session; /* session ID */ partition.partition = partition; /* partition ID */ strcpy(partition.device, DEVICE_PATH); ioctl(dev, B_SET_PARTITION, &partition); close(dev); } else { // error creating logical device } The BeOS comes with a number of add-ons to help determine session offsets, what type of partition map, if any, and what types of file systems exist on a device. These add-ons are located in the /boot/beos/system/add-ons/drive_setup/ directory. To use these add-ons, you first need to determine if the device is a CD. To do this, use the B_GET_GEOMETRY ioctl call and test against B_CD... bool is_cd; int32 dev; device_geometry geometry; if ((dev = open(DEVICE_PATH, 0)) >= 0) { if (ioctl(dev, B_GET_GEOMETRY, &geometry) == B_NO_ERROR) { is_cd = (geometry.device_type == B_CD); } else { // media not loaded } close(dev); } else { // error accessing device } If the device is indeed a CD, use the session add-on to locate the offset, length, and type of each session... #define DS_SESSION_ADDONS "drive_setup/session/" #define DS_GET_NTH_SESSION "ds_get_nth_session" typedef struct { uint64 offset; /* in device blocks */ uint64 blocks; /* number of blocks in session */ bool data; /* true: data session, session */ } session_data; bool have_session = false; int32 block_size; int32 dev; int32 index = 0; BDirectory dir; BEntry entry; BPath path; device_geometry geometry; image_id image; session_data session; status_t (*ds_get_nth_session)(int32, int32, int32, session_data*); if (ioctl(dev, B_GET_GEOMETRY, &geometry) == B_NO_ERROR) { block_size = geometry.bytes_per_sector; find_directory(B_BEOS_ADDONS_DIRECTORY, &path); dir.SetTo(path.Path()); dir.FindEntry(DS_SESSION_ADDONS, &entry); dir.SetTo(&entry); if (dir.InitCheck() == B_NO_ERROR) { dir.Rewind(); while (!have_session) { /* try loading the next add-on */ if (dir.GetNextEntry(&entry) >= 0) { entry.GetPath(&path); if ((image = load_add_on(path.Path())) >= 0) { if (get_image_symbol(image, DS_GET_NTH_SESSION, B_SYMBOL_TYPE_TEXT, &ds_get_nth_session) >= 0) { have_session = true; while ((*ds_get_nth_session)(dev, index, block_size, session) == B_NO_ERROR) { ... index++; } } unload_add_on(image); } } else break; } } } If the device is not a CD or for each session of a multi-session CD, use the partition add-ons to determine if there is a partition map and, if so, the offset and length for each individual partition... The file system add-ons are used to determine the type of file system a partition, session or raw device was initialized with...#define DS_PARTITION_ID "ds_partition_id" #define DS_PARTITION_MAP "ds_get_nth_map" typedef struct { char partition_name[B_FILE_NAME_LENGTH]; char partition_type[B_FILE_NAME_LENGTH]; char file_system_short_name[B_FILE_NAME_LENGTH]; char file_system_long_name[B_FILE_NAME_LENGTH]; char volume_name[B_FILE_NAME_LENGTH]; char mounted_at[B_FILE_NAME_LENGTH]; uint32 logical_block_size; uint64 offset; /* in logical blocks from start of session */ uint64 blocks; /* in logical blocks */ bool hidden; /* non-file system partition */ bool reserved1; uint32 reserved2; } partition_data; bool have_map = false; bool (*ds_partition_id)(uchar *, int32); uchar *block; int32 index = 0; BDirectory dir; BEntry add_on; BEntry entry; BPath path; image_id image; partition_data partition; status_t (*ds_get_nth_map)(int32, uchar*, uint64, int32, int32, partition_data*); block = (uchar *)malloc(block_size); lseek(dev, session->offset * block_size, 0); if (read(dev, block, block_size) == block_size) { find_directory(B_BEOS_ADDONS_DIRECTORY, &path); dir.SetTo(path.Path()); dir.FindEntry(DS_PART_ADDONS, &entry); dir.SetTo(&entry); if (dir.InitCheck() == B_NO_ERROR) { dir.Rewind(); while (!have_map) { /* try loading the next add-on */ if (dir.GetNextEntry(&add_on) >= 0) { add_on.GetPath(&path); if ((image = load_add_on(path.Path())) >= 0) { if (get_image_symbol(image, DS_PARTITION_ID, B_SYMBOL_TYPE_TEXT, &ds_partition_id) >= 0) { /* add-on recognize this map? */ if ((*ds_partition_id)(block, block_size)) { have_map = true; if (get_image_symbol(image, DS_PARTITION_MAP, B_SYMBOL_TYPE_TEXT, &ds_get_nth_map) >= 0) { /* gather info about each partition */ while ((*ds_get_nth_map)(dev, block, session->offset, fBlockSize, index, &partition) == B_NO_ERROR) { ... index++; } } } } } unload_add_on(image); } else break; } } free(block); } #define DS_FS_ADDONS "drive_setup/fs/" #define DS_FS_ID "ds_fs_id" bool (*ds_fs_id)(partition_data*, int32, uint64, int32); bool have_fs = FALSE; BDirectory dir; BEntry entry; BPath path; image_id image; find_directory(B_BEOS_ADDONS_DIRECTORY, &path); dir.SetTo(path.Path()); dir.FindEntry(DS_FS_ADDONS, &entry); dir.SetTo(&entry); if (dir.InitCheck() == B_NO_ERROR) { dir.Rewind(); while (!have_fs) { /* try loading next add-on */ if (dir.GetNextEntry(&entry) >= 0) { entry.GetPath(&path); if ((image = load_add_on(path.Path())) >= 0) { if (get_image_symbol(image, DS_FS_ID, B_SYMBOL_TYPE_TEXT, &ds_fs_id) = 0) { /* add-on recognize this file system? */ if ((*ds_fs_id)(partition, dev, session->offset, block_size)) { ... have_fs = TRUE; } } unload_add_on(image); } } else break; } } If the file system was successfully identified by the add-on, the file_system_short_name, file_system_long_name and volume_name fields of the partition_data structure will be filled in with the correct values. The volume name can be used to create the mount point and the file_system_short_name is used for the mount function... char mount_point[B_FILE_NAME_LENGTH]; char tmp[B_FILE_NAME_LENGTH]; int32 index = 1; int32 loop; BDirectory directory; /* if there is no volume name, use a default */ if (!strlen(partition.volume_name)) sprintf(tmp, "/disk"); else { /* create mount point at root */ sprintf(tmp, "/%s", partition.volume_name); /* convert any forward slashes to ':' */ for (loop = 1; loop < strlen(partition.volume_name); loop++) if (tmp[loop] == '/') tmp[loop] = ':'; } } /* make sure name is unique or if not unique, */ /* make sure existing directory is empty */ strcpy(mount_point, tmp); while (1) { if (mkdir(mount_point, 0777) >= 0) break; directory.SetTo(mount_point); if ((!directory.InitCheck()) && (!directory.CountEntries())) break; sprintf(mount_point, "%s%d", tmp, index++); } /* try mounting */ if (mount(partition.file_system_short_name, mount_point, device_path, 0, NULL, 0) < 0) { /* error mounting device */ }
DEVELOPERS' WORKSHOP: MIDI Masterpieces By Doug Fulton "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/developers_test/suggestion_box.html.
Q: Having just read a book on baroque counterpoint I'm now ready to create masterpieces (in MIDI format) that are indistinguishable from those of Bach, Handel, and Cannabich (my favorite!). However, I can't play a musical instrument and I'm not that great at reading music, either. Can I create MIDI files by typing them in? -- Dick "Really Scary Spice" Wagner, Bayreuth, Germany A. Well, Dick, you've dropped in at the right moment. I just popped a little MIDI-generating language out of the oven. Mmmmm, smell the aroma of copy-and-paste composition churned out by tone-deaf hobbyists whose musical education ended right after they learned that tritones sound really creepy. Before we go any further, let's do some weeding. If you don't need to generate MIDI, or if you'd rather use a GUI to enter data, leave the room. Or just skip down to the final paragraph where we pay our respects to one of the creators of the Headspace General MIDI synthesizer. For the rest of you, you'll soon be generating chromatic scales as easily as... Xchannel(1); Xvoice(B_BANJO); for (int i = 0; i < 12; i++ ) { Xnote(c4+1, 1.0, 0.5, 0.0); Xinc(1.0); } Talk about fun. How about this: Xchannel(1); Xvoice(B_OBOE); Xnote(c5, 4.0, 0.5, 0.0); // play a note XskewA(0.0); // start a pitch bend trajectory XampA(1.0); // start an amplitude trajectory Xinc(4.0); // wait for beats XskewZ(-1.0); // stop the pitch bend trajectory XampZ(0.0); // stop the amplitude trajectory This generates an oboe tone on c5 (the c above middle c), and then, over the next four beats (seconds, by default) bends the note down to bf4 and fades the note out. One more; this produces a cloud of swirly metal for about 20 seconds: Xvoice(B_REVERSE_CYMBAL); for (int i = 0; i < 100; i++) { Xabs(1.5); Xinc((rand()%100)/5.0); Xnote((rand()%30)+40, (rand()%100)/40.0+.2, ((rand()%100)/200.0)+.3, 0.); } Everything you need to scare your dog is contained in this tar file: ftp://ftp.be.com/pub/samples/midi_kit/obsolete/EdMidi.zip When you unpack the tar file, it will create a directory called "EdMidi" that contains the following seven files in three parts:
The process goes something like this:
If you pass it a trailing "r" argument, edmidi will record the playback to a sound file: $ edmidi lbjtest.lbj r Recording to Last timestamp: 23.225000 Max notes: 74 Writing midi test.midi Writing sound lbjtest.snd Setting sampling rate 44100 Replay [y]? edmidi will also let you mute and solo individual channels. It also has a number of other options that you can dump by typing 'edmidi' with no argument. Now to the serious and unfortunate part of the column. Last Friday, Jim Nitchalls, one of the creators of the Headspace synthesizer, died. I met Jim eons ago when we both were working in or around Electronic Arts. Every couple of years since then, our paths would cross with us on them at the same time; one particularly cogent collision is when he called me up two years ago to see if Be could use a General MIDI synthesizer. You may have seen Jim, possibly even chatted with him, at one of the Be Developer Conferences. If you've never actually used the Headspace synthesizer, you should try it sometime. Utter Jim's name and generate a burst of voice #126 (0-based).
Our New Developer ProgramsIf you haven't already visited the Developer section of our Web site, I'd like to direct your attention to http://www.be.com/developers/developer_program/devprogram_overview.html. As the end of the URL implies, it contains an overview of our new tiered developer programs, as well as pointers to more detailed information. This should provide you with the information you need in order to decide which of the three programs is right for you. For my part, I'd like to review the philosophy behind these changes, as well as what we are trying to accomplish for the Be community. As obvious as we think it is, it bears repeating that an operating system is useless in itself. Developers make it useful with the applications they build for it. Only after we have applications that proclaim the strengths of the BeOS (and we believe we have some already) can we think of the other constituencies in the Be community -- our customers, shareholders, business partners, and employees. So, why do we charge for developer programs if we believe developers are so important? Don't we risk turning away the next Mitch Kapor, or even the next Paul Allen? As you'll see in looking through the new programs, we are trying to juggle a contradiction. We want to make sure enthusiasts can try their hand at writing code for the BeOS in the largest possible numbers at the least possible expense. That requires access to a computer and to a copy of the BeOS. There is no annual fee at this level. Our Web site and newsgroups provide technical documentation, and access to libraries and newsletters. Your creations will be featured in the BeWare section of our Web site. For people or companies who make a business of writing BeOS commercial applications we want to offer more support. These developers get more technical and marketing assistance, their CodeWarrior tools are included in the $299 annual fee, and we'll enthusiastically distribute your commercial software through BeDepot.com. Developers with a large organization can use the $599 Corporate program with even more technical and marketing support, along with one copy of the BeOS and all upgrades released during the subscription year, a copy of the current IDE, CodeWarrior, and PackageBuilder (which lets developers build packages that can be installed with SoftwareValet). Corporate developers can also buy additional seats (BeOS, CodeWarrior, and PackageBuilder tools) "wholesale" at $99 each. Further provisions ease the transition for existing developers, especially CodeWarrior customers. It's that simple. We've already received some feedback on the letter we sent to existing developers. One suggestion was to use Silver, Gold, and Platinum labels for the three tiers. Personally, I prefer the suggestion from a Be executive (who requested anonymity): Geek, Midnight Programmer, and Commercial, if I remember correctly. Our hope is that the no-fee program will continue to attract individuals who are intrigued with the BeOS and want to try writing an application. If our product and our company do a good job for them, they'll go up one level, and make a business out of their experiment. If we all do what we're supposed to do, they'll go to the top -- and us with them. Or else they'll happily make shareware because that's what they like to do. We learned a long time ago it's not our place to tell a developer what to do. It works much better the other way around when programmers who actually struggle with the platform and the marketplace tell us what to do with our APIs and our marketing programs. Their suggestions are always colorful and useful. Speaking of hue and abuse, we're off to NYC next week for PC Expo. If you're in town, look for us at the friendly Jacob Javits Convention Center. We'll see if New York City unions and waiters are a match for French ones. More exciting still, we'll be showing off the newest BeOS applications running on Release 3.1.
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. |