You are not logged in.

#26 2012-09-15 20:24:47

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,452
Website

Re: [SOLVED] A DWM statusbar in C

Unia wrote:

Although, the code you suggested to have it updated once a minute, doesn't work

Oops, there was a typo.  I've adjusted it. "i=0" should be "loops=0" at the beginning of the if block.

Edit: now I see how most of the mpd code should work.  I was wrong about the const char * declarations, those should be fine.  The pointers need not be constant, rather they are pointers to const chars.  The main problem in your mpd code is that you do not call mpd_connection_new to create a connection.  I still have no idea what the third argument (i++) is or does.

Edit: based on the source code that third parameter essentially indicates how many tags to skip.  I don't know what tags are though.

Last edited by Trilby (2012-09-15 20:39:51)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#27 2012-09-15 21:24:07

Cloudef
Member
Registered: 2010-10-12
Posts: 636

Re: [SOLVED] A DWM statusbar in C

https://github.com/Cloudef/monsterwm/bl … erstatus.c
Also the status bar code I'm piping to dzen that has MPD code, for reference.

Offline

#28 2012-09-16 12:19:18

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

Trilby wrote:
Unia wrote:

Although, the code you suggested to have it updated once a minute, doesn't work

Oops, there was a typo.  I've adjusted it. "i=0" should be "loops=0" at the beginning of the if block.

I'm trying the new code but now it doesn't show anything for 60 seconds, then it does show for 1 second and disappears again for the next 60. I would like it to not disappear, but only get updated every 60 seconds. I'll play around with it and see if I can make this happen, shouldn't be too hard.

Trilby wrote:

Edit: now I see how most of the mpd code should work.  I was wrong about the const char * declarations, those should be fine.  The pointers need not be constant, rather they are pointers to const chars.  The main problem in your mpd code is that you do not call mpd_connection_new to create a connection.  I still have no idea what the third argument (i++) is or does.

Edit: based on the source code that third parameter essentially indicates how many tags to skip.  I don't know what tags are though.

So I should add mpd_connection_new to create a connection, and then it should work? Hm.. I'll have a look at Cloudef's code and see how he does it, thanks for pointing me to it Cloudef!


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#29 2012-09-16 12:47:46

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

Cloudef's code is a bit too..... advanced for me tongue Instead, I took another look at the source I initially copied from based on and now I have it working. I don't think I'm going to need everything from it though, so now I'm going to try to slim it down a bit. Should I succeed on that, the only thing that's left is the WiFi!

EDIT: Whoohoo, 1337 posts cool

Last edited by Unia (2012-09-16 12:49:41)


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#30 2012-09-16 13:06:56

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,452
Website

Re: [SOLVED] A DWM statusbar in C

Unia, the code in the if conditional that should run every 60 seconds should only create a new string variable.  Call if wifiString for example.  This string needs to be appended (strcat) to the status string every time through the main loop.

For example:

int main() {
  ...
  char wifiString[100];  /* picked 100 out of thin air, this could probably be smaller to use less memory */
  int loops=0;
  ...
  for (;;) {
    ...
    if (++loops == 60) {
      loops = 0;
      /* code here to add wifi info to wifiString instead of statnext */
    }
    strcat(status,wifiString);
    ...
  }
}

Last edited by Trilby (2012-09-16 13:07:46)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#31 2012-09-16 13:21:32

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

Hm, I never would've come up with that myself. I did completely finish the MPD part now though, so when the WiFi works now I'm all done! smile


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#32 2012-09-16 14:25:27

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

The MPD part isn't done just yet. It kept displaying the artist and title, even when I had stopped playback. This is not what I want: when I stop playback (but keep MPD running) it should not display anything.

The code that does the first, is this:

		conn = mpd_connection_new(MPD_HOST,MPD_PORT, 30000);
		mpd_command_list_begin(conn, true);
		mpd_send_current_song(conn);
		mpd_command_list_end(conn);
		if ((song = mpd_recv_song(conn)) != NULL ) {
			artist = mpd_song_get_tag(song, MPD_TAG_ARTIST,0);
			title = mpd_song_get_tag(song, MPD_TAG_TITLE,0);
		mpd_connection_free(conn);
		sprintf(statnext,MPD_STR,artist,title);
		strcat(status,statnext);
		};

