1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
|
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE chapter
[
<!ENTITY libagsthreadso "libags_thread.so">
<!ENTITY libagsaudioso "libags_audio.so">
<!ENTITY libagsso "libags.so">
<!ENTITY chap1 "chapter 1">
<!ENTITY % agsdocentities SYSTEM "xml/agsdocentities.ent">
%agsdocentities;
]>
<!-- Copyright (C) 2005-2021 Jo\u00EBl Kr\u00E4hemann -->
<!-- Permission is granted to copy, distribute and/or modify this document -->
<!-- under the terms of the GNU Free Documentation License, Version 1.3 -->
<!-- or any later version published by the Free Software Foundation; -->
<!-- with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. -->
<!-- A copy of the license is included in the section entitled "GNU -->
<!-- Free Documentation License". -->
<chapter xmlns="http://docbook.org/ns/docbook"
xmlns:xi="http://www.w3.org/2001/XInclude" version="5.0">
<title>The application context</title>
<para>
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.
</para>
<itemizedlist mark="bullet">
<listitem>
<para>
AgsConcurrencyProvider
</para>
</listitem>
<listitem>
<para>
AgsServiceProvider
</para>
</listitem>
<listitem>
<para>
AgsSoundProvider
</para>
</listitem>
</itemizedlist>
<para>
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.
</para>
<para>
Since AgsApplicationContext is a singleton you create only 1 instance of your
desired implementation. The application context is usually obtained by calling
<code language="C">AgsApplicationContext* ags_application_context_get_instance()</code>.
Make sure to instantiate an application context before using this function.
</para>
<sect1>
<title>Implementations and their interfaces</title>
<para>
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
<code language="C">AgsThread* ags_concurrency_provider_get_main_loop(AgsConcurrencyProvider*)</code>.
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.
</para>
<para>
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
<code language="C">AgsApplicationContext* ags_application_context_get_instance()</code>.
Later the code connects to the AgsApplicationContext::setup() signal. The
<code language="C">void setup_callback(AgsApplicationContext*, gpointer)</code>
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
<code language="C">AgsThread* ags_concurrency_provider_get_task_launcher(AgsConcurrencyProvider*)</code>.
</para>
<example>
<title>Thread application context</title>
<programlisting language="C">
<xi:include href="../listings/thread_application_context.c" parse="text" />
</programlisting>
</example>
<para>
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.
</para>
<para>
This example does the same as the prior, but this time instantiates the AgsAudioApplicationContext.
The <code language="C">gboolean loader_timeout(AgsApplicationContext *application_context)</code>.
does this time add the AgsStartSoundcard task to the task launcher.
</para>
<example>
<title>Audio application context</title>
<programlisting language="C">
<xi:include href="../listings/audio_application_context.c" parse="text" />
</programlisting>
</example>
</sect1>
<sect1>
<title>The main loop property</title>
<para>
AgsApplicationContext:main-loop does usually point to an AgsThread implementing
AgsMainLoop interface. &libagsthreadso; provides you the AgsGenericMainLoop object or
if you intend to use &libagsaudioso;, this property shall point to AgsAudioLoop.
</para>
<para>
However you should rather use <code language="C">AgsThread* ags_concurrency_provider_get_main_loop(AgsConcurrencyProvider*)</code>
to obtain the main loop instead.
</para>
</sect1>
<sect1>
<title>The config property</title>
<para>
The AgsApplicationContext base class provides you an AgsConfig instance. It might
load a default configuration or from current users home directory.
</para>
<para>
Since AgsConfig is a singleton you should obtain it by calling <code language="C">AgsConfig* ags_config_get_instance()</code>.
</para>
<para>
AgsConfig stores its properties as key value pairs within appropriate group. In order
to get the config instance, load default configuration and get the threading model do
the following.
</para>
<example>
<title>Get config value</title>
<programlisting language="C">
<xi:include href="../listings/config.c" parse="text" />
</programlisting>
</example>
</sect1>
<sect1>
<title>The file property</title>
<para>
You might want to set an AgsFile or AgsSimpleFile instance within your application context. This in
view of having your application persisted.
</para>
<example>
<title>The application context :file property</title>
<programlisting language="C">
<xi:include href="../listings/file_property.c" parse="text" />
</programlisting>
</example>
</sect1>
<sect1>
<title>The application mutex</title>
<para>
As version 2.0.x the application mutex was superseeded by the class mutices and a common field
:obj-mutex used by various types. The AgsMutexManager is still around but with less importance.
</para>
</sect1>
<sect1>
<title>Program start and termination</title>
<para>
The application context provides signals to make your application ready to run. You
basically implement AgsApplicationContext::prepare, AgsApplicationContext::setup and
AgsApplicationContext::register-types. It is upto you how the application shall behave.
</para>
<para>
Note since version 3.13.0 you call only AgsApplicationContext::prepare, which calls
AgsApplicationContext::setup and then enters GLib's main loop. So the prepare signal
won't return unless you terminate your application.
</para>
<para>
AgsApplicationContext::quit signal terminates your application. Feel free to provide your
own implementation.
</para>
</sect1>
<sect1>
<title>Abstract data connection</title>
<para>
AgsDataConnectionManager and AgsConnection are removed in 2.0.x. The object was somehow
overhelming because you can have properties.
</para>
<para>
The AgsConnectable interface provides 2 new
functions: <code language="C">void ags_connectable_connect_connection(AgsConnectable*, GObject*)</code> and
<code language="C">void ags_connectable_disconnect_connection(AgsConnectable*, GObject*)</code>.
</para>
<para>
Dependencies not know an instantiation time can be later connected.
</para>
</sect1>
<sect1>
<title>Common interfaces</title>
<para>
Use AgsConnectable if you intend to listen to a particular
event. If you want to connect an event of an object known during instantiation time
use ::connect and ::disconnect. Assumed the object needs to be resolved, you can
::connect-connection ::disconnect-connection, later.
</para>
<para>
AgsPlugin interface provides persistence to a well known abstract base type. Since it
has various implementations, this interface provides <code language="C">void ags_plugin_read(AgsFile*, xmlNode*, AgsPlugin*)</code>
and <code language="C">xmlNode* ags_plugin_write(AgsFile*, xmlNode*, AgsPlugin*)</code>
</para>
<para>
Likewise there are the interfaces intended to use with sound related objects AgsSoundcard,
AgsSequencer, AgsMutable and AgsSeekable.
</para>
</sect1>
</chapter>
|