I try to rewrite g15mpd to be more usefull.I've downloaded latest version from svn and add some features. But not all:
1) How can I output non-english (i.e. russian) symbols to G15 screen?
2) Progress indicator didn't update
3) I want to change volume on mpd by Ctrl+Wheel.
There is my g15mpd.c file now (all code is only in this file):
/*<br />
#include<br />
#include<br />
#include<br />
#include<br />
#include<br />
#include<br />
#include<br />
#include<br />
#include<br />
#include </p>
<p>#include<br />
#include<br />
#include<br />
#include<br />
#include </p>
<p>#include </p>
<p>extern int debug_level;<br />
int g15screen_fd, retval;<br />
g15canvas *canvas;<br />
int current_fg_check=0;<br />
static int playing;<br />
static int paused=0;<br />
static int quickscroll = 0;</p>
<p>MpdObj *obj = NULL;</p>
<p>int leaving = 0;<br />
static int voltimeout=0;<br />
static int own_keyboard=0;</p>
<p>pthread_mutex_t daemon_mutex;<br />
pthread_mutex_t lockit;</p>
<p>int mmedia_fd; </p>
<p>static int menulevel=0;<br />
#define MENU_MODE1 0<br />
#define MENU_MODE2 1<br />
#define MAX_MENU_MODES 2<br />
/* playlist mode takes over all keys on the keyboard - allowing searches/playlist scroll via volume ctrl etc.<br />
all non-valid keys are sent elsewhere via the xtest extension */<br />
static int playlist_mode=0;<br />
int playlist_selection=0;<br />
int item_selected=0;<br />
int volume_adjust=0;<br />
int mute=0;<br />
int muted_volume=0;</p>
<p>struct track_info {<br />
char artist[100];<br />
char title[100];<br />
char album[100];<br />
char date[4];<br />
int total;<br />
int elapsed;<br />
int volume;<br />
int repeat;<br />
int random;<br />
int playstate;<br />
int totalsongs_in_playlist;<br />
int currentsong;<br />
} track_info;<br />
char albumstring[105];</p>
<p>void error_callback(MpdObj *mi,int errorid, char *msg, void *userdata)<br />
{<br />
} </p>
<p>void *Lkeys_thread() {<br />
int keystate = 0;<br />
int volume;<br />
struct pollfd fds;<br />
char ver[5];</p>
<p> strncpy(ver,G15DAEMON_VERSION,3);<br />
float g15v;<br />
sscanf(ver,"%f",&g15v);</p>
<p> fds.fd = g15screen_fd;<br />
fds.events = POLLIN;</p>
<p> while(!leaving){<br />
int foo=0;<br />
current_fg_check = g15_send_cmd (g15screen_fd, G15DAEMON_IS_FOREGROUND, foo);<br />
static int last_fg_check = 0;<br />
if(playlist_mode && last_fg_check != current_fg_check){<br />
if(own_keyboard){<br />
if(current_fg_check==0){<br />
own_keyboard=0;<br />
}<br />
}else if(current_fg_check && !own_keyboard) {<br />
own_keyboard=1;<br />
}<br />
last_fg_check = current_fg_check;<br />
}</p>
<p> /* g15daemon series 1.2 need key request packets */<br />
pthread_mutex_lock(&daemon_mutex);<br />
if((g15v*10)<=18) {<br />
keystate = g15_send_cmd (g15screen_fd, G15DAEMON_GET_KEYSTATE, foo);<br />
} else {<br />
if ((poll(&fds, 1, 5)) > 0)<br />
read (g15screen_fd, &keystate, sizeof (keystate));<br />
}<br />
pthread_mutex_unlock(&daemon_mutex);</p>
<p> if (keystate)<br />
{<br />
switch (keystate)<br />
{<br />
case G15_KEY_L1:<br />
exit(1); // FIXME quick hack to exit<br />
break;<br />
case G15_KEY_L2:<br />
menulevel++;<br />
if(menulevel>=MAX_MENU_MODES)<br />
menulevel=0;<br />
break;<br />
case G15_KEY_L3:<br />
if(!own_keyboard){<br />
own_keyboard=playlist_mode=1;<br />
mpd_Song *song = mpd_playlist_get_current_song(obj);<br />
if(song)<br />
if(song->pos)<br />
track_info.currentsong=song->pos;<br />
}else{ //de-activate<br />
own_keyboard=playlist_mode=0;<br />
}<br />
break;<br />
case G15_KEY_L4:<br />
if(menulevel==MENU_MODE1){<br />
mpd_player_set_random(obj,mpd_player_get_random(obj)^1);<br />
}<br />
if(menulevel==MENU_MODE2){<br />
volume=mpd_status_get_volume(obj);<br />
if(volume>0)<br />
volume-=5;<br />
mpd_status_set_volume (obj,volume);<br />
}<br />
break;<br />
case G15_KEY_L5:<br />
if(menulevel==MENU_MODE1){<br />
mpd_player_set_repeat(obj, mpd_player_get_repeat(obj)^1);<br />
}<br />
if(menulevel==MENU_MODE2){<br />
volume=mpd_status_get_volume(obj);<br />
if(volume<100)<br />
volume+=5;<br />
mpd_status_set_volume (obj,volume);<br />
}<br />
break;<br />
default:<br />
break;<br />
}<br />
keystate = 0;<br />
}<br />
usleep(100*1000);<br />
}<br />
return NULL;<br />
}</p>
<p>void *event_key_thread() {</p>
<p> struct input_event *event;<br />
event=malloc(sizeof(struct input_event));<br />
struct pollfd fds;</p>
<p> int retval;<br />
while(!leaving) {</p>
<p> event->value=0;<br />
event->code=0;<br />
fds.fd=mmedia_fd;<br />
fds.events=POLLIN;</p>
<p> if(poll(&fds,1,500)<1)<br />
continue;</p>
<p> retval=read(mmedia_fd,event,sizeof(struct input_event));</p>
<p> if(event->value==0||current_fg_check==0)<br />
continue;</p>
<p> int keycode = event->code;<br />
int code_audio_play = KEY_PLAYPAUSE;<br />
int code_audio_stop = KEY_STOPCD;<br />
int code_audio_next = KEY_NEXTSONG;<br />
int code_audio_prev = KEY_PREVIOUSSONG;<br />
int code_audio_raisevol = KEY_VOLUMEUP;<br />
int code_audio_lowervol = KEY_VOLUMEDOWN;<br />
int code_audio_mute = KEY_MUTE;</p>
<p> /* printf("keycode = %d\n", keycode); */</p>
<p> if(keycode == code_audio_play) {<br />
if(playing && !playlist_mode) {<br />
if (paused==1) {<br />
mpd_player_play(obj);<br />
paused = 0;<br />
} else {<br />
mpd_player_pause(obj);<br />
paused = 1;</p>
<p> }</p>
<p> } else {<br />
mpd_player_play(obj);<br />
playing = 1;<br />
}<br />
if(playlist_mode){<br />
mpd_player_play_id(obj, item_selected);<br />
}<br />
}</p>
<p> if(keycode == code_audio_stop) {<br />
mpd_player_stop(obj);<br />
playing = 0;<br />
continue;<br />
}</p>
<p> if(keycode == code_audio_next) {<br />
if(playlist_mode)<br />
playlist_selection+=1;<br />
else<br />
mpd_player_next(obj);<br />
continue;<br />
}</p>
<p> if(keycode == code_audio_prev) {<br />
if(playlist_mode)<br />
playlist_selection-=1;<br />
else<br />
mpd_player_prev(obj);<br />
continue;<br />
}</p>
<p> if(keycode == code_audio_raisevol){<br />
if(playlist_mode && quickscroll)<br />
playlist_selection+=1;<br />
/* else {<br />
pthread_mutex_lock(&daemon_mutex);<br />
volume_adjust+=1;<br />
pthread_mutex_unlock(&daemon_mutex);<br />
continue;<br />
}*/<br />
}<br />
if(keycode == code_audio_lowervol){<br />
if(playlist_mode && quickscroll)<br />
playlist_selection-=1;<br />
/*else {<br />
pthread_mutex_lock(&daemon_mutex);<br />
volume_adjust-=1;<br />
pthread_mutex_unlock(&daemon_mutex);<br />
continue;<br />
}*/<br />
}</p>
<p> if(keycode == code_audio_mute){<br />
pthread_mutex_lock(&daemon_mutex);<br />
mute = 1;<br />
pthread_mutex_unlock(&daemon_mutex);<br />
continue;<br />
}</p>
<p> /* now the default stuff */<br />
if(own_keyboard) {<br />
menulevel=MENU_MODE1;<br />
continue;<br />
}<br />
}<br />
free(event);<br />
return NULL;<br />
}</p>
<p>/* take the track_info structure and render it */<br />
void *g15display_thread(){<br />
long chksum=0;<br />
static long last_chksum;<br />
int i;<br />
unsigned char time_elapsed[41];<br />
unsigned char time_total[41];<br />
static int current = 0;<br />
int changed =0;<br />
while(!leaving){<br />
if(playlist_mode){</p>
<p> int y=0;<br />
int offset=2;<br />
changed = 0;</p>
<p> if(track_info.currentsong>-1){<br />
current=track_info.currentsong;<br />
track_info.currentsong = -1;<br />
changed = 1;<br />
}</p>
<p> if(playlist_selection>0){<br />
if(current+1title!=NULL)<br />
strncpy(title,song->title,99);<br />
else<br />
strncpy(title,"",99);<br />
if(song->artist!=NULL){<br />
strncat(title," - ",99);<br />
strncat(title,song->artist,99);<br />
}<br />
}<br />
/* sanitise the display */<br />
if(i==mpd_playlist_get_playlist_length(obj))<br />
strncpy(title,"End of PlayList",99);<br />
if(i>mpd_playlist_get_playlist_length(obj))<br />
break;<br />
if(i<0)<br />
strncpy(title,"",99);</p>
<p> if(y==offset){<br />
g15r_pixelBox (canvas, 0, 7*offset, 159 , 7*(offset+1), G15_COLOR_BLACK, 1, 1);<br />
canvas->mode_xor=1;<br />
if(song)<br />
if(song->id)<br />
item_selected=song->id;<br />
}<br />
g15r_renderString (canvas, (unsigned char *)title, y, G15_TEXT_SMALL, 1, 1);<br />
canvas->mode_xor=0;<br />
y++;<br />
}<br />
}<br />
}else{<br />
/* track info */<br />
g15r_pixelBox (canvas, 0, 0, 159, 42, G15_COLOR_WHITE, 1, 1);<br />
g15r_renderString (canvas, (unsigned char *)track_info.title, 0, G15_TEXT_LARGE, 80-(strlen(track_info.title)*8)/2, 0);<br />
g15r_renderString (canvas, (unsigned char *)track_info.artist, 0, G15_TEXT_MED, 80-(strlen(track_info.artist)*5)/2, 9);<br />
g15r_renderString (canvas, (unsigned char *)track_info.album, 0, G15_TEXT_MED, 80-(strlen(track_info.album)*5)/2, 16);</p>
<p> /* elapsed time */<br />
memset(time_elapsed,0,41);<br />
memset(time_total,0,41);<br />
if (track_info.total != 0) {<br />
snprintf((char*)time_elapsed,40,"%02i:%02i",track_info.elapsed/60, track_info.elapsed%60);<br />
snprintf((char*)time_total,40,"%02i:%02i",track_info.total/60, track_info.total%60);<br />
}<br />
if(track_info.elapsed>0&&track_info.total>0)<br />
g15r_drawBar (canvas, 24, 26, 135, 30, G15_COLOR_BLACK, track_info.elapsed, track_info.total, 1);<br />
canvas->mode_xor=1;<br />
g15r_renderString (canvas,(unsigned char*)time_elapsed,0,G15_TEXT_SMALL,0,26);<br />
g15r_renderString (canvas,(unsigned char*)time_total,0,G15_TEXT_SMALL,137,26);<br />
canvas->mode_xor=0;</p>
<p> switch(track_info.playstate)<br />
{<br />
case MPD_PLAYER_PLAY:<br />
playing=1;<br />
paused=0;<br />
break;<br />
case MPD_PLAYER_PAUSE:<br />
//g15r_pixelBox (canvas, 0, 22, 159, 30, G15_COLOR_WHITE, 1, 1);<br />
//g15r_renderString (canvas, (unsigned char *)"Playback Paused", 0, G15_TEXT_LARGE, 22, 23);<br />
paused=1;<br />
break;<br />
case MPD_PLAYER_STOP:<br />
g15r_pixelBox (canvas, 0, 22, 159, 30, G15_COLOR_WHITE, 1, 1);<br />
g15r_renderString (canvas, (unsigned char *)"Playback Stopped", 0, G15_TEXT_LARGE, 18, 24);<br />
playing=0;<br />
paused=0;<br />
break;<br />
default:<br />
break;<br />
}</p>
<p> g15r_pixelBox (canvas, 0, 34, 159, 41, G15_COLOR_WHITE, 1, 1);<br />
g15r_pixelBox (canvas, 0, 34, 16, 42, G15_COLOR_BLACK, 1, 1);<br />
canvas->mode_xor=1;<br />
g15r_renderString (canvas, (unsigned char *)"Mode", 0, G15_TEXT_SMALL, 1, 36);<br />
canvas->mode_xor=0;</p>
<p> if(menulevel==MENU_MODE1){<br />
if(track_info.random){<br />
canvas->mode_xor=1;<br />
g15r_pixelBox (canvas, 105, 34, 131, 42, G15_COLOR_BLACK, 1, 1);<br />
}else{<br />
g15r_pixelBox (canvas, 105, 34, 131, 42, G15_COLOR_BLACK, 1, 0);<br />
}<br />
g15r_renderString (canvas, (unsigned char *)"Random", 0, G15_TEXT_SMALL, 107, 36);<br />
canvas->mode_xor=0;</p>
<p> if(track_info.repeat){<br />
canvas->mode_xor=1;<br />
g15r_pixelBox (canvas, 133, 34, 159, 42, G15_COLOR_BLACK, 1, 1);<br />
}else {<br />
g15r_pixelBox (canvas, 133, 34, 159, 42, G15_COLOR_BLACK, 1, 0);<br />
}</p>
<p> g15r_renderString (canvas, (unsigned char *)"Repeat", 0, G15_TEXT_SMALL, 135, 36);<br />
canvas->mode_xor=0;</p>
<p> // 2nd box from left - if you want it...<br />
//g15r_pixelBox (canvas, 34, 34, 54 , 42, G15_COLOR_BLACK, 1, 0);<br />
//g15r_renderString (canvas, (unsigned char *)"test", 0, G15_TEXT_SMALL, 36, 36);</p>
<p> if(playlist_mode==0){<br />
g15r_pixelBox (canvas, 18, 34, 54 , 42, G15_COLOR_BLACK, 1, 0);<br />
g15r_renderString (canvas, (unsigned char *)"Playlist", 0, G15_TEXT_SMALL, 20, 36);<br />
}else{<br />
canvas->mode_xor=1;<br />
g15r_pixelBox (canvas, 18, 34, 54 , 42, G15_COLOR_BLACK, 1, 1);<br />
g15r_renderString (canvas, (unsigned char *)"Playlist", 0, G15_TEXT_SMALL, 20, 36);<br />
canvas->mode_xor=0;<br />
}<br />
}</p>
<p> if(menulevel==MENU_MODE2){<br />
g15r_pixelBox (canvas, 106, 34, 132 , 42, G15_COLOR_BLACK, 1, 0);<br />
g15r_renderString (canvas, (unsigned char *)"Vol-", 0, G15_TEXT_SMALL, 112, 36);</p>
<p> g15r_pixelBox (canvas, 134, 34, 159 , 42, G15_COLOR_BLACK, 1, 0);<br />
g15r_renderString (canvas, (unsigned char *)"Vol+", 0, G15_TEXT_SMALL, 140, 36);</p>
<p> if(muted_volume != 0){<br />
g15r_drawBar (canvas, 0, 26, 160, 30, G15_COLOR_WHITE, 100, 100, 1);<br />
g15r_renderString (canvas, (unsigned char *)"MUTE", 0, G15_TEXT_LARGE, 60, 24);<br />
}<br />
else if(voltimeout){<br />
g15r_pixelBox (canvas, 0, 26, 160 , 30, G15_COLOR_WHITE, 1, 1);<br />
g15r_drawBar (canvas, 24, 26, 135, 30, G15_COLOR_BLACK, track_info.volume, 100, 1);<br />
canvas->mode_xor=1;<br />
g15r_renderString (canvas,(unsigned char*)"Vol -",0,G15_TEXT_SMALL,2,26);<br />
g15r_renderString (canvas,(unsigned char*)"Vol +",0,G15_TEXT_SMALL,141,26);<br />
canvas->mode_xor=0;<br />
}<br />
}<br />
}</p>
<p> /* do a quicky checksum - only send frame if different */<br />
chksum=0;<br />
for(i=0;ibuffer[i]*i;<br />
}<br />
pthread_mutex_lock(&daemon_mutex);<br />
if(last_chksum!=chksum) {<br />
while(g15_send(g15screen_fd,(char *)canvas->buffer,G15_BUFFER_LEN)<0 && !leaving) {<br />
perror("lost connection, tryng again\n");<br />
usleep(10000);<br />
/* connection error occurred - try to reconnect to the daemon */<br />
g15screen_fd=new_g15_screen(G15_G15RBUF);<br />
}<br />
}<br />
pthread_mutex_unlock(&daemon_mutex);<br />
last_chksum=chksum;<br />
usleep(75*1000);<br />
if(playlist_mode)<br />
usleep(75*1000);</p>
<p> }<br />
return NULL;<br />
}</p>
<p>void status_changed(MpdObj *mi, ChangedStatusType what)<br />
{<br />
pthread_mutex_lock(&lockit);</p>
<p> mpd_Song *song = mpd_playlist_get_current_song(mi);<br />
//printf (song->date);<br />
if(song) {<br />
if (song->artist!=NULL) {<br />
strncpy(track_info.artist,song->artist,99);<br />
} else {<br />
track_info.artist[0] = 0;<br />
}<br />
if (song->title!=NULL) {<br />
strncpy(track_info.title,song->title,99);<br />
} else {<br />
track_info.title[0] = 0;<br />
}<br />
if (song->album!=NULL) {<br />
strncpy(track_info.album,song->album,99);<br />
} else {<br />
track_info.album[0] = 0;<br />
}<br />
/*if (song->album!=NULL) {<br />
if (song->date!=NULL) {<br />
strncpy(track_info.album,song->date,99);<br />
strncat(track_info.album," ",99);<br />
strncat(track_info.album,song->album,99);<br />
} else {<br />
strncpy(track_info.album,song->date,99);}<br />
} else {<br />
track_info.album[0] = 0;}*/<br />
}</p>
<p> if(what&MPD_CST_CROSSFADE){<br />
// printf(GREEN"X-Fade:"RESET" %i sec.\n",mpd_status_get_crossfade(mi));<br />
}</p>
<p> if(what&MPD_CST_PLAYLIST)<br />
{<br />
// printf(GREEN"Playlist changed"RESET"\n");<br />
track_info.totalsongs_in_playlist = mpd_playlist_get_playlist_length(mi);</p>
<p> }</p>
<p> if(what&MPD_CST_ELAPSED_TIME && !voltimeout){<br />
track_info.elapsed = mpd_status_get_elapsed_song_time(mi);<br />
track_info.total = mpd_status_get_total_song_time(mi);<br />
}</p>
<p> if(what&MPD_CST_VOLUME){<br />
voltimeout=500;<br />
track_info.volume = mpd_status_get_volume(mi);<br />
}</p>
<p> if(what&MPD_CST_STATE) {<br />
track_info.playstate = mpd_player_get_state(mi);<br />
}</p>
<p> track_info.repeat = mpd_player_get_repeat(obj);<br />
track_info.random = mpd_player_get_random(obj);</p>
<p> pthread_mutex_unlock(&lockit);<br />
usleep(10*1000);<br />
}</p>
<p>int main(int argc, char **argv)<br />
{<br />
int fdstdin = 0;<br />
pthread_t Lkeys;<br />
pthread_t g15display;<br />
pthread_t EKeys;<br />
int volume;<br />
int volume_new;<br />
char devname[256] = "Unknown";<br />
int iport = 6600;<br />
char *hostname = getenv("MPD_HOST");<br />
char *port = getenv("MPD_PORT");<br />
char *password = getenv("MPD_PASSWORD");<br />
int eventdev;<br />
char evdev_name[128];<br />
pthread_mutex_init(&lockit,NULL);<br />
pthread_mutex_init(&daemon_mutex,NULL);<br />
int i;</p>
<p> for (i=0;ibuffer, 0, G15_BUFFER_LEN);<br />
canvas->mode_cache = 0;<br />
canvas->mode_reverse = 0;<br />
canvas->mode_xor = 0;<br />
}</p>
<p> /* Create mpd object */<br />
obj = mpd_new(hostname, iport,password);<br />
/* Connect signals */<br />
mpd_signal_connect_error(obj,(ErrorCallback)error_callback, NULL);<br />
mpd_signal_connect_status_changed(obj,(StatusChangedCallback)status_changed, NULL);<br />
/* Set timeout */<br />
mpd_set_connection_timeout(obj, 10);</p>
<p> if(0==mpd_connect(obj))<br />
{<br />
char buffer[20];<br />
pthread_attr_t attr;</p>
<p> mpd_send_password(obj);<br />
memset(buffer, '\0', 20);<br />
pthread_attr_init(&attr);<br />
pthread_attr_setstacksize(&attr,32*1024); /* set stack to 64k - dont need 8Mb !! */</p>
<p> pthread_create(&Lkeys, &attr, Lkeys_thread, NULL);<br />
pthread_create(&EKeys, &attr,event_key_thread, NULL);<br />
pthread_create(&g15display, &attr, g15display_thread, NULL);</p>
<p> do{<br />
pthread_mutex_lock(&daemon_mutex);<br />
if(mute){<br />
volume_adjust = 0;<br />
mute = 0;<br />
if (muted_volume == 0) {<br />
//printf("mute\n");<br />
muted_volume = mpd_status_get_volume(obj);<br />
mpd_status_set_volume (obj,0);<br />
} else {<br />
//printf("unmute\n");<br />
if (mpd_status_get_volume(obj) == 0) { /* if no other client has set volume up */<br />
mpd_status_set_volume (obj,muted_volume);<br />
}<br />
muted_volume = 0;<br />
}<br />
}<br />
if(volume_adjust != 0){<br />
if (muted_volume != 0) {<br />
volume=muted_volume;<br />
} else {<br />
volume=mpd_status_get_volume(obj);<br />
}<br />
volume_new = volume + volume_adjust;<br />
volume_adjust = 0;<br />
if(volume_new < 0)<br />
volume_new = 0;<br />
if(volume_new > 100)<br />
volume_new = 100;<br />
if(volume != volume_new || muted_volume){<br />
//printf("volume %d -> %d\n", volume, volume_new);<br />
mpd_status_set_volume (obj,volume_new);<br />
}<br />
voltimeout=200;<br />
muted_volume=0;<br />
}<br />
mpd_status_update(obj);<br />
pthread_mutex_unlock(&daemon_mutex);</p>
<p> }while(!usleep(5000) && !leaving);<br />
leaving = 1;<br />
pthread_join(Lkeys,NULL);<br />
pthread_join(g15display,NULL);<br />
}else<br />
printf("Unable to connect to MPD server. Exiting\n");</p>
<p> if(obj)<br />
mpd_free(obj);<br />
close(fdstdin);</p>
<p> if(canvas!=NULL)<br />
free(canvas);</p>
<p> close(g15screen_fd);<br />
close(mmedia_fd);</p>
<p> pthread_mutex_destroy(&lockit);</p>
<p> return 1;<br />
}<br />
Recent comments
4 weeks 2 days ago
4 weeks 2 days ago
4 weeks 4 days ago
4 weeks 4 days ago
4 weeks 5 days ago
6 weeks 3 days ago
13 weeks 1 day ago
28 weeks 2 days ago
32 weeks 12 hours ago
33 weeks 3 days ago