Detect plugins on startup.

This commit is contained in:
Dave Davenport 2017-03-04 12:00:59 +01:00
parent 45c70cbecf
commit 86dc1e1448
4 changed files with 138 additions and 117 deletions

View file

@ -1,7 +1,8 @@
#ifndef ROFI_MODE_PRIVATE_H
#define ROFI_MODE_PRIVATE_H
#define ABI_VERSION 0x00000002
#include <gmodule.h>
#define ABI_VERSION 0x00000003
/**
* @param data Pointer to #Mode object.
@ -149,5 +150,8 @@ struct rofi_mode
_mode_free free;
/** Extra fields for script */
void *ed;
/** Module */
GModule *module;
};
#endif // ROFI_MODE_PRIVATE_H

View file

@ -41,6 +41,7 @@ const Mode * rofi_get_mode ( unsigned int index );
* Queue an error.
*/
void rofi_add_error_message ( GString *str );
/**
* @param code the code to return
*
@ -48,6 +49,13 @@ void rofi_add_error_message ( GString *str );
* This function sets the code that rofi will return on exit.
*/
void rofi_set_return_code ( int code );
/**
* @param name Search for mode with this name.
*
* @return returns Mode * when found, NULL if not.
*/
Mode * rofi_collect_modi_search ( const char *name );
/** Reset terminal */
#define color_reset "\033[0m"
/** Set terminal text bold */

View file

@ -68,48 +68,22 @@ static void combi_mode_parse_switchers ( Mode *sw )
pd->switchers = (CombiMode *) g_realloc ( pd->switchers,
sizeof ( CombiMode ) * ( pd->num_switchers + 1 ) );
// Window switcher.
#ifdef WINDOW_MODE
if ( strcasecmp ( token, "window" ) == 0 ) {
Mode *mode = rofi_collect_modi_search ( token );
if ( mode ){
pd->switchers[pd->num_switchers].disable = FALSE;
pd->switchers[pd->num_switchers++].mode = &window_mode;
}
else if ( strcasecmp ( token, "windowcd" ) == 0 ) {
pd->switchers[pd->num_switchers].disable = FALSE;
pd->switchers[pd->num_switchers++].mode = &window_mode_cd;
}
else
#endif // WINDOW_MODE
// SSh dialog
if ( strcasecmp ( token, "ssh" ) == 0 ) {
pd->switchers[pd->num_switchers].disable = FALSE;
pd->switchers[pd->num_switchers++].mode = &ssh_mode;
}
// Run dialog
else if ( strcasecmp ( token, "run" ) == 0 ) {
pd->switchers[pd->num_switchers].disable = FALSE;
pd->switchers[pd->num_switchers++].mode = &run_mode;
}
#ifdef ENABLE_DRUN
else if ( strcasecmp ( token, "drun" ) == 0 ) {
pd->switchers[pd->num_switchers].disable = FALSE;
pd->switchers[pd->num_switchers++].mode = &drun_mode;
}
#endif // ENABLE_DRUN
else {
pd->switchers[pd->num_switchers++].mode = mode;
} else {
// If not build in, use custom switchers.
Mode *sw = script_switcher_parse_setup ( token );
if ( sw != NULL ) {
pd->switchers[pd->num_switchers].disable = FALSE;
pd->switchers[pd->num_switchers++].mode = sw;
}
else{
} else {
// Report error, don't continue.
fprintf ( stderr, "Invalid script switcher: %s\n", token );
token = NULL;
}
}
// Keybinding.
}
// Free string that was modified by strtok_r
g_free ( switcher_str );

View file