The code that I'm now trying, is this:

		conn = mpd_connection_new(MPD_HOST,MPD_PORT, 30000);
		mpd_command_list_begin(conn, true);
		mpd_send_current_song(conn);
		mpd_command_list_end(conn);
		//if ((song = mpd_recv_song(conn)) != NULL ) {
		if (mpd_status_get_state(theStatus) == MPD_STATE_PLAY) {
			artist = mpd_song_get_tag(song, MPD_TAG_ARTIST,0);
			title = mpd_song_get_tag(song, MPD_TAG_TITLE,0);
		mpd_connection_free(conn);
		sprintf(statnext,MPD_STR,artist,title);
		strcat(status,statnext);
		};

This, however, segfaults. The first piece does not. It's almost identical though (one line difference), and the lines that differ come from my MPD-Notify, which works without hiccups.

This is the backtrace:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7692d50 in mpd_status_get_state () from /usr/lib/libmpdclient.so.2

EDIT: As usual, I forgot the complete code: https://gist.github.com/3732629

Last edited by Unia (2012-09-16 14:26:51)


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#33 2012-09-16 15:40:09

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,452
Website

Re: [SOLVED] A DWM statusbar in C

In MPD-notify you get theStauts and check that it is not null.  You do not do that here.

Also, the mpd_connection_free call be outside the if statement.

In looking at the full code, theStatus would definitely be null.  You get the status of "conn" before you open the connection.  You need to set "theStatus" every time through the loop, both to avoid this problem, and to get any useful information.  Even if it worked the way you have it set up, the only status you'd ever get was the status of MPD when you started your dwm status bar.

Last edited by Trilby (2012-09-16 15:42:16)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#34 2012-09-16 18:37:37

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

Before I look into the MPD code, there's two things that I want to settle with the WiFi:

1. How can I know what's the smallest number I can assign to wifiString?
2. With this loop, it takes 60 seconds for the whole statusbar to show. Is there a way I can make it show everything (incl. WiFi) from the start and then start the 60 seconds loop for WiFi?


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#35 2012-09-16 18:57:49

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,452
Website

Re: [SOLVED] A DWM statusbar in C

1. How can I know what's the smallest number I can assign to wifiString?

Honestly you probably shouldn't bother worrying about it.  I have a bit of resource minimalist OCD, but a hundred byte string is a drop in the ocean of any modern computer system's memory.  If you do want to optimize it as much as possible there are two approaches I can think of.

First, limit what you copy to it to only the number of characters you want.  For example, If a network has a ridiculously long ESSID, you probably don't want the whole thing littering your statusbar.  In looking at the ESSID's of networks I commonly use, the longest are around a dozen characters.  Just make sure when you get the string from iwlib to put in wifiString that you use one of the length-restricted string functions like strncpy or strncat not strcpy or strcat.  If your wifiString will hold this essid, plus a space and a percentage, then you'd want to add 4 more characters.  In other words, count up the greatest number of characters that you'd ever put in it, then add one (for the '\0').  I'll often round up just a bit in case I counted something wrong.

Second, you could look up whether there is a wireless standard that limits the length of ESSID's.  I'm sure there is one - but I don't know what it is.  The above strategy seems better to me though.  Most essid's are short.  There is no reason your status bar layout should get completely rearranged by one ridiculously long ESSID.  It seems more reasonable to truncate long ESSIDs.

2. With this loop, it takes 60 seconds for the whole statusbar to show. Is there a way I can make it show everything (incl. WiFi) from the start and then start the 60 seconds loop for WiFi?

Sure, just change the initializer for the loops variable to 60.  (ie "int loops;" becomes "int loops=60;")


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#36 2012-09-16 20:59:09

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

Trilby wrote:

