pthread_cond_signal和pthread_cond_wait的标准用法
http://code.google.com/p/eee-osd/source/browse/trunk/asus_osd/asusosd.c?r=15
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <libconfig.h>
#include "asusosd_image.h"
#include "asusosd_queue.h"
#include <asm-generic/errno.h>
#include <errno.h>
struct config_t cfg;
static pthread_mutex_t q_lock;
static pthread_cond_t q_empty;
static int thread_alive;
char filename[128];
const char *temp;
char themepath[128] = "/usr/local/share/asus_osd/";
char fnf6command[128] = "/usr/bin/gnome-system-monitor &";
int xpos = 2;
int ypos = 2;
unsigned int img_data;
int wlan_value;
int bri_value;
int vol_value;
int vol_level;
char muted;
char configfile[64];
config_setting_t *setting;
char* hotkey_get(int);
unsigned int hotkey_parse(char*);
void* image_thread(void*);
extern int create_image(char*);
extern void close_image();
void image_close();
void image_open();
int main (int argc, char *argv[])
{
queue *img_queue;
pthread_t img_thread;
int socket_fd;
struct sockaddr_un socket_addr;
char *hotkey;
unsigned int data;
FILE *pfile;
int i;
char cmd[64];
i = 1;
while(i < argc)
{
if(!strcmp(argv[i], "-v"))
{
printf(VERSION"\n");
exit(0);
}
i++;
}
/* Initialize the configuration */
config_init(&cfg);
/* Trying to load users conf-file */
sprintf(configfile, "%s/.asusosd/asusosd.conf", getenv("HOME"));
printf("Trying to read configfile %s...", configfile);
if (!config_read_file(&cfg, configfile)) {
printf("failed\n");
/* Trying to load generic conf-file */
sprintf(configfile, "/etc/asusosd.conf");
printf("Trying to read configfile %s...", configfile);
if (!config_read_file(&cfg, configfile)) {
printf("failed\n");
} else {
printf("success\n");
}
} else {
printf("success\n");
}
setting = config_lookup(&cfg, "themepath");
if (setting) {
temp = config_setting_get_string(setting);
strcpy(themepath, temp);
}
setting = config_lookup(&cfg, "fnf6command");
if (setting) {
temp = config_setting_get_string(setting);
sprintf(fnf6command,"%s &", temp);
}
setting = config_lookup(&cfg, "xpos");
if (setting) {
xpos = config_setting_get_int(setting);
}
setting = config_lookup(&cfg, "ypos");
if (setting) {
ypos = config_setting_get_int(setting);
}
img_queue = (queue *)queue_new(10);
pthread_mutex_init(&q_lock, NULL);
pthread_cond_init(&q_empty, NULL);
pthread_create(&img_thread, NULL, image_thread, img_queue);
socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (socket_fd < 0) {
printf("cannot create socket\n");
return socket_fd;
}
memset(&socket_addr, 0, sizeof(socket_addr));
socket_addr.sun_family = AF_UNIX;
sprintf(socket_addr.sun_path, "%s", "/var/run/acpid.socket");
if(connect(socket_fd, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
{
printf("cannot connect socket\n");
close(socket_fd);
return -1;
}
fcntl(socket_fd, F_SETFD, FD_CLOEXEC);
setvbuf(stdout, NULL, _IOLBF, 0);
bri_value = 0;
if((pfile=fopen("/proc/acpi/asus/brn","rb"))==NULL)
{
printf("cannot open /proc/acpi/asus/brn\n");
}
else
{
if(fscanf(pfile, "%d", &bri_value) != 1)
{
printf("cannot read /proc/acpi/asus/brn\n");
}
if(bri_value < 0 || 15 < bri_value)
{
bri_value = 0;
printf("read an invalid value [%d] from /proc/acpi/asus/brn\n", bri_value);
}
fclose(pfile);
}
sprintf(cmd, "/etc/acpi/queryvolume.sh");
vol_level = system(cmd) / 1024;
while(1)
{
hotkey = hotkey_get(socket_fd);
if(hotkey)
{
if(strncmp("hotkey ATKD ", hotkey, 12))
continue;
data = hotkey_parse(hotkey+12);
if(data == IMG_TASK_MANAGER)
continue;
if(data > 0)
{
pthread_mutex_lock(&q_lock);
while(img_queue->add(img_queue, (unsigned int)data))
{
pthread_mutex_unlock(&q_lock);
pthread_cond_signal(&q_empty);
usleep(1);
pthread_mutex_lock(&q_lock);
}
pthread_mutex_unlock(&q_lock);
pthread_cond_signal(&q_empty);
usleep(2);
}
}
}
thread_alive = 0;
pthread_cond_signal(&q_empty);
pthread_join(img_thread, NULL);
pthread_mutex_destroy(&q_lock);
pthread_cond_destroy(&q_empty);
queue_destroy(img_queue);
close(socket_fd);
return 0;
}
char*
hotkey_get(int sfd)
{
static char *buf;
int buflen = 64;
int i = 0;
int r;
int searching = 1;
while (searching) {
buf = realloc(buf, buflen);
if (!buf) {
fprintf(stderr, "ERR: malloc(%d): %s\n",
buflen, strerror(errno));
return NULL;
}
memset(buf+i, 0, buflen-i);
while (i < buflen) {
r = read(sfd, buf+i, 1);
if (r < 0 && errno != EINTR) {
/* we should do something with the data */
fprintf(stderr, "ERR: read(): %s\n",
strerror(errno));
return NULL;
} else if (r == 0) {
/* signal this in an almost standard way */
errno = EPIPE;
return NULL;
} else if (r == 1) {
/* scan for a newline */
if (buf[i] == '\n') {
searching = 0;
buf[i] = '\0';
break;
}
i++;
}
}
if (buflen >= 1024/* max length of buffer */) {
break;
}
buflen *= 2;
}
return buf;
}
unsigned int
hotkey_parse(char* data)
{
int hotkey;
int val;
char cmd[64];
if(strncmp("000000", data, 6))
return 0;
if(data[6] == '2')
{
if('0'<=data[7] && data[7]<='9')
val = data[7] - '0';
else if('a'<=data[7] && data[7]<='f')
val = data[7] -'a' +10;
else if('A'<= data[7] && data[7]<='F')
val = data[7] -'A' +10;
else val = bri_value;
if((val > bri_value) || val==15)
hotkey = IMG_BRN_UP|(val<<8);
else if(val < bri_value || val==0)
hotkey = IMG_BRN_DN|(val<<8);
bri_value = val;
}
else
{
data[8] = 0;
hotkey = atoi(data);
switch(hotkey)
{
case 12: //taskmanager
system(fnf6command);
break;
case 13: //mute
if(muted) //off
{
muted = 0;
sprintf(cmd, "amixer sset Front %d > /dev/null", (vol_level * 4));
system(cmd);
hotkey = 16;//then on
}
else
{
muted = 1;
sprintf(cmd, "amixer sset Front 0 > /dev/null");
system(cmd);
}
break;
case 14: //volume down
if(muted) {
muted = 0;
}
vol_level--;
if(vol_level < 0)
{
vol_level = 0;
}
else if(vol_level > 16)
{
vol_level = 16;
}
sprintf(cmd, "amixer sset Front %i > /dev/null", (vol_level * 4));
system(cmd);
hotkey = hotkey|((vol_level) << 8);
break;
case 15: //volume up
if(muted) {
muted = 0;
}
vol_level++;
if(vol_level < 0)
{
vol_level = 0;
}
else if(vol_level > 16)
{
vol_level = 16;
}
sprintf(cmd, "amixer sset Front %i > /dev/null", (vol_level * 4));
system(cmd);
hotkey = hotkey|((vol_level) << 8);
break;
}
}
return (unsigned int)hotkey;
}
//static gboolean expose(GtkWidget *widget, GdkScreen *old_screen, gpointer userdata)
static int expose()
{
unsigned int val;
val = (img_data&VALUE_MASK) >> 8;
memset(filename, 0, 128);
if ((img_data&IMAGE_MASK) == IMG_WLAN_ON)
sprintf(filename, "%s%s", themepath,"wlanon.png");
else if ((img_data&IMAGE_MASK) == IMG_WLAN_OFF)
sprintf(filename, "%s%s", themepath,"wlanoff.png");
else if ((img_data&IMAGE_MASK) == IMG_DISP_LCD)
sprintf(filename, "%s%s", themepath,"lcd.png");
else if ((img_data&IMAGE_MASK) == IMG_DISP_CRT)
sprintf(filename, "%s%s", themepath,"crt.png");
else if ((img_data&IMAGE_MASK) == IMG_DISP_LCD_CRT)
sprintf(filename, "%s%s", themepath,"crt_lcd.png");
else if ((img_data&IMAGE_MASK) == IMG_AUDIO_MUTE)
sprintf(filename, "%s%s", themepath,"VolumeMute.png");
else if ((img_data&IMAGE_MASK) == IMG_AUDIO_ON)
sprintf(filename, "%s%s", themepath,"VolumeOn.png");
else if ((img_data&IMAGE_MASK) == IMG_BRN_DN)
sprintf(filename, "%s%s%d%s", themepath,"BrightnessDown",val,".png");
else if ((img_data&IMAGE_MASK) == IMG_BRN_UP)
sprintf(filename, "%s%s%d%s", themepath,"BrightnessUP",val,".png");
else if ((img_data&IMAGE_MASK) == IMG_VOL_DN)
sprintf(filename, "%s%s%d%s", themepath,"VolumeDN",val,".png");
else if ((img_data&IMAGE_MASK) == IMG_VOL_UP)
sprintf(filename, "%s%s%d%s", themepath,"VolumeUP",val,".png");
else if ((img_data&IMAGE_MASK) == IMG_AC_IN)
sprintf(filename, "%s%s", themepath,"ACMode.png");
else if ((img_data&IMAGE_MASK) == IMG_AC_OUT)
sprintf(filename, "%s%s", themepath,"BatteryMode.png");
else return -1;
return 0;
}
void* image_thread (void *arg)
{
queue *q;
int ret;
struct timespec tm;
q = (queue *)arg;
thread_alive = 1;
while(thread_alive)
{
pthread_mutex_lock(&q_lock);
while(q->isEmpty(q) && thread_alive)
{
if(tm.tv_sec > 0)
{
ret = pthread_cond_timedwait(&q_empty, &q_lock, &tm);
if(ret == ETIMEDOUT)
image_close();
tm.tv_sec = 0;
}
else pthread_cond_wait (&q_empty, &q_lock);
}
img_data = q->remove(q);
pthread_mutex_unlock(&q_lock);
image_open();
tm.tv_sec = time(NULL) + 2;
}
return NULL;
}
void image_open()
{
if(!expose())
{
create_image(filename);
}
else printf("image_open error.\n");
}
void image_close()
{
close_image();
}