@ -81,6 +81,7 @@ const char *cache_dir = NULL;
/** List of error messages.*/
GList *list_of_error_msgs = NULL;
static void rofi_collect_modi_destroy ( void );
void rofi_add_error_message ( GString *str )
{
list_of_error_msgs = g_list_append ( list_of_error_msgs, str );
@ -397,6 +398,116 @@ static void cleanup ()
rofi_theme = NULL;
}
TIMINGS_STOP ();
rofi_collect_modi_destroy ( );
}
/**
* Collected modi
*/
// List of (possibly uninitialized) modi's
Mode ** available_modi = NULL;
unsigned int num_available_modi = 0;
/**
* @param name Search for mode with this name.
*
* @return returns Mode * when found, NULL if not.
*/
Mode * rofi_collect_modi_search ( const char *name )
{
for ( unsigned int i = 0; i < num_available_modi; i++ ){
if ( g_strcmp0 ( name, available_modi[i]->name ) == 0 ) {
return available_modi[i];
}
}
return NULL;
}
/**
* @param mode Add mode to list.
*
* @returns TRUE when success.
*/
static gboolean rofi_collect_modi_add ( Mode *mode )
{
Mode *m = rofi_collect_modi_search ( mode->name );
if ( m == NULL ) {
available_modi = g_realloc ( available_modi, sizeof(Mode *)*(num_available_modi+1));
// Set mode.
available_modi[num_available_modi] = mode;
num_available_modi++;
return TRUE;
}
return FALSE;
}
/**
* Find all available modi.
*/
static void rofi_collect_modi ( void )
{
#ifdef WINDOW_MODE
rofi_collect_modi_add ( &window_mode );
rofi_collect_modi_add ( &window_mode_cd );
#endif
rofi_collect_modi_add ( &run_mode );
rofi_collect_modi_add ( &ssh_mode );
#ifdef ENABLE_DRUN
rofi_collect_modi_add ( &drun_mode );
#endif
rofi_collect_modi_add ( &combi_mode );
rofi_collect_modi_add ( &help_keys_mode );
GDir *dir = g_dir_open ( PLUGIN_PATH, 0, NULL );
if ( dir ) {
const char *dn = NULL;
while ( ( dn = g_dir_read_name ( dir ) ) )
{
if ( !g_str_has_suffix ( dn, G_MODULE_SUFFIX ) ) {
continue;
}
char *fn = g_build_filename ( PLUGIN_PATH, dn, NULL );
GModule *mod = g_module_open ( fn, G_MODULE_BIND_LAZY|G_MODULE_BIND_LOCAL );
if ( mod ) {
Mode *m = NULL;
if ( g_module_symbol ( mod, "mode", (gpointer *)&m) ){
if ( m->abi_version != ABI_VERSION ) {
fprintf(stderr, "ABI version of plugin does not match: %08X expecting: %08X\n", m->abi_version, ABI_VERSION);
g_module_close ( mod );
} else {
m->module = mod;
if ( ! rofi_collect_modi_add ( m ) ) {
g_module_close ( mod );
}
}
} else {
fprintf(stderr, "Symbol 'mode' not found in module: %s\n", fn);
g_module_close ( mod );
}
}
g_free ( fn );
}
g_dir_close ( dir );
}
}
/**
* Setup configuration for config.
*/
static void rofi_collect_modi_setup ( void )
{
for ( unsigned int i = 0; i < num_available_modi ; i++ ) {
mode_set_config ( available_modi[i] );
}
}
static void rofi_collect_modi_destroy ( void )
{
for ( unsigned int i = 0; i < num_available_modi ; i++ ) {
if ( available_modi[i]->module ) {
g_module_close ( available_modi[i]->module );
}
}
g_free ( available_modi );
available_modi = NULL;
num_available_modi = 0;
}
/**
@ -412,85 +523,18 @@ static int add_mode ( const char * token )
// Resize and add entry.
modi = (Mode * *) g_realloc ( modi, sizeof ( Mode* ) * ( num_modi + 1 ) );
// Window switcher.
#ifdef WINDOW_MODE
if ( strcasecmp ( token, "window" ) == 0 ) {
modi[num_modi] = &window_mode;
Mode *mode = rofi_collect_modi_search ( token );
if ( mode ) {
modi[num_modi] = mode;
num_modi++;
}
else if ( strcasecmp ( token, "windowcd" ) == 0 ) {
modi[num_modi] = &window_mode_cd;
num_modi++;
}
else
#endif // WINDOW_MODE
// SSh dialog
if ( strcasecmp ( token, "ssh" ) == 0 ) {
modi[num_modi] = &ssh_mode;
num_modi++;
}
else if ( strcasecmp ( token, mode_get_name ( &help_keys_mode ) ) == 0 ) {
modi[num_modi] = &help_keys_mode;
num_modi++;
}
// Run dialog
else if ( strcasecmp ( token, "run" ) == 0 ) {
modi[num_modi] = &run_mode;
num_modi++;
}
#ifdef ENABLE_DRUN
else if ( strcasecmp ( token, "drun" ) == 0 ) {
modi[num_modi] = &drun_mode;
num_modi++;
}
#endif
// combi dialog
else if ( strcasecmp ( token, "combi" ) == 0 ) {
modi[num_modi] = &combi_mode;
num_modi++;
}
else if ( g_str_has_suffix ( token, G_MODULE_SUFFIX ) )
{
gchar *fn;
if ( token[0] != G_DIR_SEPARATOR) {
fn = g_build_filename ( PLUGIN_PATH, token, NULL );
} else {
fn = g_strdup ( token );
}
TICK_N("Loading module");
// Load module.
GModule *mod = g_module_open ( fn, G_MODULE_BIND_LAZY|G_MODULE_BIND_LOCAL );
if ( mod ) {
Mode *m = NULL;
if ( g_module_symbol ( mod, "mode", (gpointer *)&m) ){
// Simple abi check.
if ( m->abi_version != ABI_VERSION ){
fprintf(stderr, "ABI version of plugin does not match: %08X expecting: %08X\n", m->abi_version, ABI_VERSION);
g_module_close ( mod );
} else {
modi[num_modi] = m;
num_modi++;
}
} else {
fprintf(stderr, "Symbol 'mode' not found in module: %s\n", token);
g_module_close ( mod );
}
} else {
fprintf ( stderr, "Failed to open module: %s\n", token);
}
g_free(fn);
TICK_N("Loading module done");
}
else {
// If not build in, use custom modi.
Mode *sw = script_switcher_parse_setup ( token );
if ( sw != NULL ) {
modi[num_modi] = sw;
mode_set_config ( sw );
num_modi++;
}
else{
} else {
// Report error, don't continue.
fprintf ( stderr, "Invalid script switcher: %s\n", token );
}
@ -509,19 +553,7 @@ static void setup_modi ( void )
}
// Free string that was modified by strtok_r
g_free ( switcher_str );
// We cannot do this in main loop, as we create pointer to string,
// and re-alloc moves that pointer.
mode_set_config ( &ssh_mode );
mode_set_config ( &run_mode );
#ifdef ENABLE_DRUN
mode_set_config ( &drun_mode );
#endif
#ifdef WINDOW_MODE
mode_set_config ( &window_mode );
mode_set_config ( &window_mode_cd );
#endif // WINDOW_MODE
mode_set_config ( &combi_mode );
rofi_collect_modi_setup ();
}
/**
@ -892,7 +924,10 @@ int main ( int argc, char *argv[] )
fprintf ( stderr, "Failed to open display: %s", display_str );
return EXIT_FAILURE;
}
TICK_N ( "Open Display" );
rofi_collect_modi ();
TICK_N ( "Collect MODI" );
xcb->screen = xcb_aux_get_screen ( xcb->connection, xcb->screen_nbr );