From: kate_smith@next.com (Kate Smith)
Newsgroups: comp.sys.next.programmer
Subject: New NeXTanswer on Services
Keywords: NeXTanswer services register
Date: 14 Oct 92 00:03:44 GMT

This NeXTanswer will be on the next release of NeXTanswers.  I thought you  
might find it useful now.  Sorry for the formatting, I usually prefer RTF.

Kate Smith
NeXT Developer Support

services register install

Q:  Where should I install a new service (regular, filter or printer)?

A:  Release 3 adds new flexibility in providing services.  The format of  
the service definition remains the same, but new places are searched for  
services. 
	1) Your app wrapper can contain a service description file
	named services. (e.g. ~/Apps/MyApp.app/services)  To include
	it in your ProjectBuider project, just drop it into the Other
	Resources briefcase in the files viewer of ProjectBuilder.
	
	This is the preferred way to provide a service.  Even
	lightweight services providers should have a small NeXTstep
	interface which at least allows the user to get information,
	help, and possibly set preferences for the service.

	2) The service registration process also recognizes files and
	directories with a .service extension which are installed in
	one of the newly established  ~/Library/Services or
	/LocalLibrary/Services directories.   A file with a .service
	extension must be a valid service description file.  A
	.service directory must contain a valid service description
	file named services.  (e.g.  the service description file
	would be named something like
	~/Library/Services/myOwn.service or
	/LocalLibrary/Services/ALocalOne.service/services.)  This is
	the least preferred way because it doesn't allow the for a
	NeXTstep interface to the service.  Also, the Workspace
	Manager only registers these services when the user logs in,
	it doesn't automatically update the service cache during a
	working session.

The proper format for a service description file is described in the  
documentation.  Here is an example for a ficticious app called MyApp.  It  
owns the .mine extension and has a mine-ascii filter which is installed in  
the MyApp.app directory.  Here is the filter service description file  
which is also in the MyApp.app directory:
		Filter:
		Port: NXUNIXSTDIO
		Send Type: NXTypedFilenamePboardType:mine
		Return Type: NXAsciiPboardType
		Executable: mine-ascii
Note that you don't need to specify the full pathname of the executable if  
it is in the same directory as the service description file.
	
For backward compatibility, the services registration process continues to  
look for the __services section of the __ICON segment in Mach-O files that  
are installed in your application path.

Note that if you convert a 2.0 IB.proj file file to a 3.0 PB.project file  
you will have probably want to make two changes so that your services file  
will conform to the new preferred protocol for installing services;
	* delete the line in your Makefile.preamble which builds the
	services file into your Mach-O.  It looks something like
		"LDFLAGS=-sectcreate __ICON __services services"
	* make sure that the service specification file is called
	services and move it from the Supporting Files briefcase to
	the Other Resources briefcase.  This will ensure that it gets
	copied into the app wrapper when you install.


Q:  How do I register my service dynamically while I am debugging it?

A:  The Workspace Manager (WSM) dynamically registers or reregisters any  
services described in an application wrapper that is dragged into one of  
the directories in your application path (e.g. ~/Apps, /LocalApps).  Note  
that the WSM does not notice if you just drop a new services file into  
your app wrapper, you must install the whole application.

If you add the service using some other method, you can rebuild the  
services cache in one of two ways.
	1) You can call the function NXUpdateDynamicServices(void) to
	register services which you add programmatically.  Note that
	this function spawns a task in parallel that may take a short
	time to complete, so do not expect the services to be
	immediately available.
	2) You can rebuild the services cache manually.  This is
	useful if you are editing the services file in place and
	don't want to install a new copy of the app each time you
	make a change, or if you install a .service in one of the
	Services directories, or if you install the service using
	ProjectBuilder or the command line interface to UNIX.  To
	rebuild the services cache you can run  the make_services
	program from a Terminal window manually or log in and out so
	the WSM will rebuild the services cache.


Q:  How can I tell which services have been installed?

A:  For regular services that are installed properly in an application  
wrapper, you can simply bring the Services menu of any application  
onscreen.  It rebuilds itself if  needed before it is redisplayed.  You no  
longer have to quit an application to take advantage of a new service.   
But remember to be patient, it takes a short time to reregister all of the  
services.  So you might toggle the Services menu of an app that can take  
advantage of the particular data type until your new service appears.

If you are installing a filter service, it's difficult to know if it's  
really installed properly because there are no UI elements which display  
it.  But you can use the make_services program to explicitly update all of  
the services.  It has a debugging mode which prints out the service  
information as it is processed.  Run it from a Terminal window:
		make_services debug

Alternately, this bit of codes prints the list of services that are  
available for a given filename:
	// -clearText and -appendText: are methods in my Controller
	// which simply clear and append to the debugging text.
	- printTypesForFile:(const char *)filename
	{
		const NXAtom	*listOfTypes;
		static Pasteboard *pb = nil;
		
		if (pb) pb = [pb free];
		pb = [Pasteboard newByFilteringFile:filename];
		if (!(listOfTypes = [pb types]) || !listOfTypes[0])
			return (const NXAtom *) 0;
	
		[self clearText];
		for (; listOfTypes && *listOfTypes; listOfTypes++) {
			[self appendText: *listOfTypes];
			[self appendText:"\n"];
		}
		return self;
	}


Q: What if there is more than one filter service provider for a given set  
of send and receive types?

A: All services are installed even if duplicated, but there is no  
guaranteed order of registration.  The first one encountered with the  
proper send and return types is the one that happens to be used.


Q: Any known bugs?

A: 
#24667 registering for more services in the middle of handling a service  
is dicey.

#29821 your filter service cannot expect to be launched with a full  
pathname if it uses the special NXUNIXSTDIO port.  For example, if a  
mine-ascii filter is registered for the .mine extension, it will be  
spawned like so:
		execl("/LocalApps/myApp.app/mine-ascii",
				"mine-ascii", "somefile.mine")
Since the second argument doesn't include the full path, mine-ascii can't  
check its name from within the program to see where it was run from.  But  
you shouldn't need to do this anyway.

#29905 the documentation describes new features for the WSM which don't  
currently work, this NeXTanswer documents the mechanisms that work.  Here  
are the bugs for your info:
	* The WSM doesn't register .service files or directories that
	are installed in your application path.  It only understands
	about services files within app wrappers in your app path,
	and .services in the Services directories.
	* The WSM doesn't  automatically update your services if you
	drop a new .service into one of the Services directories.
	You have to log out/in to get it to register if you install
	it there.
	* The WSM doesn't automatically update when you drop a new
	services file into your app wrapper, you have to drop the
	whole app into the Apps directory

#29924 don't kill make_services before it is finished.  It doesn't delete  
the lock file that it uses to make sure that only one process is  
rebuilding the service cache.

Q:  Where else can I get information about Services, especially about the  
format for a service description file?

A:  You can read the release notes, and the services chapter of the  
concepts manual.
	/NextLibrary/Documentation/NextDev/Concepts/Services.rtf
	/NextLibrary/Documentation/NextDev/ReleaseNotes/Appkit.rtf

QAxx

Valid for 3.0

Newsgroups: comp.sys.next.programmer