Whole document tree J-Pilot Plugin ManualUpdatesThis document was last updated 19 March 2001, for J-Pilot-0.99.What are plugins?A plugin is code that can extend the functionality of j-pilot without adding any code to j-pilot, or recompiling it. It is basically just a shared library that contains pre-defined callback functions.A callback function is a function that is not called from the application itself, but from an external program. When J-Pilot starts up it will scan the plugin directories for any shared libraries (~/.jpilot/plugins/ and $BASE_DIR/lib/jpilot/plugins). When it finds a shared library it will find callback functions inside of the library and call them when needed. So, a plugin can be an integral part of the overall program just by its existence and when taken away the main program will still run only missing the functionality that the plugin provided. Creating pluginsPlugins are relatively easy to write for J-Pilot. All you need to do is implement the plugin callback functions as needed and write the application specific code. I have provided an example plugin for the Expense application. I used this application because it is included in the palm pilot ROM and everyone should have it. Since then I have been proved wrong. The new m100s don't have Expense and I think some old Pilots don't have it. It took me about 10 hours to write it with a lot of code reuse from other parts of j-pilot.I have created a library of useful functions for writing J-Pilot conduits. The code is inside j-pilot and the header file is libplugin.h. The naming convention is that all of these functions start with "jp_". There are some I threw in there and didn't add a jp_ prefix because I would have had to change too much existing code. If you do create a plugin I would appreciate it if you would give me a link to the site so that I can put it on my website. This will encourage more people to use J-Pilot and your plugin. Even if you are working on a plugin you can let me know and I will put it down as in progress so that someone doesn't duplicate your effort. Its GNU licensed code so you are free to do not tell me of course, as long as you follow the GNU license. My email is Judd Montgomery <judd@engineer.com>. The official J-Pilot website is at http://jpilot.org. Example PluginsI have written Expense and SyncTime as example plugins. Expense is a GUI (Graphical User Interface) application and SyncTime has no GUI. It shouldn't be too hard to use these as a base point for writing your own.Plugin call back functionsThese functions are functions that you may implement in your plugin application. Most of them are not required. All you have to do is write them and they will be called at the appropriate times. The naming convention is that all of these functions start with "plugin_".
int plugin_search(char *search_string, int case_sense, struct search_result **sr); struct search_result
char *search_string - input parameter, a string that
the user is searching on.
struct search_result
This function will be called from the search window of the main program. The output parameter search_result will be displayed in the search window.
int plugin_get_name(char *name, int len); char *name - output parameter, a pointer to a pre-allocated
buffer in j-pilots address space. The plugin should copy its name
into this string.
This function is used to get the name of the plugin, e.g. "Expense 1.0". This function must be implemented or the plugin won't be loaded..
int plugin_get_menu_name(char *name, int len); char *name - output parameter, a pointer to a pre-allocated
buffer in j-pilots address space. The plugin should copy its name
into this string.
This function is used to get the name of the plugin, e.g. "Expense". This is the name that will appear in the j-pilot menu under plugins. It is possible to have a plugin that isn't accessible under the menu, in that case this function should not be implemented.
int plugin_get_help_name(char *name, int len); char *name - output parameter, a pointer to a pre-allocated
buffer in j-pilots address space. The plugin should copy its name
into this string.
This function is used to get the name of the plugin as it wishes to appear in the help menu pulldown, e.g. "About Expense". This function is not mandatory.
int plugin_help(char **text, int *width, int *height); char **text - output parameter, the plugin should point
this string pointer to a string to be displayed in the help box.
int plugin_get_db_name(char *name, int len); char *name - output parameter, a pointer to a pre-allocated
buffer in j-pilots address space.
This function is used to get the name of the palm database (pdb file) that is to be synced. This DB will be automatically synced when j-pilot performs a sync. For example the expense plugin uses the DB file "ExpenseDB.pdb", it would copy "ExpenseDB" to name, leaving off the extension. A normal plugin that just adds, deletes, and changes DB records using the plugin API will not have to do any special work during a sync process, it will be automatic.
int plugin_startup(jp_startup_info *info); typedef struct
This plugin function is called when j-pilot starts up. Any initialization
needed should be done here.
int plugin_gui(GtkWidget *vbox, GtkWidget *hbox, unsigned int unique_id); GtkWidget *vbox - input parameter, the box underneath
the sync and quit buttons. This is where the main applications put
the delete button.
This plugin function is called when the plugin is selected from the j-pilot menu, or from the search window. This is where the plugin can draw on the screen and provide the GUI interface, etc. If unique_id is non-null then the application should go directly to that record. This is how the search window forces the applications to go to the search result records.
int plugin_help(char **text, int *width, int *height); char **text - output parameter, the text to be displayed
on the about dialog window.
This plugin function is called when the plugin is selected from the
j-pilot help menu pulldown. 2 things can be done here.
int plugin_gui_cleanup(); This plugin function is called when another application has been called and the boxes for the plugin GUI screen are about to be destroyed. Most widgets will be destroyed when their parents are destroyed, so this function normally is not needed.
int plugin_pre_sync(void); This function is called after the j-pilot sync button is pressed and before the sync with the pilot is started.
int plugin_sync(int sd);
This function is called after the sync button is pressed and during
the sync process.
int plugin_post_sync(void); This function is called after the sync process is completed. Screen redraws may be a good thing to do here, as categories and records may have changed during the sync.
int plugin_exit_cleanup(void); This function is called when j-pilot is shutting down.
int plugin_print(?,?); There will be a print API here, but printing has not been implemented yet.
Plugin API functionsThese functions are provided to make it easier to develop plugins for J-Pilot. If you need something that isn't here and it is something that J-Pilot already does, or something that you think others might need in the future, it should probably be added into this library.
int jp_init(void);This function must be called in the plugin. Preferable in plugin_startup, but it should be in the first function to be called. int jp_logf(int level, char *format, ...);int level - is the logging level. It may be user configurable in the future, but right now I don't see a need for it. char *format,... - is the same type of things that you would pass to printf. example:
There are 3 places for logging output to go to. Standard output (stdout, usually the terminal window), the log file in ~/.jpilot/, and the ouput window (the one that pops up while you are syncing). Logging levels are bitmasks, so they may be combined with a logical OR. You can run J-Pilot in debug mode by executing "jpilot -d" to force
debug output.
int jp_install_append_line(char *line); char *line - input parameter, this is just a line to write to the install file. The install file is a file that is read line by line during the sync
process. Each line is the full path to a file name to be installed.
Once the file is installed on the pilot successfully then that line is
removed from the file.
int jp_install_remove_line(int deleted_line); int deleted_line - input parameter, This is the line number to be deleted from the install file. The first line is line zero.
const char *jp_strstr(const char *haystack, const char *needle, int case_sense); This function is analogous to the C function strstr except that it has a case sensitive parameter.
int jp_get_app_info(char *DB_name, void **buf, int buf_size); char *DB_name - input parameter, the name of the DB
file to be read. For example to read the Expense data you would pass
"ExpenseDB", leaving off the .pdb extension.
This function retrieves the application info from a PDB file. It is packed and must be unpacked into a format that is specific to each palm application.
int jp_open_home_file(char *filename, char *mode); char *filename - input parameter, the name of the file to be opened. char *mode - input parameter, mode to open file in. See man page for fopen. This function opens a file in $JPILOT_HOME/.jpilot/ Its analogous to fopen except that it looks in the jpilot directory for the file.
Using J-Pilot database filesTo write plugins that utililize j-pilot's built in database and sync abilities it is necessary to understand how the databases are used. J-Pilot treats the pdb files as read-only, except at sync time. It will not modify the pdb file in anyway. Actually it never does, it lets the palm pilot do that work. I may change this in the future to achieve faster syncs, but I will try to keep this API the same. J-pilot keeps a "pc" file of all the changes the user has made to the database. These are "reconciled" at sync time, and the PC file is cleared out. So, after a successful sync all of the data should be in the pdb file and the pc file should be 0 in size. The pc files have the extension ".pc". So there will be an AddressDB.pdb file and an AddressDB.pc file in ~/.jpilot/. The pdb file belongs to the pilot and the pc file belongs to j-pilot.Records are just chunks of data. They must be packed and unpacked into some meaningful form by the desktop application. To do this it is neccessary to know the record format of the palm application. The palm processor is Motorola 68000 based and the palm stores integers native to its own processor, so some translations need to be made on integer data. There are examples of this in the pilot-link library code. To modify a record you must write the new record to the pc file and then delete the original record. Actually if its a record in the pdb file it won't actually get deleted. A "deleted record" with the same unique_id will have to be written to the pc file. You don't really have to worry about the details of doing this since there is a library to do it for you. So, when you read a database using the libplugin calls you will get records back with different record types depending on where they came from and what they are scheduled to do at sync time. This is a short explanation of each record type: PALM_REC: This record was read from the palm pdb file. It is unchanged by j-pilot. MODIFIED_PALM_REC: This record has been modified by j-pilot. What this means is that this record has been deleted and a new record has been created to reflect the changes. This is the original record that still exists in the pdb file and it will be deleted at sync time. This record is kept so that at sync time it can be compared with the palm pilots record to see if it was modified on the pilot and in j-pilot. This record shouldn't be shown to the user. DELETED_PALM_REC: This record has been scheduled to be deleted from the pdb file at sync time. This is the record retrieved from the pdb file and there is another record in the pc file with a matching unique_id to mark this record as deleted. This record should not be shown to the user. NEW_PC_REC: This is a new record that has been added by j-pilot. It is in the pc file and will be written to the palm during the next sync and then retrieved back from the palm into the pdb file. DELETED_PC_REC: This record was created in the pc file and then later deleted. It shouldn't be shown to the user. DELETED_DELETED_PALM_REC: This record should only exist during a sync process. During the sync when a DELETED_PALM_REC gets deleted from the pilot it will be marked with this record type and then as soon as the sync is finished the pc file will get cleaned up and it should be removed. If a crash occurs it could be possible for this record to be in the pc file. The SPENT_PC_RECORD_BIT means that this record will be removed
during the next pc file cleanup. If this bit is set then the record
can be totally ignored.
typedef enum {
int jp_read_DB_files(char *DB_name, GList **records); char *DB_name is a pointer to the name of the DB file
to be read. For example to read the Expense data you would pass "ExpenseDB",
leaving off the .pdb extension. Both the pdb and the
pc files are read.
This function will read the pdb file and the pc file out of the $(HOME)/.jpilot/ directory and put all the records into a list. The list contains structures of the following: typedef struct
PCRecType rt - This has been explained in the previous
paragraph.
int jp_free_DB_records(GList **records); GList **records is a pointer to pointer to a list of
records to be freed.
This call should be used to free the record list allocated by jp_read_DB_files().
int jp_delete_record(char *DB_name, buf_rec *br, int flag); char *DB_name is the DB name to be witten to.
For example to write to the Expense application database you would pass
"ExpenseDB". Do not pass the file extension (".pdb").
int jp_pc_write(char *DB_name, buf_rec *br); char *DB_name is the DB name to be witten to.
For example to write to the Expense application database you would pass
"ExpenseDB". Do not pass the file extension (".pdb").
typedef struct
This function is used for writing a record to the pc database file.
The record type should almost always be NEW_PC_REC. Unique_id can
be left blank since it is an outgoing parameter. A new unique id
will be assigned and placed in the structure. Attrib is the record
attributes, buf is a raw database record, and size is the size of the record.
Other Miscellaneous API Functionsint unlink_file(char *filename); char *filename is the filename to remove. This function is like unlink except that it looks for the file in the jpilot directory.
int rename_file(char *old_filename, char *new_filename); char *old_filename is the filename to rename. char *new_filename is the filename to rename to. This function is like rename except that it looks for the files in the jpilot directory.
int get_app_info_size(FILE *in, int *size); FILE *in input parameter, an open file pointer to a palm pdb file. int *size output parameter, is the size of the application info block.
int read_header(FILE *pc_in, PC3RecordHeader *header); FILE *pc_in input parameter, an open file pointer to a J-Pilot pc3 file pdb file. PC3RecordHeader *header output parameter, the header from the file read in.
int write_header(FILE *pc_out, PC3RecordHeader *header); FILE *pc_out input parameter, an open file pointer to a J-Pilot pc3 file pdb file. PC3RecordHeader *header input parameter, the header to be written to the file.
|