1. How can I know what's the smallest number I can assign to wifiString?

Honestly you probably shouldn't bother worrying about it.  I have a bit of resource minimalist OCD, but a hundred byte string is a drop in the ocean of any modern computer system's memory.  If you do want to optimize it as much as possible there are two approaches I can think of.

Yea, your OCD is also in my code wink One of the reasons I wanted to do this project is also memory and processor efficiency, so it seems good to also apply that in the WiFi string. I was just curious if there's any way to see how much memory you should give a string. Are your values of statnext and status also random grabs, or is there a reason behind these? Anyway, I have now set mine to 30 for now. I think that suffices for most occasions.

Trilby wrote:

2. Sure, just change the initializer for the loops variable to 60.  (ie "int loops;" becomes "int loops=60;")

Darn, didn't think of that lol Setting it to 60 didn't help though, it wouldn't show the WiFi at all. I changed the code to if (++loops > 60) instead of == 60 and now it does work.

So, now it's really only MPD left. Thanks again guys (esp. Trilby) to stay on this and help me smile


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#37 2012-09-16 22:00:57

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,452
Website

Re: [SOLVED] A DWM statusbar in C

Ah yes, loops should have actually been initialized to 59 as the conditional in the if increments if *before* checking whether it equals 60.  Greater than works too though.

The lengths of status and statnext were based off of the maximum that would be used (but rounded up a bit).  Counting characters was a bit tricky though as there were a number of wchars (2-byte characters).  I suspect if you didn't/dont increase the size of the status string but you try to add this additional information to it that it will segfault.

Edit: I just checked what is actually on my github - perhaps for status I just used a round 100 bytes.  This code is in a variety of forms on a variety of my machines, on one of them I really did "optimize" the size of the strings.

Last edited by Trilby (2012-09-16 22:02:33)


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#38 2012-09-17 16:59:22

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

To get the MPD part working, I have "made" a second version, which contains only the relevant info for MPD and localtime (localtime to see if it actually works, I didn't get compilation errors but it still didn't work).

Now I have stopped the segfaulting, because I added an error checker that checks if there is a connection with MPD. Before I didn't check this and that's why it would segfault. Now it just exists cleanly, but of course that's not the purpose tongue

So, how can I now succesfully make a connection with MPD? I'm not doing anything different than in my MPD-notify program (actually, I have just copy/pasted the code and adapted it), it just won't connect.

Here's the complete code:

#include <mpd/client.h>
#include <mpd/status.h>
#include <mpd/entity.h>
#include <mpd/search.h>
#include <mpd/tag.h>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <X11/Xlib.h>

#define INTERVAL	1								// Sleeps for INTERVAL seconds between updates
#define MPD_HOST	"localhost"						// MPD host
#define MPD_PORT	6600							// MPD port
#define MPD_STR		"%s \x02-\x01 %s \x02•\x01 "	// MPD, playing/paused
#define MPD_NP_STR	" "								// MPD, stopped
#define DATE_TIME_STR	"%a %b %d\x02,\x01 %H:%M "	// This is a strftime format string which is passed localtime

