1. My ".rule" file draft with e-sexp style for GSmartMix
It looks like this now,
;;-*-lisp-*-
(begin
;; some debug stuffs that list the available indentifiers
;; (for the parser, an unknown identifier is a set/get
;; over the current sink properties)
(print "\nEvent: changed property")
(print changed-property)
(print "\nSink event, dumping state:")
(print service-name)
(print program-name)
(print application-name)
(print class-name)
(print state)
(print has-focus)
(print volume-level)
(print position)
;; these are class settings, loaded from the corresponding gconf path
;; if not available in gconf, set them manually
;; gconf is convenient, because it is synchronized with other apps
;; (configuration UI) and persistent
;; a class is described by:
;; - foreground volume level
;; - background volume level
;; - slide time (time of volume adjustments)
;; - a class policy
;; - "LIF" Last In Foreground
;; - "FIF" First In Foreground
;; - "AIF" All In Foreground
;; - "NA" No Adjustments (nothing will be done automatically)
;; - a foreground state
;; - a background state
(if (not (class-load "Default"))
(class-settings "Default" 0.7 0.6 1.0 "LIF" "playing" "paused"))
(if (not (class-load "Voice"))
(begin
(class-settings "Voice" 0.9 0.3 1.0 "FIF" "playing" "playing")
(class-exclusion "Voice" "Music" "Movie")))
(if (not (class-load "Event"))
(class-settings "Event" 0.3 0.3 1.0 "AIF" "playing" "playing"))
(if (not (class-load "Alarm"))
(class-settings "Alarm" 1.0 0.6 1.0 "AIF" "playing" "playing"))
(if (not (class-load "Music"))
(begin
(class-settings "Music" 1.0 0.6 1.0 "LIF" "playing" "paused")
(class-exclusion "Music" "Movie")))
(if (not (class-load "Movie"))
(begin
(class-settings "Movie" 1.0 0.6 1.0 "NA" "playing" "paused")
(class-exclusion "Movie" "Music")))
;; this is the way an application can have a default class
;; if it is not set by the application itself
(if (is class-name "Default")
(begin
(if (is program-name "rhythmbox")
(set class-name "Music"))
(if (is program-name "totem")
(set class-name "Movie"))
(if (is program-name "listen")
(set class-name "Music"))
(if (is program-name "sound-juicer")
(set class-name "Music"))
(if (is program-name "ekiga")
(set class-name "Voice"))
(if (is program-name "tapioca")
(set class-name "Voice"))
(if (is program-name "countdowntimer")
(set class-name "Alarm"))
(if (is program-name "gaim2")
(set class-name "Event"))))
;; I don't like the class set by the application, let me override it
(if (is class-name "Chat")
(begin
(set class-name "Voice")))
;; this rule is common to every class
(if (is changed-property "state")
(begin
(if (is state "playing") (set position "foreground"))
(if (is state "ready") (set position "background"))))
;; let the class make the adjustments, change volume, and state
(class-adjustments)
;; this is an application rule
(if (is program-name "rhythmbox")
(begin
(if (is changed-property "has-focus")
(if has-focus (set position "force-foreground") else (set position "background")))))
;; So far, all the orders are compiled,
;; let's bump them up to the sink
(apply)
;; further developpments might include
;; - priority (the queues have priority)
;; - metadata, meta.BuddyName, meta.Group, meta.EventName...
;; - ?
)