~ubuntu-branches/ubuntu/saucy/cairo-dock-plug-ins/saucy

« back to all changes in this revision

Viewing changes to Impulse/src/applet-impulse.c

  • Committer: Matthieu Baerts
  • Date: 2011-08-09 19:51:45 UTC
  • mfrom: (1.1.12 upstream)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: matttbe@gmail.com-20110809195145-6t55jtykipujuyn5
* New upstream release. (LP: #823514)
* Upstream (short) ChangeLog:
 - The Power-Manager applet has been rewritten to work on any plateform.
 - Compiz-icon applet has been replaced by Composite-Manager.
 - Improved integration in the XFCE, LXDE and GNOME3 desktop.
 - Logout is now working even if there is no/an unknow session manager.
 - Several new DBus methods lets you interact on the dock more easily.
 - Added the possibility to shutdown/logout with GMenu.
 - Improved Status-Notifier and added its own watcher.
 - Added a new applet: Impulse (still need testing).
 - Fixed a few bugs as usual.
* debian/patches:
 - Removed all patches (they was already unapplied).
* debian/copyright:
 - Updated with new files/directory.
* debian/cairo-dock-plug-ins.install:
 - Added status-notifier-watcher used by Status-Notifier applet.
* debian/control:
 - Updated the version of cairo-dock-[core;data;dev].
 - Bump Standard-Version to 3.9.2.
 - Added fftw3, pulse (Impulse) and upower-glib (Logout)
    as new dependences for the build process.
 - Added indicator-[me;messages] as new recommendations
    for cairo-dock-plug-ins (needed for [Me;Messaging]Menu applets).
 - Removed gawk from the build dependences list (no longer needed).
* cairo-dock-plug-ins package needs to be recompiled (LP: #811579)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
* This file is a part of the Cairo-Dock project
 
3
*
 
4
* Copyright : (C) see the 'copyright' file.
 
5
* E-mail    : see the 'copyright' file.
 
6
*
 
7
* This program is free software; you can redistribute it and/or
 
8
* modify it under the terms of the GNU General Public License
 
9
* as published by the Free Software Foundation; either version 3
 
10
* of the License, or (at your option) any later version.
 
11
*
 
12
* This program is distributed in the hope that it will be useful,
 
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
* GNU General Public License for more details.
 
16
* You should have received a copy of the GNU General Public License
 
17
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
18
*/
 
19
 
 
20
#include <stdint.h>
 
21
#include <stdio.h>
 
22
#include <unistd.h>
 
23
#include <glib.h>
 
24
 
 
25
#include "applet-impulse.h"
 
26
#include "Impulse.h"
 
27
 
 
28
#define IM_TAB_SIZE 256
 
29
 
 
30
extern CairoDockHidingEffect *g_pHidingBackend;  // cairo_dock_is_hidden
 
31
 
 
32
////////////////// IMPULSE \\\\\\\\\\\\\\\\\\\\
 
33
 
 
34
void _im_start (void)
 
35
{
 
36
        cd_debug ("Impulse: start im");
 
37
        im_start ();
 
38
}
 
39
 
 
40
void _im_stop (void)
 
41
{
 
42
        cd_debug ("Impulse: stop im");
 
43
        //im_stop(); // FIXME => if stopped, the client is not stopped and im_getSnapshot(IM_FFT) give always the same thing...
 
44
}
 
45
 
 
46
void cd_impulse_im_setSourceIndex (gint iSourceIndex)
 
47
{
 
48
        cd_debug ("Impulse: iSourceIndex = %d", iSourceIndex);
 
49
        im_setSourceIndex (iSourceIndex);
 
50
}
 
51
 
 
52
////////////////// USEFUL FUNCTIONS \\\\\\\\\\\\\\\\\\\\
 
53
 
 
54
static void _get_icons_list_without_separators (CDSharedMemory *pSharedMemory)
 
55
{
 
56
        if (pSharedMemory->pDock == NULL)
 
57
        {
 
58
                pSharedMemory->pIconsList = NULL;
 
59
                return;
 
60
        }
 
61
 
 
62
        pSharedMemory->bIsUpdatingIconsList = TRUE;
 
63
 
 
64
        pSharedMemory->pIconsList = NULL;
 
65
        GList *ic;
 
66
        Icon *pIcon;
 
67
        for (ic = pSharedMemory->pDock->icons; ic != NULL; ic = ic->next)
 
68
        {
 
69
                pIcon = ic->data;
 
70
                // cd_debug ("Impulse: icon name=%s", pIcon->cName);
 
71
                if (! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon))
 
72
                        pSharedMemory->pIconsList = g_list_append (pSharedMemory->pIconsList, pIcon);
 
73
        }
 
74
        g_list_free (ic);
 
75
        pSharedMemory->bIsUpdatingIconsList = FALSE;
 
76
        cd_debug ("Impulse: updated icons list: %d", g_list_length(pSharedMemory->pIconsList));
 
77
}
 
78
 
 
79
//static gboolean _animate_the_dock (CDSharedMemory *pSharedMemory)
 
80
static gboolean _animate_the_dock (gpointer data)
 
81
{
 
82
        CD_APPLET_ENTER;
 
83
        // cd_debug ("Impulse: in");
 
84
        if (myData.pSharedMemory->bIsUpdatingIconsList
 
85
                || cairo_dock_is_hidden (myData.pSharedMemory->pDock)) // not needed for the animations but not for pulse.
 
86
                CD_APPLET_LEAVE (TRUE);
 
87
 
 
88
        if (myData.pSharedMemory->pIconsList == NULL)
 
89
        {
 
90
                cd_impulse_stop_animations ();
 
91
                CD_APPLET_LEAVE (FALSE);
 
92
        }
 
93
 
 
94
        guint iIcons = IM_TAB_SIZE / g_list_length (myData.pSharedMemory->pIconsList); // number of icons (without separators)
 
95
 
 
96
        double *array = im_getSnapshot(IM_FFT);
 
97
 
 
98
        // we check if there is a signal (most of the time, all values are > 0)
 
99
        if (array[0] == 0.0)
 
100
        {       // is it really null?
 
101
                int j;
 
102
                for (j = 1; j < IM_TAB_SIZE; j++)
 
103
                {
 
104
                        if (array[j] != 0)
 
105
                                break; // there is a signal
 
106
                }
 
107
 
 
108
                cd_debug ("Impulse: No Signal? %d", j);
 
109
                if (j == IM_TAB_SIZE)
 
110
                        CD_APPLET_LEAVE (TRUE);
 
111
                /* TODO?
 
112
                        * if null, increase the time of the loop?
 
113
                        * Maybe use: PA_SUBSCRIPTION_EVENT_CLIENT?
 
114
                        * or something else in pulse?
 
115
                        */
 
116
        }
 
117
 
 
118
        // Computing and animations
 
119
        int i;
 
120
        double l = 0.0;
 
121
        GList *ic = myData.pSharedMemory->pIconsList;
 
122
        Icon *pIcon;
 
123
        gboolean bHasNotBeenAnimated = TRUE;
 
124
        for (i = 0; ic != NULL; i++) // i < 256
 
125
        {
 
126
                l += array[i]; // a sum for the average
 
127
                if (i != 0 && (i % iIcons) == 0)
 
128
                {
 
129
                        pIcon = ic->data;
 
130
                        // cd_debug ("Impulse: Average: i=%d, l=%f ; I=%d ; l/I=%f ; %s", i, l, iIcons, l/iIcons, pIcon->cName);
 
131
                        if ((l/iIcons) > myData.pSharedMemory->fMinValueToAnim) // animation
 
132
                        {
 
133
                                //cd_debug ("Impulse: animation on this icon=%s", pIcon->cName);
 
134
                                cairo_dock_request_icon_animation (pIcon,
 
135
                                        myData.pSharedMemory->pDock,
 
136
                                        myData.pSharedMemory->cIconAnimation,
 
137
                                        myData.pSharedMemory->iNbAnimations);
 
138
                                bHasNotBeenAnimated = FALSE;
 
139
                                myData.pSharedMemory->bNeedRefreshIfNotAnimated = TRUE;
 
140
                        }
 
141
                        else if (myData.pSharedMemory->bStopAnimations)
 
142
                                cairo_dock_stop_icon_animation (pIcon);
 
143
                        l = 0.0;
 
144
                        ic = ic->next;
 
145
                }
 
146
        }
 
147
        if (bHasNotBeenAnimated && myData.pSharedMemory->bStopAnimations && myData.pSharedMemory->bNeedRefreshIfNotAnimated)
 
148
        {
 
149
                cd_debug ("Impulse: refresh container");
 
150
                cairo_dock_redraw_container (CAIRO_CONTAINER (myData.pSharedMemory->pDock));
 
151
                myData.pSharedMemory->bNeedRefreshIfNotAnimated = FALSE; // no need of refresh until the next animation and if bHasNotBeenAnimated
 
152
        }
 
153
 
 
154
        //cd_debug ("Impulse: out");
 
155
        g_list_free (ic);
 
156
        CD_APPLET_LEAVE (TRUE);
 
157
}
 
158
 
 
159
static gboolean _impulse_check_pulse_status (void)
 
160
{
 
161
        myData.iSidCheckStatus = 0;
 
162
 
 
163
        cd_debug ("Impulse: checking PulseAudio Context status");
 
164
 
 
165
        if (! myData.bHasBeenStarted && im_context_state () == IM_FAILED)
 
166
        {
 
167
                cd_impulse_stop_animations ();
 
168
                cd_debug ("Impulse: starting failed");
 
169
                cairo_dock_remove_dialog_if_any (myIcon);
 
170
                cairo_dock_show_temporary_dialog_with_icon (D_("There is something wrong with PulseAudio.\nCan you check its status (installed? running? version?) and report this bug (if any) to forum.glx-dock.org"),
 
171
                        myIcon,
 
172
                        myContainer,
 
173
                        5000,
 
174
                        MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
 
175
                CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cIconImpulseERROR, "impulse-error.svg");
 
176
        }
 
177
 
 
178
        return FALSE;
 
179
}
 
180
 
 
181
////////////////// NOTIFICATIONS \\\\\\\\\\\\\\\\\\\\
 
182
 
 
183
/*void cd_impulse_start_animations (void)
 
184
{
 
185
        myData.iSidAnimate = g_timeout_add (myConfig.iLoopTime, (GSourceFunc) _animate_the_dock, NULL);
 
186
}*/
 
187
 
 
188
void _remove_notifications (void)
 
189
{
 
190
        cairo_dock_remove_notification_func_on_object (&myDocksMgr,
 
191
                NOTIFICATION_ICON_MOVED,
 
192
                (CairoDockNotificationFunc) cd_impulse_on_icon_changed, NULL);
 
193
        cairo_dock_remove_notification_func_on_object (&myDocksMgr,
 
194
                NOTIFICATION_INSERT_ICON,
 
195
                (CairoDockNotificationFunc) cd_impulse_on_icon_changed, NULL);
 
196
        cairo_dock_remove_notification_func_on_object (&myDocksMgr,
 
197
                NOTIFICATION_REMOVE_ICON,
 
198
                (CairoDockNotificationFunc) cd_impulse_on_icon_changed, NULL);
 
199
}
 
200
 
 
201
void _register_notifications (void)
 
202
{
 
203
        cairo_dock_register_notification_on_object (&myDocksMgr,
 
204
                NOTIFICATION_ICON_MOVED,
 
205
                (CairoDockNotificationFunc) cd_impulse_on_icon_changed,
 
206
                CAIRO_DOCK_RUN_FIRST, NULL);
 
207
        cairo_dock_register_notification_on_object (&myDocksMgr,
 
208
                NOTIFICATION_INSERT_ICON,
 
209
                (CairoDockNotificationFunc) cd_impulse_on_icon_changed,
 
210
                CAIRO_DOCK_RUN_FIRST, NULL);
 
211
        cairo_dock_register_notification_on_object (&myDocksMgr,
 
212
                NOTIFICATION_REMOVE_ICON,
 
213
                (CairoDockNotificationFunc) cd_impulse_on_icon_changed,
 
214
                CAIRO_DOCK_RUN_FIRST, NULL);
 
215
}
 
216
 
 
217
////////////////// GENERAL FUNCTIONS \\\\\\\\\\\\\\\\\\\\
 
218
 
 
219
void cd_impulse_stop_animations (void)
 
220
{
 
221
        //if (myData.pTask != NULL)
 
222
        if (myData.iSidAnimate != 0)
 
223
        {
 
224
                /*cairo_dock_discard_task (myData.pTask);
 
225
                myData.pTask = NULL;*/
 
226
                g_source_remove (myData.iSidAnimate);
 
227
                myData.iSidAnimate = 0;
 
228
                // _free_shared_memory (myData.pSharedMemory);
 
229
                _remove_notifications ();
 
230
        }
 
231
        if (myData.bPulseLaunched)
 
232
                _im_stop();
 
233
        cd_impulse_draw_current_state ();
 
234
        // myData.bPulseLaunched = FALSE; //FIXME => if already started and stopped, it will crash... because not correctly stopped...
 
235
}
 
236
 
 
237
void cd_impulse_launch_task (void) //(CairoDockModuleInstance *myApplet)
 
238
{
 
239
        // if a task is already launching
 
240
        /*if (myData.pTask != NULL)
 
241
        {
 
242
                cairo_dock_discard_task (myData.pTask);
 
243
                myData.pTask = NULL;
 
244
        }*/
 
245
        if (myData.iSidAnimate != 0)
 
246
                cd_impulse_stop_animations ();
 
247
 
 
248
        // PulseAudio Server
 
249
        if (! myData.bPulseLaunched)
 
250
        {
 
251
                _im_start (); // FIXME => if already started and stopped, it will crash... because not correctly stopped...
 
252
                myData.bPulseLaunched = TRUE;
 
253
        }
 
254
 
 
255
        /*myData.pTask = cairo_dock_new_task_full (1,// (SECOND) myConfig.iLoopTime,
 
256
                // (CairoDockGetDataAsyncFunc) _get_icons_list_without_separators,
 
257
                NULL,
 
258
                (CairoDockUpdateSyncFunc) _animate_the_dock,
 
259
                (GFreeFunc) _free_shared_memory,
 
260
                myData.pSharedMemory);
 
261
        _get_icons_list_without_separators (myData.pSharedMemory);
 
262
        cairo_dock_launch_task (myData.pTask);*/
 
263
 
 
264
        _get_icons_list_without_separators (myData.pSharedMemory);
 
265
        _register_notifications();
 
266
 
 
267
        myData.iSidAnimate = g_timeout_add (myConfig.iLoopTime, (GSourceFunc) _animate_the_dock, NULL); // or into a thread + time?
 
268
        cd_debug ("Impulse: animations started (checking status: %d)", myData.iSidCheckStatus);
 
269
        cd_impulse_draw_current_state ();
 
270
 
 
271
        if (myData.iSidCheckStatus == 0)
 
272
                myData.iSidCheckStatus = g_timeout_add_seconds (1, (GSourceFunc) _impulse_check_pulse_status, NULL);
 
273
}
 
274
 
 
275
gboolean cd_impulse_on_icon_changed (gpointer pUserData, Icon *pIcon, CairoDock *pDock)
 
276
{
 
277
        // launched and something has changed in the right dock
 
278
        //cd_debug ("Impulse: update needed? %d | %d", pDock, myConfig.pDock);
 
279
        if (myData.iSidAnimate != 0 && pDock == myConfig.pDock)
 
280
        {
 
281
                _get_icons_list_without_separators (myData.pSharedMemory);
 
282
        }
 
283
        return CAIRO_DOCK_LET_PASS_NOTIFICATION;
 
284
}
 
285
 
 
286
void cd_impulse_draw_current_state (void)
 
287
{
 
288
        if (myData.iSidAnimate != 0)
 
289
                CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cIconImpulseON, "impulse-running.svg");
 
290
        else
 
291
                CD_APPLET_SET_USER_IMAGE_ON_MY_ICON (myConfig.cIconImpulseOFF, "impulse-stopped.svg");
 
292
}
 
