Browse Source

Initial commit

master
Ludovic 'Archivist' Lagouardette 4 years ago
commit
2597c8e4e6
14 changed files with 579 additions and 0 deletions
  1. +1
    -0
      .gitignore
  2. +34
    -0
      Makefile
  3. +0
    -0
      config/pomodoro.tasks
  4. +3
    -0
      config/rp.cfg
  5. +0
    -0
      config/sms-alert-1-daniel_simon
  6. BIN
      config/sound.wav
  7. +47
    -0
      include/rigid_paradise/config.h
  8. +68
    -0
      include/rigid_paradise/display.h
  9. +40
    -0
      include/rigid_paradise/pomodoro.h
  10. +2
    -0
      include/rigid_paradise/systems/stdio.h
  11. +31
    -0
      include/rigid_paradise/systems/unix/stdio.h
  12. +255
    -0
      src/pomodoro/pomodoro.cpp
  13. +31
    -0
      src/pomodoro/pomodoro_tasks.cpp
  14. +67
    -0
      src/yes/yes.cpp

+ 1
- 0
.gitignore View File

@ -0,0 +1 @@
build/*

+ 34
- 0
Makefile View File

@ -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 \

+ 0
- 0
config/pomodoro.tasks View File


+ 3
- 0
config/rp.cfg View File

@ -0,0 +1,3 @@
pomodoro_sound ~/.rigidparadise/sound.wav
pomodoro.tasks ~/.rigidparadise/pomodoro.tasks
pomodoro.log ~/.rigidparadise/pomodoro.log

+ 0
- 0
config/sms-alert-1-daniel_simon View File


BIN
config/sound.wav View File


+ 47
- 0
include/rigid_paradise/config.h View File

@ -0,0 +1,47 @@
#pragma once
#include <fstream>
#include <iostream>
#include <string>
#include <cctype>
#include <algorithm>
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"<<std::endl;
}
while(config_file.good())
{
std::string str;
getline (config_file, str);
if(str.size()>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;
}
}

+ 68
- 0
include/rigid_paradise/display.h View File

@ -0,0 +1,68 @@
#pragma once
#include <string>
#include <sstream>
#include <chrono>
#include <iostream>
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 "<<app_name<<std::endl;
}
template<typename T>
void pair_set(const T& value)
{
for(auto action : value)
{
std::cout << " [" << action.first << "]: " << action.second<<std::endl;
}
}
}

+ 40
- 0
include/rigid_paradise/pomodoro.h View File

@ -0,0 +1,40 @@
#pragma once
#include <utility>
#include <set>
#include <fstream>
#include <rigid_paradise/config.h>
namespace pomodoro
{
using pomotask = std::pair<int, std::string>;
std::set<pomotask> get_pomodoro_tasks()
{
std::set<std::pair<int, std::string>> 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<char, std::string>('P',"Productive work"),\
std::make_pair<char, std::string>('B',"Parallel work"),\
std::make_pair<char, std::string>('C',"Non productive work"),\
std::make_pair<char, std::string>('D',"Productive discution or chat"),\
std::make_pair<char, std::string>('E',"Non productive chat"),\
std::make_pair<char, std::string>('T',"Learning"),\
std::make_pair<char, std::string>('S',"Improductive activity"),\
std::make_pair<char, std::string>('Z',"Break")\
}

+ 2
- 0
include/rigid_paradise/systems/stdio.h View File

@ -0,0 +1,2 @@
#pragma once
#include "rigid_paradise/systems/unix/stdio.h"

+ 31
- 0
include/rigid_paradise/systems/unix/stdio.h View File

@ -0,0 +1,31 @@
#pragma once
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
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);
};
}

+ 255
- 0
src/pomodoro/pomodoro.cpp View File

@ -0,0 +1,255 @@
#include <SDL2/SDL.h>
#ifdef SV_EXP
#include <experimental/string_view>
namespace std
{
using string_view = std::experimental::string_view;
}
#else
#include <string_view>
#endif
#include <vector>
#include <set>
#include <chrono>
#include <thread>
#include <atomic>
#include <string>
#include <utility>
#include <iostream>
#include <sstream>
#include <cassert>
#include <random>
#include <fstream>
#include <algorithm>
#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<std::string_view> audioDeviceNames;
std::vector<SDL_AudioDeviceID> 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<bool> must_play = false;
std::minstd_rand bad_rng;
std::set<std::pair<char, std::string>> 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) <<std::endl;
std::cout << "> Tasklist excerpt:\n";
std::array<pomodoro::pomotask,5> 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 << "> ["<<it->first<<"]: "<<it->second<<"\n";
}
std::cout<<std::endl;
std::this_thread::sleep_for(wait_interval);
must_play.store(true);
{
display::header("Pomodoro");
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:"<<std::endl;
display::pair_set(task_list);
int task_nb;
std::string task_label;
valid=false;
do
{
try
{
std::cin >> 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)<<std::chrono::seconds(std::time(NULL)).count()<<"\t"<<action<<"\t"<<task_label<<std::endl;
}
must_play.store(false);
}
// shut everything down
SDL_CloseAudio();
SDL_FreeWAV(wav_buffer);
}

+ 31
- 0
src/pomodoro/pomodoro_tasks.cpp View File

@ -0,0 +1,31 @@
#ifdef SV_EXP
#include <experimental/string_view>
namespace std
{
using string_view = std::experimental::string_view;
}
#else
#include <string_view>
#endif
#include <vector>
#include <set>
#include <chrono>
#include <thread>
#include <atomic>
#include <string>
#include <utility>
#include <iostream>
#include <sstream>
#include <cassert>
#include <random>
#include <fstream>
#include <algorithm>
#include "rigid_paradise/display.h"
#include "rigid_paradise/config.h"
#include "rigid_paradise/pomodoro.h"
using namespace std::chrono_literals;
std::set<std::pair<char, std::string>> pomodoro_actions = pomodoro_actions_unwrap;

+ 67
- 0
src/yes/yes.cpp View File

@ -0,0 +1,67 @@
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <rigid_paradise/systems/stdio.h>
#include <string.h>
#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<char> 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;
}

Loading…
Cancel
Save