PDA

View Full Version : Switching profiles with a script


Arcnsparc
January 9th, 2008, 12:08 AM
I am trying to hotkey different compiz settings through gconf. I think the way I will have to do this is through a script that does something like this:

Metacity replace (to turn off compiz)
Replace compiz profile via cp or something like that
compiz replace (this startup it should use the new settings)

I am just trying to figure out where the .profile file that compiz uses at start up is so I can pull the switcheroo...

Thanks for any help!

Deciare
January 9th, 2008, 12:55 AM
*.profile files aren't actually used by the compizconfig system. They only store settings so that you can import them onto other computers or user accounts, so you won't need them at all if you're only moving between different profiles on the same user account.

What actually happens when you switch profiles depends on the configuration backend you're using with the ccp plugin.


If you use the Flat-file configuration backend, each "profile" is stored as a separate .ini file in the ~/.config/compiz/compizconfig/ directory. The particular file read by the ccp plugin is dependent on the contents of the file named ~/.config/compiz/compizconfig/config:
[gnome_session]
backend = ini
profile =
integration = false
If the profile field is blank, settings are read from Default.ini. If the profile field contains the name of a profile, then settings are read from name_of_profile.ini. So switching profiles doesn't involve copying files at all, but replacing a single line in the config file. :) This command will do it:
sed -i -e 's/profile = .*/profile = name_of_new_profile/' ~/.config/compiz/compizconfig/config


If you use the GConf configuration backend, it's a little more complicated. Your currently active settings are kept under /apps/compiz of the GConf database. Settings for your other profiles are kept under /apps/compizconfig/profiles/name_of_profile. Changing your profile involves replacing the profile field in your ~/.config/compiz/compizconfig/config file (as described above), then taking the current settings under /apps/compiz and saving them under /apps/compizconfig/profiles/name_of_old_profile, and taking the new settings from /apps/compizconfig/profiles/name_of_new_profile and saving them into /apps/compiz. You'll probably need to use multiple commands:
sed -i -e 's/profile = .*/profile = name_of_new_profile/' ~/.config/compiz/compizconfig/config

# Fetch data from GConf database about the profile we're about to switch away from, and the new profile we're about to switch to
gconftool-2 --dump /apps/compiz >oldprofile.xml
gconftool-2 --dump /apps/compizconfig/profiles/name_of_new_profile >newprofile.xml

# Remove stale data from GConf database
gconftool-2 --recursive-unset /apps/compiz
gconftool-2 --recursive-unset /apps/compizconfig/profiles/name_of_new_profile

# Load new profile data into /apps/compiz, save old profile data into /apps/compizconfig/profiles
gconftool-2 --load newprofile.xml /apps/compiz
gconftool-2 --load oldprofile.xml /apps/compizconfig/profiles/name_of_old_profile

Arcnsparc
January 9th, 2008, 03:03 AM
Thanks! This is exactly what I needed, Ive been trying to do this for a week and since im new to linux its been kinda hard. At first I didn't think that I would have to save my old profiles, but then when I was switching between profiles manually it would reset individual plugin settings back to default. This is why I should include the Save Old Profile stuff in there isn't it? When I change profiles it even dumps the Commands and Run Command settings.

Just to recap, this doesn't change the profile in the preferences tab right? I ran the script and that didnt change. All I could tell that the script did was generate two XML files next to it, and the first line worked putting in the new profile in the config file.

Would it be easier for me to forget the Gconf route and go with the flat file back end? That would make a script much easier I think. But then how would I hotkey the switches without gconf? I tried using gconf-editor to change the commands and global key bindings in metacity like i did before to assign hotkeys, but they wont work if im using a flat file back end...

Im sorry for all the trouble and I really am thankful, this will really help me convert my friends and family to ubuntu when I can show off such a pretty and free system.

Arcnsparc
January 9th, 2008, 03:12 AM
After some thought, it seems to get my plugins to retain their settings after changing profiles I would have to change each plugin's config file where ever it is... Im going to see if I can figure out how to do this.

