📜 ⬆️ ⬇️

Extend conky functionality: add function to display MPD track date

Introduction


I recently switched from ncmpc to ncmpcpp. I was pleased with the “alternative display mode”, in which the track information is displayed not from below, but from above, and in two lines, and not in one, it looks like this:



Then I wanted the MPD information to be displayed in a similar way in conky. But bad luck - conky can show the name of the track, album, artist, but the date does not know how. But this is not a big problem for us, opensource, after all, let's add the necessary functionality with our own hands.

Source Code Analysis


To begin with we will study source codes of conky. To do this, download the tarball and unpack it:
')
$ wget http://downloads.sourceforge.net/project/conky/conky/1.8.1/conky-1.8.1.tar.bz2 $ tar -xf conky-1.8.1.tar.bz2 $ cd conky-1.8.1/src 



Here you can see four files with the name 'mpd': mpd.c, mpd.h, libmpdclient.c and libmpdclient.h. The conky developers did not bother with their own implementation of mpd support and took libmpdclient ready. Well, let's see what kind of track information mpd gives (in libmpdclient.h):

 typedef struct _mpd_Song { /* filename of song */ char *file; /* artist, maybe NULL if there is no tag */ char *artist; /* title, maybe NULL if there is no tag */ char *title; /* album, maybe NULL if there is no tag */ char *album; /* track, maybe NULL if there is no tag */ char *track; /* name, maybe NULL if there is no tag; it's the name of the current song, * fe the icyName of the stream */ char *name; /* date */ char *date; /* added by qball */ /* Genre */ char *genre; /* Composer */ char *composer; /* Performer */ char *performer; /* Disc */ char *disc; /* Comment */ char *comment; /* length of song in seconds, check that it is not MPD_SONG_NO_TIME */ int time; /* if plchanges/playlistinfo/playlistid used, is the position of the song * in the playlist */ int pos; /* song id for a song in the playlist */ int id; } mpd_Song; 

So, artist, title, album, and date are all char *. The task is simplified - it is enough to do everything in the image and likeness.

Adding functionality


I took the conky mpd_title function as a basis. Let's see where it is mentioned:

 $ grep mpd_title *.c *.h 



First, let's deal with mpd.h and mpd.c. Mpd.h describes the structure:

 struct mpd_s { char *title; char *artist; char *album; const char *status; const char *random; const char *repeat; char *track; char *name; char *file; int is_playing; int vol; float progress; int bitrate; int length; int elapsed; }; 

Add a date field of type char * to it:
  char *date; 

Below is the description of the print_mpd_title function:
 void print_mpd_title(struct text_object *, char *, int); 

Copy it and replace the title with the date:
 void print_mpd_date(struct text_object *, char *, int); 

There is no need to change anything else in this file. Now you need to edit mpd.c. Strange, but there seems to be no mention of mpd_title? Let's just search for the title.

 $ grep title mpd.c 



