15 #include <mcabber/modules.h> |
15 #include <mcabber/modules.h> |
16 |
16 |
17 typedef void (*module_init_t)(void); |
17 typedef void (*module_init_t)(void); |
18 typedef void (*module_uninit_t)(void); |
18 typedef void (*module_uninit_t)(void); |
19 |
19 |
20 typedef struct { |
20 typedef struct module_info_struct module_info_t; |
21 const gchar *mcabber_version; |
21 struct module_info_struct { |
|
22 const gchar *branch; |
22 module_init_t init; |
23 module_init_t init; |
23 module_uninit_t uninit; |
24 module_uninit_t uninit; |
24 const gchar **requires; |
25 const gchar **requires; |
25 } module_info_t; |
26 guint api; |
|
27 const gchar *version; |
|
28 const gchar *description; |
|
29 module_info_t *next; |
|
30 }; |
26 -------------------------------------------------------- |
31 -------------------------------------------------------- |
27 |
32 |
28 Callbacks init and uninit will be called after module |
33 Callbacks init and uninit will be called after module |
29 and it's dependencies loading. 'requires' should contain |
34 and it's dependencies loading. 'requires' can contain a |
30 NULL-terminated list of module names, that should be loaded |
35 NULL-terminated list of module names, that should be loaded |
31 before this. 'mcabber_version' is required and should contain |
36 before this. 'branch' and 'api' are required and should |
32 mcabber version, that this module is designed to work with. |
37 contain mcabber branch and api version, that this module is |
33 Three other fields may be NULL. |
38 designed to work with. For these values see ChangeLog.api. |
|
39 'version' and 'description' fields are optional and just |
|
40 provide user with additional information about module. |
|
41 'description' field can contain newlines. 'next' field can |
|
42 contain pointer to the next struct with another branch of |
|
43 mcabber, if your module can work with multiple branches. |
34 |
44 |
35 To load modules, mcabber uses glib's GModule, thus, in your |
45 To load modules, mcabber uses glib's GModule, thus, in your |
36 module you can also use functions |
46 module you can also use functions |
37 |
47 |
38 -------------------------------------------------------- |
48 -------------------------------------------------------- |
74 - check if module is present, and if present just |
84 - check if module is present, and if present just |
75 increase it's reference count |
85 increase it's reference count |
76 - load .so via glib (and call g_module_check_init, if |
86 - load .so via glib (and call g_module_check_init, if |
77 present) |
87 present) |
78 - check for information structure presence |
88 - check for information structure presence |
79 - check target mcabber version compatibility |
89 - find suitable branch and check api version |
|
90 compatibility |
80 - load modules, that this module requires (note, that |
91 - load modules, that this module requires (note, that |
81 dependency problems will be reported as error |
92 dependency problems will be reported as error |
82 invariably, force flag have no effect on this check) |
93 invariably, force flag have no effect on this check) |
83 - module placed into a list of modules |
94 - module placed into a list of modules |
84 - module init routine is called |
95 - module init routine is called |
319 { |
330 { |
320 scr_LogPrint (LPRINT_NORMAL, "Bye, World!"); |
331 scr_LogPrint (LPRINT_NORMAL, "Bye, World!"); |
321 } |
332 } |
322 |
333 |
323 module_info_t info_hello = { |
334 module_info_t info_hello = { |
324 .mcabber_version = "0.10.0", |
335 .branch = "dev", |
|
336 .api = 1, |
325 .requires = NULL, |
337 .requires = NULL, |
326 .init = hello_init, |
338 .init = hello_init, |
327 .uninit = hello_uninit, |
339 .uninit = hello_uninit, |
|
340 .version = "0.0.1", |
|
341 .description = "Hello world module\n" |
|
342 "(as well as bye world module)", |
|
343 .next = NULL, |
328 }; |
344 }; |
329 |
345 |
330 /* The End */ |
346 /* The End */ |
331 -------------------------------------------------------- |
347 -------------------------------------------------------- |
332 |
348 |
452 compl_del_category (hello_cid); |
473 compl_del_category (hello_cid); |
453 cmd_del ("hello"); |
474 cmd_del ("hello"); |
454 } |
475 } |
455 |
476 |
456 module_info_t hello_info = { |
477 module_info_t hello_info = { |
457 .mcabber_version = "0.10.0", |
478 .branch = "dev", |
|
479 .api = 1, |
458 .requires = NULL, |
480 .requires = NULL, |
459 .init = hello_init, |
481 .init = hello_init, |
460 .uninit = hello_uninit, |
482 .uninit = hello_uninit, |
|
483 .version = "0.0.3", |
|
484 .description = "Hello world module" |
|
485 "Provides command /hello with completion", |
|
486 .next = NULL, |
461 } |
487 } |
462 |
488 |
463 /* The End */ |
489 /* The End */ |
464 -------------------------------------------------------- |
490 -------------------------------------------------------- |
465 |
491 |
559 if (beep_cid) |
585 if (beep_cid) |
560 compl_del_category (beep_cid); |
586 compl_del_category (beep_cid); |
561 } |
587 } |
562 |
588 |
563 module_info_t beep_info = { |
589 module_info_t beep_info = { |
564 .mcabber_version = "0.10.0", |
590 .branch = "dev", |
|
591 .api = 1, |
565 .requires = NULL, |
592 .requires = NULL, |
566 .init = beep_init, |
593 .init = beep_init, |
567 .uninit = beep_uninit, |
594 .uninit = beep_uninit, |
|
595 .version = "0.0.1", |
|
596 .description = "Simple beeper module\n" |
|
597 "Recognizes option beep_enable\n" |
|
598 "Provides command /beep", |
|
599 .next = NULL, |
568 } |
600 } |
569 |
601 |
570 /* The End */ |
602 /* The End */ |
571 -------------------------------------------------------- |
603 -------------------------------------------------------- |
572 |
604 |
609 #include <mcabber/modules.h> |
641 #include <mcabber/modules.h> |
610 |
642 |
611 const gchar *a_deps[] = { "b", "c", NULL }; |
643 const gchar *a_deps[] = { "b", "c", NULL }; |
612 |
644 |
613 module_info_t info_a = { |
645 module_info_t info_a = { |
614 .mcabber_version = "0.10.0", |
646 .branch = "dev", |
|
647 .api = 1, |
615 .requires = a_deps, |
648 .requires = a_deps, |
616 .init = a_init, |
649 .init = a_init, |
617 .uninit = a_uninit, |
650 .uninit = a_uninit, |
|
651 .version = NULL, |
|
652 .description = NULL, |
|
653 .next = NULL, |
618 }; |
654 }; |
619 -------------------------------------------------------- |
655 -------------------------------------------------------- |
620 |
656 |
621 If your module needs to "authenticate" mcabber version |
657 If your module needs to "authenticate" mcabber version |
622 too, this can be done in g_module_check_init: |
658 too, this can be done in g_module_check_init: |
624 -------------------------------------------------------- |
660 -------------------------------------------------------- |
625 #include <glib.h> |
661 #include <glib.h> |
626 #include <gmodule.h> |
662 #include <gmodule.h> |
627 |
663 |
628 #include <mcabber/main.h> |
664 #include <mcabber/main.h> |
|
665 #include <mcabber/modules.h> |
629 |
666 |
630 const gchar *g_module_check_init (GModule *module) |
667 const gchar *g_module_check_init (GModule *module) |
631 { |
668 { |
632 char *ver = mcabber_version (); |
669 char *ver = mcabber_version (); |
633 |
|
634 // ver now contains version in format |
670 // ver now contains version in format |
635 // X.X.X[-xxx][ (XXXXXXXXX)] |
671 // X.X.X[-xxx][ (XXXXXXXXXXXXX)] |
|
672 const gchar *branch = mcabber_branch; |
|
673 guint api = mcabber_api_version; |
|
674 const gchar *error = NULL; |
|
675 |
636 if (...) |
676 if (...) |
637 return "Incompatible mcabber version"; |
677 error = "Incompatible mcabber version"; |
638 |
678 |
639 g_free (ver); |
679 g_free (ver); |
640 return NULL; |
680 return error; |
641 } |
681 } |
642 -------------------------------------------------------- |
682 -------------------------------------------------------- |
643 |
683 |
644 Also you can use glib check_init routine to modify |
684 Also you can use glib check_init routine to modify |
645 module information, that will be checked by mcabber, |
685 module information, that will be checked by mcabber, |
646 eg. if you want your module to always pass mcabber |
686 eg. if you want your module to always pass mcabber |
647 version check, you can assign version, obtained from |
687 version check, you can assign branch information, |
648 mcabber_version() to corresponding field in your struct. |
688 obtained from mcabber_... variables to corresponding |
|
689 fields in your struct. |
649 Or you can modify your module's dependencies, though |
690 Or you can modify your module's dependencies, though |
650 direct module_load() will have the same effect, and |
691 direct module_load() will have the same effect, and |
651 can be used for optional dependencies, that your module |
692 can be used for optional dependencies, that your module |
652 can work without. |
693 can still work without. |
653 |
694 |
654 Note: remember, that g_module_check_init will be always |
695 Note: remember, that g_module_check_init will be always |
655 called, even if later module will not pass checks, thus: |
696 called, even if later module will not pass checks, thus: |
656 - do not use functions from other modules there; |
697 - do not use functions from other modules there; |
657 - provide g_module_unload to undo anything, check_init |
698 - provide g_module_unload to undo anything, check_init |