Arcnsparc
January 9th, 2008, 03:30 AM
Well, I think your script was perfect. And it does work right, but even when I switch manually between profiles nothing happens. For example I have two profiles, one for running graphical apps (this profile doesnt have cube or anything like that) and another that is for computer speed so i can play games. When I switch between them everything stays the same! Maybe I messed up a file somewhere or something and should do a reinstall, but i tried reseting everything to Default in CCSM and that didnt help...

Deciare
January 9th, 2008, 03:33 AM
Just to recap, this doesn't change the profile in the preferences tab right? I ran the script and that didnt change. All I could tell that the script did was generate two XML files next to it, and the first line worked putting in the new profile in the config file.
I just tested that with my computer, and it does. :) ccsm gets the name of the current profile directly from ~/.config/compiz/compizconfig/config.

Would it be easier for me to forget the Gconf route and go with the flat file back end? That would make a script much easier I think.
Yes, and a lot shorter. There are also mysterious glitches with the GConf configuration backend that have been around seemingly forever (partially due to a lack of a detailed bug report about it) that simply don't affect the flat-file backend.

But then how would I hotkey the switches without gconf? I tried using gconf-editor to change the commands and global key bindings in metacity like i did before to assign hotkeys, but they wont work if im using a flat file back end...
Compiz uses its own keybindings independently from Metacity's. That's because only one window manager can run at once, and Metacity and Compiz are both window managers, so starting Compiz necessarily stops Metacity. With the Metacity process stopped, it no longer handles any key bindings; that becomes Compiz's responsibility.

A lot of general-purpose bindings, including up to 14 key bindings for arbitrary shell commands, can be configured in ccsm->General Options under the Commands, Key bindings, or Actions tabs (depending on your version of ccsm).

Im sorry for all the trouble and I really am thankful, this will really help me convert my friends and family to ubuntu when I can show off such a pretty and free system.
You're very welcome, I'm grateful for being able to help. :D

Having an opportunity to help someone who wants to learn is even better. ^_^

Deciare
January 9th, 2008, 03:36 AM
Well, I think your script was perfect. And it does work right, but even when I switch manually between profiles nothing happens. For example I have two profiles, one for running graphical apps (this profile doesnt have cube or anything like that) and another that is for computer speed so i can play games. When I switch between them everything stays the same! Maybe I messed up a file somewhere or something and should do a reinstall, but i tried reseting everything to Default in CCSM and that didnt help...
Actually... I have trouble switching profiles directly from within ccsm as well. I don't usually use multiple profiles, so it doesn't usually bother me, but while testing my instructions for you earlier this evening, the inconsistent behaviour from ccsm bothered me a lot. ^^;

Does profile switching also fail to work even when not going through ccsm, using the instructions I provided earlier? You would have had to make some modifications to my script to make it work--at least replace the name_of_new_profile placeholders--so may I see your modified version? I'd like to test with it to confirm that everything is correct.

Oh, and have you tried restarting Compiz after each profile switch?

Arcnsparc
January 9th, 2008, 03:41 AM
Sorry for the weird comments, this is the second script ive worked on so im not too good, but i learn fast and understand everything but that first line, which i dont need to get now anyways.

#get compiz to chill out
metacity --replace
#work infil magic I dont understand
sed -i -e 's/profile = .*/profile = Fire/' ~/.config/compiz/compizconfig/config

# Fetch data from GConf database about the profile we're about to switch away from, and the new profile we're about to switch to
gconftool-2 --dump /apps/compiz >main.xml
gconftool-2 --dump /apps/compizconfig/profiles/Fire >Fire.xml

# Remove stale data from GConf database
gconftool-2 --recursive-unset /apps/compiz
gconftool-2 --recursive-unset /apps/compizconfig/profiles/Fire
#load into correct spots
gconftool-2 --load Fire.xml /apps/compiz
gconftool-2 --load main.xml /apps/compizconfig/profiles/main
#restart
compiz


Thanks so much for the help!

Deciare
January 9th, 2008, 04:29 AM
"Infil magic"? That's somehow funny. :D Does it mean anything?