The MPD_PRINT_GENERATOR (title, "% s") line explains everything - macros are used to generate functions, so the "mpd_title" line was not found. Well, for each line with title we will make an analogue with date:

 static void clear_mpd(void) { #define xfree(x) if (x) free(x) xfree(mpd_info.title); xfree(mpd_info.date); /* <-- */ xfree(mpd_info.artist); xfree(mpd_info.album); /* do not free() the const char *status! */ /* do not free() the const char *random! */ /* do not free() the const char *repeat! */ xfree(mpd_info.track); xfree(mpd_info.name); xfree(mpd_info.file); #undef xfree memset(&mpd_info, 0, sizeof(struct mpd_s)); } ... SONGSET(artist); SONGSET(album); SONGSET(title); SONGSET(date); /* <-- */ SONGSET(track); SONGSET(name); SONGSET(file); ... MPD_PRINT_GENERATOR(title, "%s") MPD_PRINT_GENERATOR(date, "%s") /* <-- */ MPD_PRINT_GENERATOR(artist, "%s") MPD_PRINT_GENERATOR(album, "%s") MPD_PRINT_GENERATOR(random, "%s") MPD_PRINT_GENERATOR(repeat, "%s") MPD_PRINT_GENERATOR(track, "%s") MPD_PRINT_GENERATOR(name, "%s") MPD_PRINT_GENERATOR(file, "%s") MPD_PRINT_GENERATOR(vol, "%d") MPD_PRINT_GENERATOR(bitrate, "%d") MPD_PRINT_GENERATOR(status, "%s") 

After these changes, mpd.c can also be closed. At this stage, we have ensured that conky receives the necessary information from MPD. It remains to teach him to show this information. Edit conky.c in the same way - copy what mpd_title has, and change the title to date:

 #ifdef MPD OBJ(mpd_title) print_mpd_title(obj, p, p_max_size); OBJ(mpd_date) /* <-- */ print_mpd_date(obj, p, p_max_size); /* <-- */ 

Now the same in core.c:

  END OBJ(mpd_title, &update_mpd) mpd_set_maxlen(mpd_title); init_mpd(); END OBJ(mpd_date, &update_mpd) /* <-- */ mpd_set_maxlen(mpd_date); /* <-- */ init_mpd(); /* <-- */ 

Well, the final touch - text_object.h:

 #ifdef MPD OBJ_mpd_title, OBJ_mpd_date, /* <-- */ 

This completes the work with the source text, it remains to collect. First, the configuration:

 $ cd ..; ./configure 

Here I do not specify any additional parameters, since mpd support is enabled by default. About all available options you can learn from the output ./configure --help.

configure, if successful, will display information about the enabled and disabled options:



MPD: yes - this is what we need. Now you need to actually collect:

 make 

In case of a successful build, you can already check if our mpd_date function works. For this we add it somewhere in ~ / .conkyrc. In my case, a piece of the config looks like this:

 ${alignc}$mpd_title ${alignc}${color #dddd55}$mpd_artist ${alignc}${color #55dd88}$mpd_album $color(${color yellow}$mpd_date$color) 

We start just assembled conky:

 ./src/conky 



Works!

Build Package


It now remains to assemble the package for your distribution and replace it with the one that comes with the distribution. If you are too lazy to do this, you can simply make a sudo make install; in this case, conky will be installed in / usr / local; however, this is not recommended for various reasons.

So, the bonus part: build the package for your distribution.

Portage-based (Gentoo, Sabayon)

If you do not have a local overlay yet, now is the time to create it .

Suppose your local overlay is located in / usr / local / portage. Create a directory for conky and copy the ebuild and already existing patches:

 # mkdir -p /usr/local/portage/app-admin/conky/files # cd /usr/local/portage/app-admin/conky # cp /usr/portage/app-admin/conky/conky-1.8.1-r5.ebuild conky-1.8.1-r6.ebuild # cp /usr/portage/app-admin/conky/files files/ 

Now you need to make a patch. To make it, you must firstly clear the source code from what appeared there after the build, secondly, unpack the original source code to another place, thirdly, run “diff -aur <original> <modified copy>”. Without further ado, I will simply post here its text:

 diff -aur conky-1.8.1.orig/src/conky.c conky-1.8.1/src/conky.c --- conky-1.8.1.orig/src/conky.c 2010-10-06 01:29:36.000000000 +0400 +++ conky-1.8.1/src/conky.c 2011-11-13 01:11:06.894704215 +0400 @@ -1945,6 +1945,8 @@ print_mpd_artist(obj, p, p_max_size); OBJ(mpd_album) print_mpd_album(obj, p, p_max_size); + OBJ(mpd_date) + print_mpd_date(obj, p, p_max_size); OBJ(mpd_random) print_mpd_random(obj, p, p_max_size); OBJ(mpd_repeat) diff -aur conky-1.8.1.orig/src/core.c conky-1.8.1/src/core.c --- conky-1.8.1.orig/src/core.c 2010-10-06 01:29:36.000000000 +0400 +++ conky-1.8.1/src/core.c 2011-11-13 01:11:06.894704215 +0400 @@ -925,6 +925,9 @@ END OBJ(mpd_album, &update_mpd) mpd_set_maxlen(mpd_album); init_mpd(); + END OBJ(mpd_date, &update_mpd) + mpd_set_maxlen(mpd_date); + init_mpd(); END OBJ(mpd_vol, &update_mpd) init_mpd(); END OBJ(mpd_bitrate, &update_mpd) init_mpd(); END OBJ(mpd_status, &update_mpd) init_mpd(); @@ -1733,6 +1736,7 @@ case OBJ_mpd_title: case OBJ_mpd_artist: case OBJ_mpd_album: + case OBJ_mpd_date: case OBJ_mpd_random: case OBJ_mpd_repeat: case OBJ_mpd_vol: diff -aur conky-1.8.1.orig/src/mpd.c conky-1.8.1/src/mpd.c --- conky-1.8.1.orig/src/mpd.c 2010-10-06 01:29:36.000000000 +0400 +++ conky-1.8.1/src/mpd.c 2011-11-13 01:16:50.699508331 +0400 @@ -95,6 +95,7 @@ xfree(mpd_info.title); xfree(mpd_info.artist); xfree(mpd_info.album); + xfree(mpd_info.date); /* do not free() the const char *status! */ /* do not free() the const char *random! */ /* do not free() the const char *repeat! */ @@ -273,6 +274,7 @@ SONGSET(artist); SONGSET(album); SONGSET(title); + SONGSET(date); SONGSET(track); SONGSET(name); SONGSET(file); @@ -403,6 +405,7 @@ MPD_PRINT_GENERATOR(title, "%s") MPD_PRINT_GENERATOR(artist, "%s") MPD_PRINT_GENERATOR(album, "%s") +MPD_PRINT_GENERATOR(date, "%s") MPD_PRINT_GENERATOR(random, "%s") MPD_PRINT_GENERATOR(repeat, "%s") MPD_PRINT_GENERATOR(track, "%s") diff -aur conky-1.8.1.orig/src/mpd.h conky-1.8.1/src/mpd.h --- conky-1.8.1.orig/src/mpd.h 2010-10-06 01:29:36.000000000 +0400 +++ conky-1.8.1/src/mpd.h 2011-11-13 01:11:06.898037530 +0400 @@ -7,6 +7,7 @@ char *title; char *artist; char *album; + char *date; const char *status; const char *random; const char *repeat; @@ -41,6 +42,7 @@ void print_mpd_title(struct text_object *, char *, int); void print_mpd_artist(struct text_object *, char *, int); void print_mpd_album(struct text_object *, char *, int); +void print_mpd_date(struct text_object *, char *, int); void print_mpd_random(struct text_object *, char *, int); void print_mpd_repeat(struct text_object *, char *, int); void print_mpd_track(struct text_object *, char *, int);   conky-1.8.1/src: stamp-h1 diff -aur conky-1.8.1.orig/src/text_object.h conky-1.8.1/src/text_object.h --- conky-1.8.1.orig/src/text_object.h 2010-10-06 01:29:36.000000000 +0400 +++ conky-1.8.1/src/text_object.h 2011-11-13 01:13:54.990460229 +0400 @@ -327,6 +327,7 @@ OBJ_mpd_title, OBJ_mpd_artist, OBJ_mpd_album, + OBJ_mpd_date, OBJ_mpd_random, OBJ_mpd_repeat, OBJ_mpd_vol, 

This patch should be saved to the files folder, I did not change the principle of patch naming and called it "conky-1.8.1-mpd-date.patch". Now we need to tweak the ebuild a bit so that our patch is also applied. Open the ebuild, and in the “src_prepare” function add our patch to the list of applicable:

 src_prepare() { epatch "${FILESDIR}/${P}-nvidia-x.patch" \ "${FILESDIR}/${P}-xmms2.patch" \ "${FILESDIR}/${P}-secunia-SA43225.patch" \ "${FILESDIR}/${P}-acpitemp.patch" \ "${FILESDIR}/${P}-curl-headers.patch" \ "${FILESDIR}/${P}-maxinterfaces.patch" \ "${FILESDIR}/${P}-utf8-scroll.patch" \ "${FILESDIR}/${P}-mpd-date.patch" eautoreconf } 

Save the changes, create the Manifest:

 # ebuild conky-1.8.1-r6.ebuild manifest 

Now you can install:

 # emerge conky 

DEB-based (Debian, Ubuntu), RPM-based (Fedora, OpenSuSE), Slackware

We use the universal program checkinstall . First, we reconfigure the sources, specifying the normal installation paths, and assemble them:

 $ ./configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --datadir=/usr/share --sysconfdir=/etc --localstatedir=/var/lib --libdir=/usr/lib $ make 

Now, instead of make install, run checkinstall.

To create a deb package:

 checkinstall -D make install 

To create an rpm package:

 checkinstall -R make install 

To create a Slackware package:

 checkinstall -S make install 

After that, the package can be installed by means of your distribution.

Note: I do not have much experience in creating packages for such package managers, therefore, perhaps the chosen method is not the best.

Source: https://habr.com/ru/post/132975/


All Articles