diff --git a/Makefile b/Makefile index ce67b4a..35204aa 100644 --- a/Makefile +++ b/Makefile @@ -31,8 +31,7 @@ EMSCRIPTEN_CFLAGS = -O3 -Wall -s USE_SDL=2 -s USE_SDL_IMAGE=2 -s SDL2_IMAGE_FORM -s USE_SDL_TTF=2 -s USE_SDL_MIXER=2 -s MAX_WEBGL_VERSION=1 -s EXTRA_EXPORTED_RUNTIME_METHODS="['ccall']" \ -s EXPORTED_FUNCTIONS="['_main', '_reset_game']" -s ALLOW_MEMORY_GROWTH=1 -s GL_PREINITIALIZED_CONTEXT=1 \ -s ENVIRONMENT=web --shell-file shell_minimal.html --no-heap-copy -I$(SFW_LIB_DIR) -I$(SFW_SRC_DIR) -EMSCRIPTEN_PRELOADS = --preload-file "BPmono.ttf"@/ --preload-file "config.json" \ - --preload-file "resource" +EMSCRIPTEN_PRELOADS = --preload-file "BPmono.ttf"@/ --preload-file "config.json" --preload-file "resource" $(SDLGFX2_DIR)%.o: $(SDLGFX2_DIR)%.c $(SDLGFX2_DIR)%.h $(GLEW_DIR)%.o: $(GLEW_DIR)%.c $(GLEW_DIR)%.h @@ -59,13 +58,16 @@ $(SRC_DIR)Pudding.o : $(addprefix $(SRC_DIR), Item.hpp) $(SFW_H_FILES) linux : CC = clang linux : CPPC = clang++ -linux : CFLAGS = -Wall -Wextra -O3 -c -I$(SFW_LIB_DIR) -I$(SFW_SRC_DIR) $(SDL_FLAGS) +linux : CFLAGS = -g3 -Wall -Wextra -Og -c -I$(SFW_LIB_DIR) -I$(SFW_SRC_DIR) $(SDL_FLAGS) -I$(HOME)/local/zbar/include \ + -I$(HOME)/local/opencv/include/opencv4 linux : CPP_FLAGS = $(CFLAGS) --std=c++17 -linux : LFLAGS = $(shell $(SDLCONFIG) --libs) -lpthread +linux : LFLAGS = $(shell $(SDLCONFIG) --libs) -lpthread -lGL -lGLESv2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lcurl -lstdc++fs \ + -L/home/frank/local/opencv/lib -Wl,-rpath,/home/frank/local/opencv/lib -Wl,--enable-new-dtags -lopencv_videoio -lopencv_core \ + -lopencv_highgui linux : $(GLEW_DIR)glew.o $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPrimitives.o) \ $(SFW_O_FILES) $(GAME_O_FILES) $(CREATE_FONT_SYMLINK) - $(CPPC) $(LFLAGS) -D__LINUX__ -lGL -lGLESv2 -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lcurl -lstdc++fs $^ -o pudding + $(CPPC) $(LFLAGS) -D__LINUX__ $^ -o pudding emscripten : CC = $(EMSCRIPTENHOME)/emcc emscripten : CPPC = $(EMSCRIPTENHOME)/em++ @@ -94,10 +96,11 @@ collide_test_emscripten : $(addprefix $(SDLGFX2_DIR),SDL2_rotozoom.o SDL2_gfxPri .PHONY : clean clean : - -rm *.o - -rm $(SFW_SRC_DIR)*.o - -rm $(GLEW_DIR)*.o - -rm $(SDLGFX2_DIR)*.o + -rm $(SRC_DIR)*.o + +.PHONY : clean-all +clean-all : + -find . -iname "*.o" -exec rm {} \; android : if [ ! -d $(BUILDDIR) ]; then mkdir $(BUILDDIR); fi; diff --git a/config.json b/config.json index 26b0716..44ca451 100644 --- a/config.json +++ b/config.json @@ -1,7 +1,7 @@ { "display": { - "dimensions": [680, 384], + "dimensions": [960, 540], "framerate": 60, "title": "Pudding", "debug": false, @@ -37,7 +37,8 @@ { "json-save": true, "json-save-directory": "local/scans", - "barcode": "400063314395" + "barcode": "400063314395", + "capture-device": "/dev/video0" }, "api": { @@ -47,6 +48,10 @@ "edamam-app-id": "c23b139f", "edamam-app-key": "c54cf8c997534caf7ee92b1ccc7d95a3", "best-buy-api-key": "vAC23XA5YWBzaYiGtOkoNlXZ", - "giantbomb-api-key": "91a395231f4e1fd9f9ba8840c52a61cda343cd70" + "giantbomb-api-key": "91a395231f4e1fd9f9ba8840c52a61cda343cd70", + "nutronix-enabled": false, + "edamam-enabled": false, + "open-food-enabled": false, + "best-buy-enabled": true } } diff --git a/lib/sfw b/lib/sfw index fff9e13..95a1e6b 160000 --- a/lib/sfw +++ b/lib/sfw @@ -1 +1 @@ -Subproject commit fff9e13562d63ccd0b478e15d1953d1c7e3c08f9 +Subproject commit 95a1e6b5b126af2541c7ea0d0e978f021cea2018 diff --git a/src/Pudding.cpp b/src/Pudding.cpp index 89f37e4..d6f35c7 100644 --- a/src/Pudding.cpp +++ b/src/Pudding.cpp @@ -27,6 +27,20 @@ int main() Pudding::Pudding() { get_delegate().subscribe(&Pudding::respond, this); + int device_id = 0; + capture.open(device_id); + std::stringstream message; + if (capture.isOpened()) + { + message << "opened and initialized " << capture.get(cv::CAP_PROP_FRAME_WIDTH) << "x" << + capture.get(cv::CAP_PROP_FRAME_HEIGHT) << ", " << capture.get(cv::CAP_PROP_FPS) << + "fps video capture device ID #" << device_id << " using " << capture.getBackendName(); + } + else + { + message << "failed to open video capture device ID #" << device_id; + } + log(message.str()); load_sdl_context(); } @@ -59,10 +73,22 @@ void Pudding::add_item(const std::string& upc) { Item item(this); item.set_upc(upc); - incorporate_open_food_api(item); - incorporate_nutronix_api(item); - incorporate_edamam_api(item); - incorporate_best_buy_api(item); + if (get_configuration()["api"]["open-food-enabled"]) + { + incorporate_open_food_api(item); + } + if (get_configuration()["api"]["nutronix-enabled"]) + { + incorporate_nutronix_api(item); + } + if (get_configuration()["api"]["edamam-enabled"]) + { + incorporate_edamam_api(item); + } + if (get_configuration()["api"]["best-buy-enabled"]) + { + incorporate_best_buy_api(item); + } items.push_back(item); } @@ -337,6 +363,7 @@ Item& Pudding::get_current_item() /* Update parameters and draw the screen */ void Pudding::update() { + /* reload the config file every frame to check for changes */ get_root()->configuration.load("config.json"); get_root()->configuration.merge(); if (current_barcode != get_configuration()["scan"]["barcode"]) @@ -344,8 +371,31 @@ void Pudding::update() current_barcode = get_configuration()["scan"]["barcode"]; add_item(current_barcode); } + /* draw the current item image to the left half of the screen if items are available */ + Box video_box = get_window_box(); if (items.size() > 0) { - SDL_RenderCopyF(get_renderer(), get_current_item().get_active_image_texture().get(), nullptr, nullptr); + Box item_box = Box({0.0f, 0.0f}, {get_window_box().get_w() / 2.0f, get_window_box().get_h()}); + SDL_RenderCopyF(get_renderer(), get_current_item().get_active_image_texture().get(), nullptr, &item_box); + video_box.set_left(get_window_box().get_center_x(), true); + } + /* draw the camera to the right half of the screen if the camera has been opened */ + if (capture.isOpened()) + { + capture.read(capture_frame); + if (!capture_frame.empty()) + { + /* convert opencv matrix to sdl texture */ + SDL_Texture* texture = SDL_CreateTexture( + get_renderer(), SDL_PIXELFORMAT_BGR24, SDL_TEXTUREACCESS_STATIC, capture_frame.cols, capture_frame.rows); + SDL_UpdateTexture(texture, nullptr, static_cast(capture_frame.data), capture_frame.step1()); + SDL_RenderCopyF(get_renderer(), texture, nullptr, &video_box); + SDL_DestroyTexture(texture); + previously_captured_frame_index = capture.get(cv::CAP_PROP_POS_FRAMES); + } + else + { + log("video capture device frame empty"); + } } } diff --git a/src/Pudding.hpp b/src/Pudding.hpp index d09d0d7..2d418cf 100644 --- a/src/Pudding.hpp +++ b/src/Pudding.hpp @@ -1,6 +1,7 @@ #ifndef Pudding_h_ #define Pudding_h_ +#include #include #include #include @@ -10,6 +11,10 @@ #include "SDL.h" #include "json/json.hpp" #include "glm/vec2.hpp" +#include "opencv2/core.hpp" +#include "opencv2/videoio.hpp" +#include "opencv2/highgui.hpp" +#include "zbar.h" #include "Game.hpp" #include "Sprite.hpp" #include "Color.hpp" @@ -31,7 +36,9 @@ private: const std::string GIANTBOMB_API_URL = "https://www.giantbomb.com/api/release/?api_key="; std::string current_barcode; std::vector items; - int current_item_index; + int previously_captured_frame_index = -1, current_item_index = 0; + cv::VideoCapture capture; + cv::Mat capture_frame; void incorporate_open_food_api(Item&); void incorporate_nutronix_api(Item&);