commit 2597c8e4e6c6664f5604873c901fe5e064a00232 Author: Ludovic 'Archivist' Lagouardette Date: Tue Jun 11 11:35:55 2019 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a007fea --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..be0903a --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +CXX = clang++ +CXXFLAGS = --std=c++17 -O3 -Iinclude +USE_THREADS = -pthread +USE_FILESYSTEM = -lc++fs +USE_SDL = -lSDL2 + +all: build + +build: pomodoro unix + +unix: yes + +clean: clean_pomodoro + +dirs: + @mkdir -p ./build/bin + +pomodoro: dirs + $(CXX) $(CXXFLAGS) $(USE_SDL) $(USE_THREADS) src/pomodoro/pomodoro.cpp -o ./build/bin/pomodoro_view + +clean_pomodoro: + -@rm ./build/bin/pomodoro_view + +yes: dirs + $(CXX) $(CXXFLAGS) src/yes/yes.cpp -o ./build/bin/yes + +yes_clean: + -@rm ./build/bin/yes + +astyle: + astyle --style=bsd --align-reference=type --align-pointer=type --break-blocks --indent-namespaces --indent=tab --add-brackets \ + include/rigid_paradise/*.h \ + src/pomodoro/pomodoro.cpp \ + src/yes/yes.cpp \ diff --git a/config/pomodoro.tasks b/config/pomodoro.tasks new file mode 100644 index 0000000..e69de29 diff --git a/config/rp.cfg b/config/rp.cfg new file mode 100644 index 0000000..ff7783a --- /dev/null +++ b/config/rp.cfg @@ -0,0 +1,3 @@ +pomodoro_sound ~/.rigidparadise/sound.wav +pomodoro.tasks ~/.rigidparadise/pomodoro.tasks +pomodoro.log ~/.rigidparadise/pomodoro.log \ No newline at end of file diff --git a/config/sms-alert-1-daniel_simon b/config/sms-alert-1-daniel_simon new file mode 100644 index 0000000..e69de29 diff --git a/config/sound.wav b/config/sound.wav new file mode 100644 index 0000000..abceafd Binary files /dev/null and b/config/sound.wav differ diff --git a/include/rigid_paradise/config.h b/include/rigid_paradise/config.h new file mode 100644 index 0000000..e39828c --- /dev/null +++ b/include/rigid_paradise/config.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include +#include +#include + + +namespace config +{ + inline std::string get_value(const std::string& source) + { + std::string ret = source; + + try + { + std::ifstream config_file("/home/archivist/.rigidparadise/rp.cfg"); + + if(!config_file.good()) + { + std::cerr << "Unable to read configuration"<1 && str[0] != '#') + { + auto end = std::find_if(str.begin(), str.end(), isspace); + size_t pos = end-str.begin(); + std::string_view name{str.data(), pos}; + + if(name == source) + { + ret = std::string{end+1, str.end()}; + } + } + } + } + catch(...) + {} + + return ret; + } +} diff --git a/include/rigid_paradise/display.h b/include/rigid_paradise/display.h new file mode 100644 index 0000000..21fc2d2 --- /dev/null +++ b/include/rigid_paradise/display.h @@ -0,0 +1,68 @@ +#pragma once +#include +#include +#include +#include + +namespace display +{ + inline std::string escape_csv(const std::string& value) + { + std::stringstream ret; + ret<<"\""; + + for(auto v : value) + { + switch(v) + { + case '\n': + ret << "\\n"; + break; + + case '\t': + ret << "\\t"; + break; + + case '"': + ret << "\\\""; + break; + + default: + ret << v; + break; + } + } + + ret<<"\""; + return ret.str(); + } + + inline std::string to_string(std::chrono::seconds v) + { + std::stringstream ret; + ret << v.count() << " second" << (v.count()!=1?"s":""); + return ret.str(); + } + + inline std::string to_string(std::chrono::minutes v) + { + std::stringstream ret; + ret << v.count() << " minute" << (v.count()!=1?"s":""); + return ret.str(); + } + + inline void header(std::string app_name) + { + std::cout << "\033[2J" << "\033[1;1H"; + std::cout << "Rigid Paradise's "< + void pair_set(const T& value) + { + for(auto action : value) + { + std::cout << " [" << action.first << "]: " << action.second< +#include +#include +#include + +namespace pomodoro +{ + using pomotask = std::pair; + std::set get_pomodoro_tasks() + { + std::set> ret; + std::ifstream tasks(config::get_value("pomodoro.tasks")); + int counter = 1; + + while(tasks.good()) + { + std::string str; + getline (tasks, str); + + if(str.size()>1 && str[0] != '#') + { + ret.insert(std::make_pair(counter++, str)); + } + } + + return ret; + } +} + +#define pomodoro_actions_unwrap {\ + std::make_pair('P',"Productive work"),\ + std::make_pair('B',"Parallel work"),\ + std::make_pair('C',"Non productive work"),\ + std::make_pair('D',"Productive discution or chat"),\ + std::make_pair('E',"Non productive chat"),\ + std::make_pair('T',"Learning"),\ + std::make_pair('S',"Improductive activity"),\ + std::make_pair('Z',"Break")\ +} \ No newline at end of file diff --git a/include/rigid_paradise/systems/stdio.h b/include/rigid_paradise/systems/stdio.h new file mode 100644 index 0000000..1853219 --- /dev/null +++ b/include/rigid_paradise/systems/stdio.h @@ -0,0 +1,2 @@ +#pragma once +#include "rigid_paradise/systems/unix/stdio.h" \ No newline at end of file diff --git a/include/rigid_paradise/systems/unix/stdio.h b/include/rigid_paradise/systems/unix/stdio.h new file mode 100644 index 0000000..8b0a827 --- /dev/null +++ b/include/rigid_paradise/systems/unix/stdio.h @@ -0,0 +1,31 @@ +#pragma once +#include +#include +#include + +namespace os{ + constexpr auto write = [](int32_t fd, const char* ptr, int64_t size){ + do + { + auto check = ::write(fd, ptr, size); + + if(check<0) + { + return check; + } + + size-=check; + ptr+=check; + }while(size!=0); + return size; + }; + + constexpr auto stdout_write = [](const char* ptr, size_t size){ + return write(0, ptr, size); + }; + + constexpr auto stderr_write = [](const char* ptr, size_t size){ + return write(2, ptr, size); + }; + +} \ No newline at end of file diff --git a/src/pomodoro/pomodoro.cpp b/src/pomodoro/pomodoro.cpp new file mode 100644 index 0000000..361d6b6 --- /dev/null +++ b/src/pomodoro/pomodoro.cpp @@ -0,0 +1,255 @@ +#include +#ifdef SV_EXP +#include +namespace std +{ + using string_view = std::experimental::string_view; +} +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rigid_paradise/display.h" +#include "rigid_paradise/config.h" +#include "rigid_paradise/pomodoro.h" + +using namespace std::chrono_literals; + +auto wait_interval = 12min; +//auto wait_interval = 12s; + +std::vector audioDeviceNames; +std::vector audioDeviceIDs; +Uint8* audio_pos; // global pointer to the audio buffer to be played +Uint8* audio_pos_orig; // global pointer to the audio buffer to be played +Uint32 audio_len; // remaining length of the sample we have to play +Uint32 audio_len_orig; // remaining length of the sample we have to play +std::atomic must_play = false; + +std::minstd_rand bad_rng; + +std::set> pomodoro_actions = pomodoro_actions_unwrap; + +namespace sound_mng +{ + + void my_audio_callback(void* userdata, Uint8* stream, int len) + { + + if (audio_len ==0) + { + return; + } + + len = ( len > audio_len ? audio_len : len ); + //SDL_memcpy (stream, audio_pos, len); // simply copy from one buffer into the other + SDL_MixAudio(stream, audio_pos, len, SDL_MIX_MAXVOLUME);// mix from one buffer into another + + audio_pos += len; + audio_len -= len; + } + + constexpr SDL_AudioSpec base_spec = + { + .freq = 48000, + .format = AUDIO_F32, + .channels = 2, + .silence = 0, + .samples = 4096, + .callback = my_audio_callback, + .userdata = nullptr + }; + + void loadAudioDevices() + { + int i, count = SDL_GetNumAudioDevices(0); + + for (i = 0; i < count; ++i) + { + const char* name = SDL_GetAudioDeviceName(i, 0); + audioDeviceNames.push_back(name); + SDL_AudioSpec ignored; + audioDeviceIDs.push_back(SDL_OpenAudioDevice( + name, + 0, + &base_spec, + &ignored, + 0 + )); + } + } + + + void player() + { + while ( true ) + { + while(must_play) + { + SDL_PauseAudio(0); + std::this_thread::sleep_for(1s); + audio_pos = audio_pos_orig; + audio_len = audio_len_orig; + SDL_PauseAudio(1); + std::this_thread::sleep_for(3s); + } + + std::this_thread::sleep_for(1s); + } + + return; + } +} + +int main(); + +int WinMain() +{ + return main(); +} + +int main() +{ + assert(SDL_Init(SDL_INIT_AUDIO) >= 0); + + sound_mng::loadAudioDevices(); + + // sound data + static Uint32 wav_length; // length + static Uint8* wav_buffer; // buffer containing our audio file + static SDL_AudioSpec wav_spec; // the specs of our sound + + + // Load the WAV + assert( SDL_LoadWAV(config::get_value("pomodoro_sound").c_str(), &wav_spec, &wav_buffer, &wav_length) != NULL ); + + // set the callback function + wav_spec.callback = sound_mng::my_audio_callback; + wav_spec.userdata = NULL; + // set our global static variables + audio_pos = wav_buffer; // copy sound buffer + audio_pos_orig = wav_buffer; // copy sound buffer + audio_len = wav_length; // copy file length + audio_len_orig = wav_length; // copy file length + + /* Open the device */ + if ( SDL_OpenAudio(&wav_spec, NULL) < 0 ) + { + fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError()); + exit(-1); + } + + std::thread my_player{sound_mng::player}; + + /********************* MAIN LOOP *************************/ + + bool quit = false; + + while(!quit) + { + display::header("Pomodoro"); + std::cout << "> Interval time is: "<< display::to_string(wait_interval) < Tasklist excerpt:\n"; + + std::array sample; + + auto list = pomodoro::get_pomodoro_tasks(); + + auto smp_end = std::sample(list.begin(), list.end(), sample.begin(),5, bad_rng); + + for(auto it = sample.begin(); it != smp_end; it++) + { + std::cout << "> ["<first<<"]: "<second<<"\n"; + } + + std::cout< Select your current action:" << std::endl; + + display::pair_set(pomodoro_actions); + + char action; + bool valid=false; + + do + { + std::string str; + getline (std::cin, str); + + auto is_matching = [&](auto action) + { + return str[0]==action.first; + }; + + if( + std::any_of( + pomodoro_actions.begin(), + pomodoro_actions.end(), + is_matching + ) + ) + { + action=str[0]; + valid=true; + } + } + while(!valid); + + auto task_list = pomodoro::get_pomodoro_tasks(); + std::cout<<"> Select your current assigned task:"<> task_nb; + } + catch(...) + { + task_nb = 0; + } + + std::for_each(task_list.begin(), task_list.end(), [&](auto action) + { + if(task_nb==action.first) + { + valid=true; + task_label = display::escape_csv(action.second); + } + }); + + } + while(!valid); + + + std::ofstream(config::get_value("pomodoro.log"), std::ofstream::app)< +namespace std +{ + using string_view = std::experimental::string_view; +} +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rigid_paradise/display.h" +#include "rigid_paradise/config.h" +#include "rigid_paradise/pomodoro.h" + +using namespace std::chrono_literals; + +std::set> pomodoro_actions = pomodoro_actions_unwrap; + + diff --git a/src/yes/yes.cpp b/src/yes/yes.cpp new file mode 100644 index 0000000..dd5e245 --- /dev/null +++ b/src/yes/yes.cpp @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE -1 +#endif + +const char* help = +"RigidParadise Yes, no version number\n\ + Archivist - 2019\n\ +usage: yes [STRING]*\n\ + Repeatedly output a line with all specified STRING(s), or 'y'.\n\ + yes --help\n\ + yes --version\n\ + Display this text.\n"; +const size_t help_len = strlen(help); + +int main(int argc, char** argv) +{ + std::string to_write = "y\n"; + std::vector str; + constexpr size_t target_size = 1 << 15; + str.reserve(target_size); + + if(argc>1) + { + if(argv[1][0]=='-' && argv[1][1]=='-') + { + os::stdout_write(help, help_len); + return 0; + } + + std::stringstream generator; + std::for_each(argv+1, argv+argc, [&](auto cstring) + { + generator << cstring << ' '; + }); + to_write = generator.str(); + to_write[to_write.size()-1]='\n'; + } + + do + { + for(auto a : to_write) + { + str.push_back(a); + } + } + while(str.size()<(target_size)); + + do + { + auto check = os::stdout_write(str.data() , str.size()); + + if(check<0) + { + return EXIT_FAILURE; + } + } + while(1); + + return 0; +}