int main(int argc, char ** argv) {
	Display *dpy;
	Window root;
	int num;
	long lnum1,lnum2;
	char statnext[100], status[300];
	struct mpd_connection *conn = mpd_connection_new(MPD_HOST, MPD_PORT, 30000);
	struct mpd_status *theStatus = mpd_recv_status(conn);
	const char * title = NULL;
	const char * artist = NULL;
	struct mpd_song * song = NULL;
	time_t current;
	// Setup X display and root window id:
	dpy=XOpenDisplay(NULL);
	if ( dpy == NULL) {
		fprintf(stderr, "ERROR: could not open display\n");
		exit(1);
	}
	root = XRootWindow(dpy,DefaultScreen(dpy));
// MAIN LOOP STARTS HERE
	for (;;) {
		status[0]='\0';
	// MPD
		if ( ! theStatus)
			exit(1);
		else
		if (mpd_status_get_state(theStatus) == MPD_STATE_PLAY) {
			mpd_command_list_begin(conn, true);
			mpd_send_status(conn);
			mpd_send_current_song(conn);
			mpd_command_list_end(conn);
			mpd_response_next(conn);

			song = mpd_recv_song(conn);
			title = mpd_song_get_tag(song,MPD_TAG_TITLE,0);
			artist = mpd_song_get_tag(song,MPD_TAG_ARTIST,0);

			sprintf(statnext,MPD_STR,title,artist);
		}
		else if (mpd_status_get_state(theStatus) == MPD_STATE_STOP) {
			sprintf(statnext,MPD_NP_STR);
		}
		mpd_response_finish(conn);
		mpd_song_free(song);
		mpd_connection_free(conn);
		strcat(status,statnext);
	// Time
		time(&current);
		strftime(statnext,38,DATE_TIME_STR,localtime(&current));
		strcat(status,statnext);
	// Set root name
		XStoreName(dpy,root,status);
		XFlush(dpy);
		sleep(INTERVAL);
	}
// NEXT LINES SHOULD NEVER EXECUTE, only here to satisfy Trilby's O.C.D. ;)
	XCloseDisplay(dpy);
	return 0;
}

If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#39 2012-09-17 20:13:04

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,452
Website

Re: [SOLVED] A DWM statusbar in C

As I mentioned above, you are only getting the connection and status once at the very start.  This wouldn't be very useful as you presumably want your status bar to change when  the MPD status changes.  You have to get a *new* status from MPD each time through the loop.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#40 2012-09-17 20:43:15

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

Trilby wrote:

As I mentioned above, you are only getting the connection and status once at the very start.  This wouldn't be very useful as you presumably want your status bar to change when  the MPD status changes.  You have to get a *new* status from MPD each time through the loop.

Doesn't help. It just won't connect to MPD. Even it I had it at the very start, it should still display the song that is currently playing, but it didn't.


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#41 2012-09-21 22:20:23

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

Just chiming in here to mention that I've managed to got it running and working properly. It will show the artist and title when it's playing, will display the previous with "Paused:" in front of it if paused and will show nothing when stopped.

You can find the full code at my GitHub, incl. a simple Makefile and a PKGBUILD in the PKGBUILDs repository.

Code @ GitHub

I'd appreciate it if you could review the MPD part and see if I can improve it somewhere!


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#42 2012-09-21 23:11:55

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,452
Website

Re: [SOLVED] A DWM statusbar in C

Looks great (though I don't have MPD so I can't test that).  There is one sprintf that just copies an empty string to the statnext variable - this could be simplified a bit if you really want to optimize.  It is perfectly good as is, and you would never really notice the difference, but sprintf can be a bit of an "expensive" function for only copying an empty string.  `strcpy(statnext," ");` might be the first improvement - but then all string functions carry a bit of overhead and in such a "fixed-case" you can be more efficient with `statnext[0]=' '; statnext[1]='\0';`

I also noticed the malloc + memset at the beginning.  I doubt this would make any difference, particularly since that only runs once at startup anyhow, but a calloc function could replace a malloc + memset.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#43 2012-09-22 11:17:27

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

Trilby wrote:

Looks great (though I don't have MPD so I can't test that).  There is one sprintf that just copies an empty string to the statnext variable - this could be simplified a bit if you really want to optimize.  It is perfectly good as is, and you would never really notice the difference, but sprintf can be a bit of an "expensive" function for only copying an empty string.  `strcpy(statnext," ");` might be the first improvement - but then all string functions carry a bit of overhead and in such a "fixed-case" you can be more efficient with `statnext[0]=' '; statnext[1]='\0';`

For simplicity's sake, I'd rather stay with just sprintf instead of introducing another variable. This could be because of my lack of understanding C, but for now I'm satisfied with this. Also I'm not sure what you mean with the overhead?

Trilby wrote:

I also noticed the malloc + memset at the beginning.  I doubt this would make any difference, particularly since that only runs once at startup anyhow, but a calloc function could replace a malloc + memset.

