time (Tim Endres) (03/22/91)
In article <1991Mar21.223638.4346@ssd.kodak.com>, ph@ssd.kodak.com (Pete Hoch) writes: > So I was wondering, do they all do it the same way? Should > Apple step in and provide a filter manager? Is this hard to > do today without Apples help? Also, is this a good idea? Most of these mechanisms use a very similar technique. However, all differ in content and calling conventions, and it is very doubtful that a universal solution would be easily decided upon. However, I am certain some could be standardized. For instance, there could be a common interface for operations that work on text selections. Of course, even then, some cases will still not fit... ------------------------------------------------------------- Tim Endres | time@ice.com ICE Engineering | uupsi!ice.com!time 8840 Main Street | Voice FAX Whitmore Lake MI. 48189 | (313) 449 8288 (313) 449 9208
ph@ssd.kodak.com (Pete Hoch) (03/22/91)
Hi all, I have noticed lately that more and more applications are supporting 'drop in' code resources. Perhaps the most famous example of this is PhotoShop. However StuffIt now supports drop in filters and even Apple's own Communications tool box will run seperate code segments. So I was wondering, do they all do it the same way? Should Apple step in and provide a filter manager? Is this hard to do today without Apples help? Also, is this a good idea? It seems to me that it would be hard tocome up with a general toolbox interface that would handle any filtering need that application programmers could come up with. However there are some basic concepts of piping and filtering that have stood the test of time in UNIX. Would it be usefull to say have a filtered read command so that when an application reads a disk file that byte stream passes through a filter on its way in? Perhaps I have not phrased my questions well but if you have some ideas on how to go about doing this I would be very interested. Pete Hoch -- Pete Hoch | ..somewhere..!kodak!ph ..or.. Color Systems ISPD. 3/65/RL | ph@ssd.kodak.com ..or.. Eastman Kodak Co. | ph@kodak.com Rochester, NY 14650-1805 | 716-722-????
hawley@adobe.COM (Steve Hawley) (03/23/91)
In article <1CE00001.aolmdnz@tbomb.ice.com> time@ice.com writes: > >In article <1991Mar21.223638.4346@ssd.kodak.com>, ph@ssd.kodak.com (Pete Hoch) writes: >> So I was wondering, do they all do it the same way? Should >> Apple step in and provide a filter manager? Is this hard to >> do today without Apples help? Also, is this a good idea? > >Most of these mechanisms use a very similar technique. > >However, all differ in content and calling conventions, and it is >very doubtful that a universal solution would be easily decided upon. >However, I am certain some could be standardized. For instance, there >could be a common interface for operations that work on text selections. >Of course, even then, some cases will still not fit... Since Pete was interested in a general way of doing filters, why not have the following (off the top of my head) for byte oriented streams: typedef struct { /* stream operations. These would probably follow Pascal calling conventions */ boolean (*EndOfStreamFunc)(); char (*GetCharFunc)(); OSErr (*PutCharFunc)(); OSErr (*UngetCharFunc)(); /* maybe Seek, and Length too */ } StreamOps, *StreamOpsPtr; /* prototype function to do filtering */ pascal void main(SOps) StreamOpsPtr SOps; { /* your code to do filtering */ } The idea is that the parent program passes in pointer to functions to do all operations one would need for a stream. The main could then use the ops on the stream to transform the data as needed: pascal void main(SOps) register StreamOpsPtr SOps; { /* convert an uppercase bytes stream to lowercase */ register char *c; while (! (SOps->EndOfStreamFunc)()) { c = (SOps->GetCharFunc)(); if (isupper(c)) c = tolower(c); /* whatever the syntax is for CallPascal -- I forget */ CallPascal1(SOps->PutCharFunc, c); } } Of course, this will not be particularly speedy because of the overhead added by the function calling, but you wanted generality, right? Steve Hawley hawley@adobe.com -- "Did you know that a cow was *MURDERED* to make that jacket?" "Yes. I didn't think there were any witnesses, so I guess I'll have to kill you too." -Jake Johansen
d88-jwa@byse.nada.kth.se (Jon W{tte) (03/25/91)
In article <13094@adobe.UUCP> hawley@adobe.COM (Steve Hawley) writes: typedef struct { /* stream operations. These would probably follow Pascal calling conventions */ boolean (*EndOfStreamFunc)(); char (*GetCharFunc)(); OSErr (*PutCharFunc)(); OSErr (*UngetCharFunc)(); /* maybe Seek, and Length too */ } StreamOps, *StreamOpsPtr; You would rather want to get blocks at a time - like, typedef struct { long amountToRead ; long flags ; /* bit 0 == SetPosition supported &c */ pascal OSErr ( * ReadBlock ) ( char * , long ) ; pascal OSErr ( * PeekBlock ) ( char * , long ) ; pascal OSErr ( * WriteBlock ) ( char * , long ) ; pascal OSErr ( * SetPosition ) ( char * , long ) ; pascal OSErr ( * TellUser ) ( char * ) ; } filterParam ; pascal OSErr MyFilterFunc ( filterParam * p , char * userData ) { } Or should it be handle-based ? Maybe bit 1 == Handles instead of pointers ? Who should be responsible for allocating memory ? Should operations in site be allowed ? (more flags :-) userData could be filter-dependent, like "awk" command lines, or it could be app-dependent. More ideas ! Maybe the Net is strong enough to actually support a de-facto standard. But we'd have to talk a few major players into using this standard. Happy hacking, h+@nada.kth.se Jon W{tte -- "The IM-IV file manager chapter documents zillions of calls, all of which seem to do almost the same thing and none of which seem to do what I want them to do." -- Juri Munkki in comp.sys.mac.programmer
peirce@outpost.UUCP (Michael Peirce) (03/25/91)
I think drop-ins can be very useful at times, but I hope that with System 7, people will start thinking about using AppleEvents to do some of this type of thing too. It would be nice to be able to ask a spell checker app to check something for us for example. Or a data compression app to compress something, etc. This demands acceptance of some standard AppleEvents to make this work of course. -- michael -- Michael Peirce -- outpost!peirce@claris.com -- Peirce Software -- Suite 301, 719 Hibiscus Place -- Macintosh Programming -- San Jose, California 95117 -- & Consulting -- (408) 244-6554, AppleLink: PEIRCE
hawley@adobe.COM (Steve Hawley) (03/26/91)
In article <D88-JWA.91Mar24213927@byse.nada.kth.se> d88-jwa@byse.nada.kth.se (Jon W{tte) writes: >You would rather want to get blocks at a time - like, > >typedef struct { > long amountToRead ; > long flags ; /* bit 0 == SetPosition supported &c */ > pascal OSErr ( * ReadBlock ) ( char * , long ) ; > pascal OSErr ( * PeekBlock ) ( char * , long ) ; > pascal OSErr ( * WriteBlock ) ( char * , long ) ; > pascal OSErr ( * SetPosition ) ( char * , long ) ; > pascal OSErr ( * TellUser ) ( char * ) ; >} filterParam ; Actually, I wouldn't want to get blocks at a time. The reason why I suggested a byte stream is that the parent program can decide what buffering scheme is most appropriate for the the drop-in module, and bytes streams will be free from typical problems associated with block reads: matching block size with ths OS for efficiency, byte ordering, word/long word alignment, what happens when I can't allocate a block size that I expected (do I put an alert? *CAN* I put up an alert? Am I allowed to move memory?) etc. It all depends on what you want, really. A stream oriented program is geared especially well for text and files and will work with a minimum of hassle with for many other applications as well. The outline of a stream based filter is straight forward and uncomplicated (for the most part -- there are always degenerate cases). It is simply easier to write a correct stream-based filter than it is to write a correct block-based filter, and you are forcing everyone who writes a drop in module to do their own buffer handling. If you have a program with a couple dozen drop-in modules, wouldn't you rather have the block buffering in one place than in 20? The down side (as I mentioned before) is that you pay for a function call for each byte you read. Obviously, for something like filtering of, say, 24 bit graphics data, a stream-oriented method is going to be extremely painful. In fact, so will a block-oriented method unless the only block that gets passed is a pointer or handle to a data structure describing the data (like a PixMap). So, back to the original question of "why is there no standard way for handling drop-in modules?" Do you have your answer now? Because no two people will ever agree on what is a "good" standard and the approach you take must be geared for the type of data you intend to be fiddling with. I'm glad I don't work on a standards committee... Steve Hawley hawley@adobe.com -- "Did you know that a cow was *MURDERED* to make that jacket?" "Yes. I didn't think there were any witnesses, so I guess I'll have to kill you too." -Jake Johansen
d88-jwa@byse.nada.kth.se (Jon W{tte) (03/26/91)
In article <13180@adobe.UUCP> hawley@adobe.COM (Steve Hawley) writes:
Actually, I wouldn't want to get blocks at a time. The reason why I
suggested a byte stream is that the parent program can decide what
buffering scheme is most appropriate for the the drop-in module, and
What keeps you from reading blocksa of 1 byte ? And what keeps the
host application from passing pointers into its own buffers ? It tells
the filter how much there is to read, and the filter tells the host
how much it wants...
than it is to write a correct block-based filter, and you are forcing
everyone who writes a drop in module to do their own buffer handling.
Do I ?
drop-in modules?" Do you have your answer now? Because no two people will
ever agree on what is a "good" standard and the approach you take must be
geared for the type of data you intend to be fiddling with.
Hmmm... well, maybe I'll sit down and design a _real_ complex interface
that lets you pass whatever you choose, and automatically handles
interface kinks, as well as lowers your taxes and configures sendmail
for you.
:-)
h+@nada.kth.se
Jon W{tte
--
"The IM-IV file manager chapter documents zillions of calls, all of which
seem to do almost the same thing and none of which seem to do what I want
them to do." -- Juri Munkki in comp.sys.mac.programmer
time@ice.com (Tim Endres) (03/26/91)
In article <D88-JWA.91Mar26101759@byse.nada.kth.se>, d88-jwa@byse.nada.kth.se (Jon W{tte) writes: > Hmmm... well, maybe I'll sit down and design a _real_ complex interface > that lets you pass whatever you choose, and automatically handles > interface kinks, as well as lowers your taxes and configures sendmail > for you. :-) And if you can get it to handle my lawyers, you'd really have something!!! :-)^2 tim. ------------------------------------------------------------- Tim Endres | time@ice.com ICE Engineering | uupsi!ice.com!time 8840 Main Street | Voice FAX Whitmore Lake MI. 48189 | (313) 449 8288 (313) 449 9208
ph@ssd.kodak.com (Pete Hoch) (03/27/91)
>><1991Mar21.223638.4346@ssd.kodak.com>, ph@ssd.kodak.com (Pete Hoch) writes: >>> So I was wondering, do they all do it the same way? Should >>> Apple step in and provide a filter manager? Is this hard to >>> do today without Apples help? Also, is this a good idea? >In article <1CE00001.aolmdnz@tbomb.ice.com> time@ice.com writes: >>Most of these mechanisms use a very similar technique. >>However, all differ in content and calling conventions, and it is In article <13094@adobe.UUCP> hawley@adobe.UUCP (Steve Hawley) writes: >Since Pete was interested in a general way of doing filters, why not have >the following (off the top of my head) for byte oriented streams: prototypes deleted >The idea is that the parent program passes in pointer to functions to do all >operations one would need for a stream. The main could then use the ops on >the stream to transform the data as needed: >Of course, this will not be particularly speedy because of the overhead added >by the function calling, but you wanted generality, right? However the overhead could be such a problem that this would not be practical. What I was thinking was something more allong the lines of a call back routine that the programmer supplies to the system. For example: pascal OSErr myFilter( void *source, // The data comes from long sSize, // size of the data in bytes long sNext, // offset to the next sample void *dest, // The data goes to long dSize, // size of the data in bytes long dNext) // offset to the next sample Then you need a way to select and install filters. Perhaps the Comm ToolBox is a good example of this and can be expanded and generalized. Pete -- Pete Hoch | ..somewhere..!kodak!ph ..or.. Color Systems ISPD. 3/65/RL | ph@ssd.kodak.com ..or.. Eastman Kodak Co. | ph@kodak.com Rochester, NY 14650-1805 | 716-722-????
ph@ssd.kodak.com (Pete Hoch) (03/27/91)
In article <0B010004.ma805a@outpost.UUCP> peirce@outpost.UUCP writes: >I think drop-ins can be very useful at times, but I hope that with >System 7, people will start thinking about using AppleEvents to do >some of this type of thing too. > >It would be nice to be able to ask a spell checker app to check something >for us for example. Or a data compression app to compress something, etc. > >This demands acceptance of some standard AppleEvents to make this work >of course. > >-- michael This is all well and good for System 7.0 but what about all of the people that still use 6.X? Also there are some things that cannot take the performance hit inherent in AppleEvents. If we can get a good general flexable design for drop in code filters it would be a trivial matter to write a faceless app in 7.0 that accepted AppleEvents and then called the filter manager. So I still think the basic design of a general filter manager is worth talking about. Pete -- Pete Hoch | ..somewhere..!kodak!ph ..or.. Color Systems ISPD. 3/65/RL | ph@ssd.kodak.com ..or.. Eastman Kodak Co. | ph@kodak.com Rochester, NY 14650-1805 | 716-722-????
hawley@adobe.COM (Steve Hawley) (03/27/91)
In article <D88-JWA.91Mar26101759@byse.nada.kth.se> d88-jwa@byse.nada.kth.se (Jon W{tte) writes: >What keeps you from reading blocksa of 1 byte ? And what keeps the >host application from passing pointers into its own buffers ? It tells >the filter how much there is to read, and the filter tells the host >how much it wants... Nothing *keeps* you from reading one byte blocks. You're right. But tell me, do _you_ define getchar like this? int mygetchar() { char c; if (read(0, &c, 1)) return(c); else return(EOF); } Just for kicks I wrote a program to consume standard input (under UNIX) and found that using standard getchar takes .2 seconds of user time and .2 seconds of system time to read the man page for the c shell. The same program with mygetchar used instead requires 3.4 seconds of user time and 43.4 seconds of system time. Now, as a final trick, I modified mygetchar() to use a 8192 bytes buffer instead of a 1 bytes buffer to simulate a drop in module with a fairly generous buffer size. It took .1 seconds of user time and .1 seconds of system time. Not significantly different over a 75K file. > than it is to write a correct block-based filter, and you are forcing > everyone who writes a drop in module to do their own buffer handling. > >Do I ? No, you're right. You don't _have_ to write buffer handling routines. See above for what happens when you don't have them, and if the only way to get buffered IO is by putting it in the drop in module and stream oriented I/O is the most appropriate means of getting bytes across then your application will be much bigger than it has to be because for every drop in module, there will be stream I/O code with buffer management. Now before we start getting into another series of "great taste/less filling" arguments, please keep in mind that I am not rabidly against block style I/O, nor am I rabidly for stream-style buffered I/O. Let's be computer scientists for a minute, OK? Can you implement stream-style buffered I/O using block style I/O routines? Yes? Good. Can you implement block-style unbuffered I/O routines with stream routines? Let's not see the same hands... Right, you can. Gosh! They're equivalent! So why use one over the other? Only your application will dictate which is more appropriate. If I write a terminal emulator and decide that I want to allow drop in modules for transfer protocol or emulation, I'm probably going to want to use stream IO. If I write something like PhotoShop, I'd probably want block IO (in fact, I'd probably rather have the pointer to a data structure). The important point (do I really have to type this for the third time?) which is the answer to the original question of "why is there no standard means of doing drop-in modules" is that there is no standard task that needs to be done by a drop-in module. The needs are different, so therefore are the means of satisfying that need. My original article was meant to pose a general, not universal, method for handling communication between a parent application and drop-in modules. I chose a stream model for a few reasons: 1) It's simple to interface to 2) It's reasonably efficient for a wide range of tasks 3) The directional nature of it allows for easy connection (similar to pipes) bewteen modules. 4) Provides a "feel" similar to UNIX stream IO. I realy didn't mean for this to get into so much "block IO! Nyah! stream IO! Nyah!" traffic. Really. Steve Hawley hawley@adobe.com -- "Did you know that a cow was *MURDERED* to make that jacket?" "Yes. I didn't think there were any witnesses, so I guess I'll have to kill you too." -Jake Johansen
urlichs@smurf.sub.org (Matthias Urlichs) (03/28/91)
In comp.sys.mac.programmer, article <13180@adobe.UUCP>,
hawley@adobe.UUCP (Steve Hawley) writes:
<
<The down side (as I mentioned before) is that you pay for a function call for
<each byte you read. Obviously, for something like filtering of, say, 24 bit
<graphics data, a stream-oriented method is going to be extremely painful. In
<fact, so will a block-oriented method unless the only block that gets passed
<is a pointer or handle to a data structure describing the data (like a PixMap).
You could conceivably get the best of both worlds by also passing a parameter
on how many bytes to read. The drop-in module should of course be able to
handle partial reads.
If you want to get fancy, pass another parameter to flag that the application
should stop after the first CR, thus implementing line-at-a-time reads.
It might also be a good idea to lock the buffer and pass its address back to
the filter instead of copying the data into the filter's buffer; most filters
can't read into their final data structure anyway -- a filter's job is to
convert data, right?
How do existing filter interfaces (Claris, Stuffit) handle these problems?
--
Matthias Urlichs -- urlichs@smurf.sub.org -- urlichs@smurf.ira.uka.de /(o\
Humboldtstrasse 7 - 7500 Karlsruhe 1 - FRG -- +49-721-621127(0700-2330) \o)/
ph@ssd.kodak.com (Pete Hoch) (03/28/91)
In article <13225@adobe.UUCP> hawley@adobe.UUCP (Steve Hawley) writes: > If I write a terminal emulator and decide that I want to allow drop > in modules for transfer protocol or emulation, I'm probably going to > want to use stream IO. If I write something like PhotoShop, I'd > probably want block IO (in fact, I'd probably rather have > the pointer to a data structure). How about if we go one further and instead of a pointer to a data structure we define a whole object. The data object would need methods for data access to override, but the actual data storage etc, would be left up to the subclass. Apple has been claiming for almost two years now that objects are the way to go. Prehaps this is the time to design a filter manager that coordinates the instilation of filter objects. (Are you listening CTB developers?) >The important point (do I really have to type this for the third time?) which >is the answer to the original question of "why is there no standard means of >doing drop-in modules" is that there is no standard task that needs to be done >by a drop-in module. The needs are different, so therefore are the means of >satisfying that need. Perhaps my original question was based at too low a level. Let me refraze. I have noticed the use of 'drop in' code in more and more application. Examples of this are Photoshop, Stuffit, and the comm toolbox. All of these have their own way of selecting the 'drop in' code from the users point of view. And each had to impliment a method for loading and exicuting the `drop ins`. So what I was really thinking, (if not specificly asking) was, can there and *should there* be a high level filter manager that regardless of functionality will provide the user with a consistent way of dealing with 'drop ins'? >I realy didn't mean for this to get into so much "block IO! Nyah! stream IO! >Nyah!" traffic. Really. Me either. Pete -- Pete Hoch | ..somewhere..!kodak!ssd!bashow!ph ..or.. Color Systems ISPD. 3/65/RL | ph@ekcolorlink.ssd.kodak.com ..or.. Eastman Kodak Co. | ph@bashow.ssd.kodak.com Rochester, NY 14650-1805 | 716-722-3285
time@ice.com (Tim Endres) (03/30/91)
In article <1991Mar27.204705.5725@ssd.kodak.com> you write: > and exicuting the `drop ins`. So what I was really thinking, (if not > specificly asking) was, can there and *should there* be a high level > filter manager that regardless of functionality will provide the user > with a consistent way of dealing with 'drop ins'? In uAccess, the user can add drop-ins two ways. One is to drop resources into a specified file. The other is to move files into a specified folder. The former is hard, the latter easy. What would be nice is if Apple provided a common mechanism, similar to the Control Panel, that would provide a common interface for all applications for adding, removing, and configuring drop-ins. As for a "universal" calling convention, seems like a waste of effort, since not every case can be fully covered. HOwever, it does seem that a large number of "obvious" cases could be generalized. For instance, uAccess has drop-ins that work on text selections in a text window. This is the type of operation that could be generalized. tim. ------------------------------------------------------------- Tim Endres | time@ice.com ICE Engineering | uupsi!ice.com!time 8840 Main Street | Voice FAX Whitmore Lake MI. 48189 | (313) 449 8288 (313) 449 9208