Ah, and just so you know what it does, here's a breakdown of that command:
sed -i -e 's/profile = .*/profile = Fire/' ~/.config/compiz/compizconfig/config
sed is the name of a single-line text editor from way back before they had full-screen text editors
-i tells sed to modify the target file directly instead of printing the proposed modifications to stdout
-e tells sed that a regular expression is coming
's/profile = .*/profile = Fire/' is a regular expression that means:
s - replace
/profile = .*/ - strings matching this regular expression ("profile = " followed by any number (*) of the preceding character ("." means "any"))
profile = Fire/ - and replace them with "profile = Fire"
~/.config/compiz/compizconfig/config is the target file

Anyway, after a lot of testing, I found a solution that doesn't make much sense.

There needs to be a break between the last recursive-unset and the first load. So the script, which broke on my machine as well, works perfectly if you insert a 3-second pause like so:
#work infil magic I dont understand
sed -i -e 's/profile = .*/profile = Fire/' ~/.config/compiz/compizconfig/config

# Fetch data from GConf database about the profile we're about to switch away from, and the new profile we're about to switch to
gconftool-2 --dump /apps/compiz >main.xml
gconftool-2 --dump /apps/compizconfig/profiles/Fire >Fire.xml

# Remove stale data from GConf database
gconftool-2 --recursive-unset /apps/compiz
gconftool-2 --recursive-unset /apps/compizconfig/profiles/Fire
#load into correct spots
sleep 3
gconftool-2 --load Fire.xml /apps/compiz
gconftool-2 --load main.xml /apps/compizconfig/profiles/main
#restart
compiz
I can only imagine why that's necessary. Maybe Compiz needs time to let its new settings settle down whenever /apps/compiz is massively modified like we've done. But that doesn't even make sense in your case since the first thing you do is stop Compiz by starting Metacity. :/ Anyway, try inserting that sleep command and let me know how it goes.

This script is still not perfect. Currently, it'll only go one way: main to Fire. If you want to go from the Fire profile back to main, you'd need a separate script. I'm going to improve on this some more...

Deciare
January 9th, 2008, 04:45 AM
Here's the updated script, complete with basic error checking. :D

It accepts the name of the profile you wish to use as a parameter, so use it like:
./profile-switch Fire
to switch to the Fire profile.

#!/bin/bash

# Name of new profile specified on the command line
newprofile="$@"
if [ -z "$newprofile" ]; then
echo "Usage: $0 <profile>"
exit 1
fi

# Find the name of the currently active profile
oldprofile=$(grep -m 1 'profile = ' ~/.config/compiz/compizconfig/config | cut -d '=' -f 2 | cut -d ' ' -f 2)
if [ -z "$oldprofile" ]; then
oldprofile="Default"
fi

if [ "$oldprofile" = "$newprofile" ]; then
echo "The $newprofile profile is already active."
exit 0
fi

# Specify name of new profile in compizconfig config file
sed -i -e 's/profile = .*/profile = '"$newprofile"'/' ~/.config/compiz/compizconfig/config

# Fetch data from GConf database about the profile we're about to switch away from, and the new profile we're about to switch to
gconftool-2 --dump /apps/compiz >"${oldprofile}-dump.xml"
gconftool-2 --dump /apps/compizconfig/profiles/"$newprofile" >"${newprofile}-dump.xml"

# Remove stale data from GConf database
gconftool-2 --recursive-unset /apps/compiz
gconftool-2 --recursive-unset /apps/compizconfig/profiles/"$newprofile"

# Swap locations of new <-> old profiles
sleep 3
gconftool-2 --load "${newprofile}-dump.xml" /apps/compiz
gconftool-2 --load "${oldprofile}-dump.xml" /apps/compizconfig/profiles/"$oldprofile"
rm "${newprofile}-dump.xml" "${oldprofile}-dump.xml"

# Restart Compiz
compiz --replace ccp &

Edit: I hope you don't mind, but I've renamed this thread to something that I believe better describes the way this discussion has turned out.

Arcnsparc
January 10th, 2008, 11:31 PM
I think I may be missing a tool:

jake@MultiVAC:~/Documents/Ubuntu/scripts$ ./ProfileChange.sh Fire
./ProfileChange.sh: line 11: cut-d: command not found

