This is just a brief rundown on how the various threads interact via mutexes and semaphores. There are three main threads, gtk runs in its own thread the display function runs its own thread the grab function (gets the picture from the cam) runs its own thread there are three semaphores s_draw s_grab1 s_grab2 and three mutexes pref_mutex freeze_mutex iscam_mutex There are two picture buffers, one (camera->pic) is the one that is displayed. The other (camera->picbuff) is the one that is written to by the grab thread the display function waits for the s_draw semaphore to be raised. It then swaps the two buffers (pic/picbuff) and raises the s_grab1 sempahore Then it displays the image using gtk Then it goes back to the top, and waits for the s_draw sempahore to be raised again. The grab function waits on alot of stuff, but mainly it waits for the two grab semaphores to be raised. As we have seen, display() raises the s_grab1 semaphore whenever it wants a new image in camera->picbuff. The s_grab2 sempahore is used if you are doing frames per second limiting. if FPS is locked at 10 fps, 10 times a second the s_grab2 semaphore will be raised. So whenever display() wants another image AND we haven't gotten a new image in the last 10th of a second, get an image. This is complicated a bit because we don't want to get any new images when the 'freeze' button is on, and we don't want to try to get images when we don't have an open camera. This is where two of our three mutexes come in. open_camera and close_camera control the 'iscam_mutex' When there is NOT a camera, that mutex is locked. The grab function wants to lock that mutex before it grabs an image, so if close_camera locked the mutex, grab_image() will sit and wait for open_camera() to release the iscam_mutex. The freeze_mutex works similarly. When you click the 'freeze' button, it locks the freeze_mutex. grab_image() will wait to get another image until it can get the freeze_mutex. When you click on the 'freeze' button to turn it off, it releases the mutex and grab_image() will start running again. If you were wondering why freeze_mutex and iscam_mutex are in grab_image instead of display, don't. It doesn't really matter which they are in, I just felt like putting them in grab_image(). The only mutex left is pref_mutex. I don't know how neccessary this one really is, but it makes me feel much safer knowing it is there. This mutex is used whenever you click a slider or push a radio button. Only one thread can access the preferences at a time, so they don't get in each other's way. This might be overkill, but it makes me feel safer. grab_image() checks the camera->update_camera value, and if it is set, it does a set_camera and clears the update_camera flag. Thats the whole explanation, I hope it was more helpful than confusing. The nice thing about this little setup is that the grab_image() thread starts reading another picture AT THE SAME TIME that the display thread is writing to the screen. This allows me to get 30 fps on my CPiA camera that has a theoretical limit of, well, 30. With weaker threading, or just a single process for grab/display I could only get a max of 28 fps. Besides, this is more fun. enjoy, john smallberries ( spred@geocities.com )