293
 
 
294
////////////////// DELAY \\\\\\\\\\\\\\\\\\\\
 
295
 
 
296
static gboolean _impulse_restart_delayed (void)
 
297
{
 
298
        myData.iSidRestartDelayed = 0;
 
299
 
 
300
        if (! myData.bHasBeenStarted)
 
301
        {
 
302
                myData.bHasBeenStarted = TRUE;
 
303
                cd_message ("Impulse has been started");
 
304
 
 
305
                if (myConfig.bFree) // It's maybe a hack but Cairo-Penguin does that :)
 
306
                {
 
307
                        cairo_dock_detach_icon_from_dock (myIcon, myDock, myIconsParam.iSeparateIcons);
 
308
                        cairo_dock_update_dock_size (myDock);
 
309
                }
 
310
                else
 
311
                        cairo_dock_insert_icon_in_dock (myIcon, myDock, CAIRO_DOCK_UPDATE_DOCK_SIZE, CAIRO_DOCK_ANIMATE_ICON);
 
312
 
 
313
                cd_impulse_launch_task (); // launched the animations
 
314
        }
 
315
 
 
316
        return FALSE;
 
317
}
 
318
 
 
319
void cd_impulse_start_animating_with_delay (void)
 
320
{
 
321
        if (myData.iSidRestartDelayed != 0)
 
322
                return ;
 
323
 
 
324
        if (cairo_dock_is_loading ())
 
325
                myData.iSidRestartDelayed = g_timeout_add_seconds (2, (GSourceFunc) _impulse_restart_delayed, NULL);  // priority to the loading of the dock
 
326
        else
 
327
                myData.iSidRestartDelayed = g_timeout_add_seconds (1, (GSourceFunc) _impulse_restart_delayed, NULL);  // if we have to detach the icon
 
328
}