├── .gitignore ├── .gitmodules ├── .mailmap ├── .travis.yml ├── COPYING ├── README.md ├── autogen.sh ├── input-output └── i3bar │ ├── man │ └── j4status-i3bar.conf.xml │ ├── meson.build │ └── src │ ├── input.c │ └── output.c ├── input ├── file-monitor │ ├── man │ │ └── j4status-file-monitor.conf.xml │ ├── meson.build │ └── src │ │ └── file-monitor.c ├── mpd │ ├── man │ │ └── j4status-mpd.conf.xml │ ├── meson.build │ └── src │ │ └── mpd.c ├── nl │ ├── man │ │ └── j4status-nl.conf.xml │ ├── meson.build │ └── src │ │ └── nl.c ├── pulseaudio │ ├── man │ │ └── j4status-pulseaudio.conf.xml │ ├── meson.build │ └── src │ │ └── pulseaudio.c ├── sensors │ ├── man │ │ └── j4status-sensors.conf.xml │ ├── meson.build │ └── src │ │ └── sensors.c ├── systemd │ ├── man │ │ └── j4status-systemd.conf.xml │ ├── meson.build │ └── src │ │ └── systemd.c ├── time │ ├── man │ │ └── j4status-time.conf.xml │ ├── meson.build │ └── src │ │ └── time.c └── upower │ ├── man │ └── j4status-upower.conf.xml │ ├── meson.build │ └── src │ └── upower.c ├── libj4status-plugin ├── include │ ├── j4status-plugin-input.h │ ├── j4status-plugin-output.h │ ├── j4status-plugin-private.h │ └── j4status-plugin.h ├── meson.build ├── pkgconfig │ └── libj4status-plugin.pc.in └── src │ ├── config.c │ ├── core.c │ ├── plugin.c │ ├── section.c │ └── utils.c ├── main ├── man │ ├── j4status.conf.xml │ └── j4status.xml ├── meson.build ├── src │ ├── io.c │ ├── io.h │ ├── j4status.c │ ├── j4status.h │ ├── plugins.c │ ├── plugins.h │ └── types.h └── units │ ├── j4status@.service.in │ └── j4status@.socket.in ├── meson.build ├── meson_options.txt ├── output ├── debug │ ├── meson.build │ └── src │ │ └── debug.c ├── evp │ ├── man │ │ └── j4status-evp.conf.xml │ ├── meson.build │ └── src │ │ └── evp.c ├── flat │ ├── man │ │ └── j4status-flat.conf.xml │ ├── meson.build │ └── src │ │ └── flat.c └── pango │ ├── man │ └── j4status-pango.conf.xml │ ├── meson.build │ └── src │ └── pango.c └── src └── config.ent.in /.gitignore: -------------------------------------------------------------------------------- 1 | /local-rules.mk 2 | 3 | /src/config.h.in 4 | /src/config.h 5 | /src/config.ent 6 | 7 | /j4status 8 | *.1 9 | *.5 10 | *.pc 11 | *.service 12 | *.socket 13 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libgwater"] 2 | path = subprojects/libgwater 3 | url = https://github.com/sardemff7/libgwater 4 | [submodule "libnkutils"] 5 | path = subprojects/libnkutils 6 | url = https://github.com/sardemff7/libnkutils 7 | -------------------------------------------------------------------------------- /.mailmap: -------------------------------------------------------------------------------- 1 | Morgane Glidic 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | 4 | language: c 5 | compiler: 6 | - gcc 7 | - clang 8 | 9 | addons: 10 | apt: 11 | packages: 12 | - autoconf 13 | - automake 14 | - make 15 | - xsltproc 16 | - docbook-xsl 17 | - docbook-xml 18 | - libglib2.0-dev 19 | - libyajl-dev 20 | - libnl-3-dev 21 | - libnl-genl-3-dev 22 | - libnl-route-3-dev 23 | - libpulse-dev 24 | - libmpdclient-dev 25 | - libupower-glib-dev 26 | install: 27 | - sudo apt-get install -y libsensors4-dev 28 | 29 | before_script: 30 | - autoreconf -fi 31 | - ./configure --disable-silent-rules --enable-debug --enable-mpd-input --enable-systemd-input 32 | script: 33 | - make && make check && make distcheck 34 | after_failure: 35 | - cat test-suite.log 36 | - cat j4status-*/test-suite.log 37 | 38 | 39 | notifications: 40 | email: false 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | j4status 2 | ======== 3 | 4 | j4status, a small daemon to act on remote or local events 5 | 6 | 7 | Website 8 | ------- 9 | 10 | To get further information, please visit j4status’s website at: 11 | https://sardemff7.github.io/j4status/ 12 | 13 | 14 | My config 15 | --------- 16 | 17 | Here is my configuration: 18 | 19 | [Plugins] 20 | Output = i3bar 21 | Input = mpd;pulseaudio;nl;sensors;upower;time; 22 | 23 | [Time] 24 | Zones = Europe/Paris;UTC; 25 | Formats = %F %a %T;%T; 26 | 27 | [Sensors] 28 | Sensors = coretemp-isa-0000; 29 | 30 | [MPD] 31 | Actions=mouse:1 toggle;mouse:4 previous;mouse:5 next; 32 | 33 | [PulseAudio] 34 | Actions=mouse:1 mute toggle;mouse:4 raise;mouse:5 lower; 35 | 36 | [Override sensors:coretemp-isa-0000/temp1] 37 | Disable=true 38 | 39 | [Netlink] 40 | Interfaces=eth;wlan; 41 | 42 | 43 | Build from Git 44 | -------------- 45 | 46 | To build j4status from Git, you will need some additional dependencies: 47 | - Meson 0.47.0 (or newer) 48 | - pkg-config 0.25 (or newer) or pkgconf 0.2 (or newer) 49 | 50 | Make sure to clone the repository with submodules: `git clone --recursive` 51 | Alternatively, you can clone them as a second step: `git submodule update --init` 52 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | mkdir -p m4 4 | autoreconf --install --force 5 | -------------------------------------------------------------------------------- /input-output/i3bar/man/j4status-i3bar.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-i3bar.conf 46 | 5 47 | 48 | 49 | 50 | j4status-i3bar.conf 51 | j4status i3bar plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the i3bar plugin 57 | 58 | 59 | The i3bar plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the i3bar plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[i3bar]</varname> 76 | 77 | 78 | Output plugin keys 79 | 80 | 81 | 82 | 83 | NoStateColour= 84 | (colour string, defaults to "none") 85 | 86 | 87 | Colour to use for sections without state. 88 | 89 | 90 | 91 | 92 | 93 | UnavailableColour= 94 | (colour string, defaults to "#0000FF") 95 | 96 | 97 | Colour to use for sections with unavailable state. 98 | 99 | 100 | 101 | 102 | 103 | BadColour= 104 | (colour string, defaults to "#FF0000") 105 | 106 | 107 | Colour to use for sections with bad state. 108 | 109 | 110 | 111 | 112 | 113 | AverageColour= 114 | (colour string, defaults to "#FFFF00") 115 | 116 | 117 | Colour to use for sections with average state. 118 | 119 | 120 | 121 | 122 | 123 | GoodColour= 124 | (colour string, defaults to "#00FF00") 125 | 126 | 127 | Colour to use for sections with good state. 128 | 129 | 130 | 131 | 132 | 133 | Align= 134 | (boolean, defaults to false) 135 | 136 | 137 | Whether or not to pass i3bar the alignment data. 138 | 139 | 140 | 141 | 142 | 143 | NoClickEvents= 144 | (boolean, defaults to false) 145 | 146 | 147 | Whether or not to disable actions/click events support. 148 | 149 | 150 | 151 | 152 | 153 | 154 | Input plugin keys 155 | 156 | 157 | 158 | 159 | Clients= 160 | (A list of commands) 161 | 162 | 163 | The list of clients to run. 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | See Also 173 | 174 | j4status.conf5 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /input-output/i3bar/meson.build: -------------------------------------------------------------------------------- 1 | yajl_min_version='2.0.0' 2 | 3 | yajl = dependency('yajl', version: '>=@0@'.format(yajl_min_version), required: get_option('i3bar')) 4 | 5 | if yajl.found() 6 | shared_library('i3bar', [ config_h ] + files( 7 | 'src/input.c', 8 | 'src/output.c', 9 | ), 10 | c_args: [ 11 | '-DG_LOG_DOMAIN="j4status-i3bar"', 12 | ], 13 | dependencies: [ yajl, libj4status_plugin, gio_platform, gio, glib ], 14 | name_prefix: '', 15 | install: true, 16 | install_dir: plugins_install_dir, 17 | ) 18 | 19 | man_pages += [ [ files('man/j4status-i3bar.conf.xml'), 'j4status-i3bar.conf.5' ] ] 20 | docbook_conditions += 'enable_i3bar_input_output' 21 | endif 22 | -------------------------------------------------------------------------------- /input/file-monitor/man/j4status-file-monitor.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-file-monitor.conf 46 | 5 47 | 48 | 49 | 50 | j4status-file-monitor.conf 51 | j4status file-monitor plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the file-monitor plugin 57 | 58 | 59 | The file-monitor plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the file-monitor plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[FileMonitor]</varname> 76 | 77 | 78 | 79 | 80 | Files= 81 | (list of file names or paths) 82 | 83 | 84 | Files to monitor in the plugin runtime directory. 85 | You can specify absolute paths too. 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | Directory 94 | 95 | 96 | 97 | $XDG_RUNTIME_DIR/&PACKAGE_NAME;/file-monitor 98 | 99 | The directory in which the plugin will search files. 100 | If $XDG_RUNTIME_DIR is not set, we use $XDG_CACHE_HOME, with a fallback to ~/.cache. 101 | 102 | 103 | 104 | 105 | 106 | 107 | See Also 108 | 109 | j4status.conf5 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /input/file-monitor/meson.build: -------------------------------------------------------------------------------- 1 | shared_library('file-monitor', [ config_h ] + files( 2 | 'src/file-monitor.c', 3 | ), 4 | c_args: [ 5 | '-DG_LOG_DOMAIN="j4status-file-monitor"', 6 | ], 7 | dependencies: [ libj4status_plugin, gio, glib ], 8 | name_prefix: '', 9 | install: true, 10 | install_dir: plugins_install_dir, 11 | ) 12 | 13 | man_pages += [ [ files('man/j4status-file-monitor.conf.xml'), 'j4status-file-monitor.conf.5' ] ] 14 | -------------------------------------------------------------------------------- /input/file-monitor/src/file-monitor.c: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "j4status-plugin-input.h" 31 | 32 | struct _J4statusPluginContext { 33 | J4statusCoreInterface *core; 34 | GList *sections; 35 | }; 36 | 37 | typedef struct { 38 | J4statusPluginContext *context; 39 | GFileMonitor *monitor; 40 | J4statusSection *section; 41 | } J4statusFileMonitorSection; 42 | 43 | static void 44 | _j4status_file_monitor_changed(GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, gpointer user_data) 45 | { 46 | J4statusFileMonitorSection *section = user_data; 47 | 48 | GFileInputStream *stream; 49 | stream = g_file_read(file, NULL, NULL); 50 | if ( stream != NULL ) 51 | { 52 | GDataInputStream *data_stream; 53 | data_stream = g_data_input_stream_new(G_INPUT_STREAM(stream)); 54 | g_object_unref(stream); 55 | gsize length; 56 | j4status_section_set_value(section->section, g_data_input_stream_read_upto(data_stream, "", -1, &length, NULL, NULL)); 57 | } 58 | } 59 | 60 | static void 61 | _j4status_file_monitor_section_free(gpointer data) 62 | { 63 | J4statusFileMonitorSection *section = data; 64 | 65 | j4status_section_free(section->section); 66 | 67 | g_object_unref(section->monitor); 68 | 69 | g_free(section); 70 | } 71 | 72 | static J4statusPluginContext * 73 | _j4status_file_monitor_init(J4statusCoreInterface *core) 74 | { 75 | GKeyFile *key_file = NULL; 76 | 77 | gchar *dir; 78 | dir = g_build_filename(g_get_user_runtime_dir(), PACKAGE_NAME G_DIR_SEPARATOR_S "file-monitor", NULL); 79 | if ( ( ! g_file_test(dir, G_FILE_TEST_IS_DIR) ) && ( g_mkdir_with_parents(dir, 0755) < 0 ) ) 80 | { 81 | g_warning("Couldn't create the directory to monitor '%s': %s", dir, g_strerror(errno)); 82 | goto fail; 83 | } 84 | key_file = j4status_config_get_key_file("FileMonitor"); 85 | if ( key_file == NULL ) 86 | { 87 | g_message("Missing configuration: No section, aborting"); 88 | goto fail; 89 | } 90 | 91 | gchar **files; 92 | files = g_key_file_get_string_list(key_file, "FileMonitor", "Files", NULL, NULL); 93 | if ( files == NULL ) 94 | { 95 | g_message("Missing configuration: Empty list of files to monitor, aborting"); 96 | goto fail; 97 | } 98 | 99 | g_key_file_free(key_file); 100 | 101 | J4statusPluginContext *context; 102 | context = g_new0(J4statusPluginContext, 1); 103 | context->core = core; 104 | 105 | gchar **file; 106 | for ( file = files ; *file != NULL ; ++file ) 107 | { 108 | GError *error = NULL; 109 | GFile *g_file; 110 | GFileMonitor *monitor; 111 | 112 | if ( g_path_is_absolute(*file) ) 113 | g_file = g_file_new_for_path(*file); 114 | else 115 | { 116 | gchar *filename; 117 | filename = g_build_filename(dir, *file, NULL); 118 | 119 | g_file = g_file_new_for_path(filename); 120 | g_free(filename); 121 | } 122 | monitor = g_file_monitor_file(g_file, G_FILE_MONITOR_NONE, NULL, &error); 123 | g_object_unref(g_file); 124 | if ( monitor == NULL ) 125 | { 126 | g_warning("Couldn't monitor file '%s': %s", *file, error->message); 127 | g_clear_error(&error); 128 | continue; 129 | } 130 | 131 | J4statusFileMonitorSection *section; 132 | section = g_new0(J4statusFileMonitorSection, 1); 133 | section->context = context; 134 | section->monitor = monitor; 135 | section->section = j4status_section_new(context->core); 136 | 137 | j4status_section_set_name(section->section, "file-monitor"); 138 | j4status_section_set_instance(section->section, *file); 139 | j4status_section_set_label(section->section, *file); 140 | g_signal_connect(monitor, "changed", G_CALLBACK(_j4status_file_monitor_changed), section); 141 | 142 | if ( j4status_section_insert(section->section) ) 143 | context->sections = g_list_prepend(context->sections, section); 144 | else 145 | _j4status_file_monitor_section_free(section); 146 | } 147 | g_strfreev(files); 148 | g_free(dir); 149 | 150 | if ( context->sections == NULL ) 151 | { 152 | g_free(context); 153 | g_free(dir); 154 | return NULL; 155 | } 156 | 157 | return context; 158 | 159 | fail: 160 | if ( key_file != NULL ) 161 | g_key_file_free(key_file); 162 | g_free(dir); 163 | return NULL; 164 | } 165 | 166 | static void 167 | _j4status_file_monitor_uninit(J4statusPluginContext *context) 168 | { 169 | g_list_free_full(context->sections, _j4status_file_monitor_section_free); 170 | 171 | g_free(context); 172 | } 173 | 174 | J4STATUS_EXPORT void 175 | j4status_input_plugin(J4statusInputPluginInterface *interface) 176 | { 177 | libj4status_input_plugin_interface_add_init_callback(interface, _j4status_file_monitor_init); 178 | libj4status_input_plugin_interface_add_uninit_callback(interface, _j4status_file_monitor_uninit); 179 | } 180 | -------------------------------------------------------------------------------- /input/mpd/man/j4status-mpd.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-mpd.conf 46 | 5 47 | 48 | 49 | 50 | j4status-mpd.conf 51 | j4status MPD plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the MPD plugin 57 | 58 | 59 | The MPD plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the MPD plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[MPD]</varname> 76 | 77 | 78 | 79 | 80 | Host= 81 | (An hostname or a path to a UNIX socket, defaults to $MPD_HOST) 82 | 83 | 84 | The MPD host to connect to. 85 | 86 | 87 | 88 | 89 | 90 | Port= 91 | (A port numbre, defaults to $MPD_PORT) 92 | 93 | 94 | The port to use to connect to MPD using TCP/IP. 95 | 96 | 97 | 98 | 99 | Password= 100 | (A string, defaults to the pre-'@' part of $MPD_HOST) 101 | 102 | 103 | The MPD password. 104 | 105 | 106 | 107 | 108 | 109 | Actions= 110 | (A list of action bindings) 111 | 112 | 113 | 114 | action can be: 115 | 116 | toggle 117 | play 118 | pause 119 | stop 120 | next 121 | previous 122 | 123 | 124 | See j4status1 and j4status.conf5 for the reference on event id and action bindings. 125 | 126 | 127 | 128 | 129 | 130 | 131 | Section <varname>[MPD <replaceable>host</replaceable>]</varname> 132 | 133 | 134 | 135 | 136 | Format= 137 | (A format string, defaults to "${song:-No song}${database:+ ↻} [${options[repeat]:{;r; }}${options[random]:{;z; }}${options[single]:{;1; }}${options[consume]:{;-; }}]") 138 | 139 | 140 | reference can be: 141 | 142 | 143 | state 144 | 145 | 146 | An enumeration representing the playing state of MPD. Can be 147 | 148 | 0 for playing 149 | 1 for paused 150 | 2 for stopped 151 | . 152 | This state is also reflected using section colour if available. 153 | 154 | 155 | 156 | 157 | 158 | song 159 | 160 | The played song name. If MPD is stopped, the song which would be played. 161 | 162 | 163 | 164 | 165 | database 166 | 167 | A boolean indicating if the database is currently updating. 168 | 169 | 170 | 171 | 172 | options 173 | 174 | The play options of the server. It is a dictionnary of booleans. The following keys are available: 175 | 176 | repeat 177 | random 178 | single 179 | consume 180 | 181 | 182 | 183 | 184 | 185 | volume 186 | 187 | The current volume (as a percentage), if available. 188 | 189 | 190 | 191 | Here are some examples: 192 | 193 | "${song}" 194 | "${state:[;0;2;⏵;⏸;⏹]} ${song}" 195 | "${song} ${volume}${volume:+%}" 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | See Also 206 | 207 | j4status.conf5 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /input/mpd/meson.build: -------------------------------------------------------------------------------- 1 | libmpdclient = dependency('libmpdclient', required: get_option('mpd')) 2 | 3 | if libmpdclient.found() 4 | libgwater_mpd = subproject('libgwater').get_variable('libgwater_mpd') 5 | 6 | shared_library('mpd', [ config_h ] + files( 7 | 'src/mpd.c', 8 | ), 9 | c_args: [ 10 | '-DG_LOG_DOMAIN="j4status-mpd"', 11 | ], 12 | dependencies: [ libmpdclient, libgwater_mpd, libj4status_plugin, gio, gobject, glib ], 13 | name_prefix: '', 14 | install: true, 15 | install_dir: plugins_install_dir, 16 | ) 17 | 18 | man_pages += [ [ files('man/j4status-mpd.conf.xml'), 'j4status-mpd.conf.5' ] ] 19 | docbook_conditions += 'enable_mpd_input' 20 | endif 21 | -------------------------------------------------------------------------------- /input/nl/man/j4status-nl.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-nl.conf 46 | 5 47 | 48 | 49 | 50 | j4status-nl.conf 51 | j4status Netlink plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the Netlink plugin 57 | 58 | 59 | The Netlink plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the Netlink plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[Netlink]</varname> 76 | 77 | 78 | 79 | 80 | Interfaces= 81 | (list of interfaces names, defaults to empty) 82 | 83 | 84 | The list of interfaces the plugin will monitor. 85 | 86 | 87 | 88 | 89 | 90 | 91 | Section <varname>[Netlink Formats]</varname> 92 | 93 | 94 | 95 | 96 | Addresses= 97 | (An enumeration: 98 | 99 | "IPv4" 100 | "IPv6" 101 | "All" 102 | , 103 | defaults to "All") 104 | 105 | 106 | Which addresses to display. 107 | 108 | 109 | 110 | 111 | 112 | Up= 113 | (format string, defaults to "${addresses}") 114 | 115 | 116 | This format is used for all non-WiFi active interfaces. 117 | reference can be: 118 | 119 | 120 | addresses 121 | 122 | The addresses of the interface (as an array). 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | Down= 132 | (format string, defaults to "Down") 133 | 134 | 135 | This format is used for non-WiFi inactive interfaces. 136 | No reference for this format. 137 | 138 | 139 | 140 | 141 | 142 | UpWiFi= 143 | (format string, defaults to "${addresses} (${strength}${strength:+% }${ssid/^.+$/at \0, }${bitrate:+${bitrate(p)}b/s})") 144 | 145 | 146 | This format is used for active WiFi interfaces. 147 | reference can be: 148 | 149 | 150 | addresses 151 | 152 | The addresses of the interface (as an array). 153 | 154 | 155 | 156 | 157 | 158 | 159 | strength 160 | 161 | The strength of the signal (in percentage). 162 | 163 | 164 | 165 | 166 | 167 | 168 | ssid 169 | 170 | The SSID. 171 | 172 | 173 | 174 | 175 | 176 | 177 | bitrate 178 | 179 | The bitrate of the connection in b/s. 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | DownWiFi= 189 | (format string, defaults to "Down${aps/^.+$/ (\0 APs)}") 190 | 191 | 192 | This format is used for inactive WiFi interfaces. 193 | reference can be: 194 | 195 | 196 | aps 197 | 198 | The numbre of available access points. 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | See Also 210 | 211 | j4status.conf5 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /input/nl/meson.build: -------------------------------------------------------------------------------- 1 | 2 | libnl_route = dependency('libnl-route-3.0', required: get_option('nl')) 3 | libnl_genl = dependency('libnl-genl-3.0', required: get_option('nl')) 4 | 5 | if libnl_route.found() and libnl_genl.found() 6 | libgwater_nl = subproject('libgwater').get_variable('libgwater_nl') 7 | foreach h : [ 'sys/socket.h', 'linux/if_arp.h', 'linux/nl80211.h' ] 8 | if not c_compiler.has_header(h) 9 | error('Header @0@ was not found, but is required'.format(h)) 10 | endif 11 | endforeach 12 | 13 | shared_library('nl', [ config_h ] + files( 14 | 'src/nl.c', 15 | ), 16 | c_args: [ 17 | '-DG_LOG_DOMAIN="j4status-nl"', 18 | ], 19 | dependencies: [ libnl_route, libnl_genl, libgwater_nl, libj4status_plugin, gio_platform, gio, gobject, glib ], 20 | name_prefix: '', 21 | install: true, 22 | install_dir: plugins_install_dir, 23 | ) 24 | 25 | man_pages += [ [ files('man/j4status-nl.conf.xml'), 'j4status-nl.conf.5' ] ] 26 | docbook_conditions += 'enable_nl_input' 27 | endif 28 | -------------------------------------------------------------------------------- /input/pulseaudio/man/j4status-pulseaudio.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-pulseaudio.conf 46 | 5 47 | 48 | 49 | 50 | j4status-pulseaudio.conf 51 | j4status PulseAudio plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the PulseAudio plugin 57 | 58 | 59 | The PulseAudio plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the PulseAudio plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[PulseAudio]</varname> 76 | 77 | 78 | 79 | 80 | Increment= 81 | (A volume (a percentage), defaults to 5) 82 | 83 | 84 | The volume increment to use for "raise" and "lower" actions. 85 | 86 | 87 | 88 | 89 | 90 | Volume= 91 | (A volume (a percentage), defaults to 100) 92 | 93 | 94 | The volume to use for the "set" action. 95 | 96 | 97 | 98 | 99 | 100 | UnlimitedVolume= 101 | (A boolean, defaults to false) 102 | 103 | 104 | Whether to block volume to 100% or not for "raise" and "lower" actions. 105 | 106 | 107 | 108 | 109 | 110 | Format= 111 | (A format string, defaults to "${volume[@% ]}%") 112 | 113 | 114 | reference can be: 115 | 116 | 117 | port 118 | 119 | 120 | An enumeration representing the active port of the sink. Can be 121 | 122 | 0 for speaker 123 | 1 for headphones 124 | . 125 | 126 | 127 | 128 | 129 | 130 | mute 131 | 132 | A boolean representing the mute state of the sink. 133 | This state is also reflected using section colour if available. 134 | 135 | 136 | 137 | 138 | volume 139 | 140 | The current volume of all channels (as an array, in percentage). If all channels are the same, the array will contain a single value. 141 | 142 | 143 | 144 | 145 | Here are some examples: 146 | 147 | "${port:[;0;1;🔈;🎧]} ${volume[@% ]}%" 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | Actions= 156 | (A list of action bindings) 157 | 158 | 159 | 160 | action can be: 161 | 162 | raise 163 | lower 164 | set 165 | mute toggle 166 | next 167 | previous 168 | 169 | 170 | See j4status1 and j4status.conf5 for the reference on event id and action bindings. 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | See Also 179 | 180 | j4status.conf5 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /input/pulseaudio/meson.build: -------------------------------------------------------------------------------- 1 | libpulse_min_version = '0.9.16' 2 | 3 | libpulse = dependency('libpulse', version: '>=@0@'.format(libpulse_min_version), required: get_option('pulseaudio')) 4 | libpulse_glib = dependency('libpulse-mainloop-glib', required: get_option('pulseaudio')) 5 | 6 | if libpulse.found() and libpulse_glib.found() 7 | shared_library('pulseaudio', [ config_h ] + files( 8 | 'src/pulseaudio.c', 9 | ), 10 | c_args: [ 11 | '-DG_LOG_DOMAIN="j4status-pulseaudio"', 12 | ], 13 | dependencies: [ libpulse_glib, libpulse, libj4status_plugin, glib ], 14 | name_prefix: '', 15 | install: true, 16 | install_dir: plugins_install_dir, 17 | ) 18 | 19 | man_pages += [ [ files('man/j4status-pulseaudio.conf.xml'), 'j4status-pulseaudio.conf.5' ] ] 20 | docbook_conditions += 'enable_pulseaudio_input' 21 | endif 22 | -------------------------------------------------------------------------------- /input/sensors/man/j4status-sensors.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-sensors.conf 46 | 5 47 | 48 | 49 | 50 | j4status-sensors.conf 51 | j4status sensors plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the sensors plugin 57 | 58 | 59 | The sensors plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the sensors plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[Sensors]</varname> 76 | 77 | 78 | 79 | 80 | Interval= 81 | (A number of seconds, defaults to 2) 82 | 83 | 84 | The number of seconds between each update. 85 | Minimum of 2 because libsensors does not update more often. 86 | 87 | 88 | 89 | 90 | 91 | Sensors= 92 | (list of sensor names, defaults to empty) 93 | 94 | 95 | The list of sensors the plugin will watch. 96 | They may contain wildcards. The default empty value makes the plugin watch all the available sensors. 97 | See the output of sensors1. 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | Examples 106 | 107 | 108 | Only monitor one chip 109 | 110 | 111 | [Sensors] 112 | Sensors=coretemp-isa-0000; 113 | 114 | 115 | 116 | 117 | Only monitor two features on one chip 118 | 119 | 120 | [Sensors] 121 | Sensors=coretemp-isa-0000; 122 | 123 | # Disable the first feature, named “Physical id 0” on my computer 124 | [Override sensors:coretemp-isa-0000/temp1] 125 | Disable=true 126 | 127 | 128 | 129 | 130 | Full filtering and renaming 131 | 132 | 133 | [Sensors] 134 | Sensors=coretemp-isa-0000; 135 | 136 | # Disable the first feature, named “Physical id 0” on my computer 137 | [Override sensors:coretemp-isa-0000/temp1] 138 | Disable=true 139 | 140 | # Put a nice label for the two CPU 141 | [Override sensors:coretemp-isa-0000/temp2] 142 | Label=🌡 143 | [Override sensors:coretemp-isa-0000/temp3] 144 | Label=🌡 145 | 146 | 147 | 148 | 149 | 150 | See Also 151 | 152 | j4status.conf5 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /input/sensors/meson.build: -------------------------------------------------------------------------------- 1 | libsensors = c_compiler.find_library('sensors', required: get_option('sensors')) 2 | 3 | if libsensors.found() 4 | shared_library('sensors', [ config_h ] + files( 5 | 'src/sensors.c', 6 | ), 7 | c_args: [ 8 | '-DG_LOG_DOMAIN="j4status-sensors"', 9 | ], 10 | dependencies: [ libsensors, libj4status_plugin, glib ], 11 | name_prefix: '', 12 | install: true, 13 | install_dir: plugins_install_dir, 14 | ) 15 | 16 | man_pages += [ [ files('man/j4status-sensors.conf.xml'), 'j4status-sensors.conf.5' ] ] 17 | docbook_conditions += 'enable_sensors_input' 18 | endif 19 | -------------------------------------------------------------------------------- /input/systemd/man/j4status-systemd.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-systemd.conf 46 | 5 47 | 48 | 49 | 50 | j4status-systemd.conf 51 | j4status systemd plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the systemd plugin 57 | 58 | 59 | The systemd plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the systemd plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[systemd]</varname> 76 | 77 | 78 | 79 | 80 | Units= 81 | (list of unit names, defaults to empty) 82 | 83 | 84 | The list of units the plugin will monitor. 85 | 86 | 87 | 88 | 89 | 90 | MaskedStates= 91 | (list of unit states, defaults to empty) 92 | 93 | 94 | The states from this list will be ignored. 95 | You can use it to e.g. only display units in a non-active state, so you can focus on failing units. 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | Examples 104 | 105 | 106 | Monitor your Apache HTTPd service 107 | 108 | 109 | [systemd] 110 | Units=apache.service; 111 | 112 | 113 | Here is the expected output : 114 | 115 | 116 | apache.service: active When the service is active 117 | apache.service: reloading When currently reloading the configuration 118 | apache.service: failed When service failed or died 119 | 120 | 121 | 122 | 123 | 124 | See Also 125 | 126 | j4status.conf5 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /input/systemd/meson.build: -------------------------------------------------------------------------------- 1 | shared_library('systemd', [ config_h ] + files( 2 | 'src/systemd.c', 3 | ), 4 | c_args: [ 5 | '-DG_LOG_DOMAIN="j4status-systemd"', 6 | ], 7 | dependencies: [ libj4status_plugin, gio, glib ], 8 | name_prefix: '', 9 | install: true, 10 | install_dir: plugins_install_dir, 11 | ) 12 | 13 | man_pages += [ [ files('man/j4status-systemd.conf.xml'), 'j4status-systemd.conf.5' ] ] 14 | -------------------------------------------------------------------------------- /input/systemd/src/systemd.c: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "j4status-plugin-input.h" 31 | 32 | #define SYSTEMD_BUS_NAME "org.freedesktop.systemd1" 33 | #define SYSTEMD_OBJECT_PATH "/org/freedesktop/systemd1" 34 | #define SYSTEMD_MANAGER_INTERFACE_NAME SYSTEMD_BUS_NAME ".Manager" 35 | #define SYSTEMD_UNIT_INTERFACE_NAME SYSTEMD_BUS_NAME ".Unit" 36 | 37 | struct _J4statusPluginContext { 38 | J4statusCoreInterface *core; 39 | GList *sections; 40 | gchar **masked_states; 41 | GDBusConnection *connection; 42 | gboolean started; 43 | GDBusProxy *manager; 44 | }; 45 | 46 | typedef struct { 47 | J4statusPluginContext *context; 48 | J4statusSection *section; 49 | gchar *unit_name; 50 | GDBusProxy *unit; 51 | } J4statusSystemdSection; 52 | 53 | static gboolean 54 | _j4status_systemd_dbus_call(GDBusProxy *proxy, const gchar *method, GError **error) 55 | { 56 | GVariant *ret; 57 | ret = g_dbus_proxy_call_sync(proxy, method, g_variant_new("()"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, error); 58 | if ( ret == NULL ) 59 | return FALSE; 60 | g_variant_get(ret, "()"); 61 | g_variant_unref(ret); 62 | return TRUE; 63 | } 64 | 65 | static GDBusProxy * 66 | _j4status_systemd_dbus_get_unit(J4statusPluginContext *context, const gchar *unit_name) 67 | { 68 | GVariant *ret; 69 | 70 | ret = g_dbus_proxy_call_sync(context->manager, "GetUnit", g_variant_new("(s)", unit_name), G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); 71 | if ( ret == NULL ) 72 | return NULL; 73 | 74 | const gchar *unit_object_path; 75 | g_variant_get(ret, "(&o)", &unit_object_path); 76 | 77 | GError *error = NULL; 78 | GDBusProxy *unit; 79 | unit = g_dbus_proxy_new_sync(context->connection, G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, NULL, SYSTEMD_BUS_NAME, unit_object_path, SYSTEMD_UNIT_INTERFACE_NAME, NULL, &error); 80 | if ( unit == NULL ) 81 | g_warning("Could not monitor unit %s: %s", unit_name, error->message); 82 | g_clear_error(&error); 83 | 84 | g_variant_unref(ret); 85 | 86 | return unit; 87 | } 88 | 89 | static GVariant * 90 | _j4status_systemd_dbus_get_property(GDBusProxy *proxy, const gchar *property) 91 | { 92 | GError *error = NULL; 93 | GVariant *ret, *val = NULL; 94 | 95 | val = g_dbus_proxy_get_cached_property(proxy, property); 96 | if ( val == NULL ) 97 | { 98 | ret = g_dbus_proxy_call_sync(proxy, "org.freedesktop.DBus.Properties.Get", g_variant_new("(ss)", g_dbus_proxy_get_interface_name(proxy), property), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error); 99 | if ( ret == NULL ) 100 | g_warning("Could get property %s . %s: %s", g_dbus_proxy_get_interface_name(proxy), property, error->message); 101 | else 102 | { 103 | g_variant_get(ret, "(v)", &val); 104 | g_variant_unref(ret); 105 | } 106 | g_clear_error(&error); 107 | } 108 | 109 | return val; 110 | } 111 | 112 | static gchar * 113 | _j4status_systemd_dbus_get_property_string(GDBusProxy *proxy, const gchar *property, const gchar *default_value) 114 | { 115 | GVariant *ret; 116 | 117 | ret = _j4status_systemd_dbus_get_property(proxy, property); 118 | if ( ret == NULL ) 119 | return g_strdup(default_value); 120 | 121 | gchar *val; 122 | g_variant_get(ret, "s", &val); 123 | g_variant_unref(ret); 124 | 125 | return val; 126 | } 127 | 128 | static void 129 | _j4status_systemd_unit_state_changed(GDBusProxy *gobject, GVariant *changed_properties, GStrv invalidated_properties, gpointer user_data) 130 | { 131 | J4statusSystemdSection *section = user_data; 132 | 133 | J4statusState state; 134 | gchar *status; 135 | status = _j4status_systemd_dbus_get_property_string(section->unit, "ActiveState", "Unknown"); 136 | if ( ( g_strcmp0(status, "active") == 0 ) || ( g_strcmp0(status, "reloading") == 0 ) ) 137 | state = J4STATUS_STATE_GOOD; 138 | else if ( ( g_strcmp0(status, "failed") == 0 ) ) 139 | state = J4STATUS_STATE_BAD; 140 | else 141 | state = J4STATUS_STATE_NO_STATE; 142 | 143 | if ( ( section->context->masked_states != NULL ) && g_strv_contains((const gchar * const *) section->context->masked_states, status) ) 144 | status = (g_free(status), NULL); 145 | 146 | j4status_section_set_state(section->section, state); 147 | j4status_section_set_value(section->section, status); 148 | } 149 | 150 | static void 151 | _j4status_systemd_section_attach_unit(gpointer data, gpointer user_data) 152 | { 153 | J4statusPluginContext *context = user_data; 154 | J4statusSystemdSection *section = data; 155 | 156 | if ( section->unit != NULL ) 157 | return; 158 | 159 | section->unit = _j4status_systemd_dbus_get_unit(context, section->unit_name); 160 | 161 | if ( section->unit != NULL ) 162 | { 163 | g_signal_connect(section->unit, "g-properties-changed", G_CALLBACK(_j4status_systemd_unit_state_changed), section); 164 | _j4status_systemd_unit_state_changed(section->unit, NULL, NULL, section); 165 | } 166 | } 167 | 168 | static void 169 | _j4status_systemd_section_detach_unit(gpointer data, gpointer user_data) 170 | { 171 | J4statusSystemdSection *section = data; 172 | 173 | if ( section->unit != NULL ) 174 | g_object_unref(section->unit); 175 | section->unit = NULL; 176 | j4status_section_set_state(section->section, J4STATUS_STATE_UNAVAILABLE); 177 | j4status_section_set_value(section->section, NULL); 178 | } 179 | 180 | static void 181 | _j4status_systemd_bus_signal(GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, gpointer user_data) 182 | { 183 | J4statusPluginContext *context = user_data; 184 | 185 | if ( g_strcmp0(signal_name, "Reloading") == 0 ) 186 | { 187 | gboolean reloading; 188 | g_variant_get(parameters, "(b)", &reloading); 189 | if ( reloading ) 190 | g_list_foreach(context->sections, _j4status_systemd_section_detach_unit, context); 191 | else 192 | g_list_foreach(context->sections, _j4status_systemd_section_attach_unit, context); 193 | } 194 | } 195 | 196 | static void 197 | _j4status_systemd_section_free(gpointer data) 198 | { 199 | J4statusSystemdSection *section = data; 200 | 201 | if ( section->unit != NULL ) 202 | g_object_unref(section->unit); 203 | 204 | j4status_section_free(section->section); 205 | g_free(section->unit_name); 206 | 207 | g_free(section); 208 | } 209 | 210 | 211 | static void 212 | _j4status_systemd_section_new(J4statusPluginContext *context, gchar *unit_name) 213 | { 214 | J4statusSystemdSection *section; 215 | 216 | section = g_new0(J4statusSystemdSection, 1); 217 | section->context = context; 218 | section->unit_name = unit_name; 219 | section->section = j4status_section_new(context->core); 220 | 221 | j4status_section_set_name(section->section, "systemd"); 222 | j4status_section_set_instance(section->section, unit_name); 223 | 224 | if ( g_str_has_suffix(unit_name, ".service") ) 225 | { 226 | gsize l; 227 | gchar *label; 228 | l = strlen(unit_name) - strlen(".service") + 1; 229 | label = g_newa(gchar, l); 230 | g_snprintf(label, l, "%s", unit_name); 231 | j4status_section_set_label(section->section, label); 232 | } 233 | else 234 | { 235 | j4status_section_set_label(section->section, unit_name); 236 | } 237 | 238 | /* Possible unit states: 239 | * loaded failed active inactive not-found listening running waiting plugged mounted exited dead masked */ 240 | j4status_section_set_max_width(section->section, -strlen("listening")); 241 | 242 | if ( j4status_section_insert(section->section) ) 243 | context->sections = g_list_prepend(context->sections, section); 244 | else 245 | _j4status_systemd_section_free(section); 246 | } 247 | 248 | static void _j4status_systemd_uninit(J4statusPluginContext *context); 249 | 250 | J4statusPluginContext * 251 | _j4status_systemd_init(J4statusCoreInterface *core) 252 | { 253 | GKeyFile *key_file; 254 | key_file = j4status_config_get_key_file("systemd"); 255 | if ( key_file == NULL ) 256 | { 257 | g_message("Missing configuration: No section, aborting"); 258 | return NULL; 259 | } 260 | 261 | gchar **units; 262 | gchar **masked_states = NULL; 263 | units = g_key_file_get_string_list(key_file, "systemd", "Units", NULL, NULL); 264 | if ( units == NULL ) 265 | { 266 | g_message("Missing configuration: Empty list of units to monitor, aborting"); 267 | g_key_file_free(key_file); 268 | return NULL; 269 | } 270 | masked_states = g_key_file_get_string_list(key_file, "systemd", "MaskedStates", NULL, NULL); 271 | g_key_file_free(key_file); 272 | 273 | GError *error = NULL; 274 | 275 | GDBusConnection *connection = NULL; 276 | 277 | connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); 278 | if ( connection == NULL ) 279 | { 280 | g_warning("Couldn't connect to D-Bus: %s", error->message); 281 | goto fail; 282 | } 283 | 284 | GDBusProxy *manager; 285 | manager = g_dbus_proxy_new_sync(connection, G_DBUS_PROXY_FLAGS_NONE, NULL, SYSTEMD_BUS_NAME, SYSTEMD_OBJECT_PATH, SYSTEMD_MANAGER_INTERFACE_NAME, NULL, &error); 286 | if ( manager == NULL ) 287 | { 288 | g_warning("Couldn't connect to systemd manager D-Bus interface: %s", error->message); 289 | goto fail; 290 | } 291 | 292 | J4statusPluginContext *context = NULL; 293 | 294 | context = g_new0(J4statusPluginContext, 1); 295 | context->core = core; 296 | 297 | context->connection = connection; 298 | context->manager = manager; 299 | 300 | gchar **unit; 301 | for ( unit = units ; *unit != NULL ; ++unit ) 302 | _j4status_systemd_section_new(context, *unit); 303 | g_free(units); 304 | 305 | context->masked_states = masked_states; 306 | 307 | if ( context->sections == NULL ) 308 | { 309 | _j4status_systemd_uninit(context); 310 | return NULL; 311 | } 312 | 313 | g_signal_connect(context->manager, "g-signal", G_CALLBACK(_j4status_systemd_bus_signal), context); 314 | 315 | return context; 316 | 317 | fail: 318 | g_clear_error(&error); 319 | if ( connection != NULL ) 320 | g_object_unref(connection); 321 | g_strfreev(masked_states); 322 | g_strfreev(units); 323 | 324 | return NULL; 325 | } 326 | 327 | static void 328 | _j4status_systemd_uninit(J4statusPluginContext *context) 329 | { 330 | g_list_free_full(context->sections, _j4status_systemd_section_free); 331 | g_strfreev(context->masked_states); 332 | 333 | g_object_unref(context->manager); 334 | g_object_unref(context->connection); 335 | 336 | g_free(context); 337 | } 338 | 339 | static void 340 | _j4status_systemd_start(J4statusPluginContext *context) 341 | { 342 | context->started = TRUE; 343 | _j4status_systemd_dbus_call(context->manager, "Subscribe", NULL); 344 | g_list_foreach(context->sections, _j4status_systemd_section_attach_unit, context); 345 | } 346 | 347 | static void 348 | _j4status_systemd_stop(J4statusPluginContext *context) 349 | { 350 | context->started = FALSE; 351 | _j4status_systemd_dbus_call(context->manager, "Unsubscribe", NULL); 352 | g_list_foreach(context->sections, _j4status_systemd_section_detach_unit, context); 353 | } 354 | 355 | J4STATUS_EXPORT void 356 | j4status_input_plugin(J4statusInputPluginInterface *interface) 357 | { 358 | libj4status_input_plugin_interface_add_init_callback(interface, _j4status_systemd_init); 359 | libj4status_input_plugin_interface_add_uninit_callback(interface, _j4status_systemd_uninit); 360 | 361 | libj4status_input_plugin_interface_add_start_callback(interface, _j4status_systemd_start); 362 | libj4status_input_plugin_interface_add_stop_callback(interface, _j4status_systemd_stop); 363 | } 364 | -------------------------------------------------------------------------------- /input/time/man/j4status-time.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-time.conf 46 | 5 47 | 48 | 49 | 50 | j4status-time.conf 51 | j4status time plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the time plugin 57 | 58 | 59 | The time plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the time plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[Time]</varname> 76 | 77 | 78 | 79 | 80 | Interval= 81 | (A number of seconds, defaults to 1) 82 | 83 | 84 | The number of seconds between each update. 85 | 86 | 87 | 88 | 89 | 90 | Format= 91 | (format string, defaults to "%F %T") 92 | 93 | 94 | Format string used to display date and time. 95 | See strftime3. 96 | 97 | 98 | 99 | 100 | 101 | Zones= 102 | (list of timezone names, defaults to local) 103 | 104 | 105 | Timezones to print the time for. 106 | See strftime3. 107 | 108 | 109 | 110 | 111 | 112 | Formats= 113 | (list of format string, defaults to empty) 114 | 115 | 116 | Each timezone may have its own format string. You must have exactly the same number of format strings as timezones for the Zones key. 117 | An empty format string tells the plugin to use the Format key format. 118 | See strftime3. 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | Examples 127 | 128 | 129 | Displaying local time (default) 130 | 131 | 132 | The default configuration is to display local time in the “YYYY-MM-DD HH:MM:SS” format. 133 | 134 | 135 | Here is the expected output : 136 | 137 | 138 | 2013-10-21 08:48:30 139 | 140 | 141 | 142 | 143 | Displaying time for Toronto, Paris and Tokyo (with some fancyness) 144 | 145 | 146 | [Time] 147 | Zones=America/Toronto;Europe/Paris;Asia/Tokyo 148 | Formats=%I:%M %p %Z;%c;; 149 | 150 | 151 | This configuration will display three timezones: America/Toronto, Europe/Paris and Asia/Tokyo. 152 | The Toronto part will display a 12-hour time with timezone name. 153 | The Paris part will display localised date and time. 154 | The Tokyo part will use the global format, which is the default here. 155 | 156 | 157 | Here is the expected output : 158 | 159 | 160 | 02:48 AM EDT | Mon Oct 21 08:48:30 CEST 2013 | 2013-10-21 15:48:30 161 | 162 | 163 | 164 | 165 | 166 | See Also 167 | 168 | j4status.conf5 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /input/time/meson.build: -------------------------------------------------------------------------------- 1 | shared_library('time', [ config_h ] + files( 2 | 'src/time.c', 3 | ), 4 | c_args: [ 5 | '-DG_LOG_DOMAIN="j4status-time"', 6 | ], 7 | dependencies: [ libj4status_plugin, glib ], 8 | name_prefix: '', 9 | install: true, 10 | install_dir: plugins_install_dir, 11 | ) 12 | 13 | man_pages += [ [ files('man/j4status-time.conf.xml'), 'j4status-time.conf.5' ] ] 14 | -------------------------------------------------------------------------------- /input/time/src/time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "j4status-plugin-input.h" 31 | 32 | #define TIME_SIZE 4095 33 | 34 | struct _J4statusPluginContext { 35 | J4statusCoreInterface *core; 36 | guint64 interval; 37 | gchar *format; 38 | GList *sections; 39 | guint timeout_id; 40 | }; 41 | 42 | typedef struct { 43 | J4statusSection *section; 44 | GTimeZone *tz; 45 | gchar *format; 46 | } J4statusTimeSection; 47 | 48 | static gboolean 49 | _j4status_time_update(gpointer user_data) 50 | { 51 | J4statusPluginContext *context = user_data; 52 | GDateTime *date_time; 53 | GDateTime *zone_date_time; 54 | date_time = g_date_time_new_now_utc(); 55 | 56 | GList *section_; 57 | for ( section_ = context->sections ; section_ != NULL ; section_ = g_list_next(section_) ) 58 | { 59 | J4statusTimeSection *section = section_->data; 60 | zone_date_time = g_date_time_to_timezone(date_time, section->tz); 61 | j4status_section_set_value(section->section, g_date_time_format(zone_date_time, ( section->format != NULL ) ? section->format : context->format)); 62 | g_date_time_unref(zone_date_time); 63 | } 64 | 65 | g_date_time_unref(date_time); 66 | 67 | return G_SOURCE_CONTINUE; 68 | } 69 | 70 | static void 71 | _j4status_time_section_free(gpointer data) 72 | { 73 | J4statusTimeSection *section = data; 74 | 75 | g_free(section->format); 76 | g_time_zone_unref(section->tz); 77 | 78 | 79 | j4status_section_free(section->section); 80 | 81 | g_free(section); 82 | } 83 | 84 | static void 85 | _j4status_time_section_new(J4statusPluginContext *context, const gchar *timezone, gchar *format) 86 | { 87 | J4statusTimeSection *section; 88 | 89 | section = g_new0(J4statusTimeSection, 1); 90 | section->tz = ( timezone != NULL ) ? g_time_zone_new(timezone) : g_time_zone_new_local(); 91 | section->format = format; 92 | section->section = j4status_section_new(context->core); 93 | 94 | timezone = ( timezone != NULL ) ? timezone : "local"; 95 | 96 | j4status_section_set_name(section->section, "time"); 97 | j4status_section_set_instance(section->section, timezone); 98 | 99 | if ( j4status_section_insert(section->section) ) 100 | context->sections = g_list_prepend(context->sections, section); 101 | else 102 | _j4status_time_section_free(section); 103 | } 104 | 105 | static void _j4status_time_uninit(J4statusPluginContext *context); 106 | 107 | static J4statusPluginContext * 108 | _j4status_time_init(J4statusCoreInterface *core) 109 | { 110 | J4statusPluginContext *context; 111 | 112 | context = g_new0(J4statusPluginContext, 1); 113 | context->core = core; 114 | 115 | context->format = g_strdup("%F %T"); 116 | gchar **timezones = NULL; 117 | gchar **formats = NULL; 118 | 119 | GKeyFile *key_file; 120 | key_file = j4status_config_get_key_file("Time"); 121 | if ( key_file != NULL ) 122 | { 123 | context->interval = g_key_file_get_uint64(key_file, "Time", "Interval", NULL); 124 | 125 | gchar *format; 126 | format = g_key_file_get_string(key_file, "Time", "Format", NULL); 127 | if ( format != NULL ) 128 | { 129 | g_free(context->format); 130 | context->format = format; 131 | } 132 | 133 | gsize timezones_length; 134 | gsize formats_length; 135 | 136 | timezones = g_key_file_get_string_list(key_file, "Time", "Zones", &timezones_length, NULL); 137 | formats = g_key_file_get_string_list(key_file, "Time", "Formats", &formats_length, NULL); 138 | if ( ( formats != NULL ) && ( formats_length != timezones_length ) ) 139 | { 140 | g_warning("You should specify one format per timezone. Will use global format"); 141 | g_strfreev(formats); 142 | formats = NULL; 143 | } 144 | 145 | g_key_file_free(key_file); 146 | } 147 | if ( context->interval < 1 ) 148 | context->interval = 1; 149 | 150 | if ( timezones == NULL ) 151 | _j4status_time_section_new(context, NULL, NULL); 152 | else 153 | { 154 | gchar **timezone; 155 | if ( formats != NULL ) 156 | { 157 | gchar **format; 158 | for ( timezone = timezones, format = formats ; *timezone != NULL ; ++timezone, ++format ) 159 | { 160 | if ( **format == '\0' ) 161 | { 162 | g_free(*format); 163 | *format = NULL; 164 | } 165 | _j4status_time_section_new(context, *timezone, *format); 166 | } 167 | g_free(formats); 168 | } 169 | else 170 | { 171 | for ( timezone = timezones ; *timezone != NULL ; ++timezone ) 172 | _j4status_time_section_new(context, *timezone, NULL); 173 | } 174 | g_strfreev(timezones); 175 | } 176 | 177 | if ( context->sections == NULL ) 178 | { 179 | _j4status_time_uninit(context); 180 | return NULL; 181 | } 182 | 183 | return context; 184 | } 185 | 186 | static void 187 | _j4status_time_uninit(J4statusPluginContext *context) 188 | { 189 | g_list_free_full(context->sections, _j4status_time_section_free); 190 | 191 | g_free(context->format); 192 | 193 | g_free(context); 194 | } 195 | 196 | static void 197 | _j4status_time_start(J4statusPluginContext *context) 198 | { 199 | _j4status_time_update(context); 200 | context->timeout_id = g_timeout_add_seconds(context->interval, _j4status_time_update, context); 201 | } 202 | 203 | static void 204 | _j4status_time_stop(J4statusPluginContext *context) 205 | { 206 | g_source_remove(context->timeout_id); 207 | context->timeout_id = 0; 208 | } 209 | 210 | J4STATUS_EXPORT void 211 | j4status_input_plugin(J4statusInputPluginInterface *interface) 212 | { 213 | libj4status_input_plugin_interface_add_init_callback(interface, _j4status_time_init); 214 | libj4status_input_plugin_interface_add_uninit_callback(interface, _j4status_time_uninit); 215 | 216 | libj4status_input_plugin_interface_add_start_callback(interface, _j4status_time_start); 217 | libj4status_input_plugin_interface_add_stop_callback(interface, _j4status_time_stop); 218 | } 219 | -------------------------------------------------------------------------------- /input/upower/man/j4status-upower.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-upower.conf 46 | 5 47 | 48 | 49 | 50 | j4status-upower.conf 51 | j4status UPower plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the UPower plugin 57 | 58 | 59 | The UPower plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the UPower plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[UPower]</varname> 76 | 77 | 78 | 79 | 80 | Format= 81 | (A format string, defaults to "${status:[;0;3;Empty;Full;Chr;Bat]}${charge:+ ${charge(f.2)}%}${time:+ (${time(d%{days:+%{days}d }%{hours:!00}%{hours(f02)}:%{minutes:!00}%{minutes(f02)}:%{seconds:!00}%{seconds(f02)})})}") 82 | 83 | 84 | reference can be: 85 | 86 | 87 | status 88 | 89 | 90 | An enumeration representing the status of the battery. Can be 91 | 92 | 0 for empty 93 | 1 for full 94 | 2 for charging 95 | 3 for discharging 96 | . 97 | 98 | 99 | 100 | 101 | 102 | charge 103 | 104 | A percentage representing the battery charge. 105 | This state is also reflected using section colour if available. 106 | 107 | 108 | 109 | 110 | time 111 | 112 | If charging, the time until full charge. If discharging, the time until empty. 113 | 114 | 115 | 116 | 117 | Here are some examples: 118 | 119 | "${port:[;0;1;🔈;🎧]} ${volume[@% ]}%" 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | See Also 130 | 131 | j4status.conf5 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /input/upower/meson.build: -------------------------------------------------------------------------------- 1 | upower = dependency('upower-glib', version: '>=0.99.8', required: get_option('upower')) 2 | 3 | if upower.found() 4 | shared_library('upower', [ config_h ] + files( 5 | 'src/upower.c', 6 | ), 7 | c_args: [ 8 | '-DG_LOG_DOMAIN="j4status-upower"', 9 | ], 10 | dependencies: [ upower, libj4status_plugin, glib ], 11 | name_prefix: '', 12 | install: true, 13 | install_dir: plugins_install_dir, 14 | ) 15 | 16 | man_pages += [ [ files('man/j4status-upower.conf.xml'), 'j4status-upower.conf.5' ] ] 17 | docbook_conditions += 'enable_upower_input' 18 | endif 19 | -------------------------------------------------------------------------------- /input/upower/src/upower.c: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "j4status-plugin-input.h" 31 | 32 | #define J4STATUS_UPOWER_DEFAULT_FORMAT "${status:[;0;3;Empty;Full;Chr;Bat]}${charge:+ ${charge(f.2)}%}${time:+ (${time(d%{days:+%{days}d }%{hours:!00}%{hours(f02)}:%{minutes:!00}%{minutes(f02)}:%{seconds:!00}%{seconds(f02)})})}" 33 | 34 | struct _J4statusPluginContext { 35 | J4statusCoreInterface *core; 36 | GList *sections; 37 | J4statusFormatString *format; 38 | UpClient *up_client; 39 | gboolean started; 40 | }; 41 | 42 | typedef struct { 43 | J4statusPluginContext *context; 44 | GObject *device; 45 | J4statusSection *section; 46 | } J4statusUpowerSection; 47 | 48 | typedef enum { 49 | TOKEN_STATUS, 50 | TOKEN_CHARGE, 51 | TOKEN_TIME, 52 | } J4statusUpowerFormatToken; 53 | 54 | static const gchar * const _j4status_upower_format_tokens[] = { 55 | [TOKEN_STATUS] = "status", 56 | [TOKEN_CHARGE] = "charge", 57 | [TOKEN_TIME] = "time", 58 | }; 59 | 60 | typedef enum { 61 | STATE_EMPTY, 62 | STATE_FULL, 63 | STATE_CHARGING, 64 | STATE_DISCHARGING, 65 | } J4statusUpowerStatus; 66 | 67 | typedef struct { 68 | J4statusUpowerStatus status; 69 | gdouble percentage; 70 | gint64 time; 71 | } J4statusUpowerFormatData; 72 | 73 | static GVariant * 74 | _j4status_upower_format_callback(G_GNUC_UNUSED const gchar *token, guint64 value, gconstpointer user_data) 75 | { 76 | const J4statusUpowerFormatData *data = user_data; 77 | 78 | switch ( (J4statusUpowerFormatToken) value ) 79 | { 80 | case TOKEN_STATUS: 81 | return g_variant_new_byte(data->status); 82 | case TOKEN_CHARGE: 83 | if ( data->percentage < 0 ) 84 | return NULL; 85 | return g_variant_new_double(data->percentage); 86 | case TOKEN_TIME: 87 | if ( data->time < 0 ) 88 | return NULL; 89 | return g_variant_new_int64(data->time); 90 | } 91 | return NULL; 92 | } 93 | 94 | static void 95 | _j4status_upower_device_changed(GObject *device, GParamSpec *pspec, gpointer user_data) 96 | { 97 | J4statusUpowerSection *section = user_data; 98 | 99 | UpDeviceState device_state; 100 | J4statusState state = J4STATUS_STATE_NO_STATE; 101 | J4statusUpowerFormatData data = { 102 | .status = STATE_EMPTY, 103 | .percentage = -1, 104 | .time = -1, 105 | }; 106 | 107 | g_object_get(device, "percentage", &data.percentage, "state", &device_state, NULL); 108 | 109 | switch ( device_state ) 110 | { 111 | case UP_DEVICE_STATE_LAST: /* Size placeholder */ 112 | case UP_DEVICE_STATE_UNKNOWN: 113 | j4status_section_set_state(section->section, J4STATUS_STATE_UNAVAILABLE); 114 | j4status_section_set_value(section->section, g_strdup("No battery")); 115 | return; 116 | case UP_DEVICE_STATE_EMPTY: 117 | state = J4STATUS_STATE_BAD | J4STATUS_STATE_URGENT; 118 | break; 119 | case UP_DEVICE_STATE_FULLY_CHARGED: 120 | data.status = STATE_FULL; 121 | state = J4STATUS_STATE_GOOD; 122 | break; 123 | case UP_DEVICE_STATE_CHARGING: 124 | case UP_DEVICE_STATE_PENDING_CHARGE: 125 | data.status = STATE_CHARGING; 126 | state = J4STATUS_STATE_AVERAGE; 127 | 128 | g_object_get(device, "time-to-full", &data.time, NULL); 129 | break; 130 | case UP_DEVICE_STATE_DISCHARGING: 131 | case UP_DEVICE_STATE_PENDING_DISCHARGE: 132 | data.status = STATE_DISCHARGING; 133 | if ( data.percentage < 15 ) 134 | state = J4STATUS_STATE_BAD; 135 | else 136 | state = J4STATUS_STATE_AVERAGE; 137 | 138 | if ( data.percentage < 5 ) 139 | state |= J4STATUS_STATE_URGENT; 140 | 141 | g_object_get(device, "time-to-empty", &data.time, NULL); 142 | break; 143 | } 144 | j4status_section_set_state(section->section, state); 145 | 146 | 147 | gchar *value; 148 | value = j4status_format_string_replace(section->context->format, _j4status_upower_format_callback, &data); 149 | j4status_section_set_value(section->section, value); 150 | } 151 | 152 | static void 153 | _j4status_upower_section_free(gpointer data) 154 | { 155 | J4statusUpowerSection *section = data; 156 | 157 | j4status_section_free(section->section); 158 | 159 | g_object_unref(section->device); 160 | 161 | g_free(section); 162 | } 163 | 164 | static void 165 | _j4status_upower_section_new(J4statusPluginContext *context, GObject *device, gboolean all_devices) 166 | { 167 | UpDeviceKind kind; 168 | 169 | g_object_get(device, "kind", &kind, NULL); 170 | 171 | const gchar *path; 172 | const gchar *name = NULL; 173 | const gchar *instance = NULL; 174 | const gchar *label = NULL; 175 | 176 | path = up_device_get_object_path(UP_DEVICE(device)); 177 | instance = g_utf8_strrchr(path, -1, '/') + strlen("/") + strlen(up_device_kind_to_string(kind)) + strlen("_"); 178 | 179 | switch ( kind ) 180 | { 181 | case UP_DEVICE_KIND_BATTERY: 182 | name = "upower-battery"; 183 | break; 184 | #define EXTRA_KIND(e, n, l) \ 185 | case UP_DEVICE_KIND_##e: \ 186 | if ( ! all_devices ) \ 187 | return; \ 188 | name = "upower-" #n; \ 189 | label = #l; \ 190 | break; 191 | EXTRA_KIND(UPS, ups, UPS) 192 | EXTRA_KIND(MONITOR, monitor, Monitor) 193 | EXTRA_KIND(MOUSE, mouse, Mouse) 194 | EXTRA_KIND(KEYBOARD, keyboard, Keyboard) 195 | EXTRA_KIND(PDA, pda, PDA) 196 | EXTRA_KIND(PHONE, phone, Phone) 197 | EXTRA_KIND(MEDIA_PLAYER, media-player, Media player) 198 | EXTRA_KIND(TABLET, tablet, Tablet) 199 | EXTRA_KIND(COMPUTER, computer, Computer) 200 | EXTRA_KIND(GAMING_INPUT, gaming-input, Gaming input) 201 | #if UP_CHECK_VERSION(0,99,12) 202 | EXTRA_KIND(PEN, pen, Pen) 203 | EXTRA_KIND(TOUCHPAD, touchpad, Touchpad) 204 | EXTRA_KIND(MODEM, modem, Modem) 205 | EXTRA_KIND(NETWORK, network, Network) 206 | EXTRA_KIND(HEADSET, headset, Headset) 207 | EXTRA_KIND(SPEAKERS, speakers, Speakers) 208 | EXTRA_KIND(HEADPHONES, headphones, Headphones) 209 | EXTRA_KIND(VIDEO, video, Video) 210 | EXTRA_KIND(OTHER_AUDIO, other-audio, Other audio) 211 | EXTRA_KIND(REMOTE_CONTROL, remote-control, Remote control) 212 | EXTRA_KIND(PRINTER, printer, Printer) 213 | EXTRA_KIND(SCANNER, scanner, Scanner) 214 | EXTRA_KIND(CAMERA, camera, Camera) 215 | EXTRA_KIND(WEARABLE, wearable, Wearable) 216 | EXTRA_KIND(TOY, toy, Toy) 217 | EXTRA_KIND(BLUETOOTH_GENERIC, bluetooth-generic, Bluetooth generic) 218 | #endif /* UP_CHECK_VERSION(0,99,12) */ 219 | #undef EXTRA_KIND 220 | case UP_DEVICE_KIND_UNKNOWN: 221 | case UP_DEVICE_KIND_LINE_POWER: 222 | case UP_DEVICE_KIND_LAST: /* Size placeholder */ 223 | return; 224 | } 225 | 226 | J4statusUpowerSection *section; 227 | section = g_new0(J4statusUpowerSection, 1); 228 | section->context = context; 229 | section->device = g_object_ref(device); 230 | section->section = j4status_section_new(context->core); 231 | 232 | j4status_section_set_name(section->section, name); 233 | j4status_section_set_instance(section->section, instance); 234 | if ( label != NULL ) 235 | j4status_section_set_label(section->section, label); 236 | 237 | if ( j4status_section_insert(section->section) ) 238 | { 239 | context->sections = g_list_prepend(context->sections, section); 240 | 241 | g_signal_connect(device, "notify", G_CALLBACK(_j4status_upower_device_changed), section); 242 | _j4status_upower_device_changed(device, NULL, section); 243 | } 244 | else 245 | _j4status_upower_section_free(section); 246 | } 247 | 248 | static void _j4status_upower_uninit(J4statusPluginContext *context); 249 | 250 | static J4statusPluginContext * 251 | _j4status_upower_init(J4statusCoreInterface *core) 252 | { 253 | J4statusPluginContext *context; 254 | context = g_new0(J4statusPluginContext, 1); 255 | context->core = core; 256 | 257 | context->up_client = up_client_new(); 258 | 259 | gboolean all_devices = FALSE; 260 | gchar *format = NULL; 261 | 262 | GKeyFile *key_file; 263 | key_file = j4status_config_get_key_file("UPower"); 264 | if ( key_file != NULL ) 265 | { 266 | all_devices = g_key_file_get_boolean(key_file, "UPower", "AllDevices", NULL); 267 | format = g_key_file_get_string(key_file, "UPower", "Format", NULL); 268 | g_key_file_free(key_file); 269 | } 270 | context->format = j4status_format_string_parse(format, _j4status_upower_format_tokens, G_N_ELEMENTS(_j4status_upower_format_tokens), J4STATUS_UPOWER_DEFAULT_FORMAT, NULL); 271 | 272 | GPtrArray *devices; 273 | guint i; 274 | 275 | devices = up_client_get_devices2(context->up_client); 276 | if ( devices == NULL ) 277 | { 278 | g_warning("No devices to monitor, aborting"); 279 | g_object_unref(context->up_client); 280 | g_free(context); 281 | return NULL; 282 | } 283 | for ( i = 0 ; i < devices->len ; ++i ) 284 | _j4status_upower_section_new(context, g_ptr_array_index(devices, i), all_devices); 285 | g_ptr_array_unref(devices); 286 | 287 | if ( context->sections == NULL ) 288 | { 289 | g_message("Missing configuration: No device to monitor, aborting"); 290 | _j4status_upower_uninit(context); 291 | return NULL; 292 | } 293 | 294 | 295 | return context; 296 | } 297 | 298 | static void 299 | _j4status_upower_uninit(J4statusPluginContext *context) 300 | { 301 | j4status_format_string_unref(context->format); 302 | 303 | g_list_free_full(context->sections, _j4status_upower_section_free); 304 | 305 | g_free(context); 306 | } 307 | 308 | static void 309 | _j4status_upower_start(J4statusPluginContext *context) 310 | { 311 | context->started = TRUE; 312 | } 313 | 314 | static void 315 | _j4status_upower_stop(J4statusPluginContext *context) 316 | { 317 | context->started = FALSE; 318 | } 319 | 320 | J4STATUS_EXPORT void 321 | j4status_input_plugin(J4statusInputPluginInterface *interface) 322 | { 323 | libj4status_input_plugin_interface_add_init_callback(interface, _j4status_upower_init); 324 | libj4status_input_plugin_interface_add_uninit_callback(interface, _j4status_upower_uninit); 325 | 326 | libj4status_input_plugin_interface_add_start_callback(interface, _j4status_upower_start); 327 | libj4status_input_plugin_interface_add_stop_callback(interface, _j4status_upower_stop); 328 | } 329 | -------------------------------------------------------------------------------- /libj4status-plugin/include/j4status-plugin-input.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libj4status-plugin - Library to implement a j4status plugin 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #ifndef __J4STATUS_J4STATUS_PLUGIN_INPUT_H__ 24 | #define __J4STATUS_J4STATUS_PLUGIN_INPUT_H__ 25 | 26 | #include 27 | 28 | typedef void (*J4statusSectionActionCallback)(J4statusSection *section, const gchar *event_id, gpointer user_data); 29 | 30 | typedef struct _J4statusInputPluginInterface J4statusInputPluginInterface; 31 | 32 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(input, Input, init, Init); 33 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(input, Input, uninit, Simple); 34 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(input, Input, start, Simple); 35 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(input, Input, stop, Simple); 36 | 37 | J4statusSection *j4status_section_new(J4statusCoreInterface *core); 38 | void j4status_section_free(J4statusSection *section); 39 | 40 | /* API before inserting the section in the list */ 41 | void j4status_section_set_name(J4statusSection *section, const gchar *name); 42 | void j4status_section_set_instance(J4statusSection *section, const gchar *instance); 43 | void j4status_section_set_label(J4statusSection *section, const gchar *label); 44 | void j4status_section_set_label_colour(J4statusSection *section, J4statusColour colour); 45 | void j4status_section_set_align(J4statusSection *section, J4statusAlign align); 46 | void j4status_section_set_max_width(J4statusSection *section, gint64 max_width); 47 | void j4status_section_set_action_callback(J4statusSection *section, J4statusSectionActionCallback callback, gpointer user_data); 48 | gboolean j4status_section_insert(J4statusSection *section) G_GNUC_WARN_UNUSED_RESULT; 49 | 50 | /* API once the section is inserted in the list */ 51 | void j4status_section_set_state(J4statusSection *section, J4statusState state); 52 | void j4status_section_set_colour(J4statusSection *section, J4statusColour colour); 53 | void j4status_section_set_background_colour(J4statusSection *section, J4statusColour colour); 54 | void j4status_section_set_value(J4statusSection *section, gchar *value); 55 | void j4status_section_set_short_value(J4statusSection *section, gchar *short_value); 56 | 57 | #endif /* __J4STATUS_J4STATUS_PLUGIN_INPUT_H__ */ 58 | -------------------------------------------------------------------------------- /libj4status-plugin/include/j4status-plugin-output.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libj4status-plugin - Library to implement a j4status plugin 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #ifndef __J4STATUS_J4STATUS_PLUGIN_OUTPUT_H__ 24 | #define __J4STATUS_J4STATUS_PLUGIN_OUTPUT_H__ 25 | 26 | #include 27 | #include 28 | 29 | typedef struct _J4statusIOStream J4statusCoreStream; 30 | typedef struct _J4statusOutputPluginStream J4statusOutputPluginStream; 31 | 32 | void j4status_core_trigger_action(J4statusCoreInterface *core, const gchar *section_id, const gchar *event_id); 33 | GInputStream *j4status_core_stream_get_input_stream(J4statusCoreInterface *core, J4statusCoreStream *stream); 34 | GOutputStream *j4status_core_stream_get_output_stream(J4statusCoreInterface *core, J4statusCoreStream *stream); 35 | void j4status_core_stream_reconnect(J4statusCoreInterface *core, J4statusCoreStream *stream); 36 | void j4status_core_stream_free(J4statusCoreInterface *core, J4statusCoreStream *stream); 37 | 38 | typedef gboolean (*J4statusPluginSendFunc)(J4statusPluginContext *context, J4statusOutputPluginStream *stream, GError **error); 39 | typedef void (*J4statusPluginGenerateLineFunc)(J4statusPluginContext *context, GList *sections); 40 | typedef J4statusOutputPluginStream *(*J4statusPluginStreamNewFunc)(J4statusPluginContext *context, J4statusCoreStream *stream); 41 | typedef void (*J4statusPluginStreamFunc)(J4statusPluginContext *context, J4statusOutputPluginStream *stream); 42 | 43 | typedef struct _J4statusOutputPluginInterface J4statusOutputPluginInterface; 44 | 45 | #define LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(type, Type, action, Action) void libj4status_##type##_plugin_interface_add_##action##_callback(J4status##Type##PluginInterface *interface, J4statusPlugin##Action##Func callback) 46 | 47 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(output, Output, init, Init); 48 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(output, Output, uninit, Simple); 49 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(output, Output, send_header, Send); 50 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(output, Output, generate_line, GenerateLine); 51 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(output, Output, send_line, Send); 52 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(output, Output, stream_new, StreamNew); 53 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(output, Output, stream_free, Stream); 54 | 55 | const gchar *j4status_section_get_name(const J4statusSection *section); 56 | const gchar *j4status_section_get_instance(const J4statusSection *section); 57 | const gchar *j4status_section_get_label(const J4statusSection *section); 58 | J4statusColour j4status_section_get_label_colour(const J4statusSection *section); 59 | J4statusAlign j4status_section_get_align(const J4statusSection *section); 60 | gint64 j4status_section_get_max_width(const J4statusSection *section); 61 | J4statusState j4status_section_get_state(const J4statusSection *section); 62 | J4statusColour j4status_section_get_colour(const J4statusSection *section); 63 | J4statusColour j4status_section_get_background_colour(const J4statusSection *section); 64 | const gchar *j4status_section_get_value(const J4statusSection *section); 65 | const gchar *j4status_section_get_short_value(const J4statusSection *section); 66 | 67 | gboolean j4status_section_is_dirty(const J4statusSection *section); 68 | void j4status_section_set_cache(J4statusSection *section, gchar *cache); 69 | const gchar *j4status_section_get_cache(const J4statusSection *section); 70 | void j4status_section_set_output_user_data(J4statusSection *section, gpointer user_data, GDestroyNotify notify); 71 | gpointer j4status_section_get_output_user_data(J4statusSection *section); 72 | 73 | #endif /* __J4STATUS_J4STATUS_PLUGIN_OUTPUT_H__ */ 74 | -------------------------------------------------------------------------------- /libj4status-plugin/include/j4status-plugin-private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libj4status-plugin - Library to implement a j4status plugin 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #ifndef __J4STATUS_J4STATUS_PLUGIN_PRIVATE_H__ 24 | #define __J4STATUS_J4STATUS_PLUGIN_PRIVATE_H__ 25 | 26 | struct _J4statusSection { 27 | J4statusCoreInterface *core; 28 | gboolean freeze; 29 | gchar *id; 30 | /* Reserved for the core */ 31 | gint64 weight; 32 | GList *link; 33 | 34 | /* Input plugins can only touch these 35 | * before inserting the section in the list */ 36 | gchar *name; 37 | gchar *instance; 38 | gchar *label; 39 | J4statusColour label_colour; 40 | J4statusAlign align; 41 | gint64 max_width; 42 | struct { 43 | J4statusSectionActionCallback callback; 44 | gpointer user_data; 45 | } action; 46 | 47 | /* Input plugins can only touch these 48 | * once the section is inserted in the list */ 49 | J4statusState state; 50 | J4statusColour colour; 51 | J4statusColour background_colour; 52 | gchar *value; 53 | gchar *short_value; 54 | 55 | /* Reserved for the output plugin */ 56 | gboolean dirty; 57 | gchar *cache; 58 | struct { 59 | gpointer user_data; 60 | GDestroyNotify notify; 61 | } output; 62 | }; 63 | 64 | typedef struct _J4statusCoreContext J4statusCoreContext; 65 | 66 | typedef void (*J4statusCoreFunc)(J4statusCoreContext *context); 67 | typedef gboolean (*J4statusCoreSectionAddFunc)(J4statusCoreContext *context, J4statusSection *section); 68 | typedef void (*J4statusCoreSectionFunc)(J4statusCoreContext *context, J4statusSection *section); 69 | typedef void (*J4statusCoreTriggerGenerateFunc)(J4statusCoreContext *context, gboolean force); 70 | typedef void (*J4statusCoreTriggerActionFunc)(J4statusCoreContext *context, const gchar *section_id, const gchar *event_id); 71 | typedef GInputStream *(*J4statusCoreStreamGetInputStreamFunc)(J4statusCoreStream *stream); 72 | typedef GOutputStream *(*J4statusCoreStreamGetOutputStreamFunc)(J4statusCoreStream *stream); 73 | typedef void (*J4statusCoreStreamFunc)(J4statusCoreStream *stream); 74 | 75 | struct _J4statusCoreInterface { 76 | J4statusCoreContext *context; 77 | J4statusCoreSectionAddFunc add_section; 78 | J4statusCoreSectionFunc remove_section; 79 | J4statusCoreTriggerGenerateFunc trigger_generate; 80 | J4statusCoreTriggerActionFunc trigger_action; 81 | J4statusCoreStreamGetInputStreamFunc stream_get_input_stream; 82 | J4statusCoreStreamGetOutputStreamFunc stream_get_output_stream; 83 | J4statusCoreStreamFunc stream_reconnect; 84 | J4statusCoreStreamFunc stream_free; 85 | }; 86 | 87 | 88 | struct _J4statusOutputPluginInterface { 89 | J4statusPluginInitFunc init; 90 | J4statusPluginSimpleFunc uninit; 91 | 92 | J4statusPluginStreamNewFunc stream_new; 93 | J4statusPluginStreamFunc stream_free; 94 | 95 | J4statusPluginSendFunc send_header; 96 | J4statusPluginGenerateLineFunc generate_line; 97 | J4statusPluginSendFunc send_line; 98 | }; 99 | 100 | struct _J4statusInputPluginInterface { 101 | J4statusPluginInitFunc init; 102 | J4statusPluginSimpleFunc uninit; 103 | 104 | J4statusPluginSimpleFunc start; 105 | J4statusPluginSimpleFunc stop; 106 | }; 107 | 108 | #endif /* __J4STATUS_J4STATUS_PLUGIN_PRIVATE_H__ */ 109 | -------------------------------------------------------------------------------- /libj4status-plugin/include/j4status-plugin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * libj4status-plugin - Library to implement a j4status plugin 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #ifndef __J4STATUS_J4STATUS_PLUGIN_H__ 24 | #define __J4STATUS_J4STATUS_PLUGIN_H__ 25 | 26 | #include 27 | 28 | typedef struct _J4statusCoreInterface J4statusCoreInterface; 29 | 30 | 31 | typedef struct _J4statusPluginContext J4statusPluginContext; 32 | 33 | typedef J4statusPluginContext *(*J4statusPluginInitFunc)(J4statusCoreInterface *core); 34 | typedef void(*J4statusPluginSimpleFunc)(J4statusPluginContext *context); 35 | 36 | 37 | #define LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(type, Type, action, Action) void libj4status_##type##_plugin_interface_add_##action##_callback(J4status##Type##PluginInterface *interface, J4statusPlugin##Action##Func callback) 38 | 39 | 40 | typedef enum { 41 | J4STATUS_ALIGN_CENTER = 0, 42 | J4STATUS_ALIGN_LEFT, 43 | J4STATUS_ALIGN_RIGHT 44 | } J4statusAlign; 45 | 46 | typedef enum { 47 | J4STATUS_STATE_NO_STATE = 0, 48 | J4STATUS_STATE_UNAVAILABLE, 49 | J4STATUS_STATE_BAD, 50 | J4STATUS_STATE_AVERAGE, 51 | J4STATUS_STATE_GOOD, 52 | #define _J4STATUS_STATE_SIZE (J4STATUS_STATE_GOOD+1) 53 | J4STATUS_STATE_URGENT = (1 << 31) 54 | } J4statusState; 55 | 56 | #define J4STATUS_STATE_FLAGS (J4STATUS_STATE_URGENT) 57 | 58 | GKeyFile *j4status_config_get_key_file(const gchar *section); 59 | gboolean j4status_config_key_file_get_enum(GKeyFile *key_file, const gchar *group_name, const gchar *key, const gchar * const *values, guint64 size, guint64 *value); 60 | GHashTable *j4status_config_key_file_get_actions(GKeyFile *key_file, const gchar *group_name, const gchar * const *values, guint64 size); 61 | 62 | typedef struct _NkFormatString J4statusFormatString; 63 | 64 | typedef GVariant *(*J4statusFormatStringReplaceCallback)(const gchar *token, guint64 value, gconstpointer user_data); 65 | 66 | J4statusFormatString *j4status_format_string_parse(gchar *string, const gchar * const *tokens, guint64 size, const gchar *default_string, guint64 *used_tokens); 67 | J4statusFormatString *j4status_format_string_ref(J4statusFormatString *format_string); 68 | void j4status_format_string_unref(J4statusFormatString *format_string); 69 | gchar *j4status_format_string_replace(const J4statusFormatString *format_string, J4statusFormatStringReplaceCallback callback, gconstpointer user_data); 70 | 71 | typedef struct { 72 | gboolean set; 73 | guint8 red; 74 | guint8 green; 75 | guint8 blue; 76 | guint8 alpha; 77 | } J4statusColour; 78 | 79 | void j4status_colour_reset(J4statusColour *colour); 80 | J4statusColour j4status_colour_parse(const gchar *string); 81 | J4statusColour j4status_colour_parse_length(const gchar *string, gint size); 82 | const gchar *j4status_colour_to_hex(J4statusColour colour); 83 | const gchar *j4status_colour_to_rgb(J4statusColour colour); 84 | 85 | typedef struct _J4statusSection J4statusSection; 86 | 87 | #endif /* __J4STATUS_J4STATUS_PLUGIN_H__ */ 88 | -------------------------------------------------------------------------------- /libj4status-plugin/meson.build: -------------------------------------------------------------------------------- 1 | # Plugin and core interfaces manipulation library 2 | 3 | libj4status_plugin_inc = include_directories('include') 4 | libj4status_plugin_dep = [ 5 | libnkutils, 6 | glib, 7 | ] 8 | 9 | libj4status_plugin_sources = files( 10 | 'src/utils.c', 11 | 'src/plugin.c', 12 | 'src/core.c', 13 | 'src/config.c', 14 | 'src/section.c', 15 | 16 | ) 17 | 18 | libj4status_plugin_lib = library('j4status-plugin', [ config_h ] + files( 19 | 'include/j4status-plugin-private.h', 20 | ) + libj4status_plugin_sources, 21 | c_args: [ 22 | '-DG_LOG_DOMAIN="libj4status-plugins"', 23 | ], 24 | dependencies: libj4status_plugin_dep, 25 | version: '0.0.0', 26 | include_directories: libj4status_plugin_inc, 27 | install: true, 28 | ) 29 | 30 | libj4status_plugin_headers = files( 31 | 'include/j4status-plugin.h', 32 | 'include/j4status-plugin-input.h', 33 | 'include/j4status-plugin-output.h', 34 | ) 35 | 36 | install_headers(libj4status_plugin_headers, 37 | subdir: meson.project_name(), 38 | ) 39 | 40 | libj4status_plugin = declare_dependency(link_with: libj4status_plugin_lib, include_directories: libj4status_plugin_inc, dependencies: libj4status_plugin_dep) 41 | 42 | pkgconfig.generate(libj4status_plugin_lib, 43 | filebase: 'libj4status-plugin', 44 | name: 'libj4status-plugin', 45 | version: meson.project_version(), 46 | description: 'Library to implement a j4status plugin', 47 | url: 'https://sardemff7.github.io/j4status/', 48 | subdirs: meson.project_name(), 49 | variables: [ 50 | 'pluginsdir=@0@'.format(join_paths('${prefix}', plugins_install_dir)), 51 | ], 52 | ) 53 | -------------------------------------------------------------------------------- /libj4status-plugin/pkgconfig/libj4status-plugin.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | pkglibdir=@pkglibdir@ 6 | pkgincludedir=@pkgincludedir@ 7 | 8 | pluginsdir=@pluginsdir@ 9 | 10 | Name: libj4status-plugin 11 | Description: Library to implement a j4status plugin 12 | URL: http://j4status.j4tools.org/ 13 | Version: @VERSION@ 14 | Requires.private: glib-2.0 gio-2.0 15 | Libs: -L${libdir} -lj4status-plugin 16 | Cflags: -I${pkgincludedir} 17 | -------------------------------------------------------------------------------- /libj4status-plugin/src/config.c: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include 28 | 29 | #include "nkutils-enum.h" 30 | 31 | #define CONFIG_SYSCONFFILE J4STATUS_SYSCONFDIR G_DIR_SEPARATOR_S PACKAGE_NAME G_DIR_SEPARATOR_S "config" 32 | #define CONFIG_DATAFILE J4STATUS_DATADIR G_DIR_SEPARATOR_S PACKAGE_NAME G_DIR_SEPARATOR_S "config" 33 | #define CONFIG_LIBFILE J4STATUS_LIBDIR G_DIR_SEPARATOR_S PACKAGE_NAME G_DIR_SEPARATOR_S "config" 34 | 35 | static GKeyFile * 36 | _j4status_config_try_dir(const gchar *filename, const gchar *section) 37 | { 38 | GKeyFile *key_file = NULL; 39 | if ( g_file_test(filename, G_FILE_TEST_EXISTS) && ( ! g_file_test(filename, G_FILE_TEST_IS_DIR) ) ) 40 | { 41 | GError *error = NULL; 42 | key_file = g_key_file_new(); 43 | if ( ! g_key_file_load_from_file(key_file, filename, 0, &error) ) 44 | { 45 | g_key_file_free(key_file); 46 | g_warning("Couldn't load key_file '%s': %s", filename, error->message); 47 | g_clear_error(&error); 48 | return NULL; 49 | } 50 | if ( g_key_file_has_group(key_file, section) ) 51 | return key_file; 52 | else 53 | { 54 | g_key_file_free(key_file); 55 | return NULL; 56 | } 57 | } 58 | return key_file; 59 | } 60 | 61 | 62 | J4STATUS_EXPORT GKeyFile * 63 | j4status_config_get_key_file(const gchar *section) 64 | { 65 | GKeyFile *key_file; 66 | gchar *file = NULL; 67 | 68 | const gchar *env_file; 69 | env_file = g_getenv("J4STATUS_CONFIG_FILE"); 70 | if ( env_file != NULL ) 71 | { 72 | if ( strchr(env_file, G_DIR_SEPARATOR) == NULL ) 73 | env_file = file = g_build_filename(g_get_user_config_dir(), PACKAGE_NAME, env_file, NULL); 74 | key_file = _j4status_config_try_dir(env_file, section); 75 | g_free(file); 76 | if ( key_file != NULL ) 77 | return key_file; 78 | } 79 | 80 | file = g_build_filename(g_get_user_config_dir(), PACKAGE_NAME G_DIR_SEPARATOR_S "config", NULL); 81 | key_file = _j4status_config_try_dir(file, section); 82 | g_free(file); 83 | if ( key_file != NULL ) 84 | return key_file; 85 | 86 | key_file = _j4status_config_try_dir(CONFIG_SYSCONFFILE, section); 87 | if ( key_file != NULL ) 88 | return key_file; 89 | key_file = _j4status_config_try_dir(CONFIG_DATAFILE, section); 90 | if ( key_file != NULL ) 91 | return key_file; 92 | key_file = _j4status_config_try_dir(CONFIG_LIBFILE, section); 93 | if ( key_file != NULL ) 94 | return key_file; 95 | 96 | return NULL; 97 | } 98 | 99 | J4STATUS_EXPORT gboolean 100 | j4status_config_key_file_get_enum(GKeyFile *key_file, const gchar *group_name, const gchar *key, const gchar * const *values, guint64 size, guint64 *value) 101 | { 102 | gchar *string; 103 | string = g_key_file_get_string(key_file, group_name, key, NULL); 104 | if ( string == NULL ) 105 | return FALSE; 106 | 107 | gboolean r; 108 | 109 | r = nk_enum_parse(string, values, size, NK_ENUM_MATCH_FLAGS_IGNORE_CASE, value); 110 | g_free(string); 111 | 112 | return r; 113 | } 114 | 115 | J4STATUS_EXPORT GHashTable * 116 | j4status_config_key_file_get_actions(GKeyFile *key_file, const gchar *group_name, const gchar * const *actions, guint64 size) 117 | { 118 | gchar **strings; 119 | strings = g_key_file_get_string_list(key_file, group_name, "Actions", NULL, NULL); 120 | if ( strings == NULL ) 121 | return NULL; 122 | 123 | GHashTable *table; 124 | table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); 125 | 126 | gchar **string; 127 | for ( string = strings ; *string != NULL ; ++string ) 128 | { 129 | gchar *id = *string; 130 | gchar *action; 131 | guint64 value; 132 | 133 | action = g_utf8_strchr(*string, -1, ' '); 134 | if ( action == NULL ) 135 | goto next; 136 | *action++ = '\0'; 137 | 138 | if ( nk_enum_parse(action, actions, size, NK_ENUM_MATCH_FLAGS_IGNORE_CASE, &value) ) 139 | g_hash_table_insert(table, g_strdup(id), GUINT_TO_POINTER(value)); 140 | 141 | next: 142 | g_free(*string); 143 | } 144 | g_free(strings); 145 | 146 | if ( g_hash_table_size(table) < 1 ) 147 | { 148 | g_hash_table_unref(table); 149 | return NULL; 150 | } 151 | 152 | return table; 153 | } 154 | -------------------------------------------------------------------------------- /libj4status-plugin/src/core.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libj4status-plugin - Library to implement a j4status plugin 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include "j4status-plugin-output.h" 28 | #include "j4status-plugin-input.h" 29 | #include "j4status-plugin-private.h" 30 | 31 | J4STATUS_EXPORT void 32 | j4status_core_trigger_action(J4statusCoreInterface *core, const gchar *section_id, const gchar *event_id) 33 | { 34 | return core->trigger_action(core->context, section_id, event_id); 35 | } 36 | 37 | 38 | J4STATUS_EXPORT GInputStream * 39 | j4status_core_stream_get_input_stream(J4statusCoreInterface *core, J4statusCoreStream *stream) 40 | { 41 | return core->stream_get_input_stream(stream); 42 | } 43 | 44 | J4STATUS_EXPORT GOutputStream * 45 | j4status_core_stream_get_output_stream(J4statusCoreInterface *core, J4statusCoreStream *stream) 46 | { 47 | return core->stream_get_output_stream(stream); 48 | } 49 | 50 | J4STATUS_EXPORT void 51 | j4status_core_stream_reconnect(J4statusCoreInterface *core, J4statusCoreStream *stream) 52 | { 53 | return core->stream_reconnect(stream); 54 | } 55 | 56 | J4STATUS_EXPORT void 57 | j4status_core_stream_free(J4statusCoreInterface *core, J4statusCoreStream *stream) 58 | { 59 | return core->stream_free(stream); 60 | } 61 | -------------------------------------------------------------------------------- /libj4status-plugin/src/plugin.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libj4status-plugin - Library to implement a j4status plugin 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include "j4status-plugin-output.h" 28 | #include "j4status-plugin-input.h" 29 | #include "j4status-plugin-private.h" 30 | 31 | #define LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(type, Type, action, Action) J4STATUS_EXPORT LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK(type, Type, action, Action) { interface->action = callback; } 32 | 33 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(output, Output, init, Init) 34 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(output, Output, uninit, Simple) 35 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(output, Output, stream_new, StreamNew) 36 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(output, Output, stream_free, Stream) 37 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(output, Output, send_header, Send) 38 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(output, Output, generate_line, GenerateLine) 39 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(output, Output, send_line, Send) 40 | 41 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(input, Input, init, Init) 42 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(input, Input, uninit, Simple) 43 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(input, Input, start, Simple) 44 | LIBJ4STATUS_PLUGIN_INTERFACE_ADD_CALLBACK_DEF(input, Input, stop, Simple) 45 | -------------------------------------------------------------------------------- /libj4status-plugin/src/utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * libj4status-plugin - Library to implement a j4status plugin 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "nkutils-format-string.h" 31 | #include "nkutils-colour.h" 32 | 33 | #include "j4status-plugin.h" 34 | 35 | J4STATUS_EXPORT J4statusFormatString * 36 | j4status_format_string_parse(gchar *string, const gchar * const *tokens, guint64 size, const gchar *default_string, guint64 *used_tokens) 37 | { 38 | NkFormatString *token_list = NULL; 39 | 40 | if ( string != NULL ) 41 | token_list = nk_format_string_parse_enum(string, '$', tokens, size, used_tokens, NULL); 42 | 43 | if ( token_list == NULL ) 44 | token_list = nk_format_string_parse_enum(g_strdup(default_string), '$', tokens, size, used_tokens, NULL); 45 | 46 | return token_list; 47 | } 48 | 49 | J4STATUS_EXPORT J4statusFormatString * 50 | j4status_format_string_ref(J4statusFormatString *format_string) 51 | { 52 | if ( format_string == NULL ) 53 | return NULL; 54 | 55 | return nk_format_string_ref(format_string); 56 | } 57 | 58 | J4STATUS_EXPORT void 59 | j4status_format_string_unref(J4statusFormatString *format_string) 60 | { 61 | if ( format_string == NULL ) 62 | return; 63 | 64 | nk_format_string_unref(format_string); 65 | } 66 | 67 | J4STATUS_EXPORT gchar * 68 | j4status_format_string_replace(const J4statusFormatString *format_string, J4statusFormatStringReplaceCallback callback, gconstpointer user_data) 69 | { 70 | if ( format_string == NULL ) 71 | return NULL; 72 | 73 | return nk_format_string_replace(format_string, (NkFormatStringReplaceReferenceCallback) callback, (gpointer) user_data); 74 | } 75 | 76 | J4STATUS_EXPORT void 77 | j4status_colour_reset(J4statusColour *colour) 78 | { 79 | colour->set = FALSE; 80 | colour->red = 0; 81 | colour->green = 0; 82 | colour->blue = 0; 83 | colour->alpha = 0xff; 84 | } 85 | 86 | J4STATUS_EXPORT J4statusColour 87 | j4status_colour_parse(const gchar *string) 88 | { 89 | J4statusColour ret = { FALSE, 0, 0, 0, 0xff }; 90 | NkColour colour_; 91 | 92 | if ( nk_colour_parse(string, &colour_) ) 93 | { 94 | ret.set = TRUE; 95 | ret.red = colour_.red * 255; 96 | ret.green = colour_.green * 255; 97 | ret.blue = colour_.blue * 255; 98 | ret.alpha = colour_.alpha * 255; 99 | } 100 | 101 | return ret; 102 | } 103 | 104 | J4STATUS_EXPORT J4statusColour 105 | j4status_colour_parse_length(const gchar *colour, gint length) 106 | { 107 | gchar string[length + 1]; 108 | g_sprintf(string, "%.*s", length, colour); 109 | return j4status_colour_parse(string); 110 | } 111 | 112 | J4STATUS_EXPORT const gchar * 113 | j4status_colour_to_hex(J4statusColour colour) 114 | { 115 | if ( ! colour.set ) 116 | return NULL; 117 | 118 | NkColour colour_ = { 119 | .red = colour.red / 255., 120 | .green = colour.green / 255., 121 | .blue = colour.blue / 255., 122 | .alpha = colour.alpha / 255., 123 | }; 124 | 125 | return nk_colour_to_hex(&colour_); 126 | } 127 | 128 | J4STATUS_EXPORT const gchar * 129 | j4status_colour_to_rgb(J4statusColour colour) 130 | { 131 | if ( ! colour.set ) 132 | return NULL; 133 | 134 | NkColour colour_ = { 135 | .red = colour.red / 255., 136 | .green = colour.green / 255., 137 | .blue = colour.blue / 255., 138 | .alpha = colour.alpha / 255., 139 | }; 140 | 141 | return nk_colour_to_rgba(&colour_); 142 | } 143 | -------------------------------------------------------------------------------- /main/meson.build: -------------------------------------------------------------------------------- 1 | # Server 2 | j4status_c_args = [ 3 | '-DG_LOG_DOMAIN="j4status"', 4 | ] 5 | j4status_deps = [ 6 | libj4status_plugin, 7 | gthread, 8 | gio_platform, 9 | gio, 10 | gmodule, 11 | gobject, 12 | glib 13 | ] 14 | if get_option('systemd') 15 | j4status_deps += dependency('libsystemd', version: '>= 209') 16 | j4status_c_args += '-DENABLE_SYSTEMD' 17 | docbook_conditions += 'enable_systemd' 18 | endif 19 | 20 | j4status = executable('j4status', [ config_h ] + files( 21 | 'src/plugins.c', 22 | 'src/plugins.h', 23 | 'src/io.c', 24 | 'src/io.h', 25 | 'src/j4status.c', 26 | 'src/j4status.h', 27 | 'src/types.h', 28 | ), 29 | c_args: j4status_c_args, 30 | dependencies: j4status_deps, 31 | install: true, 32 | ) 33 | 34 | 35 | man_pages += [ [ files('man/j4status.xml'), 'j4status.1' ] ] 36 | man_pages += [ [ files('man/j4status.conf.xml'), 'j4status.conf.5' ] ] 37 | 38 | if get_option('systemd') 39 | systemd = dependency('systemd') 40 | j4status_units = [ 41 | 'j4status@.socket', 42 | 'j4status@.service', 43 | ] 44 | systemduserunit_install_dir = get_option('systemduserunitdir') 45 | if systemduserunit_install_dir == '' 46 | systemduserunit_install_dir = systemd.get_pkgconfig_variable('systemduserunitdir') 47 | endif 48 | eventd_user_units = [] 49 | foreach u : j4status_units 50 | configure_file( 51 | input: files('units/@0@.in'.format(u)), 52 | output: u, 53 | configuration: other_conf, 54 | install_dir: systemduserunit_install_dir, 55 | ) 56 | endforeach 57 | endif 58 | -------------------------------------------------------------------------------- /main/src/io.h: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #ifndef __J4STATUS_IO_H__ 24 | #define __J4STATUS_IO_H__ 25 | 26 | #include "types.h" 27 | 28 | J4statusIOContext *j4status_io_new(J4statusCoreContext *core, J4statusOutputPlugin *plugin, const gchar * const *servers_desc, const gchar * const *streams_desc); 29 | void j4status_io_free(J4statusIOContext *io); 30 | 31 | void j4status_io_update_line(J4statusIOContext *io); 32 | GInputStream *j4status_io_stream_get_input_stream(J4statusIOStream *stream); 33 | GOutputStream *j4status_io_stream_get_output_stream(J4statusIOStream *stream); 34 | void j4status_io_stream_reconnect(J4statusIOStream *stream); 35 | void j4status_io_stream_free(J4statusIOStream *stream); 36 | 37 | #endif /* __J4STATUS_IO_H__ */ 38 | -------------------------------------------------------------------------------- /main/src/j4status.h: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #ifndef __J4STATUS_J4STATUS_H__ 24 | #define __J4STATUS_J4STATUS_H__ 25 | 26 | #include "types.h" 27 | 28 | void j4status_core_action(J4statusCoreContext *context, gchar *action_description); 29 | void j4status_core_quit(J4statusCoreContext *context); 30 | 31 | #endif /* __J4STATUS_J4STATUS_H__ */ 32 | -------------------------------------------------------------------------------- /main/src/plugins.c: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "j4status-plugin-output.h" 30 | #include "j4status-plugin-input.h" 31 | #include "j4status-plugin-private.h" 32 | 33 | #include "plugins.h" 34 | 35 | #define PLUGINS_DATADIR J4STATUS_DATADIR G_DIR_SEPARATOR_S PACKAGE_NAME G_DIR_SEPARATOR_S "plugins" 36 | #define PLUGINS_LIBDIR J4STATUS_LIBDIR G_DIR_SEPARATOR_S PACKAGE_NAME G_DIR_SEPARATOR_S "plugins" 37 | 38 | static GModule * 39 | _j4status_plugins_try_dir(const gchar *dir, const gchar *file) 40 | { 41 | if ( ! g_file_test(dir, G_FILE_TEST_IS_DIR) ) 42 | return NULL; 43 | 44 | gchar *filename; 45 | filename = g_build_filename(dir, file, NULL); 46 | 47 | GModule *module = NULL; 48 | if ( g_file_test(filename, G_FILE_TEST_EXISTS) && ( ! g_file_test(filename, G_FILE_TEST_IS_DIR) ) ) 49 | { 50 | module = g_module_open(filename, G_MODULE_BIND_LAZY|G_MODULE_BIND_LOCAL); 51 | if ( module == NULL ) 52 | g_warning("Couldn't load module '%s': %s", file, g_module_error()); 53 | } 54 | g_free(filename); 55 | return module; 56 | } 57 | 58 | 59 | static GModule * 60 | _j4status_plugins_get_module(const gchar *file) 61 | { 62 | GModule *module; 63 | 64 | const gchar *env_dir; 65 | env_dir = g_getenv("J4STATUS_PLUGINS_DIR"); 66 | if ( env_dir != NULL ) 67 | { 68 | module = _j4status_plugins_try_dir(env_dir, file); 69 | if ( module != NULL ) 70 | return module; 71 | } 72 | 73 | gchar *dir; 74 | dir = g_build_filename(g_get_user_data_dir(), PACKAGE_NAME G_DIR_SEPARATOR_S "plugins", NULL); 75 | module = _j4status_plugins_try_dir(dir, file); 76 | g_free(dir); 77 | if ( module != NULL ) 78 | return module; 79 | 80 | module = _j4status_plugins_try_dir(PLUGINS_DATADIR, file); 81 | if ( module != NULL ) 82 | return module; 83 | module = _j4status_plugins_try_dir(PLUGINS_LIBDIR, file); 84 | if ( module != NULL ) 85 | return module; 86 | 87 | return NULL; 88 | } 89 | 90 | typedef void(*J4statusOutputPluginGetInterfaceFunc)(J4statusOutputPluginInterface *interface); 91 | 92 | J4statusOutputPlugin * 93 | j4status_plugins_get_output_plugin(J4statusCoreInterface *core, const gchar *name) 94 | { 95 | if ( name == NULL ) 96 | return j4status_plugins_get_output_plugin(core, "flat"); 97 | GModule *module; 98 | 99 | gchar *file; 100 | file = g_strconcat(name, "." G_MODULE_SUFFIX, NULL); 101 | module = _j4status_plugins_get_module(file); 102 | g_free(file); 103 | 104 | if ( module == NULL ) 105 | { 106 | if ( g_strcmp0(name, "flat") == 0 ) 107 | return NULL; 108 | return j4status_plugins_get_output_plugin(core, "flat"); 109 | } 110 | 111 | J4statusOutputPluginGetInterfaceFunc func; 112 | 113 | if ( ! g_module_symbol(module, "j4status_output_plugin", (gpointer *)&func) ) 114 | return NULL; 115 | 116 | if ( func == NULL ) 117 | { 118 | g_warning("Plugin '%s' must define j4status_output_plugin", name); 119 | return NULL; 120 | } 121 | 122 | J4statusOutputPlugin *plugin; 123 | plugin = g_new0(J4statusOutputPlugin, 1); 124 | plugin->module = module; 125 | 126 | func(&plugin->interface); 127 | 128 | if ( plugin->interface.init != NULL ) 129 | { 130 | plugin->context = plugin->interface.init(core); 131 | if ( plugin->context == NULL ) 132 | { 133 | /* 134 | * Returning NULL here means the plugin will not work. 135 | * Just return anything but NULL if you needs init 136 | * without a context. 137 | */ 138 | g_module_close(plugin->module); 139 | g_free(plugin); 140 | return NULL; 141 | } 142 | fflush(stdout); 143 | } 144 | 145 | return plugin; 146 | } 147 | 148 | typedef void(*J4statusInputPluginGetInterfaceFunc)(J4statusInputPluginInterface *interface); 149 | 150 | static J4statusInputPlugin * 151 | j4status_plugins_get_input_plugin(J4statusCoreInterface *core, const gchar *name) 152 | { 153 | if ( name == NULL ) 154 | return NULL; 155 | GModule *module; 156 | 157 | gchar *file; 158 | file = g_strconcat(name, "." G_MODULE_SUFFIX, NULL); 159 | module = _j4status_plugins_get_module(file); 160 | g_free(file); 161 | 162 | if ( module == NULL ) 163 | return NULL; 164 | 165 | J4statusInputPluginGetInterfaceFunc func; 166 | 167 | if ( ! g_module_symbol(module, "j4status_input_plugin", (gpointer *)&func) ) 168 | return NULL; 169 | 170 | if ( func == NULL ) 171 | { 172 | g_warning("Plugin '%s' must define j4status_input_plugin", name); 173 | return NULL; 174 | } 175 | 176 | J4statusInputPlugin *plugin; 177 | plugin = g_new0(J4statusInputPlugin, 1); 178 | plugin->module = module; 179 | 180 | func(&plugin->interface); 181 | 182 | if ( plugin->interface.init != NULL ) 183 | { 184 | plugin->context = plugin->interface.init(core); 185 | if ( plugin->context == NULL ) 186 | { 187 | /* 188 | * Returning NULL here means the plugin will not work. 189 | * Just return anything but NULL if you needs init 190 | * without a context. 191 | */ 192 | g_free(plugin); 193 | return NULL; 194 | } 195 | } 196 | 197 | return plugin; 198 | } 199 | 200 | GList * 201 | j4status_plugins_get_input_plugins(J4statusCoreInterface *core, gchar **names) 202 | { 203 | if ( names == NULL ) 204 | return NULL; 205 | 206 | GList *input_plugins = NULL; 207 | 208 | gchar **name; 209 | J4statusInputPlugin *plugin; 210 | for ( name = names ; *name != NULL ; ++name ) 211 | { 212 | plugin = j4status_plugins_get_input_plugin(core, *name); 213 | if ( plugin != NULL ) 214 | input_plugins = g_list_prepend(input_plugins, plugin); 215 | } 216 | 217 | return g_list_reverse(input_plugins); 218 | } 219 | -------------------------------------------------------------------------------- /main/src/plugins.h: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #ifndef __J4STATUS_PLUGINS_H__ 24 | #define __J4STATUS_PLUGINS_H__ 25 | 26 | typedef struct { 27 | gpointer module; 28 | J4statusPluginContext *context; 29 | J4statusOutputPluginInterface interface; 30 | } J4statusOutputPlugin; 31 | 32 | typedef struct { 33 | gpointer module; 34 | J4statusPluginContext *context; 35 | J4statusInputPluginInterface interface; 36 | } J4statusInputPlugin; 37 | 38 | J4statusOutputPlugin *j4status_plugins_get_output_plugin(J4statusCoreInterface *core, const gchar *name); 39 | 40 | GList *j4status_plugins_get_input_plugins(J4statusCoreInterface *core, gchar **names); 41 | 42 | #endif /* __J4STATUS_PLUGINS_H__ */ 43 | -------------------------------------------------------------------------------- /main/src/types.h: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #ifndef __J4STATUS_TYPES_H__ 24 | #define __J4STATUS_TYPES_H__ 25 | 26 | typedef struct _J4statusCoreContext J4statusCoreContext; 27 | typedef struct _J4statusIOContext J4statusIOContext; 28 | typedef struct _J4statusIOStream J4statusIOStream; 29 | 30 | #endif /* __J4STATUS_TYPES_H__ */ 31 | -------------------------------------------------------------------------------- /main/units/j4status@.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=j4status %I output to socket 3 | 4 | [Service] 5 | Sockets=j4status@%i.socket 6 | ExecStart=@bindir@/j4status --config %i 7 | 8 | [Install] 9 | Also=j4status@%i.socket 10 | -------------------------------------------------------------------------------- /main/units/j4status@.socket.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=j4status stream socket 3 | 4 | [Socket] 5 | Service=j4status@%i.service 6 | ListenStream=%t/@PACKAGE_NAME@/%i 7 | 8 | [Install] 9 | WantedBy=sockets.target 10 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('j4status', 'c', 2 | version: '0.1', 3 | meson_version: '>=0.47.0', 4 | license: [ 'GPL3+', 'LGPL3+', 'MIT' ], 5 | default_options: [ 6 | 'c_std=gnu11', 7 | 'warning_level=2', 8 | ], 9 | ) 10 | 11 | is_unix = host_machine.system() != 'windows' 12 | is_windows = not is_unix 13 | pkgconfig = import('pkgconfig') 14 | gnome = import('gnome') 15 | 16 | glib_min_major='2' 17 | glib_min_minor='40' 18 | glib_min_version='.'.join([glib_min_major, glib_min_minor]) 19 | glib = dependency('glib-2.0', version: '>= @0@'.format(glib_min_version)) 20 | gobject = dependency('gobject-2.0') 21 | gio = dependency('gio-2.0') 22 | if is_unix 23 | gio_platform = dependency('gio-unix-2.0') 24 | else 25 | gio_platform = dependency('gio-windows-2.0') 26 | endif 27 | gthread = dependency('gthread-2.0') 28 | gmodule = dependency('gmodule-2.0') 29 | headers = [ 30 | 'string.h', 31 | 'unistd.h', 32 | 'locale.h', 33 | 'errno.h', 34 | 'signal.h', 35 | ] 36 | if is_unix 37 | headers += [ 38 | 'sys/socket.h', 39 | ] 40 | else 41 | headers += [ 42 | 'windows.h', 43 | ] 44 | endif 45 | c_compiler = meson.get_compiler('c') 46 | foreach h : headers 47 | if not c_compiler.has_header(h) 48 | error('Header @0@ was not found, but is required'.format(h)) 49 | endif 50 | endforeach 51 | 52 | plugins_install_dir = join_paths(get_option('libdir'), meson.project_name(), 'plugins') 53 | 54 | header_conf = configuration_data() 55 | other_conf = configuration_data() 56 | header_conf.set_quoted('PACKAGE_NAME', meson.project_name()) 57 | header_conf.set_quoted('PACKAGE_VERSION', meson.project_version()) 58 | header_conf.set_quoted('MODULES_VERSION', meson.project_version()) 59 | header_conf.set_quoted('GETTEXT_PACKAGE', meson.project_name()) 60 | other_conf.set('PACKAGE_NAME', meson.project_name()) 61 | other_conf.set('PACKAGE_VERSION', meson.project_version()) 62 | other_conf.set('VERSION', meson.project_version()) 63 | 64 | if is_unix 65 | header_conf.set('J4STATUS_EXPORT', '__attribute__((visibility("default")))') 66 | else 67 | header_conf.set('J4STATUS_EXPORT', '__declspec(dllexport)') 68 | header_conf.set('_WIN32_WINNT', '_WIN32_WINNT_WIN7') 69 | header_conf.set('NTDDI_VERSION', 'NTDDI_WIN7') 70 | endif 71 | header_conf.set('GLIB_VERSION_MIN_REQUIRED', '(G_ENCODE_VERSION(@0@,@1@))'.format(glib_min_major, glib_min_minor)) 72 | header_conf.set('G_LOG_USE_STRUCTURED', true) 73 | 74 | header_conf.set_quoted('J4STATUS_SYSCONFDIR', join_paths(get_option('prefix'), get_option('sysconfdir'))) 75 | header_conf.set_quoted('J4STATUS_BINDIR', join_paths(get_option('prefix'), get_option('bindir'))) 76 | header_conf.set_quoted('J4STATUS_LIBDIR', join_paths(get_option('prefix'), get_option('libdir'))) 77 | header_conf.set_quoted('J4STATUS_DATADIR', join_paths(get_option('prefix'), get_option('datadir'))) 78 | header_conf.set_quoted('J4STATUS_LOCALEDIR', join_paths(get_option('prefix'), get_option('localedir'))) 79 | other_conf.set('prefix', get_option('prefix')) 80 | other_conf.set('bindir', join_paths(get_option('prefix'), get_option('bindir'))) 81 | other_conf.set('datadir', join_paths(get_option('prefix'), get_option('datadir'))) 82 | 83 | 84 | header_conf.set('J4STATUS_DEBUG_OUTPUT', get_option('debug-output')) 85 | 86 | config_h = configure_file(output: 'config.h', configuration: header_conf) 87 | config_ent = configure_file(input: files('src/config.ent.in'), output: 'config.ent', configuration: other_conf) 88 | 89 | add_project_arguments( 90 | '-fvisibility=hidden', 91 | '-I@0@'.format(meson.build_root()), 92 | '-I@0@/src'.format(meson.source_root()), 93 | language: 'c' 94 | ) 95 | flags = [ 96 | '-Wformat=2', 97 | '-Wno-unused-parameter', 98 | ] 99 | foreach f : flags 100 | if c_compiler.has_argument(f) 101 | add_project_arguments(f, language: 'c') 102 | endif 103 | endforeach 104 | 105 | man_pages = [] 106 | docbook_conditions = [ 'installation' ] 107 | 108 | nk_options = [ 109 | 'enum=true', 110 | 'format-string=true', 111 | 'colour=true', 112 | 'git-work-tree=@0@'.format(meson.source_root()), 113 | ] 114 | nk = subproject('libnkutils', default_options: nk_options) 115 | nk_subproject_options = nk.get_variable('nk_options') 116 | foreach o : nk_options + nk_subproject_options 117 | if ( o.startswith('git-work-tree=') ) 118 | continue 119 | elif not nk_options.contains(o) or not nk_subproject_options.contains(o) 120 | error('You must not change libnkutils options @0@ != @1@'.format('|'.join(nk_options), '|'.join(nk_subproject_options))) 121 | endif 122 | endforeach 123 | libnkutils = nk.get_variable('libnkutils') 124 | nkutils_xsltpaths = nk.get_variable('nkutils_xsltpaths') 125 | nkutils_manfiles = nk.get_variable('nkutils_manfiles') 126 | nkutils_mandepends = nk.get_variable('nkutils_mandepends') 127 | docbook_conditions += nk.get_variable('nkutils_docbook_conditions') 128 | 129 | subdir('libj4status-plugin') 130 | subdir('main') 131 | 132 | subdir('output/debug') 133 | subdir('output/flat') 134 | subdir('output/pango') 135 | subdir('output/evp') 136 | 137 | subdir('input/time') 138 | subdir('input/file-monitor') 139 | subdir('input/systemd') 140 | subdir('input/upower') 141 | subdir('input/sensors') 142 | subdir('input/nl') 143 | subdir('input/pulseaudio') 144 | subdir('input/mpd') 145 | 146 | subdir('input-output/i3bar') 147 | 148 | xsltproc = [ 149 | find_program('xsltproc'), 150 | '-o', '@OUTDIR@', 151 | '--nonet', '--xinclude', 152 | '--stringparam', 'man.output.quietly', '1', 153 | '--stringparam', 'funcsynopsis.style', 'ansi', 154 | '--stringparam', 'profile.condition', ';'.join(docbook_conditions), 155 | ] 156 | foreach p : [ 157 | join_paths(meson.current_source_dir(), 'src'), 158 | meson.current_build_dir(), 159 | ] + nkutils_xsltpaths 160 | xsltproc += [ '--path', p ] 161 | endforeach 162 | xsltproc += [ 163 | 'http://docbook.sourceforge.net/release/xsl/current/manpages/profile-docbook.xsl', 164 | '@INPUT@' 165 | ] 166 | man_input = [] 167 | man_output = [] 168 | foreach m : man_pages 169 | s = m[1].split('.') 170 | section = 'man' + s[s.length() - 1] 171 | custom_target(m[1], 172 | input: m[0], 173 | output: m[1], 174 | command: xsltproc, 175 | depend_files: [ config_ent ] + nkutils_manfiles, 176 | depends: nkutils_mandepends, 177 | build_by_default: true, 178 | install: true, 179 | install_dir: join_paths(get_option('mandir'), section) 180 | ) 181 | endforeach 182 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option('systemd', type: 'boolean', value: false, description: 'systemd activation support') 2 | option('i3bar', type: 'feature', description: 'i3bar JSON protocol input-output plugin') 3 | option('evp', type: 'feature', description: 'EvP protocol/eventd output plugin') 4 | option('nl', type: 'feature', description: 'Netlink input plugin') 5 | option('upower', type: 'feature', description: 'UPower input plugin') 6 | option('sensors', type: 'feature', description: 'libsensors input plugin') 7 | option('pulseaudio', type: 'feature', description: 'PulseAudio input plugin') 8 | option('mpd', type: 'feature', description: 'MPD input plugin') 9 | option('debug-output', type: 'boolean', value: true, description: 'debug output') 10 | 11 | option('systemduserunitdir', type: 'string', description: 'Directory for systemd user unit files') 12 | -------------------------------------------------------------------------------- /output/debug/meson.build: -------------------------------------------------------------------------------- 1 | shared_library('debug', [ config_h ] + files( 2 | 'src/debug.c', 3 | ), 4 | c_args: [ 5 | '-DG_LOG_DOMAIN="j4status-debug"', 6 | ], 7 | dependencies: [ libj4status_plugin, gio, glib ], 8 | name_prefix: '', 9 | install: true, 10 | install_dir: plugins_install_dir, 11 | ) 12 | -------------------------------------------------------------------------------- /output/debug/src/debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | #include 27 | 28 | #include "j4status-plugin-output.h" 29 | 30 | #define BOOL_TO_S(bool) ((bool) ? "yes" : "no") 31 | 32 | struct _J4statusPluginContext { 33 | J4statusCoreInterface *core; 34 | gsize last_len; 35 | GString *line; 36 | }; 37 | 38 | struct _J4statusOutputPluginStream { 39 | J4statusPluginContext *context; 40 | J4statusCoreStream *stream; 41 | gchar buffer[4096]; 42 | GInputStream *in; 43 | GDataOutputStream *out; 44 | }; 45 | 46 | static J4statusPluginContext * 47 | _j4status_debug_init(J4statusCoreInterface *core) 48 | { 49 | J4statusPluginContext *context; 50 | 51 | context = g_new0(J4statusPluginContext, 1); 52 | context->core = core; 53 | 54 | context->line = g_string_new(""); 55 | 56 | return context; 57 | } 58 | 59 | static void 60 | _j4status_debug_uninit(J4statusPluginContext *context) 61 | { 62 | g_string_free(context->line, TRUE); 63 | 64 | g_free(context); 65 | } 66 | 67 | static void 68 | _j4status_debug_stream_read_callback(GObject *obj, GAsyncResult *res, gpointer user_data) 69 | { 70 | J4statusOutputPluginStream *stream = user_data; 71 | GInputStream *in = G_INPUT_STREAM(obj); 72 | GError *error = NULL; 73 | 74 | gsize size; 75 | if ( ! g_input_stream_read_all_finish(in, res, &size, &error) ) 76 | { 77 | g_warning("Input error: %s", error->message); 78 | j4status_core_stream_reconnect(stream->context->core, stream->stream); 79 | g_clear_error(&error); 80 | return; 81 | } 82 | 83 | if ( size == 0 ) 84 | j4status_core_stream_free(stream->context->core, stream->stream); 85 | else 86 | g_input_stream_read_all_async(stream->in, stream->buffer, sizeof(stream->buffer), G_PRIORITY_DEFAULT, NULL, _j4status_debug_stream_read_callback, stream); 87 | } 88 | 89 | static J4statusOutputPluginStream * 90 | _j4status_debug_stream_new(J4statusPluginContext *context, J4statusCoreStream *core_stream) 91 | { 92 | J4statusOutputPluginStream *stream; 93 | 94 | stream = g_slice_new0(J4statusOutputPluginStream); 95 | stream->context = context; 96 | stream->stream = core_stream; 97 | 98 | stream->out = g_data_output_stream_new(j4status_core_stream_get_output_stream(stream->context->core, stream->stream)); 99 | stream->in = j4status_core_stream_get_input_stream(stream->context->core, stream->stream); 100 | 101 | g_input_stream_read_all_async(stream->in, stream->buffer, sizeof(stream->buffer), G_PRIORITY_DEFAULT, NULL, _j4status_debug_stream_read_callback, stream); 102 | 103 | return stream; 104 | } 105 | 106 | static void 107 | _j4status_debug_stream_free(J4statusPluginContext *context, J4statusOutputPluginStream *stream) 108 | { 109 | g_object_unref(stream->out); 110 | 111 | g_slice_free(J4statusOutputPluginStream, stream); 112 | } 113 | 114 | static void 115 | _j4status_debug_generate_line(J4statusPluginContext *context, GList *sections) 116 | { 117 | g_string_truncate(context->line, 0); 118 | gboolean first = TRUE; 119 | GList *section_; 120 | J4statusSection *section; 121 | for ( section_ = sections ; section_ != NULL ; section_ = g_list_next(section_) ) 122 | { 123 | section = section_->data; 124 | 125 | if ( ! j4status_section_is_dirty(section) ) 126 | goto print; 127 | 128 | const gchar *align = NULL; 129 | switch ( j4status_section_get_align(section) ) 130 | { 131 | case J4STATUS_ALIGN_LEFT: 132 | align = "left"; 133 | break; 134 | case J4STATUS_ALIGN_RIGHT: 135 | align = "right"; 136 | break; 137 | case J4STATUS_ALIGN_CENTER: 138 | align = "center"; 139 | break; 140 | } 141 | 142 | J4statusState state = j4status_section_get_state(section); 143 | const gchar *state_s = NULL; 144 | switch ( state & ~J4STATUS_STATE_FLAGS ) 145 | { 146 | case J4STATUS_STATE_NO_STATE: 147 | state_s = "no state"; 148 | break; 149 | case J4STATUS_STATE_UNAVAILABLE: 150 | state_s = "unavailable"; 151 | break; 152 | case J4STATUS_STATE_BAD: 153 | state_s = "bad"; 154 | break; 155 | case J4STATUS_STATE_AVERAGE: 156 | state_s = "average"; 157 | break; 158 | case J4STATUS_STATE_GOOD: 159 | state_s = "good"; 160 | break; 161 | } 162 | 163 | #define set_colour(n) \ 164 | gchar n##_str[10] = "none"; \ 165 | G_STMT_START { \ 166 | const gchar *tmp = j4status_colour_to_hex(j4status_section_get_##n(section)); \ 167 | if ( tmp != NULL ) \ 168 | g_snprintf(n##_str, sizeof(n##_str), "%s", tmp); \ 169 | } G_STMT_END 170 | set_colour(label_colour); 171 | set_colour(colour); 172 | set_colour(background_colour); 173 | #undef set_colour 174 | 175 | gchar *cache; 176 | cache = g_strdup_printf("--" 177 | "\nName: %s" 178 | "\nInstance: %s" 179 | "\nLabel: %s" 180 | "\nLabel colour: %s" 181 | "\nAlignment: %s" 182 | "\nMaximum width: %jd" 183 | "\n" 184 | "\nState: %s" 185 | "\nUrgent: %s" 186 | "\nColour: %s" 187 | "\nBackground colour: %s" 188 | "\nValue: %s" 189 | "\n--", 190 | j4status_section_get_name(section), 191 | j4status_section_get_instance(section), 192 | j4status_section_get_label(section), 193 | label_colour_str, 194 | align, 195 | j4status_section_get_max_width(section), 196 | state_s, 197 | BOOL_TO_S(state & J4STATUS_STATE_URGENT), 198 | colour_str, 199 | background_colour_str, 200 | j4status_section_get_value(section)); 201 | 202 | j4status_section_set_cache(section, cache); 203 | 204 | print: 205 | g_string_append(context->line, j4status_section_get_cache(section)); 206 | if ( first ) 207 | first = FALSE; 208 | else 209 | g_string_append_c(context->line, '\n'); 210 | } 211 | } 212 | 213 | static gboolean 214 | _j4status_debug_send_line(J4statusPluginContext *context, J4statusOutputPluginStream *stream, GError **error) 215 | { 216 | return g_data_output_stream_put_string(stream->out, context->line->str, NULL, error); 217 | } 218 | 219 | J4STATUS_EXPORT void 220 | j4status_output_plugin(J4statusOutputPluginInterface *interface) 221 | { 222 | libj4status_output_plugin_interface_add_init_callback(interface, _j4status_debug_init); 223 | libj4status_output_plugin_interface_add_uninit_callback(interface, _j4status_debug_uninit); 224 | 225 | libj4status_output_plugin_interface_add_stream_new_callback(interface, _j4status_debug_stream_new); 226 | libj4status_output_plugin_interface_add_stream_free_callback(interface, _j4status_debug_stream_free); 227 | 228 | libj4status_output_plugin_interface_add_generate_line_callback(interface, _j4status_debug_generate_line); 229 | libj4status_output_plugin_interface_add_send_line_callback(interface, _j4status_debug_send_line); 230 | } 231 | -------------------------------------------------------------------------------- /output/evp/man/j4status-evp.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-evp.conf 46 | 5 47 | 48 | 49 | 50 | j4status-evp.conf 51 | j4status EvP plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the EvP plugin 57 | 58 | 59 | The EvP plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the EvP plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[EvP]</varname> 76 | 77 | 78 | 79 | 80 | NoStateColour= 81 | (colour string, defaults to "none") 82 | 83 | 84 | Colour to use for sections without state. 85 | 86 | 87 | 88 | 89 | 90 | UnavailableColour= 91 | (colour string, defaults to "#0000FF") 92 | 93 | 94 | Colour to use for sections with unavailable state. 95 | 96 | 97 | 98 | 99 | 100 | BadColour= 101 | (colour string, defaults to "#FF0000") 102 | 103 | 104 | Colour to use for sections with bad state. 105 | 106 | 107 | 108 | 109 | 110 | AverageColour= 111 | (colour string, defaults to "#FFFF00") 112 | 113 | 114 | Colour to use for sections with average state. 115 | 116 | 117 | 118 | 119 | 120 | GoodColour= 121 | (colour string, defaults to "#00FF00") 122 | 123 | 124 | Colour to use for sections with good state. 125 | 126 | 127 | 128 | 129 | 130 | LabelSeparator= 131 | (string, defaults to ": ") 132 | 133 | 134 | The separator between label and value. 135 | 136 | 137 | 138 | 139 | 140 | Align= 141 | (boolean, defaults to false) 142 | 143 | 144 | Whether or not to align sections. 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | See Also 153 | 154 | j4status.conf5 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /output/evp/meson.build: -------------------------------------------------------------------------------- 1 | 2 | libeventc = dependency('libeventc', required: get_option('evp')) 3 | libeventd = dependency('libeventd', required: get_option('evp')) 4 | 5 | if libeventc.found() and libeventd.found() 6 | shared_library('evp', [ config_h ] + files( 7 | 'src/evp.c', 8 | ), 9 | c_args: [ 10 | '-DG_LOG_DOMAIN="j4status-evp"', 11 | ], 12 | dependencies: [ libeventc, libeventd, libj4status_plugin, gio, glib ], 13 | name_prefix: '', 14 | install: true, 15 | install_dir: plugins_install_dir, 16 | ) 17 | 18 | man_pages += [ [ files('man/j4status-evp.conf.xml'), 'j4status-evp.conf.5' ] ] 19 | docbook_conditions += 'enable_evp_output' 20 | endif 21 | -------------------------------------------------------------------------------- /output/evp/src/evp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | #include 32 | 33 | #include "j4status-plugin-output.h" 34 | 35 | struct _J4statusPluginContext { 36 | J4statusCoreInterface *core; 37 | J4statusColour colours[_J4STATUS_STATE_SIZE]; 38 | gboolean align; 39 | EventcConnection *eventc; 40 | }; 41 | 42 | struct _J4statusOutputPluginStream { 43 | J4statusPluginContext *context; 44 | J4statusCoreStream *stream; 45 | GDataInputStream *in; 46 | GOutputStream *out; 47 | }; 48 | 49 | static J4statusOutputPluginStream * 50 | _j4status_evp_stream_new(G_GNUC_UNUSED J4statusPluginContext *context, G_GNUC_UNUSED J4statusCoreStream *core_stream) 51 | { 52 | return NULL; 53 | } 54 | 55 | static void 56 | _j4status_evp_stream_free(G_GNUC_UNUSED J4statusPluginContext *context, G_GNUC_UNUSED J4statusOutputPluginStream *stream) 57 | { 58 | } 59 | 60 | static void 61 | _j4status_evp_generate_line(J4statusPluginContext *context, GList *sections) 62 | { 63 | GList *section_; 64 | J4statusSection *section; 65 | for ( section_ = sections ; section_ != NULL ; section_ = g_list_next(section_) ) 66 | { 67 | section = section_->data; 68 | if ( ! j4status_section_is_dirty(section) ) 69 | continue; 70 | 71 | const gchar *value; 72 | value = j4status_section_get_value(section); 73 | if ( value == NULL ) 74 | continue; 75 | 76 | J4statusColour colour = {0}; 77 | 78 | EventdEvent *event; 79 | event = j4status_section_get_output_user_data(section); 80 | if ( event == NULL ) 81 | { 82 | event = eventd_event_new("j4status", j4status_section_get_name(section)); 83 | j4status_section_set_output_user_data(section, event, (GDestroyNotify) eventd_event_unref); 84 | 85 | eventd_event_add_data_string(event, g_strdup("instance"), g_strdup(j4status_section_get_instance(section))); 86 | 87 | const gchar *label; 88 | label = j4status_section_get_label(section); 89 | if ( label != NULL ) 90 | { 91 | eventd_event_add_data_string(event, g_strdup("label"), g_strdup(label)); 92 | colour = j4status_section_get_label_colour(section); 93 | if ( colour.set ) 94 | eventd_event_add_data_string(event, g_strdup("label-colour"), g_strdup(j4status_colour_to_hex(colour))); 95 | } 96 | } 97 | 98 | GVariantBuilder builder; 99 | const gchar *s = value, *c ; 100 | g_variant_builder_init(&builder, G_VARIANT_TYPE_STRING_ARRAY); 101 | while ( ( c = g_utf8_strchr(s, -1, '') ) != NULL ) 102 | { 103 | g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strndup(s, c - s))); 104 | s = g_utf8_next_char(c); 105 | } 106 | g_variant_builder_add_value(&builder, g_variant_new_string(s)); 107 | 108 | eventd_event_add_data(event, g_strdup("value"), g_variant_builder_end(&builder)); 109 | 110 | J4statusState state = j4status_section_get_state(section); 111 | colour = j4status_section_get_colour(section); 112 | if ( colour.set ) 113 | eventd_event_add_data_string(event, g_strdup("colour"), g_strdup(j4status_colour_to_hex(colour))); 114 | colour = context->colours[state & ~J4STATUS_STATE_FLAGS]; 115 | if ( colour.set ) 116 | eventd_event_add_data_string(event, g_strdup("state-colour"), g_strdup(j4status_colour_to_hex(colour))); 117 | 118 | eventd_event_add_data(event, g_strdup("state"), g_variant_new_uint32(state & ~J4STATUS_STATE_FLAGS)); 119 | eventd_event_add_data(event, g_strdup("urgent"), g_variant_new_boolean(state & J4STATUS_STATE_URGENT)); 120 | 121 | eventc_connection_send_event(context->eventc, event, NULL); 122 | 123 | j4status_section_set_cache(section, NULL); 124 | } 125 | } 126 | 127 | static void 128 | _j4status_evp_update_colour(J4statusColour *colour, GKeyFile *key_file, gchar *name) 129 | { 130 | gchar *config; 131 | config = g_key_file_get_string(key_file, "EvP", name, NULL); 132 | if ( config == NULL ) 133 | return; 134 | 135 | *colour = j4status_colour_parse(config); 136 | g_free(config); 137 | } 138 | 139 | static void 140 | _j4status_evp_connect_cb(G_GNUC_UNUSED GObject *obj, GAsyncResult *res, gpointer user_data) 141 | { 142 | J4statusPluginContext *context = user_data; 143 | 144 | eventc_connection_connect_finish(context->eventc, res, NULL); 145 | } 146 | 147 | static J4statusPluginContext * 148 | _j4status_evp_init(J4statusCoreInterface *core) 149 | { 150 | J4statusPluginContext *context; 151 | 152 | context = g_new0(J4statusPluginContext, 1); 153 | context->core = core; 154 | 155 | context->colours[J4STATUS_STATE_UNAVAILABLE].set = TRUE; 156 | context->colours[J4STATUS_STATE_UNAVAILABLE].blue = 0xff; 157 | context->colours[J4STATUS_STATE_BAD].set = TRUE; 158 | context->colours[J4STATUS_STATE_BAD].red = 0xff; 159 | context->colours[J4STATUS_STATE_AVERAGE].set = TRUE; 160 | context->colours[J4STATUS_STATE_AVERAGE].red = 0xff; 161 | context->colours[J4STATUS_STATE_AVERAGE].green = 0xff; 162 | context->colours[J4STATUS_STATE_GOOD].set = TRUE; 163 | context->colours[J4STATUS_STATE_GOOD].green = 0xff; 164 | 165 | GKeyFile *key_file; 166 | key_file = j4status_config_get_key_file("EvP"); 167 | 168 | if ( key_file != NULL ) 169 | { 170 | context->align = g_key_file_get_boolean(key_file, "EvP", "Align", NULL); 171 | _j4status_evp_update_colour(&context->colours[J4STATUS_STATE_NO_STATE], key_file, "NoStateColour"); 172 | _j4status_evp_update_colour(&context->colours[J4STATUS_STATE_UNAVAILABLE], key_file, "UnavailableColour"); 173 | _j4status_evp_update_colour(&context->colours[J4STATUS_STATE_BAD], key_file, "BadColour"); 174 | _j4status_evp_update_colour(&context->colours[J4STATUS_STATE_AVERAGE], key_file, "AverageColour"); 175 | _j4status_evp_update_colour(&context->colours[J4STATUS_STATE_GOOD], key_file, "GoodColour"); 176 | } 177 | 178 | if ( key_file != NULL ) 179 | g_key_file_free(key_file); 180 | 181 | GError *error = NULL; 182 | 183 | context->eventc = eventc_connection_new(NULL, &error); 184 | if ( context->eventc == NULL ) 185 | return NULL; 186 | 187 | eventc_connection_connect(context->eventc, _j4status_evp_connect_cb, context); 188 | 189 | return context; 190 | } 191 | 192 | static void 193 | _j4status_evp_uninit(J4statusPluginContext *context) 194 | { 195 | eventc_connection_close(context->eventc, NULL); 196 | g_object_unref(context->eventc); 197 | 198 | g_free(context); 199 | } 200 | 201 | J4STATUS_EXPORT void 202 | j4status_output_plugin(J4statusOutputPluginInterface *interface) 203 | { 204 | libj4status_output_plugin_interface_add_init_callback(interface, _j4status_evp_init); 205 | libj4status_output_plugin_interface_add_uninit_callback(interface, _j4status_evp_uninit); 206 | 207 | libj4status_output_plugin_interface_add_stream_new_callback(interface, _j4status_evp_stream_new); 208 | libj4status_output_plugin_interface_add_stream_free_callback(interface, _j4status_evp_stream_free); 209 | 210 | libj4status_output_plugin_interface_add_generate_line_callback(interface, _j4status_evp_generate_line); 211 | } 212 | -------------------------------------------------------------------------------- /output/flat/man/j4status-flat.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-flat.conf 46 | 5 47 | 48 | 49 | 50 | j4status-flat.conf 51 | j4status flat plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the flat plugin 57 | 58 | 59 | The flat plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the flat plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[Flat]</varname> 76 | 77 | Colours will be used only if your terminal has 256 colour support and $TERM ends with -256color (or -256colour). 78 | 79 | 80 | 81 | 82 | NoStateColour= 83 | (colour string, defaults to "none") 84 | 85 | 86 | Colour to use for sections without state. 87 | 88 | 89 | 90 | 91 | 92 | UnavailableColour= 93 | (colour string, defaults to "#0000FF") 94 | 95 | 96 | Colour to use for sections with unavailable state. 97 | 98 | 99 | 100 | 101 | 102 | BadColour= 103 | (colour string, defaults to "#FF0000") 104 | 105 | 106 | Colour to use for sections with bad state. 107 | 108 | 109 | 110 | 111 | 112 | AverageColour= 113 | (colour string, defaults to "#FFFF00") 114 | 115 | 116 | Colour to use for sections with average state. 117 | 118 | 119 | 120 | 121 | 122 | GoodColour= 123 | (colour string, defaults to "#00FF00") 124 | 125 | 126 | Colour to use for sections with good state. 127 | 128 | 129 | 130 | 131 | 132 | LabelSeparator= 133 | (string, defaults to ": ") 134 | 135 | 136 | The separator between label and value. 137 | 138 | 139 | 140 | 141 | 142 | Align= 143 | (boolean, defaults to false) 144 | 145 | 146 | Whether or not to align sections. 147 | 148 | 149 | 150 | 151 | 152 | UseColours= 153 | (boolean, defaults to false) 154 | 155 | 156 | Whether or not to use colours. 157 | 158 | 159 | 160 | 161 | 162 | ColoursOnBackground= 163 | (boolean, defaults to false) 164 | 165 | 166 | Use the colours as a background. 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | See Also 175 | 176 | j4status.conf5 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /output/flat/meson.build: -------------------------------------------------------------------------------- 1 | shared_library('flat', [ config_h ] + files( 2 | 'src/flat.c', 3 | ), 4 | c_args: [ 5 | '-DG_LOG_DOMAIN="j4status-flat"', 6 | ], 7 | dependencies: [ libj4status_plugin, gio, glib ], 8 | name_prefix: '', 9 | install: true, 10 | install_dir: plugins_install_dir, 11 | ) 12 | 13 | man_pages += [ [ files('man/j4status-flat.conf.xml'), 'j4status-flat.conf.5' ] ] 14 | -------------------------------------------------------------------------------- /output/flat/src/flat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "j4status-plugin-output.h" 31 | 32 | typedef struct { 33 | gchar start[28]; 34 | gchar end[5]; 35 | } ColourStr; 36 | 37 | #define COLOUR_STR(n) ColourStr n = { .start = { '\0' }, .end = { '\e', '[', '0', 'm', '\0' } }; /* strlen("\e[38;5;xxxm\e[38;5;xxxm\e[5m\x07") */ 38 | #define MAX_LINE 256 39 | 40 | struct _J4statusPluginContext { 41 | J4statusCoreInterface *core; 42 | gchar *label_separator; 43 | J4statusColour colours[_J4STATUS_STATE_SIZE]; 44 | gboolean back_colours; 45 | gboolean align; 46 | GString *line; 47 | }; 48 | 49 | struct _J4statusOutputPluginStream { 50 | J4statusPluginContext *context; 51 | J4statusCoreStream *stream; 52 | GDataInputStream *in; 53 | GDataOutputStream *out; 54 | }; 55 | 56 | static void 57 | _j4status_flat_stream_read_callback(GObject *obj, GAsyncResult *res, gpointer user_data) 58 | { 59 | J4statusOutputPluginStream *stream = user_data; 60 | GDataInputStream *in = G_DATA_INPUT_STREAM(obj); 61 | GError *error = NULL; 62 | 63 | gchar *line; 64 | line = g_data_input_stream_read_line_finish(in, res, NULL, &error); 65 | if ( line == NULL ) 66 | { 67 | if ( error == NULL ) 68 | j4status_core_stream_free(stream->context->core, stream->stream); 69 | else 70 | { 71 | g_warning("Input error: %s", error->message); 72 | j4status_core_stream_reconnect(stream->context->core, stream->stream); 73 | } 74 | g_clear_error(&error); 75 | return; 76 | } 77 | 78 | gchar *event_id = line; 79 | gchar *section_id = g_utf8_strchr(line, -1, ' '); 80 | if ( section_id != NULL ) 81 | { 82 | *section_id++ = '\0'; 83 | j4status_core_trigger_action(stream->context->core, section_id, event_id); 84 | } 85 | 86 | g_free(line); 87 | g_data_input_stream_read_line_async(in, G_PRIORITY_DEFAULT, NULL, _j4status_flat_stream_read_callback, stream); 88 | } 89 | 90 | static J4statusOutputPluginStream * 91 | _j4status_flat_stream_new(J4statusPluginContext *context, J4statusCoreStream *core_stream) 92 | { 93 | J4statusOutputPluginStream *stream; 94 | 95 | stream = g_slice_new0(J4statusOutputPluginStream); 96 | stream->context = context; 97 | stream->stream = core_stream; 98 | 99 | stream->out = g_data_output_stream_new(j4status_core_stream_get_output_stream(stream->context->core, stream->stream)); 100 | stream->in = g_data_input_stream_new(j4status_core_stream_get_input_stream(stream->context->core, stream->stream)); 101 | 102 | g_data_input_stream_read_line_async(stream->in, G_PRIORITY_DEFAULT, NULL, _j4status_flat_stream_read_callback, stream); 103 | 104 | return stream; 105 | } 106 | 107 | static void 108 | _j4status_flat_stream_free(J4statusPluginContext *context, J4statusOutputPluginStream *stream) 109 | { 110 | g_object_unref(stream->out); 111 | g_object_unref(stream->in); 112 | 113 | g_slice_free(J4statusOutputPluginStream, stream); 114 | } 115 | 116 | static void 117 | _j4status_flat_set_colour(ColourStr *out, J4statusColour colour, J4statusColour back_colour, gboolean important) 118 | { 119 | gsize o = 0; 120 | if ( colour.set ) 121 | o += g_sprintf(out->start, "\e[38;5;%03hum", 16 + ( ( colour.red / 51 ) * 36 ) + ( ( colour.green / 51 ) * 6 ) + ( colour.blue / 51 )); 122 | if ( back_colour.set ) 123 | o += g_sprintf(out->start + o, "\e[48;5;%03hum", 16 + ( ( back_colour.red / 51 ) * 36 ) + ( ( back_colour.green / 51 ) * 6 ) + ( back_colour.blue / 51 )); 124 | if ( important ) 125 | g_sprintf(out->start + o, "\e[5m\a"); 126 | else if ( ( ! colour.set ) && ( ! back_colour.set ) ) 127 | out->end[0] = '\0'; 128 | } 129 | 130 | static void 131 | _j4status_flat_generate_line(J4statusPluginContext *context, GList *sections) 132 | { 133 | g_string_truncate(context->line, 0); 134 | GList *section_; 135 | J4statusSection *section; 136 | gboolean first = TRUE; 137 | for ( section_ = sections ; section_ != NULL ; section_ = g_list_next(section_) ) 138 | { 139 | section = section_->data; 140 | const gchar *cache; 141 | if ( j4status_section_is_dirty(section) ) 142 | { 143 | gchar *new_cache = NULL; 144 | const gchar *value; 145 | value = j4status_section_get_value(section); 146 | if ( value != NULL ) 147 | { 148 | J4statusColour colour = {0}; 149 | J4statusColour back_colour = {0}; 150 | COLOUR_STR(colour_str); 151 | 152 | 153 | J4statusState state = j4status_section_get_state(section); 154 | gboolean urgent = ( state & J4STATUS_STATE_URGENT ); 155 | colour = j4status_section_get_colour(section); 156 | back_colour = j4status_section_get_background_colour(section); 157 | if ( ( ! colour.set ) && ( ! back_colour.set ) ) 158 | { 159 | if ( context->back_colours ) 160 | back_colour = context->colours[state & ~J4STATUS_STATE_FLAGS]; 161 | else 162 | colour = context->colours[state & ~J4STATUS_STATE_FLAGS]; 163 | } 164 | _j4status_flat_set_colour(&colour_str, colour, back_colour, urgent); 165 | 166 | gsize s = 1, l = 0, r = 0; 167 | 168 | if ( context->align ) 169 | { 170 | gint64 max_width; 171 | max_width = j4status_section_get_max_width(section); 172 | 173 | if ( max_width < 0 ) 174 | { 175 | s = -max_width; 176 | switch ( j4status_section_get_align(section) ) 177 | { 178 | case J4STATUS_ALIGN_CENTER: 179 | l = s / 2; 180 | r = ( s + 1 ) / 2; 181 | break; 182 | case J4STATUS_ALIGN_LEFT: 183 | r = s; 184 | break; 185 | case J4STATUS_ALIGN_RIGHT: 186 | l = s; 187 | break; 188 | } 189 | } 190 | } 191 | gchar align_left[s], align_right[s]; 192 | memset(align_left, ' ', l); align_left[l] = '\0'; 193 | memset(align_right, ' ', r); align_right[r] = '\0'; 194 | 195 | const gchar *label; 196 | label = j4status_section_get_label(section); 197 | if ( label != NULL ) 198 | { 199 | J4statusColour back_colour = {0}; 200 | COLOUR_STR(label_colour_str); 201 | _j4status_flat_set_colour(&label_colour_str, j4status_section_get_label_colour(section), back_colour, FALSE); 202 | 203 | new_cache = g_strdup_printf("%s%s%s%s%s%s%s%s%s", label_colour_str.start, label, label_colour_str.end, context->label_separator, align_left, colour_str.start, value, colour_str.end, align_right); 204 | } 205 | else 206 | new_cache = g_strdup_printf("%s%s%s%s%s", align_left, colour_str.start, value, colour_str.end, align_right); 207 | } 208 | j4status_section_set_cache(section, new_cache); 209 | cache = new_cache; 210 | } 211 | else 212 | cache = j4status_section_get_cache(section); 213 | if ( cache == NULL ) 214 | continue; 215 | if ( first ) 216 | first = FALSE; 217 | else 218 | g_string_append(context->line, " | "); 219 | g_string_append(context->line, cache); 220 | } 221 | g_string_append_c(context->line, '\n'); 222 | } 223 | 224 | static gboolean 225 | _j4status_flat_send_line(J4statusPluginContext *context, J4statusOutputPluginStream *stream, GError **error) 226 | { 227 | return g_data_output_stream_put_string(stream->out, context->line->str, NULL, error); 228 | } 229 | 230 | static void 231 | _j4status_flat_update_colour(J4statusColour *colour, GKeyFile *key_file, gchar *name) 232 | { 233 | gchar *config; 234 | config = g_key_file_get_string(key_file, "Flat", name, NULL); 235 | if ( config == NULL ) 236 | return; 237 | 238 | *colour = j4status_colour_parse(config); 239 | g_free(config); 240 | } 241 | 242 | static J4statusPluginContext * 243 | _j4status_flat_init(J4statusCoreInterface *core) 244 | { 245 | J4statusPluginContext *context; 246 | 247 | context = g_new0(J4statusPluginContext, 1); 248 | context->core = core; 249 | 250 | gboolean use_colours = FALSE; 251 | 252 | GKeyFile *key_file; 253 | key_file = j4status_config_get_key_file("Flat"); 254 | if ( key_file != NULL ) 255 | { 256 | context->align = g_key_file_get_boolean(key_file, "Flat", "Align", NULL); 257 | context->label_separator = g_key_file_get_string(key_file, "Flat", "LabelSeparator", NULL); 258 | use_colours = g_key_file_get_boolean(key_file, "Flat", "UseColours", NULL); 259 | context->back_colours = g_key_file_get_boolean(key_file, "Flat", "ColoursOnBackground", NULL); 260 | } 261 | 262 | if ( 263 | use_colours && 264 | ( g_str_has_suffix(g_getenv("TERM"), "-256color") || g_str_has_suffix(g_getenv("TERM"), "-256colour") ) 265 | ) 266 | { 267 | context->colours[J4STATUS_STATE_UNAVAILABLE].set = TRUE; 268 | context->colours[J4STATUS_STATE_UNAVAILABLE].blue = 0xff; 269 | context->colours[J4STATUS_STATE_BAD].set = TRUE; 270 | context->colours[J4STATUS_STATE_BAD].red = 0xff; 271 | context->colours[J4STATUS_STATE_AVERAGE].set = TRUE; 272 | context->colours[J4STATUS_STATE_AVERAGE].red = 0xff; 273 | context->colours[J4STATUS_STATE_AVERAGE].green = 0xff; 274 | context->colours[J4STATUS_STATE_GOOD].set = TRUE; 275 | context->colours[J4STATUS_STATE_GOOD].green = 0xff; 276 | 277 | if ( key_file != NULL ) 278 | { 279 | _j4status_flat_update_colour(&context->colours[J4STATUS_STATE_NO_STATE], key_file, "NoStateColour"); 280 | _j4status_flat_update_colour(&context->colours[J4STATUS_STATE_UNAVAILABLE], key_file, "UnavailableColour"); 281 | _j4status_flat_update_colour(&context->colours[J4STATUS_STATE_BAD], key_file, "BadColour"); 282 | _j4status_flat_update_colour(&context->colours[J4STATUS_STATE_AVERAGE], key_file, "AverageColour"); 283 | _j4status_flat_update_colour(&context->colours[J4STATUS_STATE_GOOD], key_file, "GoodColour"); 284 | } 285 | } 286 | 287 | if ( context->label_separator == NULL ) 288 | context->label_separator = g_strdup(": "); 289 | 290 | if ( key_file != NULL ) 291 | g_key_file_free(key_file); 292 | 293 | context->line = g_string_new(""); 294 | 295 | return context; 296 | } 297 | 298 | static void 299 | _j4status_flat_uninit(J4statusPluginContext *context) 300 | { 301 | g_string_free(context->line, TRUE); 302 | 303 | g_free(context->label_separator); 304 | 305 | g_free(context); 306 | } 307 | 308 | J4STATUS_EXPORT void 309 | j4status_output_plugin(J4statusOutputPluginInterface *interface) 310 | { 311 | libj4status_output_plugin_interface_add_init_callback(interface, _j4status_flat_init); 312 | libj4status_output_plugin_interface_add_uninit_callback(interface, _j4status_flat_uninit); 313 | 314 | libj4status_output_plugin_interface_add_stream_new_callback(interface, _j4status_flat_stream_new); 315 | libj4status_output_plugin_interface_add_stream_free_callback(interface, _j4status_flat_stream_free); 316 | 317 | libj4status_output_plugin_interface_add_generate_line_callback(interface, _j4status_flat_generate_line); 318 | libj4status_output_plugin_interface_add_send_line_callback(interface, _j4status_flat_send_line); 319 | } 320 | -------------------------------------------------------------------------------- /output/pango/man/j4status-pango.conf.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | %config; 5 | ]> 6 | 7 | 27 | 28 | 29 | 30 | &PACKAGE_NAME; Manual 31 | &PACKAGE_NAME; 32 | &PACKAGE_VERSION; 33 | 34 | 35 | 36 | Developer 37 | Quentin 38 | Glidic 39 | sardemff7@j4tools.org 40 | 41 | 42 | 43 | 44 | 45 | j4status-pango.conf 46 | 5 47 | 48 | 49 | 50 | j4status-pango.conf 51 | j4status Pango plugin configuration 52 | 53 | 54 | 55 | 56 | Configuration for the Pango plugin 57 | 58 | 59 | The Pango plugin use the main j4status configuration file (see j4status.conf5). 60 | 61 | 62 | 63 | 64 | Description 65 | 66 | 67 | It controls the Pango plugin behavior. 68 | 69 | 70 | 71 | 72 | Sections 73 | 74 | 75 | Section <varname>[Pango]</varname> 76 | 77 | 78 | 79 | 80 | NoStateColour= 81 | (colour string, defaults to "none") 82 | 83 | 84 | Colour to use for sections without state. 85 | 86 | 87 | 88 | 89 | 90 | UnavailableColour= 91 | (colour string, defaults to "#0000FF") 92 | 93 | 94 | Colour to use for sections with unavailable state. 95 | 96 | 97 | 98 | 99 | 100 | BadColour= 101 | (colour string, defaults to "#FF0000") 102 | 103 | 104 | Colour to use for sections with bad state. 105 | 106 | 107 | 108 | 109 | 110 | AverageColour= 111 | (colour string, defaults to "#FFFF00") 112 | 113 | 114 | Colour to use for sections with average state. 115 | 116 | 117 | 118 | 119 | 120 | GoodColour= 121 | (colour string, defaults to "#00FF00") 122 | 123 | 124 | Colour to use for sections with good state. 125 | 126 | 127 | 128 | 129 | 130 | LabelSeparator= 131 | (string, defaults to ": ") 132 | 133 | 134 | The separator between label and value. 135 | 136 | 137 | 138 | 139 | 140 | Align= 141 | (boolean, defaults to false) 142 | 143 | 144 | Whether or not to align sections. 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | See Also 153 | 154 | j4status.conf5 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /output/pango/meson.build: -------------------------------------------------------------------------------- 1 | shared_library('pango', [ config_h ] + files( 2 | 'src/pango.c', 3 | ), 4 | c_args: [ 5 | '-DG_LOG_DOMAIN="j4status-pango"', 6 | ], 7 | dependencies: [ libj4status_plugin, gio, glib ], 8 | name_prefix: '', 9 | install: true, 10 | install_dir: plugins_install_dir, 11 | ) 12 | 13 | man_pages += [ [ files('man/j4status-pango.conf.xml'), 'j4status-pango.conf.5' ] ] 14 | -------------------------------------------------------------------------------- /output/pango/src/pango.c: -------------------------------------------------------------------------------- 1 | /* 2 | * j4status - Status line generator 3 | * 4 | * Copyright © 2012-2018 Quentin "Sardem FF7" Glidic 5 | * 6 | * This file is part of j4status. 7 | * 8 | * j4status is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation, either version 3 of the License, or 11 | * (at your option) any later version. 12 | * 13 | * j4status is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with j4status. If not, see . 20 | * 21 | */ 22 | 23 | #include "config.h" 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include "j4status-plugin-output.h" 31 | 32 | typedef struct { 33 | gchar start[53]; /* strlen("") */ 34 | gchar end[8]; /* strlen("") */ 35 | } ColourStr; 36 | 37 | #define COLOUR_STR(n) ColourStr n = { .start = "", .end = "" }; 38 | 39 | struct _J4statusPluginContext { 40 | J4statusCoreInterface *core; 41 | gchar *label_separator; 42 | J4statusColour colours[_J4STATUS_STATE_SIZE]; 43 | gboolean align; 44 | GByteArray *line; 45 | }; 46 | 47 | struct _J4statusOutputPluginStream { 48 | J4statusPluginContext *context; 49 | J4statusCoreStream *stream; 50 | GDataInputStream *in; 51 | GOutputStream *out; 52 | }; 53 | 54 | static void 55 | _j4status_pango_stream_read_callback(GObject *obj, GAsyncResult *res, gpointer user_data) 56 | { 57 | J4statusOutputPluginStream *stream = user_data; 58 | GDataInputStream *in = G_DATA_INPUT_STREAM(obj); 59 | GError *error = NULL; 60 | 61 | gchar *line; 62 | line = g_data_input_stream_read_line_finish(in, res, NULL, &error); 63 | if ( line == NULL ) 64 | { 65 | if ( error == NULL ) 66 | j4status_core_stream_free(stream->context->core, stream->stream); 67 | else 68 | { 69 | g_warning("Input error: %s", error->message); 70 | j4status_core_stream_reconnect(stream->context->core, stream->stream); 71 | } 72 | g_clear_error(&error); 73 | return; 74 | } 75 | 76 | gchar *event_id = line; 77 | gchar *section_id = g_utf8_strchr(line, -1, ' '); 78 | if ( section_id != NULL ) 79 | { 80 | *section_id++ = '\0'; 81 | j4status_core_trigger_action(stream->context->core, section_id, event_id); 82 | } 83 | 84 | g_free(line); 85 | g_data_input_stream_read_line_async(in, G_PRIORITY_DEFAULT, NULL, _j4status_pango_stream_read_callback, stream); 86 | } 87 | 88 | static J4statusOutputPluginStream * 89 | _j4status_pango_stream_new(J4statusPluginContext *context, J4statusCoreStream *core_stream) 90 | { 91 | J4statusOutputPluginStream *stream; 92 | 93 | stream = g_slice_new0(J4statusOutputPluginStream); 94 | stream->context = context; 95 | stream->stream = core_stream; 96 | 97 | stream->out = j4status_core_stream_get_output_stream(stream->context->core, stream->stream); 98 | stream->in = g_data_input_stream_new(j4status_core_stream_get_input_stream(stream->context->core, stream->stream)); 99 | 100 | g_data_input_stream_read_line_async(stream->in, G_PRIORITY_DEFAULT, NULL, _j4status_pango_stream_read_callback, stream); 101 | 102 | return stream; 103 | } 104 | 105 | static void 106 | _j4status_pango_stream_free(J4statusPluginContext *context, J4statusOutputPluginStream *stream) 107 | { 108 | g_object_unref(stream->in); 109 | 110 | g_slice_free(J4statusOutputPluginStream, stream); 111 | } 112 | 113 | static gboolean 114 | _j4status_pango_send_header(J4statusPluginContext *context, J4statusOutputPluginStream *stream, GError **error) 115 | { 116 | static gchar *_j4status_pango_header = ""; 117 | return g_output_stream_write_all(stream->out, _j4status_pango_header, 1, NULL, NULL, error); 118 | } 119 | 120 | static void 121 | _j4status_pango_set_colour(ColourStr *out, J4statusColour colour, J4statusColour back_colour) 122 | { 123 | gsize l = sizeof(out->start), o = 0; 124 | if ( colour.set || back_colour.set ) 125 | o += g_snprintf(out->start + o, l - o, "end[0] = '\0'; 129 | return; 130 | } 131 | if ( colour.set ) 132 | o += g_snprintf(out->start + o, l - o, " foreground=\"%s\"", j4status_colour_to_hex(colour)); 133 | if ( back_colour.set ) 134 | o += g_snprintf(out->start + o, l - o, " background=\"%s\"", j4status_colour_to_hex(back_colour)); 135 | g_snprintf(out->start + o, l - o, ">"); 136 | } 137 | 138 | #define byte_append(b) G_STMT_START { guint8 b_ = (b); g_byte_array_append(context->line, &b_, 1); } G_STMT_END 139 | static void 140 | _j4status_pango_generate_line(J4statusPluginContext *context, GList *sections) 141 | { 142 | g_byte_array_set_size(context->line, 0); 143 | GList *section_; 144 | J4statusSection *section; 145 | gboolean urgent = FALSE; 146 | for ( section_ = sections ; section_ != NULL ; section_ = g_list_next(section_) ) 147 | { 148 | section = section_->data; 149 | const gchar *cache; 150 | if ( j4status_section_is_dirty(section) ) 151 | { 152 | gchar *new_cache = NULL; 153 | const gchar *value; 154 | value = j4status_section_get_value(section); 155 | if ( value != NULL ) 156 | { 157 | J4statusColour colour = {0}; 158 | J4statusColour back_colour = {0}; 159 | COLOUR_STR(colour_str); 160 | 161 | 162 | J4statusState state = j4status_section_get_state(section); 163 | urgent = urgent || ( state & J4STATUS_STATE_URGENT ); 164 | colour = j4status_section_get_colour(section); 165 | back_colour = j4status_section_get_background_colour(section); 166 | if ( ( ! colour.set ) && ( ! back_colour.set ) ) 167 | colour = context->colours[state & ~J4STATUS_STATE_FLAGS]; 168 | _j4status_pango_set_colour(&colour_str, colour, back_colour); 169 | 170 | gsize s = 1, l = 0, r = 0; 171 | 172 | if ( context->align ) 173 | { 174 | gint64 max_width; 175 | max_width = j4status_section_get_max_width(section); 176 | 177 | if ( max_width < 0 ) 178 | { 179 | s = -max_width; 180 | switch ( j4status_section_get_align(section) ) 181 | { 182 | case J4STATUS_ALIGN_CENTER: 183 | l = s / 2; 184 | r = ( s + 1 ) / 2; 185 | break; 186 | case J4STATUS_ALIGN_LEFT: 187 | r = s; 188 | break; 189 | case J4STATUS_ALIGN_RIGHT: 190 | l = s; 191 | break; 192 | } 193 | } 194 | } 195 | gchar align_left[s], align_right[s]; 196 | memset(align_left, ' ', l); align_left[l] = '\0'; 197 | memset(align_right, ' ', r); align_right[r] = '\0'; 198 | 199 | const gchar *label; 200 | label = j4status_section_get_label(section); 201 | if ( label != NULL ) 202 | { 203 | COLOUR_STR(label_colour_str); 204 | _j4status_pango_set_colour(&label_colour_str, j4status_section_get_label_colour(section), back_colour); 205 | 206 | new_cache = g_strdup_printf("%s%s%s%s%s%s%s%s%s", label_colour_str.start, label, label_colour_str.end, context->label_separator, align_left, colour_str.start, value, colour_str.end, align_right); 207 | } 208 | else 209 | new_cache = g_strdup_printf("%s%s%s%s%s", align_left, colour_str.start, value, colour_str.end, align_right); 210 | } 211 | j4status_section_set_cache(section, new_cache); 212 | cache = new_cache; 213 | } 214 | else 215 | cache = j4status_section_get_cache(section); 216 | if ( cache == NULL ) 217 | continue; 218 | 219 | guint64 length, size; 220 | length = strlen(cache); 221 | size = GUINT64_TO_BE(length); 222 | byte_append('s'); 223 | g_byte_array_append(context->line, (const guint8 *) &size, sizeof(size)); 224 | g_byte_array_append(context->line, (const guint8 *) cache, length); 225 | 226 | } 227 | if ( urgent ) 228 | byte_append('u'); 229 | byte_append('\0'); 230 | } 231 | 232 | static gboolean 233 | _j4status_pango_send_line(J4statusPluginContext *context, J4statusOutputPluginStream *stream, GError **error) 234 | { 235 | return g_output_stream_write_all(stream->out, context->line->data, context->line->len, NULL, NULL, error); 236 | } 237 | 238 | static void 239 | _j4status_pango_update_colour(J4statusColour *colour, GKeyFile *key_file, gchar *name) 240 | { 241 | gchar *config; 242 | config = g_key_file_get_string(key_file, "Pango", name, NULL); 243 | if ( config == NULL ) 244 | return; 245 | 246 | *colour = j4status_colour_parse(config); 247 | g_free(config); 248 | } 249 | 250 | static J4statusPluginContext * 251 | _j4status_pango_init(J4statusCoreInterface *core) 252 | { 253 | J4statusPluginContext *context; 254 | 255 | context = g_new0(J4statusPluginContext, 1); 256 | context->core = core; 257 | 258 | context->colours[J4STATUS_STATE_UNAVAILABLE].set = TRUE; 259 | context->colours[J4STATUS_STATE_UNAVAILABLE].blue = 0xff; 260 | context->colours[J4STATUS_STATE_BAD].set = TRUE; 261 | context->colours[J4STATUS_STATE_BAD].red = 0xff; 262 | context->colours[J4STATUS_STATE_AVERAGE].set = TRUE; 263 | context->colours[J4STATUS_STATE_AVERAGE].red = 0xff; 264 | context->colours[J4STATUS_STATE_AVERAGE].green = 0xff; 265 | context->colours[J4STATUS_STATE_GOOD].set = TRUE; 266 | context->colours[J4STATUS_STATE_GOOD].green = 0xff; 267 | 268 | GKeyFile *key_file; 269 | key_file = j4status_config_get_key_file("Pango"); 270 | 271 | if ( key_file != NULL ) 272 | { 273 | context->align = g_key_file_get_boolean(key_file, "Pango", "Align", NULL); 274 | context->label_separator = g_key_file_get_string(key_file, "Pango", "LabelSeparator", NULL); 275 | _j4status_pango_update_colour(&context->colours[J4STATUS_STATE_NO_STATE], key_file, "NoStateColour"); 276 | _j4status_pango_update_colour(&context->colours[J4STATUS_STATE_UNAVAILABLE], key_file, "UnavailableColour"); 277 | _j4status_pango_update_colour(&context->colours[J4STATUS_STATE_BAD], key_file, "BadColour"); 278 | _j4status_pango_update_colour(&context->colours[J4STATUS_STATE_AVERAGE], key_file, "AverageColour"); 279 | _j4status_pango_update_colour(&context->colours[J4STATUS_STATE_GOOD], key_file, "GoodColour"); 280 | } 281 | 282 | if ( context->label_separator == NULL ) 283 | context->label_separator = g_strdup(": "); 284 | 285 | if ( key_file != NULL ) 286 | g_key_file_free(key_file); 287 | 288 | context->line = g_byte_array_new(); 289 | 290 | return context; 291 | } 292 | 293 | static void 294 | _j4status_pango_uninit(J4statusPluginContext *context) 295 | { 296 | g_byte_array_unref(context->line); 297 | 298 | g_free(context->label_separator); 299 | 300 | g_free(context); 301 | } 302 | 303 | J4STATUS_EXPORT void 304 | j4status_output_plugin(J4statusOutputPluginInterface *interface) 305 | { 306 | libj4status_output_plugin_interface_add_init_callback(interface, _j4status_pango_init); 307 | libj4status_output_plugin_interface_add_uninit_callback(interface, _j4status_pango_uninit); 308 | 309 | libj4status_output_plugin_interface_add_stream_new_callback(interface, _j4status_pango_stream_new); 310 | libj4status_output_plugin_interface_add_stream_free_callback(interface, _j4status_pango_stream_free); 311 | 312 | libj4status_output_plugin_interface_add_send_header_callback(interface, _j4status_pango_send_header); 313 | libj4status_output_plugin_interface_add_generate_line_callback(interface, _j4status_pango_generate_line); 314 | libj4status_output_plugin_interface_add_send_line_callback(interface, _j4status_pango_send_line); 315 | } 316 | -------------------------------------------------------------------------------- /src/config.ent.in: -------------------------------------------------------------------------------- 1 | 21 | 22 | 23 | 24 | 25 | %git_version; 26 | --------------------------------------------------------------------------------