Index: roard/streams.c
===================================================================
--- roard/streams.c	(revision 4896)
+++ roard/streams.c	(revision 4934)
@@ -33,4 +33,8 @@
 int streams_recsource_id = -1;
 
+static const struct rolestack * streams_rolestack = NULL;
+static int streams_role_num     =  0;
+
+
 static void _streams_change_state(struct roar_stream_server * s, const int new, const char * func) {
  register int id  = ROAR_STREAM(s)->id;
@@ -122,4 +126,6 @@
 int streams_init (void) {
  int i;
+
+ streams_rolestack = rolestack_get_role(-1); // get default
 
  for (i = 0; i < ROAR_STREAMS_MAX; i++)
@@ -263,4 +269,6 @@
  roar_notify_core_emit_snoargs(ROAR_OE_BASICS_DELETE, -1, id, ROAR_OT_STREAM);
 
+ streams_set_role(id, -1);
+
  prim = s->primary;
 
@@ -513,6 +521,22 @@
 }
 
+static int streams_set_role_handle(int id) {
+   switch (streams_rolestack->action) {
+    case RS_ERROR: /* nothing to do */; break;
+    case RS_MIX:   /* nothing to do */; break;
+    case RS_KICK:  streams_delete(id);  break;
+    case RS_MUTE:  streams_set_flag(id, ROAR_FLAG_MUTE);  break;
+    case RS_PAUSE: streams_set_flag(id, ROAR_FLAG_PAUSE); break;
+   }
+ return 0;
+}
+
 int streams_set_role   (int id, int role) {
  struct roar_stream_server * ss;
+ const struct rolestack * rs;
+ int old_role;
+ int i;
+
+ ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
 
  _CHECK_SID(id);
@@ -521,6 +545,80 @@
   return -1;
 
+ old_role = ss->role;
  ss->role = role;
 
+ ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
+
+ if ( ROAR_STREAM(ss)->dir != ROAR_DIR_PLAY )
+  return 0;
+
+ ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
+
+ if ( old_role == role )
+  return 0;
+
+ if ( old_role != role && old_role != -1 && role != -1 ) {
+  streams_set_role(id, -1);
+  streams_set_role(id, role);
+ }
+
+ ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
+
+ if ( ss->role != -1 && ss->role == streams_rolestack->role ) {
+  ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
+
+  streams_role_num--;
+  if ( streams_role_num == 0 ) {
+   streams_rolestack = rolestack_get_role(-1); // get default
+   for (i = 0; i < ROAR_STREAMS_MAX; i++) {
+    if ( (ss = g_streams[i]) == NULL )
+     continue;
+    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_PLAY )
+     continue;
+    if ( ss->role == -1 )
+     continue;
+    rs = rolestack_get_role(ss->role);
+    if ( rs->index > streams_rolestack->role ) {
+     streams_rolestack = rs;
+    }
+   }
+   for (i = 0; i < ROAR_STREAMS_MAX; i++) {
+    if ( (ss = g_streams[i]) == NULL )
+     continue;
+    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_PLAY )
+     continue;
+    if ( ss->role == streams_rolestack->role )
+     streams_role_num++;
+   }
+  }
+ } else if ( role != -1 ) {
+  ROAR_DBG("streams_set_role(id=%i, role=%i) = ?", id, role);
+
+  rs = rolestack_get_role(role);
+  ROAR_DBG("streams_set_role(id=%i, role=%i): rs->index=%i, streams_rolestack->index=%i", id, role, rs->index, streams_rolestack->index);
+  if ( rs->index == streams_rolestack->index ) {
+   ROAR_DBG("streams_set_role(id=%i, role=%i): rs->index=%i, streams_rolestack->index=%i", id, role, rs->index, streams_rolestack->index);
+   streams_role_num++;
+  } else if ( rs->index > streams_rolestack->index ) {
+   ROAR_DBG("streams_set_role(id=%i, role=%i): rs=%p{.index=%i, .action=%s}", id, role, rs, rs->index, rolestack_action2str(rs->action));
+   streams_role_num  = 1;
+   streams_rolestack = rs;
+   for (i = 0; i < ROAR_STREAMS_MAX; i++) {
+    if ( (ss = g_streams[i]) == NULL )
+     continue;
+    if ( ROAR_STREAM(ss)->dir != ROAR_DIR_PLAY )
+     continue;
+    rs = rolestack_get_role(ss->role);
+    ROAR_DBG("streams_set_role(id=%i, role=%i): i=%i, rs->index=%i, streams_rolestack->index=%i", id, role, i, rs->index, streams_rolestack->index);
+    if ( rs->index < streams_rolestack->index )
+     streams_set_role_handle(i);
+   }
+  } else {
+   ROAR_DBG("streams_set_role(id=%i, role=%i): streams_rolestack->action=%s", id, role, rolestack_action2str(streams_rolestack->action));
+   streams_set_role_handle(id);
+  }
+ }
+
+ ROAR_DBG("streams_set_role(id=%i, role=%i) = 0", id, role);
  return 0;
 }
