void cd_open_wm_config (void)
{
	const gchar *cConfigTool = _get_config_tool ();
	
	if (cConfigTool != NULL)
	{
		gchar *cmd = g_strdup_printf ("which %s", cConfigTool);
		gchar *cResult = cairo_dock_launch_command_sync (cmd);
		g_free (cmd);
		if (cResult == NULL || *cResult != '/')
      	{
			gchar *msg = g_strdup_printf (D_("You need to install '%s'"), cConfigTool);
			gldi_dialog_show_temporary_with_icon (msg, myIcon, myContainer, 6000, "same icon");
			g_free (msg);
      	}
		else
		{
			cairo_dock_launch_command (cConfigTool);
		}
	}
	else
	{
		gldi_dialog_show_temporary_with_icon (D_("No configuration tool is available."), myIcon, myContainer, 6000, "same icon");
	}
}
static void _cd_do_execute_command (CDEntry *pEntry)
{
    gchar *cCommand = g_strdup_printf ("%s/calc.sh '%s'", MY_APPLET_SHARE_DATA_DIR, myData.sCurrentText->str);
    gchar *cResult = cairo_dock_launch_command_sync (cCommand);
    g_free (cCommand);
    if (cResult != NULL && strcmp (cResult, "0") != 0)
    {
        g_print (" resultat du calcul : '%s'\n", cResult);
        GtkClipboard *pClipBoard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
        gtk_clipboard_set_text (pClipBoard, cResult, -1);
        Icon *pIcon = cairo_dock_get_dialogless_icon ();
        cairo_dock_show_temporary_dialog_with_icon (D_("The value %s has been copied into the clipboard."),
                pIcon,
                CAIRO_CONTAINER (g_pMainDock),
                3000,
                MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE,
                cResult);
    }
    else  // le calcul n'a rien donne, on execute sans chercher.
    {
        g_print (" pas un calcul => on execute '%s'\n", myData.sCurrentText->str);
        cairo_dock_launch_command (myData.sCurrentText->str);
    }
    g_free (cResult);
}
static gchar *_locate_files (const char *text, int iFilter, gboolean bWithLimit)
{
	GString *sCommand = g_string_new ("locate");
	g_string_append_printf (sCommand, " -d '%s/ScoobyDo/ScoobyDo.db'", g_cCairoDockDataDir);
	if (bWithLimit)
		g_string_append_printf (sCommand, " --limit=%d", myConfig.iNbResultMax);
	if (! (iFilter & DO_MATCH_CASE))
		g_string_append (sCommand, " -i");
	if (*text != '/')
		g_string_append (sCommand, " -b");
	
	if (iFilter == DO_FILTER_NONE || iFilter == DO_MATCH_CASE)
	{
		g_string_append_printf (sCommand, " \"%s\"", text);
	}
	else
	{
		if (iFilter & DO_TYPE_MUSIC)
		{
			g_string_append_printf (sCommand, " \"*%s*.mp3\" \"*%s*.ogg\" \"*%s*.wav\"", text, text, text);
		}
		if (iFilter & DO_TYPE_IMAGE)
		{
			g_string_append_printf (sCommand, " \"*%s*.jpg\" \"*%s*.jpeg\" \"*%s*.png\"", text, text, text);
		}
		if (iFilter & DO_TYPE_VIDEO)
		{
			g_string_append_printf (sCommand, " \"*%s*.avi\" \"*%s*.mkv\" \"*%s*.ogv\" \"*%s*.wmv\" \"*%s*.mov\"", text, text, text, text, text);
		}
		if (iFilter & DO_TYPE_TEXT)
		{
			g_string_append_printf (sCommand, " \"*%s*.txt\" \"*%s*.odt\" \"*%s*.doc\"", text, text, text);
		}
		if (iFilter & DO_TYPE_HTML)
		{
			g_string_append_printf (sCommand, " \"*%s*.html\" \"*%s*.htm\"", text, text);
		}
		if (iFilter & DO_TYPE_SOURCE)
		{
			g_string_append_printf (sCommand, " \"*%s*.[ch]\" \"*%s*.cpp\"", text, text);
		}
	}
	
	g_print (">>> %s\n", sCommand->str);
	gchar *cResult = cairo_dock_launch_command_sync (sCommand->str);
	if (cResult == NULL || *cResult == '\0')
	{
		g_free (cResult);
		return NULL;
	}
	
	return cResult;
}
gboolean _check_size_is_constant (GldiModuleInstance *myApplet, const gchar *cFilePath)
{
	int iSize = cairo_dock_get_file_size (cFilePath);
	gchar *cCommand = g_strdup_printf ("ping 127.0.0.1 -i 0.2 -c 2"); // On fait un temps d'arret de 200ms
	cairo_dock_launch_command (cCommand);
	gchar *cResult = cairo_dock_launch_command_sync (cCommand);
	g_free (cCommand);
	g_free (cResult);
	gboolean bConstantSize = (iSize != 0 && iSize == myData.iCurrentFileSize);
	myData.iCurrentFileSize = iSize;
	
	return bConstantSize;
}
static void upload (const gchar *cFilePath, gchar *cLocalDir, gboolean bAnonymous, gint iLimitRate, gchar **cResultUrls, GError **pError)
{
	// Upload the file
	gchar *cCommand = g_strdup_printf ("curl -L --connect-timeout 5 --retry 2 --limit-rate %dk http://videobin.org/add -F videoFile=@\"%s\" -F api=1", iLimitRate, cFilePath);
	cd_debug ("%s", cCommand);
	gchar *cURL = cairo_dock_launch_command_sync (cCommand);
	g_free (cCommand);

	if (cURL == NULL)
	{
		DND2SHARE_SET_GENERIC_ERROR_WEBSITE ("Videobin");
		return ;
	}

	cResultUrls[0] = cURL;
}
static gboolean _wm_is_running (CDWM *wm)
{
	const gchar *cCommand = wm->cCommand;
	gchar *cWhich = g_strdup_printf ("pgrep %s$", cCommand);  // see above for the '$' character.
	gchar *str = strchr (cWhich+6, ' ');  // remove any parameter to the command, we just want the program name.
	if (str)  // a space is found.
	{
		*str = '$';
		*(str+1) = '\0';
	}
	gchar *cResult = cairo_dock_launch_command_sync (cWhich);
	gboolean bIsRunning = (cResult != NULL && *cResult != '\0');
	
	g_free (cWhich);
	g_free (cResult);
	return bIsRunning;
}
static void _check_wms (CDSharedMemory *pSharedMemory)
{
	pSharedMemory->which = cairo_dock_launch_command_sync ("which compiz kwin xfwm4 metacity");
	
	pSharedMemory->ps = _get_running_wm ();
}
static inline gchar *_get_running_wm (void)
{
	return cairo_dock_launch_command_sync ("pgrep -l \"kwin$|compiz$|xfwm4$|metacity$\"");  // -l = write the name of the program (not the command next to the PID in 'ps -ef'. we add a '$' after the names to avoid listing things like compiz-decorator or xfwm4-settings
}
static gboolean init (gpointer *pData)
{
	gchar *cResult = cairo_dock_launch_command_sync ("which locate");
	
	gboolean bAvailable = (cResult != NULL && *cResult != '\0');
	g_free (cResult);
	cd_debug ("locate available : %d", bAvailable);
	
	if (bAvailable)
	{
		gchar *cDirPath = g_strdup_printf ("%s/ScoobyDo", g_cCairoDockDataDir);
		if (! g_file_test (cDirPath, G_FILE_TEST_IS_DIR))
		{
			if (g_mkdir (cDirPath, 7*8*8+7*8+5) != 0)
			{
				cd_warning ("couldn't create directory %s", cDirPath);
				g_free (cDirPath);
				return FALSE;
			}
		}
		
		gchar *cDataBase = g_strdup_printf ("%s/ScoobyDo.db", cDirPath);
		gchar *cLastUpdateFile = g_strdup_printf ("%s/.last-update", cDirPath);
		gboolean bNeedsUpdate = FALSE;
		
		if (! g_file_test (cDataBase, G_FILE_TEST_EXISTS))
		{
			bNeedsUpdate = TRUE;
		}
		else
		{
			if (! g_file_test (cLastUpdateFile, G_FILE_TEST_EXISTS))
			{
				bNeedsUpdate = TRUE;
			}
			else
			{
				gsize length = 0;
				gchar *cContent = NULL;
				g_file_get_contents (cLastUpdateFile,
					&cContent,
					&length,
					NULL);
				if (cContent == NULL || *cContent == '\0')
				{
					bNeedsUpdate = TRUE;
				}
				else
				{
					time_t iLastUpdateTime = atoll (cContent);
					time_t iCurrentTime = (time_t) time (NULL);
					if (iCurrentTime - iLastUpdateTime > 86400)
					{
						bNeedsUpdate = TRUE;
					}
				}
				g_free (cContent);
			}
		}
		
		if (bNeedsUpdate)
		{
			cairo_dock_launch_command (MY_APPLET_SHARE_DATA_DIR"/updatedb.sh");
			gchar *cDate = g_strdup_printf ("%ld", time (NULL));
			g_file_set_contents (cLastUpdateFile,
				cDate,
				-1,
				NULL);
			g_free (cDate);
		}
		
		g_free (cDataBase);
		g_free (cLastUpdateFile);
		g_free (cDirPath);
	}
	
	return bAvailable;
}
//Fonction de lecture du tuyau.
void cd_xmms_read_pipe (CairoDockModuleInstance *myApplet)
{
	//\________________________ On determine le pipe.
	gchar *cPipeCommand = NULL;
	switch (myConfig.iPlayer) {  // On emule un pipe pour les lecteurs qui n'en ont pas.
		case MY_XMMS :
		break ;
		case MY_AUDACIOUS :  //Il faut émuler le pipe d'audacious par AUDTOOL
			cPipeCommand = g_strdup_printf ("bash %s/infoaudacious.sh", MY_APPLET_SHARE_DATA_DIR);
		break ;
		case MY_BANSHEE :  //Le pipe est trop lent et cause des freezes... // Il faut émuler le pipe de banshee par le script
			cPipeCommand = g_strdup_printf ("bash %s/infobanshee.sh", MY_APPLET_SHARE_DATA_DIR);
		break ;
		case MY_EXAILE :  //Le pipe est trop lent, récupération des infos une fois sur deux avec un pique du cpu lors de l'éxécution du script // Il faut émuler le pipe d'audacious par Exaile -q
			cPipeCommand = g_strdup_printf ("bash %s/infoexaile.sh", MY_APPLET_SHARE_DATA_DIR);
		break ;
		default :
		break ;
	}
	
	//\________________________ On lit le pipe.
	gchar *cResult = NULL;
	if (cPipeCommand != NULL)  // c'est un lecteur avec un pipe emule.
	{
		cResult = cairo_dock_launch_command_sync (cPipeCommand);
		g_free (cPipeCommand);
	}
	else if (myConfig.iPlayer == MY_XMMS)  // c'est XMMS, il a deja son propre pipe.
	{
		gchar *cPipe = g_strdup_printf ("/tmp/xmms-info_%s.0",g_getenv ("USER"));
		gsize length=0;
		GError *erreur = NULL;
		g_file_get_contents (cPipe, &cResult, &length, &erreur);
		
		if (erreur != NULL) {
			cd_warning("xmms : %s", erreur->message);
			g_error_free(erreur);
		}
		
		g_free (cPipe);
	}
	
	if (cResult == NULL)  // erreur lors de la leture du pipe, on sort.
	{
		myData.playingStatus = PLAYER_NONE;
		cd_xmms_player_none (myApplet);
		return;
	}
	
	//\________________________ On recupere les donnees.
	gchar **cInfopipesList = g_strsplit(cResult, "\n", -1);
	g_free(cResult);
	
	gchar *cQuickInfo = NULL;
	gchar *cOneInfopipe;
	myData.iTrackNumber = -1;
	myData.iCurrentTime = -1;
	myData.iSongLength = -1;
	int *pLineNumber = s_pLineNumber[myConfig.iPlayer];
	int i;
	for (i = 0; cInfopipesList[i] != NULL; i ++) {
		cOneInfopipe = cInfopipesList[i];
		if (i == pLineNumber[INFO_STATUS]) {
			gchar *str = strchr (cOneInfopipe, ' ');
			if (str != NULL) {
				str ++;
				while (*str == ' ')
					str ++;
				if ((strcmp (str, "Playing") == 0) || (strcmp (str, "playing") == 0))
					myData.playingStatus = PLAYER_PLAYING;
				else if ((strcmp (str, "Paused") == 0) || (strcmp (str, "paused") == 0))
					myData.playingStatus = PLAYER_PAUSED;
				else if ((strcmp (str, "Stopped") == 0) || (strcmp (str, "stopped") == 0))
					myData.playingStatus = PLAYER_STOPPED;
				else
					myData.playingStatus = PLAYER_BROKEN;
			}
			else
				myData.playingStatus = PLAYER_BROKEN;
		}
		else if (i == pLineNumber[INFO_TRACK_IN_PLAYLIST]) {
			if (myConfig.quickInfoType == MY_APPLET_TRACK) {
				gchar *str = strchr (cOneInfopipe, ':');
				if (str != NULL) {
					str ++;
					while (*str == ' ')
						str ++;
					myData.iTrackNumber = atoi (str);
				}
			}
		}
		else if (i == pLineNumber[INFO_TIME_ELAPSED_IN_SEC]) {
			if (myConfig.quickInfoType == MY_APPLET_TIME_ELAPSED || myConfig.quickInfoType == MY_APPLET_TIME_LEFT) {
				gchar *str = strchr (cOneInfopipe, ' ');
				if (str != NULL) {
					str ++;
					while (*str == ' ')
						str ++;
					if (*str != 'N')
						myData.iCurrentTime = atoi(str) * 1e-3;
				}
			}
		}
		else if (i == pLineNumber[INFO_TIME_ELAPSED]) {
			if ((myConfig.quickInfoType == MY_APPLET_TIME_ELAPSED || myConfig.quickInfoType == MY_APPLET_TIME_LEFT) && myData.iCurrentTime == -1) {
				gchar *str = strchr (cOneInfopipe, ' ');
				if (str != NULL) {
					str ++;
					while (*str == ' ')
						str ++;
					gchar *str2 = strchr (str, ':');
					if (str2 == NULL) { // pas de minutes.
						myData.iCurrentTime = atoi(str);
					}
					else {
						*str2 = '\0';
						myData.iCurrentTime = atoi(str2+1) + 60*atoi (str);  // prions pour qu'ils n'ecrivent jamais les heures ... xD
					}
				}
			}
		}
		else if (i == pLineNumber[INFO_TOTAL_TIME_IN_SEC]) {
			if (myConfig.quickInfoType == MY_APPLET_TIME_LEFT) {
				gchar *str = strchr (cOneInfopipe, ' ');
				if (str != NULL) {
					str ++;
					while (*str == ' ')
						str ++;
					if (*str != 'N')
						myData.iSongLength = atoi(str) * 1e-3;
				}
			}
		}
		else if (i == pLineNumber[INFO_TOTAL_TIME]) {
			if (myConfig.quickInfoType == MY_APPLET_TIME_LEFT && myData.iSongLength == -1) {
				gchar *str = strchr (cOneInfopipe, ' ');
				if (str != NULL) {
					str ++;
					while (*str == ' ')
						str ++;
					gchar *str2 = strchr (str, ':');
					if (str2 == NULL) { // pas de minutes.
						myData.iSongLength = atoi(str);
					}
					else {
						*str2 = '\0';
						myData.iSongLength = atoi(str2+1) + 60*atoi (str);  // prions pour qu'ils n'ecrivent jamais les heures ...
					}
				}
			}
		}
		else if (i == pLineNumber[INFO_NOW_TITLE]) {
			gchar *str = strchr (cOneInfopipe, ':');
			if (str != NULL) {
				str ++;
				while (*str == ' ')
					str ++;
				if ((strcmp(str," (null)") != 0) && (myData.playingTitle == NULL || strcmp(str, myData.playingTitle) != 0)) {
					g_free (myData.playingTitle);
					myData.playingTitle = g_strdup (str);
					cd_message("On a changé de son! (%s)", myData.playingTitle);
					cd_xmms_change_desklet_data(myApplet);
				}
			}
		}
	}  // fin de parcours des lignes.
	g_strfreev (cInfopipesList);
	
	if (myConfig.iPlayer != MY_XMMS) {
		g_remove (s_cTmpFile);
	}
	g_free (s_cTmpFile);
	s_cTmpFile = NULL;
}