Foobar2000:Development:Global Callbacks

From Hydrogenaudio Knowledgebase
Jump to: navigation, search

Tracking foobar2000 lifetime events: global callbacks

Multiple service classes presented by the SDK allow your component to receive notifications about various events. We'll refer to these classes as global callbacks.

Essential examples of global callbacks:

  • initquit - notification about app startup and shutdown.
  • init_stage_callback - more detailed notification about app startup and shutdown.
  • file_operation_callback - tracking file move/copy/delete operations.
  • library_callback - tracking Media Library content changes.
  • metadb_io_callback - tracking tag read / write operations altering cached/displayed media information.
  • play_callback - tracking playback related events.
  • playback_statistics_collector - collecting information about played tracks.
  • playlist_callback, playlist_callback_single - tracking playlist changes (the latter tracks only active playlist changes).
  • playback_queue_callback - tracking playback queue changes.
  • titleformat_config_callback - tracking changes of title formatting configuration.
  • ui_drop_item_callback - filtering items dropped into the UI.

All of global callbacks operate only within main app thread, allowing easy cooperation with your user interface - for an example, you perform playlist view window repainting directly from your playlist_callback implementation.

Global callback recursion issues

There are restrictions on things that are legal to call from within global callbacks. For an example, you can't modify a playlist from inside a playlist callback, because there are other registered callbacks tracking playlist changes that haven't been notified about the change being currently processed yet.

You must not enter modal message loops from inside global callbacks, as those allow any unrelated code (queued messages, user input, etc.) to be executed, without being aware that a global callback is being processed. Certain global API methods such as metadb_io::load_info_multi or threaded_process::run_modal enter modal loops when called. Use main_thread_callback service to avoid this problem and delay execution of problematic code.

You should also avoid firing a cross-thread SendMessage() inside global callbacks as well as performing any operations that dispatch global callbacks when handling a message that was sent through a cross-thread SendMessage(). Doing so may result in rare unwanted recursions - SendMessage() call will block the calling thread and immediately process any incoming cross-thread SendMessage() messages. If you're handling a cross-thread SendMessage() and need to perform such operation, delay it using PostMessage() or main_thread_callback.