Index: ChangeLog
===================================================================
--- ChangeLog	(revision 4548)
+++ ChangeLog	(revision 4552)
@@ -14,4 +14,5 @@
 	* Added new test system RAT
 	* Added support for single sink mode (Closes: #25)
+	* Implemented atomic flag toggling and flag protection.
 
 v. 0.4beta0 - Fri Oct 01 2010 13:36 CEST
Index: roarclients/roarctl.c
===================================================================
--- roarclients/roarctl.c	(revision 4536)
+++ roarclients/roarctl.c	(revision 4552)
@@ -97,4 +97,7 @@
         "                            separated list of flags.\n"
         "  unflag ID FLAGS         - Unsets flags on a stream. See flag.\n"
+        "  toogleflag ID FLAGS     - Toggels flags on a stream. See flag.\n"
+        "  protectflag ID FLAGS    - Protects flags on a stream. Those flags can not be\n"
+        "                            changed anymore after the they got protected. See flag.\n"
         "\n"
         "  kick TYPE ID            - Kicks object of TYPE with id ID\n"
@@ -926,6 +929,6 @@
 }
 
-int set_flags (struct roar_connection * con, int id, int reset, char * flags) {
- int f = ROAR_FLAG_NONE;
+int set_flags (struct roar_connection * con, int id, int action, char * flags) {
+ uint32_t f = ROAR_FLAG_NONE;
  char * c;
  struct roar_stream s[1];
@@ -976,5 +979,5 @@
  }
 
- return roar_stream_set_flags(con, s, f, reset);
+ return roar_stream_set_flags2(con, s, f, action);
 }
 
@@ -1191,4 +1194,20 @@
    }
    i++;
+  } else if ( !strcmp(k, "toggleflag") ) {
+   i++;
+   if ( set_flags(&con, atoi(argv[i]), ROAR_TOGGLE_FLAG, argv[i+1]) == -1 ) {
+    fprintf(stderr, "Error: can not toggle flags\n");
+   } else {
+    printf("flags changed\n");
+   }
+   i++;
+  } else if ( !strcmp(k, "protectflag") ) {
+   i++;
+   if ( set_flags(&con, atoi(argv[i]), ROAR_NOOP_FLAG|ROAR_PROTECT_FLAG, argv[i+1]) == -1 ) {
+    fprintf(stderr, "Error: can not protect flags\n");
+   } else {
+    printf("flags protected\n");
+   }
+   i++;
   } else if ( !strcmp(k, "metaset") ) {
    i++;
Index: roard/include/streams.h
===================================================================
--- roard/include/streams.h	(revision 4550)
+++ roard/include/streams.h	(revision 4552)
@@ -162,4 +162,6 @@
 int streams_get_flag     (int id, uint32_t flag);
 
+int streams_protect_flag (int id, uint32_t flag);
+
 int streams_set_name     (int id, char * name);
 char * streams_get_name  (int id);
Index: roard/req.c
===================================================================
--- roard/req.c	(revision 4539)
+++ roard/req.c	(revision 4552)
@@ -1073,6 +1073,8 @@
 
 int req_on_set_stream_para (int client, struct roar_message * mes, char ** data, uint32_t flags[2]) {
+ struct roar_stream_server * ss;
  uint16_t * d = (uint16_t *) mes->data;
- uint32_t tmp;
+ uint32_t tmp, tmp2, flagstore;
+ int protect = 0;
  int i;
 
@@ -1107,11 +1109,48 @@
     tmp |= d[3];
 
-    if ( d[2] == ROAR_RESET_FLAG ) {
-     if ( streams_reset_flag(mes->stream, tmp) == -1 )
-      return -1;
-    } else {
-     if ( streams_set_flag(mes->stream, tmp) == -1 )
-      return -1;
-    }
+    if ( d[2] & ROAR_PROTECT_FLAG ) {
+     protect = 1;
+     d[2] -= ROAR_PROTECT_FLAG;
+    }
+
+    switch (d[2]) {
+     case ROAR_SET_FLAG:
+       if ( streams_set_flag(mes->stream, tmp) == -1 )
+        return -1;
+      break;
+     case ROAR_RESET_FLAG:
+       if ( streams_reset_flag(mes->stream, tmp) == -1 )
+        return -1;
+      break;
+     case ROAR_NOOP_FLAG:
+      break;
+     case ROAR_TOGGLE_FLAG:
+       if ( streams_get(mes->stream, &ss) == -1 )
+        return -1;
+
+       flagstore = ss->flags;
+
+       tmp2 = flagstore & tmp; // those are the flags we need to reset.
+       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
+       if ( tmp2 )
+        if ( streams_reset_flag(mes->stream, tmp2) == -1 )
+         return -1;
+
+       tmp2 = (flagstore ^ tmp) & tmp; // those are the flags we need to set.
+       ROAR_DBG("req_on_set_stream_para(*): tmp2=0x%.8lx", (long int)tmp2);
+       if ( tmp2 )
+        if ( streams_set_flag(mes->stream, tmp2) == -1 )
+         return -1;
+      break;
+     default:
+       return -1;
+      break;
+    }
+
+   ROAR_DBG("req_on_set_stream_para(*): protect=%i", protect);
+   if ( protect )
+    if ( streams_protect_flag(mes->stream, tmp) == -1 )
+     return -1;
+
    break;
   case ROAR_STREAM_PARA_CHANMAP:
Index: roard/streams.c
===================================================================
--- roard/streams.c	(revision 4550)
+++ roard/streams.c	(revision 4552)
@@ -896,4 +896,10 @@
   flag |= ROAR_FLAG_PRIMARY;
 
+
+ // check if flags we are going to change are protected:
+ if ( g_streams[id]->flags_protection & flag )
+  return -1;
+
+
  if ( flag & ROAR_FLAG_MMAP ) {
   if ( streams_set_mmap(id, 0) == -1 ) {
@@ -984,4 +990,8 @@
  _CHECK_SID(id);
 
+ // check if flags we are going to change are protected:
+ if ( g_streams[id]->flags_protection & flag )
+  return -1;
+
  if ( g_streams[id]->flags & ROAR_FLAG_IMMUTABLE ) {
   flag |= ROAR_FLAG_PRIMARY;
@@ -1032,4 +1042,12 @@
 
  return g_streams[id]->flags & flag ? 1 : 0;
+}
+
+int streams_protect_flag (int id, uint32_t flag) {
+ _CHECK_SID(id);
+
+ g_streams[id]->flags_protection |= flag;
+
+ return 0;
 }
 
