krähemann.com

Chapter 1. The application context

Making Advanced Gtk+ Sequencer objects reachable from different contices was mandatory as introducing AgsApplicationContext. Imagine you are within a GUI callback and want to lookup a soundcard or sequencer the application context shall provide this functionality and provide access to its objects through a well defined interface. As doing it with interfaces you are not limited to one specific implementation rather having the option to choose the appropriate one implementing the interfaces.

  • AgsConcurrencyProvider

  • AgsServiceProvider

  • AgsSoundProvider

There are different contices available e.g. AgsThreadApplicationContext providing its functionality by AgsConcurrencyProvider, AgsAudioApplicationContext giving you the wished objects by implementing AgsConcurrencyProvider and AgsSoundProvider. For example the code below should each giving you the same meaning object but using different contices.

Since AgsApplicationContext is a singleton you create only 1 instance of your desired implementation. The application context is usually obtained by calling AgsApplicationContext* ags_application_context_get_instance(). Make sure to instantiate an application context before using this function.

Implementations and their interfaces

The most basic application context implementing AgsConcurrencyProvider is AgsThreadApplicationContext. If you use your very own application context implementation make sure to set main loop, because AgsThread makes use of the appropriate getter AgsThread* ags_concurrency_provider_get_main_loop(AgsConcurrencyProvider*). Further for your very own application context you should set the AgsTaskLauncher in order to take advantage of launching AgsTask implementations. The interface allows you to set a thread pool and some worker threads if needed.

This example instantiates AgsThreadApplicationContext. By instantiating the application context the global variable ags_application_context is initially set. Later you can obtain your application context by calling AgsApplicationContext* ags_application_context_get_instance(). Later the code connects to the AgsApplicationContext::setup() signal. The void setup_callback(AgsApplicationContext*, gpointer) function sets the global variable start_loader to TRUE. This causes the prior added timeout to do the actual work with AgsTaskLauncher. The task launcher is obtained by calling AgsThread* ags_concurrency_provider_get_task_launcher(AgsConcurrencyProvider*).

Example 1.1. Thread application context

#include <glib.h>
#include <glib-object.h>

#include <ags/libags.h>

void setup_callback(AgsApplicationContext *application_context, gpointer user_data);
gboolean loader_timeout(AgsApplicationContext *application_context);

#define DEFAULT_LOADER_INTERVAL (1000 / 25)

AgsApplicationContext *application_context;
gboolean start_loader;

application_context = (AgsApplicationContext *) ags_thread_application_context_new();
g_object_ref(application_context);

g_signal_connect_after(application_context, "setup",
		       G_CALLBACK(setup_callback), NULL);

start_loader = FALSE;

g_timeout_add(DEFAULT_LOADER_INTERVAL,
	      loader_timeout,
	      application_context);

ags_application_context_prepare(application_context);
ags_application_context_setup(application_context);
  
/* main loop run */
g_main_loop_run(g_main_loop_new(g_main_context_default(),
				TRUE));

void
setup_callback(AgsApplicationContext *application_context, gpointer user_data)
{
  start_loader = TRUE;
}

gboolean
loader_timeout(AgsApplicationContext *application_context)
{
  AgsTaskLauncher *task_launcher;
  
  if(!start_loader){
    return(TRUE);
  }
  
  task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));

  //TODO: add some tasks to task_launcher

  return(FALSE);
}

      

The AgsAudioApplicationContext inherites from AgsApplicationContext and implements the AgsConcurrencyProvider interface, too. So you can retrieve the task launcher the same way. But the context implements one more, the AgsSoundProvider interface. Giving you objects related to threading and audio processing.

This example does the same as the prior, but this time instantiates the AgsAudioApplicationContext. The gboolean loader_timeout(AgsApplicationContext *application_context). does this time add the AgsStartSoundcard task to the task launcher.

Example 1.2. Audio application context

#include <glib.h>
#include <glib-object.h>

#include <ags/libags.h>
#include <ags/libags-audio.h>

void setup_callback(AgsApplicationContext *application_context, gpointer user_data);
gboolean loader_timeout(AgsApplicationContext *application_context);

#define DEFAULT_LOADER_INTERVAL (1000 / 25)

AgsApplicationContext *application_context;
gboolean start_loader;

application_context = (AgsApplicationContext *) ags_audio_application_context_new();
g_signal_connect_after(application_context, "setup",
		       G_CALLBACK(setup_callback), NULL);

start_loader = FALSE;

g_timeout_add(DEFAULT_LOADER_INTERVAL,
	      loader_timeout,
	      application_context);

ags_application_context_prepare(application_context);
ags_application_context_setup(application_context);
  
/* main loop run */
g_main_loop_run(g_main_loop_new(g_main_context_default(),
				TRUE));


void
setup_callback(AgsApplicationContext *application_context, gpointer user_data)
{
  start_loader = TRUE;
}

gboolean
loader_timeout(AgsApplicationContext *application_context)
{
  AgsTaskLauncher *task_launcher;
  AgsStartSoundcard *start_soundcard;
  
  if(!start_loader){
    return(TRUE);
  }
  
  task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));

  start_soundcard = ags_start_soundcard_new();

  ags_task_launcher_add_task(task_launcher,
			     start_soundcard);
  
  return(FALSE);
}