The script continued on and restarted compiz PERFECTLY (something I could not get it to do haha).

Im going to assume that this script will work like a charm as soon as I figure out that little cut-d error...(is it supposed to be "cut -d"?)

I checked on the compiz wiki and couldnt find anything about the Profiles. Mine still dont do anything manually. If I set a profile one way, and then switch to a different one, the first one's settings all stay as they were and only the name of the profile changes. Once I do enough reading I should be able to figure it out, i guess its only a matter of time.

One last thing, once I figure all of this out and am confortable, is it okay if I use some of this post in a How-To? I think other people would be interested in this kind of thing if it can be made to work. When Im done my script will change wallpaper(got it ready), appearance(still working on it), emerald & compiz settings(still working on it), and possibly sounds & panels. Pipe dreams so far but that is what I think linux is anyways, a bunch of pipedreams coming true haha. Thanks again for the help, is there a paypal to donate to compiz?

Arcnsparc
January 10th, 2008, 11:49 PM
Everything for the profile switch is working perfectly so far, I can't thank you enough! I changed "cut-d" to "cut -d" in line 11 because that is what the next cut function looked like and the error went away.

One last question on the topic: Say I switch from Default to OtherProfile, will changes made to default be saved, i can't see why they wouldn't but Im still a Bash-Baby so I can't tell from the code.

Oh yeah, "infil" magic was supposed to be "infile" saying to myself that it changed things directly within the file

The profile problem I was having seems to have solved itself and each profile is holding all of the values independent of each other. I am going to link to this post from the Ubuntu Forums where I was asking around originally because others are interested too.

Im on to the next big challenge: Scripting Emerald theme changes!

Deciare
January 11th, 2008, 03:36 AM
Sorry~ about the cut-d thing! Copy/pasted the script over from a console, and I had checked it for errors since things often come out a bit weird when pasting from consoles, but I must have missed that one. Thanks for pointing it out!

I'm both pleased and surprised that my script, which uses knowledge I learnt just then through trial and error, actually worked better than switching profiles through ccsm. ;)

If you'd like to put up a guide about applying comprehensive themes from the command line, please do! You may be interested in SmSpillaz's Compiz Themer (http://forum.compiz-fusion.org/showthread.php?t=5351), too, once it's ready for testing. His will be GUI-based, so depending on what you prefer, you may like it more. ^^;

In any case, this has been a fun learning exercise. Thanks for the opportunity. ^_^

One last question on the topic: Say I switch from Default to OtherProfile, will changes made to default be saved, i can't see why they wouldn't but Im still a Bash-Baby so I can't tell from the code.
The script dumps the state of your currently active profile just before the switch, so any changes you made to the Default profile should be saved, yes.

Oh yeah, "infil" magic was supposed to be "infile" saying to myself that it changed things directly within the file
Aha, okay!

Im on to the next big challenge: Scripting Emerald theme changes!
Good luck! I'm sure you'll find it a lot easier than scripting compizconfig profile changes. :D

Edit: I moved this thread to Application Development because SmSpillaz did the same with the other thread (http://forum.compiz-fusion.org/showthread.php?t=6548).

maniac
January 11th, 2008, 09:31 AM
Err, just a question from the Gconf backend developer ;) :
Why do you copy the Gconf trees from within a script? The trees are automatically copied by the backend as soon as a value is read or written after the profile switch (see the function checkProfile in gconf.c) ... so just switch the profile and trigger a read of a single value. This applies to all backends, not only gconf ;)

Deciare
January 11th, 2008, 12:49 PM
lol! I don't know, this script's developer is as confused as you are. :p

I tried changing the value of ~/.config/compiz/compizconfig/config a few times and it worked exactly as you said it would, but as soon as I opened ccsm and changed the profile once from within that, my alternate profile failed to apply, and the active_plugins list was cleared. When I switched back to Default by editing config in a text editor, all my effects disappeared. (Less than default settings?)

I tried filing a bug report about ccsm's misbehaviour before I started with the script, but I couldn't see the logic behind how it was failing. I still don't understand...

Manually copying and unsetting GConf trees with gconftool-2 turned out to be completely reliable, though.