#include #include #include #include #include #include #include #include #include // #include "vene.h" #include "vene_env.h" extern "C" { #include "slstatus/slstatus.h" } using namespace std; using namespace std::chrono; using namespace std::chrono_literals; namespace fs = std::filesystem; char* HOME; char SCREEN_CAPS_DIR[64]; namespace { time_point next_update; bool has_child; Proc child; } extern "C" { // from dwm struct Monitor; typedef struct { const char *symbol; void (*arrange)(Monitor *); } Layout; struct Client { char name[256]; float mina, maxa; int x, y, w, h; int oldx, oldy, oldw, oldh; int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; int bw, oldbw; unsigned int tags; int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; Client *next; Client *snext; Monitor *mon; Window win; }; struct Monitor { char ltsymbol[16]; float mfact; int nmaster; int num; int by; /* bar geometry */ int mx, my, mw, mh; /* screen size */ int wx, wy, ww, wh; /* window area */ unsigned int seltags; unsigned int sellt; unsigned int tagset[2]; int showbar; int topbar; Client *clients; Client *sel; Client *stack; Monitor *next; Window barwin; const Layout *lt[2]; }; typedef union { int i; unsigned int ui; float f; const void *v; } Arg; extern Monitor *selmon; void updatestatus(); void view(const Arg* arg); // end void vene_setup() { // Init vars HOME = getenv("HOME"); strcpy(SCREEN_CAPS_DIR, HOME); strcat(SCREEN_CAPS_DIR, "/screenshots/ss.png"); // strcpy(BOOKMARK_DIR, HOME); // strcat(BOOKMARK_DIR, "/notes/bookmarks/web"); // sprintf(OPEN_BOOKMARK_CMD, "xdg-open $(dmenumap ~/notes/bookmarks/web/$(ls %s | dmenu "DMENU_OPTS") "DMENU_OPTS")", BOOKMARK_DIR); // strcpy(OPEN_BOOKMARK_CMD, "xdg-open $(dmenumap "DMENU_OPTS" ~/notes/bookmarks/web/$(ls "); // strcat(OPEN_BOOKMARK_CMD, BOOKMARK_DIR); // strcat(OPEN_BOOKMARK_CMD, " | dmenu "DMENU_OPTS); } void vene_updatestatus(char status[]) { using std::string; static string new_stat; new_stat.clear(); try { // Net for(const auto& dir_entry: fs::directory_iterator("/sys/class/net")) { string interface_state; string interface = dir_entry.path().filename(); switch(interface[0]) { case 'e': // if the name begins with 'e' its ethernet ifstream(dir_entry.path() / "operstate") >> interface_state; if(interface_state == "up") new_stat += "🌐 "; break; case 'w': // 'w' means wifi ifstream(dir_entry.path() / "operstate") >> interface_state; if(interface_state == "up") { new_stat += "🛜"; if(const char* ssid = wifi_essid(interface.c_str()); ssid) new_stat += ssid; new_stat += ' '; if(const char* perc = wifi_perc(interface.c_str()); perc) { new_stat += perc; new_stat += "% "; } } break; } } // Battery string charge; ifstream("/sys/class/power_supply/BAT0/capacity") >> charge; if( !charge.empty() ) // If we have a charge we have a battery { string state; ifstream("/sys/class/power_supply/BAT0/status") >> state; const char* remaining = ""; if(state == "Discharging") { new_stat += "🔋"; remaining = battery_remaining("BAT0"); } else new_stat += "🔌"; new_stat += charge; new_stat += "% "; new_stat += remaining; new_stat += ' '; } } catch(...){ cerr << "EXCEPT\n"; } // Volume string amix_out = $(Cmd("amixer", "get", AUDIO_DEV)); size_t vol_bracket = amix_out.find('['); if(vol_bracket != string::npos) { bool is_muted = amix_out.find("[on]") == string::npos; new_stat += is_muted ? "🔇" : "🔉"; size_t first_digit = vol_bracket + 1; size_t close_bracket = amix_out.find(']', first_digit); new_stat.append(amix_out, first_digit, close_bracket - first_digit); new_stat += ' '; } // Time time_t rawtime; struct tm * timeinfo; time ( &rawtime ); timeinfo = localtime ( &rawtime ); new_stat += (timeinfo->tm_hour/10) + '0'; new_stat += (timeinfo->tm_hour%10) + '0'; new_stat += ':'; new_stat += (timeinfo->tm_min/10) + '0'; new_stat += (timeinfo->tm_min%10) + '0'; strcpy(status, new_stat.c_str()); } void vene_run() // update status bar every 5 sec { time_point now = system_clock::now(); if(has_child && check_exited(child)) { // Clean up all zombies while (waitpid(-1, nullptr, WNOHANG) > 0); has_child = false; updatestatus(); next_update = now + 10s; } else if(now > next_update) { updatestatus(); next_update = now + 10s; } } void vene_browser(const Arg* browser_tag) { bool browser_tag_used = false; for(Client* c = selmon->clients; c; c = c->next) if(c->tags & browser_tag->ui) { browser_tag_used = true; break; } if( browser_tag_used ) // browser tag is used, view it { view(browser_tag); } else // start browser { Cmd(BROWSER).detach(); } } void vene_webbookmark() // todo: cppipe exceptions { Cmd dmenu( "dmenu", "-b", "-f", "-i", "-l", "30"); string bm_root (HOME); bm_root += "/sync/bookmarks/web/"; Cmd list_dirs ("ls"); list_dirs += bm_root.c_str(); while(true) { // Choose bookmark directory string dir = $(list_dirs | dmenu); if( dir.empty() ) return; string bm_dir = bm_root; bm_dir += dir; bm_dir.pop_back(); // remove trailing newline // Choose bookmark string link = $(dmenu < bm_dir.c_str()); size_t link_begin = link.find('-'); if(link_begin != string::npos) { Cmd open_bookmark(BROWSER); link = link.substr(link_begin+1); open_bookmark += link.c_str(); open_bookmark.detach(); break; } } } void vene_inc_vol(const Arg*) { Cmd inc_vol("amixer", "-q", "set", AUDIO_DEV, "3%+"); child = inc_vol.detach(); has_child = true; } void vene_dec_vol(const Arg*) { Cmd dec_vol("amixer", "-q", "set", AUDIO_DEV, "3%-"); child = dec_vol.detach(); has_child = true; } void vene_toggle_vol(const Arg*) { Cmd toggle_vol("amixer", "-q", "-Dpulse", "set", AUDIO_DEV, "toggle"); child = toggle_vol.detach(); has_child = true; } }