You mean I could simplify these two lines:

winfo = (struct wireless_info *) malloc(sizeof(struct wireless_info));
memset(winfo, 0, sizeof(struct wireless_info));

into one, with a calloc function? Hm, that's worth looking in to.


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#44 2012-09-22 11:34:36

Trilby
Inspector Parrot
Registered: 2011-11-29
Posts: 29,452
Website

Re: [SOLVED] A DWM statusbar in C

Just for clarity, changing the sprintf would not introduct another variable.  You are using sprintf to set the statnext variable.  You could, instead, set the two relevant bytes of that variable directly using the 'equals' operator rather than a call to the sprintf function.  No new variables.

And the overhead was referring to the various operations that these string functions have to do.  In effect when you call sprintf it ends up setting the two bytes of the statnext variable directly, but before it does that it creates and initializes a variety of unused data structures, calls other functions that are not needed, prepares to process a variable length list of arguments (which don't exist), etc.  sprintf is a powerful, but relatively complicated function.  If you don't need all it's bells and whistles, it's a bit of an overkill.

That said there is a code readability advantage to the parallel construction in you if statement where every possible outcome will call the sprintf function, just with different parameters.


"UNIX is simple and coherent..." - Dennis Ritchie, "GNU's Not UNIX" -  Richard Stallman

Offline

#45 2012-10-17 14:53:16

madders
Member
From: Reading, UK
Registered: 2012-04-01
Posts: 13

Re: [SOLVED] A DWM statusbar in C

Hi, I hope it's not too late to reply to this.

I've also written my status bar in C and show similar network information (for each interface I also show bytes sent / received and whether the interface is down (in red), up without an IP address (in orange) and up with an IP address (in green). For the signal / quality, you can get that from /proc/net/wireless. I decided I didn't want to use the ESSID because the name could look messy in the status bar. Since I use netcfg and have a profile for each wireless network, and I think it's much neater to show the profile name currently connected (i.e. work, home, mums, hotel etc). You can get this from /var/run/network/profiles.

Offline

#46 2012-10-17 19:33:08

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

Care to share your code?


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#47 2012-10-18 14:36:16

madders
Member
From: Reading, UK
Registered: 2012-04-01
Posts: 13

Re: [SOLVED] A DWM statusbar in C

Yeah sure. I just created a GitHub Repo for it here.

Offline

#48 2012-10-18 15:03:04

Unia
Member
From: Stockholm, Sweden
Registered: 2010-03-30
Posts: 2,486
Website

Re: [SOLVED] A DWM statusbar in C

Thanks! Always nice to see how other people do the same task. Yours sure looks more complicated than mine, at least for me tongue


If you can't sit by a cozy fire with your code in hand enjoying its simplicity and clarity, it needs more work. --Carlos Torres

Offline

#49 2012-10-18 15:36:36

madders
Member
From: Reading, UK
Registered: 2012-04-01
Posts: 13

Re: [SOLVED] A DWM statusbar in C

Yeah it's very useful to see how other people have implemented their status bar (that's how I put mine together by taking ideas from other ones I'd seen).

Mine is certainly no more complicated than yours, it's just a bit longer because it's showing more things.

Offline

#50 2012-11-09 07:27:43

domac
Member
Registered: 2012-08-06
Posts: 102

Re: [SOLVED] A DWM statusbar in C

Hey,

I looked at the statusbar of Trilby and Unia and mixed them together… here is what I came up with: http://sprunge.us/LOCN?bash
Now I'm pretty unhappy with that loop since the interval needs to be small enough to give actual data, but consumes a lot of cpu (at least for me).
Well maybe there is a chance to implement observer design pattern to optimize performance without lacking the feature of instant data.
I'm pretty busy with my study so this will need some time and I'm also no that C pro like Trilby! tongue
I'll learn that and would be happy if tips or suggestions come up here! :-)

Cheers


domac [ git ]

Offline

Board footer

Powered by FluxBB