From 8fdf8026b329393a2b111d01ea6f6e1565d428f6 Mon Sep 17 00:00:00 2001 From: Mr-Dave Date: Mon, 12 Aug 2024 01:02:33 -0600 Subject: [PATCH] Add cls_sound --- Makefile.am | 39 ++- src/alg_sec.cpp | 51 +-- src/alg_sec.hpp | 134 ++++---- src/conf.cpp | 102 +++--- src/conf.hpp | 9 +- src/dbse.cpp | 14 +- src/motionplus.cpp | 134 ++++---- src/motionplus.hpp | 92 +----- src/sound.cpp | 793 +++++++++++++++++++++++---------------------- src/sound.hpp | 126 ++++++- src/util.cpp | 113 +++++-- src/util.hpp | 2 + 12 files changed, 841 insertions(+), 768 deletions(-) diff --git a/Makefile.am b/Makefile.am index c36e81b6..f9e840e8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -62,25 +62,36 @@ maintainer-clang: ./configure --with-clang-flags CC=clang CXX=clang++ LD=clang++ && $(MAKE) clean && $(MAKE) maintainer-check: - ./configure --with-developer-flags && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-libcam && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-opencv && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-mariadb && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-mysql && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-mariadb && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-sqlite3 && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-pgsql && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-v4l2 && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-webp && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-alsa && $(MAKE) clean && $(MAKE) - ./configure --with-developer-flags --without-fftw3 && $(MAKE) clean && $(MAKE) + ./configure --with-developer-flags && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-libcam && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-opencv && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-mariadb && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-mysql && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-mariadb && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-sqlite3 && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-pgsql && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-v4l2 && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-webp && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-alsa && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-pulse && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags --without-fftw3 && $(MAKE) clean && $(MAKE) -j6 ./configure --with-developer-flags \ --without-mysql \ --without-mariadb \ - && $(MAKE) clean && $(MAKE) + && $(MAKE) clean && $(MAKE) -j6 ./configure --with-developer-flags \ --without-mysql \ --without-mariadb \ --without-sqlite3 \ --without-pgsql \ - && $(MAKE) clean && $(MAKE) + && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags \ + --without-alsa \ + --without-pulse \ + && $(MAKE) clean && $(MAKE) -j6 + ./configure --with-developer-flags \ + --without-alsa \ + --without-pulse \ + --without-fftw3 \ + && $(MAKE) clean && $(MAKE) -j6 + diff --git a/src/alg_sec.cpp b/src/alg_sec.cpp index e1521a7b..6c4b4f5e 100644 --- a/src/alg_sec.cpp +++ b/src/alg_sec.cpp @@ -597,38 +597,35 @@ void cls_algsec::start_model() } } -#endif - /** Shut down the secondary detection components */ void cls_algsec::deinit() { - #ifdef HAVE_OPENCV - int waitcnt = 0; + int waitcnt = 0; - if (handler_finished == false) { - if (handler_stop == false) { - handler_stop = true; - while ((handler_stop) && (waitcnt <10)){ - SLEEP(1,0) - waitcnt++; - } - } - if (waitcnt == 10) { - MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO - ,_("Shutdown of secondary detector failed")); - pthread_kill(handler_thread.native_handle(), SIGVTALRM); - pthread_mutex_lock(&cam->motapp->global_lock); - cam->motapp->threads_running--; - pthread_mutex_unlock(&cam->motapp->global_lock); + if (handler_finished == false) { + if (handler_stop == false) { + handler_stop = true; + while ((handler_stop) && (waitcnt <10)){ + SLEEP(1,0) + waitcnt++; } } + if (waitcnt == 10) { + MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO + ,_("Shutdown of secondary detector failed")); + pthread_kill(handler_thread.native_handle(), SIGVTALRM); + pthread_mutex_lock(&cam->motapp->global_lock); + cam->motapp->threads_running--; + pthread_mutex_unlock(&cam->motapp->global_lock); + } + } - pthread_mutex_destroy(&mutex); - myfree(image_norm); - mydelete(params); - #endif + pthread_mutex_destroy(&mutex); + myfree(image_norm); + mydelete(params); } +#endif /*Invoke the secondary detetction method*/ void cls_algsec::detect() { @@ -678,17 +675,21 @@ void cls_algsec::detect() cls_algsec::cls_algsec(ctx_dev *p_cam) { - cam = p_cam; #ifdef HAVE_OPENCV + cam = p_cam; mythreadname_set("cv",cam->threadnr,cam->conf->device_name.c_str()); load_params(); start_model(); mythreadname_set("ml",cam->threadnr,cam->conf->device_name.c_str()); + #else + (void)p_cam; #endif } cls_algsec::~cls_algsec() { - deinit(); + #ifdef HAVE_OPENCV + deinit(); + #endif } diff --git a/src/alg_sec.hpp b/src/alg_sec.hpp index 2b70f8d3..7d2e20ac 100644 --- a/src/alg_sec.hpp +++ b/src/alg_sec.hpp @@ -40,74 +40,74 @@ class cls_algsec { pthread_mutex_t mutex; private: - ctx_dev *cam; - std::thread handler_thread; - bool handler_finished; - bool handler_stop; - bool in_process; - int frame_cnt; - int frame_missed; - int too_slow; - u_char *image_norm; - int width; - int height; - int cfg_framerate; - int cfg_log_level; - std::string cfg_target_dir; - - void deinit(); - void handler(); - void start_model(); - void load_params(); - void params_defaults(); - void params_model(); - void params_log(); - - void load_dnn(); - void load_haar(); - void detect_dnn(); - void detect_haar(); - void detect_hog(); - void get_image(cv::Mat &mat_dst); - void get_image_roi(cv::Mat &mat_src, cv::Mat &mat_dst); - void label_image(cv::Mat &mat_dst, double confidence, cv::Point classIdPoint); - void label_image(cv::Mat &mat_dst, std::vector &src_pos - , std::vector &src_weights); - void image_show(cv::Mat &mat_dst); - - std::string config; - ctx_params *params; - - std::string model_file; - int frame_interval; - - std::string image_type; - int rotate; - - double scalefactor; - double threshold; - - double hog_threshold_model; - int hog_winstride; - int hog_padding; - - int haar_minneighbors; - int haar_flags; - int haar_minsize; - int haar_maxsize; - - std::string dnn_config; - std::string dnn_framework; - std::string dnn_classes_file; - - int dnn_backend; - int dnn_target; - std::vector dnn_classes; - int dnn_width; - int dnn_height; - double dnn_scale; - #ifdef HAVE_OPENCV + ctx_dev *cam; + std::thread handler_thread; + bool handler_finished; + bool handler_stop; + bool in_process; + int frame_cnt; + int frame_missed; + int too_slow; + u_char *image_norm; + int width; + int height; + int cfg_framerate; + int cfg_log_level; + std::string cfg_target_dir; + + void deinit(); + void handler(); + void start_model(); + void load_params(); + void params_defaults(); + void params_model(); + void params_log(); + + void load_dnn(); + void load_haar(); + void detect_dnn(); + void detect_haar(); + void detect_hog(); + void get_image(cv::Mat &mat_dst); + void get_image_roi(cv::Mat &mat_src, cv::Mat &mat_dst); + void label_image(cv::Mat &mat_dst, double confidence, cv::Point classIdPoint); + void label_image(cv::Mat &mat_dst, std::vector &src_pos + , std::vector &src_weights); + void image_show(cv::Mat &mat_dst); + + std::string config; + ctx_params *params; + + std::string model_file; + int frame_interval; + + std::string image_type; + int rotate; + + double scalefactor; + double threshold; + + double hog_threshold_model; + int hog_winstride; + int hog_padding; + + int haar_minneighbors; + int haar_flags; + int haar_minsize; + int haar_maxsize; + + std::string dnn_config; + std::string dnn_framework; + std::string dnn_classes_file; + + int dnn_backend; + int dnn_target; + std::vector dnn_classes; + int dnn_width; + int dnn_height; + double dnn_scale; + cv::CascadeClassifier haar_cascade; /*Haar Cascade (if applicable) */ cv::HOGDescriptor hog; cv::dnn::Net net; diff --git a/src/conf.cpp b/src/conf.cpp index 3b52ce2c..3cfd8d87 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -16,12 +16,11 @@ * */ -#include -#include #include "motionplus.hpp" #include "util.hpp" #include "logger.hpp" #include "conf.hpp" +#include "sound.hpp" /*Configuration parameters */ ctx_parm config_parms[] = { @@ -3649,17 +3648,14 @@ void cls_config::camera_parm(ctx_motapp *motapp, std::string filename) } +/* Create default configuration file name*/ void cls_config::sound_filenm(ctx_motapp *motapp) { - int indx_snd, indx; + uint indx_snd, indx; std::string dirnm, fullnm; struct stat statbuf; size_t lstpos; - if (motapp->snd_list[motapp->snd_cnt-1]->conf->conf_filename != "") { - return; - } - lstpos = motapp->conf->conf_filename.find_last_of("/"); if (lstpos != std::string::npos) { lstpos++; @@ -3670,8 +3666,8 @@ void cls_config::sound_filenm(ctx_motapp *motapp) fullnm = ""; while (fullnm == "") { fullnm = dirnm + "sound" + std::to_string(indx_snd) + ".conf"; - for (indx=0;indxsnd_cnt;indx++) { - if (fullnm == motapp->snd_list[indx_snd]->conf->conf_filename) { + for (indx = 0; indxsnd_list.size(); indx++) { + if (fullnm == motapp->snd_list[indx]->conf->conf_filename) { fullnm = ""; } } @@ -3685,56 +3681,42 @@ void cls_config::sound_filenm(ctx_motapp *motapp) } } - motapp->snd_list[motapp->snd_cnt-1]->conf->conf_filename = fullnm; - + conf_filename = fullnm; } -void cls_config::sound_add(ctx_motapp *motapp) +void cls_config::sound_add(ctx_motapp *motapp, std::string fname, bool srcdir) { + struct stat statbuf; int indx; - std::string parm_val; + std::string parm_val, parm_nm; + cls_sound *snd_cls; - motapp->snd_cnt++; - motapp->snd_list = (ctx_dev **)myrealloc( - motapp->snd_list - , sizeof(ctx_dev *) * (uint)(motapp->snd_cnt + 1) - , "config_sound"); - - motapp->snd_list[motapp->snd_cnt-1] = new ctx_dev; - memset(motapp->snd_list[motapp->snd_cnt-1],0,sizeof(ctx_dev)); - motapp->snd_list[motapp->snd_cnt-1]->conf = new cls_config; - - motapp->snd_list[motapp->snd_cnt] = NULL; - motapp->snd_list[motapp->snd_cnt-1]->motapp = motapp; + snd_cls = new cls_sound(motapp); + snd_cls->conf = new cls_config; indx = 0; while (config_parms[indx].parm_name != "") { - if (mystrne(config_parms[indx].parm_name.c_str(),"device_id")) { - motapp->conf->edit_get(config_parms[indx].parm_name - , parm_val, config_parms[indx].parm_cat); - motapp->snd_list[motapp->snd_cnt-1]->conf->edit_set( - config_parms[indx].parm_name, parm_val); + parm_nm =config_parms[indx].parm_name; + if (parm_nm == "device_id") { + motapp->conf->edit_get(parm_nm, parm_val, config_parms[indx].parm_cat); + snd_cls->conf->edit_set(parm_nm, parm_val); } indx++; } - sound_filenm(motapp); + snd_cls->conf->from_conf_dir = srcdir; + snd_cls->conf->conf_filename = fname; -} - -void cls_config::sound_parm(ctx_motapp *motapp, std::string filename) -{ - struct stat statbuf; - - if (stat(filename.c_str(), &statbuf) != 0) { + if (fname == "") { + snd_cls->conf->sound_filenm(motapp); + } else if (stat(fname.c_str(), &statbuf) != 0) { MOTPLS_LOG(ALR, TYPE_ALL, SHOW_ERRNO - ,_("Sound config file %s not found"), filename.c_str()); - return; + ,_("Sound config file %s not found"), fname.c_str()); + } else { + snd_cls->conf->process(motapp); } - sound_add(motapp); - motapp->snd_list[motapp->snd_cnt-1]->conf->conf_filename = filename; - motapp->snd_list[motapp->snd_cnt-1]->conf->process(motapp); + motapp->snd_list.push_back(snd_cls); } @@ -3762,8 +3744,7 @@ void cls_config::config_dir_parm(ctx_motapp *motapp, std::string confdir) MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO ,_("Processing as sound config file %s") , file.c_str() ); - sound_parm(motapp, file); - motapp->snd_list[motapp->snd_cnt-1]->conf->from_conf_dir = true; + sound_add(motapp, file, true); } } } @@ -3816,7 +3797,7 @@ void cls_config::process(ctx_motapp *motapp) if ((parm_nm == "camera") && (motapp->conf == this)) { camera_parm(motapp, parm_vl); } else if ((parm_nm == "sound") && (motapp->conf == this)) { - sound_parm(motapp, parm_vl); + sound_add(motapp, parm_vl, false); } else if ((parm_nm == "config_dir") && (motapp->conf == this)){ config_dir_parm(motapp, parm_vl); } else if ((parm_nm != "camera") && (parm_nm != "sound") && @@ -3863,7 +3844,7 @@ void cls_config::parms_log_parm(std::string parm_nm, std::string parm_vl) void cls_config::parms_log(ctx_motapp *motapp) { - int i, indx; + uint i, indx; std::string parm_vl, parm_main, parm_nm; std::list parm_array; std::list::iterator it; @@ -3897,7 +3878,7 @@ void cls_config::parms_log(ctx_motapp *motapp) i++; } - for (indx=0; indxcam_cnt; indx++) { + for (indx=0; indx<(uint)motapp->cam_cnt; indx++) { MOTPLS_SHT(INF, TYPE_ALL, NO_ERRNO , _("Camera %d - Config file: %s") , motapp->cam_list[indx]->device_id @@ -3925,7 +3906,7 @@ void cls_config::parms_log(ctx_motapp *motapp) } } - for (indx=0; indxsnd_cnt; indx++) { + for (indx=0; indxsnd_list.size(); indx++) { MOTPLS_SHT(INF, TYPE_ALL, NO_ERRNO , _("Sound %d - Config file: %s") , motapp->snd_list[indx]->device_id @@ -3980,7 +3961,7 @@ void cls_config::parms_write_parms(FILE *conffile, std::string parm_nm void cls_config::parms_write_app(ctx_motapp *motapp) { - int i, indx; + uint i, indx; std::string parm_vl, parm_main, parm_nm; std::list parm_array; std::list::iterator it; @@ -4027,7 +4008,7 @@ void cls_config::parms_write_app(ctx_motapp *motapp) i++; } - for (indx=0; indxcam_cnt; indx++) { + for (indx=0; indx<(uint)motapp->cam_cnt; indx++) { if (motapp->cam_list[indx]->conf->from_conf_dir == false) { parms_write_parms(conffile, "camera" , motapp->cam_list[indx]->conf->conf_filename @@ -4035,7 +4016,7 @@ void cls_config::parms_write_app(ctx_motapp *motapp) } } - for (indx=0; indxsnd_cnt; indx++) { + for (indx=0; indxsnd_list.size(); indx++) { if (motapp->snd_list[indx]->conf->from_conf_dir == false) { parms_write_parms(conffile, "sound" , motapp->snd_list[indx]->conf->conf_filename @@ -4119,7 +4100,7 @@ void cls_config::parms_write_cam(ctx_motapp *motapp) void cls_config::parms_write_snd(ctx_motapp *motapp) { - int i, indx; + uint i, indx; std::string parm_vl, parm_main, parm_nm; std::list parm_array; std::list::iterator it; @@ -4131,7 +4112,7 @@ void cls_config::parms_write_snd(ctx_motapp *motapp) time_t now = time(0); strftime(timestamp, 32, "%Y-%m-%dT%H:%M:%S", localtime(&now)); - for (indx=0; indxsnd_cnt; indx++) { + for (indx=0; indxsnd_list.size(); indx++) { conffile = myfopen(motapp->snd_list[indx]->conf->conf_filename.c_str(), "we"); if (conffile == NULL) { MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO @@ -4189,7 +4170,7 @@ void cls_config::init(ctx_motapp *motapp) std::string filename; char path[PATH_MAX]; struct stat statbuf; - int indx; + uint indx; defaults(); @@ -4240,12 +4221,12 @@ void cls_config::init(ctx_motapp *motapp) cmdline(motapp); - for (indx=0; indxcam_cnt; indx++) { - motapp->cam_list[indx]->threadnr = indx; + for (indx=0; indx<(uint)motapp->cam_cnt; indx++) { + motapp->cam_list[indx]->threadnr = (int)indx; } - for (indx=0; indxsnd_cnt; indx++) { - motapp->snd_list[indx]->threadnr = indx + motapp->cam_cnt; + for (indx=0; indxsnd_list.size(); indx++) { + motapp->snd_list[indx]->threadnr = (int)indx + motapp->cam_cnt; } } @@ -4260,13 +4241,14 @@ void cls_config::deinit(ctx_motapp *motapp) } myfree(motapp->cam_list); motapp->cam_cnt = 0; - +/* for (indx=0; indxsnd_cnt; indx++) { delete motapp->snd_list[indx]->conf; delete motapp->snd_list[indx]; } myfree(motapp->snd_list); motapp->snd_cnt = 0; +*/ } diff --git a/src/conf.hpp b/src/conf.hpp index bacede2c..de34d70f 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -197,7 +197,6 @@ bool movie_extpipe_use; std::string movie_extpipe; - /* Timelapse movie configuration parameters */ int timelapse_interval; std::string timelapse_mode; @@ -275,7 +274,9 @@ bool snd_show; void camera_add(ctx_motapp *motapp); - void sound_add(ctx_motapp *motapp); + void sound_add(ctx_motapp *motapp, std::string fname, bool srcdir); + void sound_filenm(ctx_motapp *motapp); + void process(ctx_motapp *motapp); void edit_set(std::string parm_nm, std::string parm_val); void edit_get(std::string parm_nm, std::string &parm_val, enum PARM_CAT parm_cat); @@ -294,12 +295,8 @@ void cmdline(ctx_motapp *motapp); void defaults(); - void process(ctx_motapp *motapp); - void camera_filenm(ctx_motapp *motapp); void camera_parm(ctx_motapp *motapp, std::string filename); - void sound_filenm(ctx_motapp *motapp); - void sound_parm(ctx_motapp *motapp, std::string filename); void config_dir_parm(ctx_motapp *motapp, std::string confdir); void parms_log_parm(std::string parm_nm, std::string parm_vl); diff --git a/src/dbse.cpp b/src/dbse.cpp index 39b1fa7f..734041a5 100644 --- a/src/dbse.cpp +++ b/src/dbse.cpp @@ -23,13 +23,6 @@ #include "movie.hpp" #include "dbse.hpp" -static int dbse_sqlite3db_cb (void *ptr, int arg_nb, char **arg_val, char **col_nm) -{ - cls_dbse *dbse = (cls_dbse*)ptr; - dbse->sqlite3db_cb(arg_nb, arg_val, col_nm); - return 0; -} - #ifdef HAVE_DBSE void cls_dbse::cols_add_itm(std::string nm, std::string typ) @@ -203,6 +196,13 @@ void cls_dbse::sql_motpls(std::string &sql, std::string col_nm, std::string col_ #ifdef HAVE_SQLITE3DB +static int dbse_sqlite3db_cb (void *ptr, int arg_nb, char **arg_val, char **col_nm) +{ + cls_dbse *dbse = (cls_dbse*)ptr; + dbse->sqlite3db_cb(arg_nb, arg_val, col_nm); + return 0; +} + void cls_dbse::sqlite3db_exec(std::string sql) { int retcd; diff --git a/src/motionplus.cpp b/src/motionplus.cpp index 3a3a209c..0411f94b 100644 --- a/src/motionplus.cpp +++ b/src/motionplus.cpp @@ -34,12 +34,12 @@ volatile enum MOTPLS_SIGNAL motsignal; /** Process signals sent */ static void motpls_signal_process(ctx_motapp *motapp) { - int indx; + uint indx; switch(motsignal){ case MOTPLS_SIGNAL_ALARM: /* Trigger snapshot */ if (motapp->cam_list != NULL) { - for (indx=0; indxcam_cnt; indx++) { + for (indx=0; indx<(uint)motapp->cam_cnt; indx++) { if (motapp->cam_list[indx]->conf->snapshot_interval) { motapp->cam_list[indx]->snapshot = true; } @@ -48,7 +48,7 @@ static void motpls_signal_process(ctx_motapp *motapp) break; case MOTPLS_SIGNAL_USR1: /* Trigger the end of a event */ if (motapp->cam_list != NULL) { - for (indx=0; indxcam_cnt; indx++) { + for (indx=0; indx<(uint)motapp->cam_cnt; indx++) { motapp->cam_list[indx]->event_stop = true; } } @@ -56,29 +56,25 @@ static void motpls_signal_process(ctx_motapp *motapp) case MOTPLS_SIGNAL_SIGHUP: /* Reload the parameters and restart*/ motapp->reload_all = true; motapp->webu->wb_finish = true; - for (indx=0; indxcam_cnt; indx++) { + for (indx=0; indx<(uint)motapp->cam_cnt; indx++) { motapp->cam_list[indx]->event_stop = true; motapp->cam_list[indx]->finish_dev = true; motapp->cam_list[indx]->restart_dev = false; } - for (indx=0; indxsnd_cnt; indx++) { - motapp->snd_list[indx]->event_stop = true; - motapp->snd_list[indx]->finish_dev = true; - motapp->snd_list[indx]->restart_dev = false; + for (indx=0; indxsnd_list.size(); indx++) { + motapp->snd_list[indx]->handler_stop = true; } break; case MOTPLS_SIGNAL_SIGTERM: /* Quit application */ motapp->webu->wb_finish = true; - for (indx=0; indxcam_cnt; indx++) { + for (indx=0; indx<(uint)motapp->cam_cnt; indx++) { motapp->cam_list[indx]->event_stop = true; motapp->cam_list[indx]->finish_dev = true; motapp->cam_list[indx]->restart_dev = false; } - for (indx=0; indxsnd_cnt; indx++) { - motapp->snd_list[indx]->event_stop = true; - motapp->snd_list[indx]->finish_dev = true; - motapp->snd_list[indx]->restart_dev = false; + for (indx=0; indxsnd_list.size(); indx++) { + motapp->snd_list[indx]->handler_stop = true; } motapp->finish_all = true; default: @@ -500,42 +496,44 @@ static void motpls_shutdown(ctx_motapp *motapp) static void motpls_device_ids(ctx_motapp *motapp) { - /* Set the device id's on the ctx_dev. They must be unique */ - int indx, indx2; + uint indx, indx2, sndmx, cammx; int invalid_ids; + sndmx = (uint)motapp->snd_list.size(); + cammx = (uint)motapp->cam_cnt; + /* Defaults */ - for (indx=0; indxcam_cnt; indx++) { + for (indx=0; indxcam_list[indx]->conf->device_id != 0) { motapp->cam_list[indx]->device_id = motapp->cam_list[indx]->conf->device_id; } else { - motapp->cam_list[indx]->device_id = indx + 1; + motapp->cam_list[indx]->device_id = (int)indx + 1; } } - for (indx=0; indxsnd_cnt; indx++) { + for (indx=0; indxsnd_list[indx]->conf->device_id != 0) { motapp->snd_list[indx]->device_id = motapp->snd_list[indx]->conf->device_id; } else { - motapp->snd_list[indx]->device_id = motapp->cam_cnt + indx + 1; + motapp->snd_list[indx]->device_id = motapp->cam_cnt + (int)indx + 1; } } /*Check for unique values*/ invalid_ids = false; - for (indx=0; indxcam_cnt; indx++) { - for (indx2=indx+1; indx2cam_cnt; indx2++) { + for (indx=0; indxcam_list[indx]->device_id == motapp->cam_list[indx2]->device_id) { invalid_ids = true; } } - for (indx2=0; indx2snd_cnt; indx2++) { + for (indx2=0; indx2cam_list[indx]->device_id == motapp->snd_list[indx2]->device_id) { invalid_ids = true; } } } - for (indx=0; indxsnd_cnt; indx++) { - for (indx2=indx+1; indx2snd_cnt; indx2++) { + for (indx=0; indxsnd_list[indx]->device_id == motapp->snd_list[indx2]->device_id) { invalid_ids = true; } @@ -545,11 +543,11 @@ static void motpls_device_ids(ctx_motapp *motapp) if (invalid_ids) { MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO,_("Device IDs are not unique.")); MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO,_("Falling back to sequence numbers")); - for (indx=0; indxcam_cnt; indx++) { - motapp->cam_list[indx]->device_id = indx + 1; + for (indx=0; indxcam_list[indx]->device_id = (int)indx + 1; } - for (indx=0; indxsnd_cnt; indx++) { - motapp->snd_list[indx]->device_id = motapp->cam_cnt + indx + 1; + for (indx=0; indxsnd_list[indx]->device_id = motapp->cam_cnt + (int)indx + 1; } } @@ -677,23 +675,6 @@ static void motpls_start_thread_cam(ctx_dev *cam) } -static void motpls_start_thread_snd(ctx_dev *snd) -{ - int retcd; - pthread_attr_t thread_attr; - - pthread_attr_init(&thread_attr); - pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); - - snd->restart_dev = true; - retcd = pthread_create(&snd->thread_id, &thread_attr, &snd_loop, snd); - if (retcd != 0) { - MOTPLS_LOG(WRN, TYPE_ALL, NO_ERRNO,_("Unable to start sound thread.")); - } - pthread_attr_destroy(&thread_attr); - -} - static void motpls_restart(ctx_motapp *motapp) { @@ -712,7 +693,7 @@ static void motpls_restart(ctx_motapp *motapp) } /* Check for whether any cams are locked */ -static void motpls_watchdog(ctx_motapp *motapp, int camindx) +static void motpls_watchdog(ctx_motapp *motapp, uint camindx) { int indx; @@ -801,17 +782,17 @@ static void motpls_watchdog(ctx_motapp *motapp, int camindx) static int motpls_check_threadcount(ctx_motapp *motapp) { - int thrdcnt, indx; + uint thrdcnt, indx; thrdcnt = 0; - for (indx=0; indxcam_cnt; indx++) { + for (indx=0; indx<(uint)motapp->cam_cnt; indx++) { if (motapp->cam_list[indx]->running_dev || motapp->cam_list[indx]->restart_dev) { thrdcnt++; } } - for (indx=0; indxsnd_cnt; indx++) { - if (motapp->snd_list[indx]->running_dev || motapp->snd_list[indx]->restart_dev) { + for (indx=0; indxsnd_list.size(); indx++) { + if (motapp->snd_list[indx]->handler_finished == false) { thrdcnt++; } } @@ -838,9 +819,6 @@ static void motpls_init(ctx_motapp *motapp, int argc, char *argv[]) motapp->cam_list = (ctx_dev **)mymalloc(sizeof(ctx_dev *)); motapp->cam_list[0] = nullptr; - motapp->snd_list = (ctx_dev **)mymalloc(sizeof(ctx_dev *)); - motapp->snd_list[0] = nullptr; - motapp->threads_running = 0; motapp->finish_all = false; motapp->restart_all = false; @@ -850,7 +828,6 @@ static void motpls_init(ctx_motapp *motapp, int argc, char *argv[]) motapp->cam_add = false; motapp->cam_delete = -1; motapp->cam_cnt = 0; - motapp->snd_cnt = 0; motapp->conf = nullptr; motapp->dbse = nullptr; @@ -872,7 +849,7 @@ static void motpls_init(ctx_motapp *motapp, int argc, char *argv[]) static void motpls_deinit(ctx_motapp *motapp) { - int indx; + uint indx; motpls_av_deinit(); @@ -883,16 +860,12 @@ static void motpls_deinit(ctx_motapp *motapp) mydelete(motapp->cam_list[indx]->conf); mydelete(motapp->cam_list[indx]); indx++; - }; + } myfree(motapp->cam_list); - indx = 0; - while (motapp->snd_list[indx] != nullptr) { - mydelete(motapp->snd_list[indx]->conf); + for (indx = 0; indx < motapp->snd_list.size();indx++) { mydelete(motapp->snd_list[indx]); - indx++; - }; - myfree(motapp->snd_list); + } pthread_key_delete(tls_key_threadnr); pthread_mutex_destroy(&motapp->global_lock); @@ -994,7 +967,7 @@ static void motpls_cam_delete(ctx_motapp *motapp) /** Main entry point of MotionPlus. */ int main (int argc, char **argv) { - int indx; + uint indx; ctx_motapp *motapp; motapp = new ctx_motapp; @@ -1003,24 +976,24 @@ int main (int argc, char **argv) motpls_init(motapp, argc, argv); - while (true) { + MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO + ,_("Motionplus pid: %d"), getpid()); + + while (true) { if (motapp->restart_all) { motpls_restart(motapp); } - for (indx=0; indxcam_cnt; indx++) { + for (indx=0; indx<(uint)motapp->cam_cnt; indx++) { motpls_start_thread_cam(motapp->cam_list[indx]); } - - for (indx=0; indxsnd_cnt; indx++) { - motpls_start_thread_snd(motapp->snd_list[indx]); + for (indx=0; indxsnd_list.size(); indx++) { + motapp->snd_list[indx]->start(); } - MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO - ,_("Motionplus pid: %d"), getpid()); - - if ((motapp->cam_cnt == 0) && (motapp->snd_cnt ==0)) { + if ((motapp->cam_cnt == 0) && + (motapp->snd_list.size() ==0)) { MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO , _("No camera or sound configuration files specified.")); MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO @@ -1034,7 +1007,7 @@ int main (int argc, char **argv) break; } - for (indx=0; indxcam_cnt; indx++) { + for (indx=0; indx<(uint)motapp->cam_cnt; indx++) { /* Check if threads wants to be restarted */ if ((motapp->cam_list[indx]->running_dev == false) && (motapp->cam_list[indx]->restart_dev == true)) { @@ -1045,13 +1018,20 @@ int main (int argc, char **argv) } motpls_watchdog(motapp, indx); } - for (indx=0; indxsnd_cnt; indx++) { - if ((motapp->snd_list[indx]->running_dev == false) && - (motapp->snd_list[indx]->restart_dev == true)) { + for (indx=0; indxsnd_list.size(); indx++) { + if ((motapp->snd_list[indx]->handler_finished == true) && + (motapp->snd_list[indx]->restart == true)) { MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO ,_("MotionPlus sound %d restart") , motapp->snd_list[indx]->device_id); - motpls_start_thread_snd(motapp->snd_list[indx]); + motapp->snd_list[indx]->start(); + } + if ((motapp->snd_list[indx]->handler_finished == false) && + (motapp->snd_list[indx]->handler_stop == true)) { + MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO + ,_("MotionPlus stop sound %d") + , motapp->snd_list[indx]->device_id); + motapp->snd_list[indx]->stop(); } } diff --git a/src/motionplus.hpp b/src/motionplus.hpp index 6e4a9aa7..e59c5825 100644 --- a/src/motionplus.hpp +++ b/src/motionplus.hpp @@ -60,6 +60,7 @@ #include #include + #if defined(HAVE_PTHREAD_NP_H) #include #endif @@ -116,6 +117,7 @@ struct ctx_motapp; struct ctx_images; struct ctx_image_data; +class cls_sound; class cls_algsec; class cls_alg; class cls_config; @@ -155,15 +157,6 @@ class cls_webu_stream; #define AVGCNT 30 -/* - * Structure to hold images information - * The idea is that this should have all information about a picture e.g. diffs, timestamp etc. - * The exception is the label information, it uses a lot of memory - * When the image is stored all texts motion marks etc. is written to the image - * so we only have to send it out when/if we want. - */ - -/* A image can have detected motion in it, but dosn't trigger an event, if we use minimum_motion_frames */ #define IMAGE_MOTION 1 #define IMAGE_TRIGGER 2 #define IMAGE_SAVE 4 @@ -207,10 +200,10 @@ enum CAPTURE_RESULT { }; enum DEVICE_STATUS { - STATUS_CLOSED, /* Camera is closed */ + STATUS_CLOSED, /* Device is closed */ STATUS_INIT, /* First time initialize */ STATUS_RESET, /* Clean up and re-initialize */ - STATUS_OPENED /* Successfully started the camera */ + STATUS_OPENED /* Successfully started the device */ }; enum TIMELAPSE_TYPE { @@ -387,74 +380,6 @@ struct ctx_stream { ctx_stream_data secondary; /* Copy of the image to use for web stream*/ }; -struct ctx_snd_alert { - int alert_id; /* Id number for the alert*/ - std::string alert_nm; /* Name of the alert*/ - int volume_level; /* Volume level required to consider the sample*/ - int volume_count; /* For each sample, number of times required to exceed volumne level*/ - double freq_low; /* Lowest frequency for detecting this alert*/ - double freq_high; /* Highest frequency for detecting this alert*/ - int trigger_count; /* Count of how many times it has been triggered so far*/ - int trigger_threshold; /* How many times does it need to be triggered before an event*/ - timespec trigger_time; /* The last time the trigger was invoked */ - int trigger_duration; /* Min. duration to trigger a new /event */ -}; - -struct ctx_snd_alsa { - #ifdef HAVE_ALSA - int device_id; - std::string device_nm; - snd_pcm_t *pcm_dev; - snd_pcm_info_t *pcm_info; - int card_id; - snd_ctl_card_info_t *card_info; - snd_ctl_t *ctl_hdl; - #else - int dummy; - #endif -}; - -struct ctx_snd_pulse { - #ifdef HAVE_PULSE - pa_simple *dev; - #else - int dummy; - #endif -}; - -struct ctx_snd_fftw { - #ifdef HAVE_FFTW3 - fftw_plan ff_plan; - double *ff_in; - fftw_complex *ff_out; - int bin_max; - int bin_min; - double bin_size; - #else - int dummy; - #endif -}; - -struct ctx_snd_info { - std::string source; /* Source string in ALSA format e.g. hw:1,0*/ - int sample_rate; /* Sample rate of sound source*/ - int channels; /* Number of audio channels */ - std::list alerts; /* list of sound alert criteria */ - int vol_min; /* The minimum volume from alerts*/ - int vol_max; /* Maximum volume of sample*/ - int vol_count; /* Number of times volumne exceeded user specified volume level */ - int16_t *buffer; - int buffer_size; - int frames; - std::string pulse_server; - std::string trig_freq; - std::string trig_nbr; - std::string trig_nm; - ctx_params *params; /* Device parameters*/ - ctx_snd_fftw *snd_fftw; /* fftw for sound*/ - ctx_snd_alsa *snd_alsa; /* Alsa device for sound*/ - ctx_snd_pulse *snd_pulse; /* PulseAudio for sound*/ -}; struct ctx_dev { ctx_motapp *motapp; @@ -474,7 +399,6 @@ struct ctx_dev { cls_movie *movie_extpipe; ctx_stream stream; - ctx_snd_info *snd_info; cls_draw *draw; cls_netcam *netcam; @@ -556,11 +480,14 @@ struct ctx_dev { }; -/* ctx_motapp for whole motion application including all the cameras */ +typedef std::vector vec_snd; +typedef vec_snd::iterator it_snd; + struct ctx_motapp { ctx_dev **cam_list; - ctx_dev **snd_list; + vec_snd snd_list; + pthread_mutex_t global_lock; volatile int threads_running; @@ -575,7 +502,6 @@ struct ctx_motapp { bool pause; cls_config *conf; int cam_cnt; - int snd_cnt; ctx_all_sizes *all_sizes; cls_webu *webu; cls_dbse *dbse; diff --git a/src/sound.cpp b/src/sound.cpp index c4b85f0f..32bbeaab 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -23,38 +23,27 @@ #include "util.hpp" #include "sound.hpp" -#if defined(HAVE_FFTW3) && (defined(HAVE_ALSA) || defined(HAVE_PULSE)) - -static float HammingWindow(int n1, int N2){ - return 0.54F - 0.46F * (float)(cos((2 * M_PI * n1)) / (N2 - 1)); -} -static float HannWindow(int n1, int N2){ - return 0.5F * (float)(1 - (cos(2 * M_PI * n1 * N2))); -} - -static void snd_init_values(ctx_dev *snd) +void cls_sound::init_values() { - ctx_snd_info *info = snd->snd_info; - - snd->snd_info->snd_fftw->bin_max = 0; - snd->snd_info->snd_fftw->bin_min = 0; - snd->snd_info->snd_fftw->bin_size = 0; - snd->snd_info->snd_fftw->ff_in = NULL; - snd->snd_info->snd_fftw->ff_out = NULL; - snd->snd_info->snd_fftw->ff_plan = NULL; - - info->sample_rate = 0; - info->channels = 0; - info->vol_count = 0; - info->vol_max = 0; - info->vol_min = 9999; - info->buffer = NULL; - info->buffer_size = 0; - info->pulse_server = ""; - + #ifdef HAVE_FFTW3 + snd_info->snd_fftw->bin_max = 0; + snd_info->snd_fftw->bin_min = 0; + snd_info->snd_fftw->bin_size = 0; + snd_info->snd_fftw->ff_in = NULL; + snd_info->snd_fftw->ff_out = NULL; + snd_info->snd_fftw->ff_plan = NULL; + #endif + snd_info->sample_rate = 0; + snd_info->channels = 0; + snd_info->vol_count = 0; + snd_info->vol_max = 0; + snd_info->vol_min = 9999; + snd_info->buffer = NULL; + snd_info->buffer_size = 0; + snd_info->pulse_server = ""; } -static void snd_init_alerts(ctx_snd_alert *tmp_alert) +void cls_sound::init_alerts(ctx_snd_alert *tmp_alert) { tmp_alert->alert_id = 0; tmp_alert->alert_nm = ""; @@ -69,19 +58,18 @@ static void snd_init_alerts(ctx_snd_alert *tmp_alert) } -static void snd_edit_alerts(ctx_dev *snd) +void cls_sound::edit_alerts() { - ctx_snd_info *info = snd->snd_info; std::list::iterator it_a0; std::list::iterator it_a1; int indx, id_chk, id_cnt; bool validids; validids = true; - for (it_a0=info->alerts.begin(); it_a0!=info->alerts.end(); it_a0++) { + for (it_a0=snd_info->alerts.begin(); it_a0!=snd_info->alerts.end(); it_a0++) { id_chk = it_a0->alert_id; id_cnt = 0; - for (it_a1=info->alerts.begin(); it_a1!=info->alerts.end(); it_a1++) { + for (it_a1=snd_info->alerts.begin(); it_a1!=snd_info->alerts.end(); it_a1++) { if (id_chk == it_a1->alert_id) { id_cnt++; } @@ -95,18 +83,18 @@ static void snd_edit_alerts(ctx_dev *snd) MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Sound alert ids must be unique."); MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Creating new sound alert ids."); indx = 0; - for (it_a0=info->alerts.begin(); it_a0!=info->alerts.end(); it_a0++) { + for (it_a0=snd_info->alerts.begin(); it_a0!=snd_info->alerts.end(); it_a0++) { it_a0->alert_id = indx; indx++; } } - for (it_a0=info->alerts.begin(); it_a0!=info->alerts.end(); it_a0++) { + for (it_a0=snd_info->alerts.begin(); it_a0!=snd_info->alerts.end(); it_a0++) { if (it_a0->alert_nm == "") { it_a0->alert_nm = "sound_alert" + std::to_string(it_a0->alert_id); } - if (it_a0->volume_level < info->vol_min) { - info->vol_min = it_a0->volume_level; + if (it_a0->volume_level < snd_info->vol_min) { + snd_info->vol_min = it_a0->volume_level; } MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, "Sound Alert Parameters:"); MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO, " alert_id: %d",it_a0->alert_id); @@ -121,22 +109,21 @@ static void snd_edit_alerts(ctx_dev *snd) } -static void snd_load_alerts(ctx_dev *snd) +void cls_sound::load_alerts() { - ctx_snd_info *info = snd->snd_info; ctx_snd_alert tmp_alert; std::list parm_val; std::list::iterator it_a; ctx_params *tmp_params; p_it it; - snd->conf->edit_get("snd_alerts", parm_val, PARM_CAT_18); + conf->edit_get("snd_alerts", parm_val, PARM_CAT_18); tmp_params = new ctx_params; for (it_a=parm_val.begin(); it_a!=parm_val.end(); it_a++) { tmp_params->update_params = true; util_parms_parse(tmp_params,"snd_alerts", it_a->c_str()); - snd_init_alerts(&tmp_alert); + init_alerts(&tmp_alert); for (it = tmp_params->params_array.begin(); it != tmp_params->params_array.end(); it++) { if (it->param_name == "alert_id") { @@ -164,29 +151,28 @@ static void snd_load_alerts(ctx_dev *snd) tmp_alert.trigger_duration = mtoi(it->param_value); } } - info->alerts.push_back(tmp_alert); + snd_info->alerts.push_back(tmp_alert); } delete tmp_params; - snd_edit_alerts(snd); + edit_alerts(); } -static void snd_load_params(ctx_dev *snd) +void cls_sound::load_params() { - ctx_snd_info *info = snd->snd_info; p_it it; p_lst *lst; - snd->snd_info->params->update_params = true; - util_parms_parse(snd->snd_info->params,"snd_params", snd->conf->snd_params); + snd_info->params->update_params = true; + util_parms_parse(snd_info->params,"snd_params", conf->snd_params); - util_parms_add_default(snd->snd_info->params,"source","alsa"); - util_parms_add_default(snd->snd_info->params,"channels","1"); - util_parms_add_default(snd->snd_info->params,"frames","2048"); - util_parms_add_default(snd->snd_info->params,"sample_rate","44100"); + util_parms_add_default(snd_info->params,"source","alsa"); + util_parms_add_default(snd_info->params,"channels","1"); + util_parms_add_default(snd_info->params,"frames","2048"); + util_parms_add_default(snd_info->params,"sample_rate","44100"); - lst = &snd->snd_info->params->params_array; + lst = &snd_info->params->params_array; for (it = lst->begin(); it != lst->end(); it++) { MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "%s : %s" @@ -195,29 +181,28 @@ static void snd_load_params(ctx_dev *snd) for (it = lst->begin(); it != lst->end(); it++) { if (it->param_name == "source") { - info->source = it->param_value; + snd_info->source = it->param_value; } if (it->param_name == "channels") { - info->channels = mtoi(it->param_value); + snd_info->channels = mtoi(it->param_value); } if (it->param_name == "frames") { - info->frames = mtoi(it->param_value); + snd_info->frames = mtoi(it->param_value); } if (it->param_name == "sample_rate") { - info->sample_rate = mtoi(it->param_value); + snd_info->sample_rate = mtoi(it->param_value); } if (it->param_name == "pulse_server") { - info->pulse_server = it->param_value; + snd_info->pulse_server = it->param_value; } } } -/************ Start ALSA *******************/ -#ifdef HAVE_ALSA +#ifdef HAVE_ALSA /************ Start ALSA *******************/ -static void snd_alsa_list_subdev(ctx_dev *snd) +void cls_sound::alsa_list_subdev() { - ctx_snd_alsa *alsa = snd->snd_info->snd_alsa; + ctx_snd_alsa *alsa = snd_info->snd_alsa; int indx, retcd, cnt; MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Card %i(%s): %s [%s]") @@ -250,9 +235,9 @@ static void snd_alsa_list_subdev(ctx_dev *snd) } -static void snd_alsa_list_card(ctx_dev *snd) +void cls_sound::alsa_list_card() { - ctx_snd_alsa *alsa = snd->snd_info->snd_alsa; + ctx_snd_alsa *alsa = snd_info->snd_alsa; int retcd; retcd = snd_ctl_card_info(alsa->ctl_hdl, alsa->card_info); @@ -277,7 +262,7 @@ static void snd_alsa_list_card(ctx_dev *snd) snd_pcm_info_set_stream(alsa->pcm_info, SND_PCM_STREAM_CAPTURE); retcd = snd_ctl_pcm_info(alsa->ctl_hdl, alsa->pcm_info); if (retcd == 0) { - snd_alsa_list_subdev(snd); + alsa_list_subdev(); } else if (retcd != -ENOENT){ MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("control digital audio info (%i): %s") @@ -291,12 +276,12 @@ static void snd_alsa_list_card(ctx_dev *snd) } -static void snd_alsa_list(ctx_dev *snd) +void cls_sound::alsa_list() { - ctx_snd_alsa *alsa = snd->snd_info->snd_alsa; + ctx_snd_alsa *alsa = snd_info->snd_alsa; int retcd; - if (snd->device_status == STATUS_CLOSED) { + if (device_status == STATUS_CLOSED) { return; } @@ -308,9 +293,7 @@ static void snd_alsa_list(ctx_dev *snd) if ((retcd < 0) || (alsa->card_id == -1)) { MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("no soundcards found...")); - snd->device_status = STATUS_CLOSED; - snd->restart_dev = false; - snd->finish_dev = true; + device_status = STATUS_CLOSED; return; } @@ -320,7 +303,7 @@ static void snd_alsa_list(ctx_dev *snd) alsa->device_nm="hw:"+std::to_string(alsa->card_id); retcd = snd_ctl_open(&alsa->ctl_hdl, alsa->device_nm.c_str(), 0); if (retcd == 0) { - snd_alsa_list_card(snd); + alsa_list_card(); snd_ctl_close(alsa->ctl_hdl); } else { MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO, _("control open (%i): %s") @@ -331,26 +314,25 @@ static void snd_alsa_list(ctx_dev *snd) } -static void snd_alsa_start(ctx_dev *snd) +void cls_sound::alsa_start() { - ctx_snd_alsa *alsa = snd->snd_info->snd_alsa; - ctx_snd_info *info = snd->snd_info; + ctx_snd_alsa *alsa = snd_info->snd_alsa; snd_pcm_hw_params_t *hw_params; snd_pcm_uframes_t frames_per; snd_pcm_format_t actl_sndfmt; unsigned int actl_rate, smpl_rate; int retcd; - frames_per = (uint)info->frames; - smpl_rate = (unsigned int)info->sample_rate; + frames_per = (uint)snd_info->frames; + smpl_rate = (unsigned int)snd_info->sample_rate; retcd = snd_pcm_open(&alsa->pcm_dev - , snd->conf->snd_device.c_str(), SND_PCM_STREAM_CAPTURE, 0); + , conf->snd_device.c_str(), SND_PCM_STREAM_CAPTURE, 0); if (retcd < 0) { MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_open device %s (%s)") - , snd->conf->snd_device.c_str(), snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + , conf->snd_device.c_str(), snd_strerror (retcd)); + device_status = STATUS_CLOSED; return; } @@ -359,7 +341,7 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params_malloc(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -368,7 +350,7 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params_any(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -378,7 +360,7 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params_set_access(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -388,7 +370,7 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params_set_format(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -398,17 +380,17 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params_set_rate_near(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } retcd = snd_pcm_hw_params_set_channels(alsa->pcm_dev - , hw_params, (uint)info->channels); + , hw_params, (uint)snd_info->channels); if (retcd < 0) { MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params_set_channels(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -418,7 +400,7 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params_set_period_size_near(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -427,7 +409,7 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -438,7 +420,7 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_prepare(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -448,7 +430,7 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params_get_format(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -457,7 +439,7 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params_get_rate(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -466,7 +448,7 @@ static void snd_alsa_start(ctx_dev *snd) MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO , _("error: snd_pcm_hw_params_get_period_size(%s)") , snd_strerror (retcd)); - snd->device_status = STATUS_CLOSED; + device_status = STATUS_CLOSED; return; } @@ -483,172 +465,152 @@ static void snd_alsa_start(ctx_dev *snd) /*************************************************************/ /** allocate and initialize the sound buffers */ /*************************************************************/ - info->frames = (int)frames_per; - info->buffer_size = info->frames * 2; - info->buffer = (int16_t*)mymalloc((uint)info->buffer_size * sizeof(int16_t)); - memset(info->buffer, 0x00, (uint)info->buffer_size * sizeof(int16_t)); + snd_info->frames = (int)frames_per; + snd_info->buffer_size = snd_info->frames * 2; + snd_info->buffer = (int16_t*)mymalloc( + (uint)snd_info->buffer_size * sizeof(int16_t)); + memset(snd_info->buffer, 0x00 + , (uint)snd_info->buffer_size * sizeof(int16_t)); MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Started."); - snd->device_status =STATUS_OPENED; + device_status =STATUS_OPENED; } -#endif - -static void snd_alsa_init(ctx_dev *snd) +void cls_sound::alsa_init() { - #ifdef HAVE_ALSA - ctx_snd_alsa *alsa = snd->snd_info->snd_alsa; + ctx_snd_alsa *alsa = snd_info->snd_alsa; - alsa->pcm_dev = NULL; - alsa->pcm_info = NULL; - alsa->card_id = -1; - alsa->card_info = NULL; - alsa->pcm_dev = NULL; - alsa->ctl_hdl = NULL; - alsa->card_info = NULL; - alsa->card_id = 0; - alsa->pcm_info = NULL; - alsa->device_nm = ""; - alsa->device_id = 0; + if (snd_info->source != "alsa") { + return; + } - snd_alsa_list(snd); - snd_alsa_start(snd); - #else - snd->device_status = STATUS_CLOSED; - snd->finish_dev = true; - snd->restart_dev = false; - #endif + alsa->pcm_dev = NULL; + alsa->pcm_info = NULL; + alsa->card_id = -1; + alsa->card_info = NULL; + alsa->pcm_dev = NULL; + alsa->ctl_hdl = NULL; + alsa->card_info = NULL; + alsa->card_id = 0; + alsa->pcm_info = NULL; + alsa->device_nm = ""; + alsa->device_id = 0; + + alsa_list(); + alsa_start(); } -static void snd_alsa_capture(ctx_dev *snd) +void cls_sound::alsa_capture() { - #ifdef HAVE_ALSA - ctx_snd_info *info = snd->snd_info; - ctx_snd_alsa *alsa = snd->snd_info->snd_alsa; - long int retcd; + ctx_snd_alsa *alsa = snd_info->snd_alsa; + long int retcd; - retcd = snd_pcm_readi(alsa->pcm_dev, info->buffer, (uint)info->frames); - if (retcd != info->frames) { - MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO - , _("error: read from audio interface failed (%s)") - , snd_strerror((int)retcd)); - snd->device_status = STATUS_CLOSED; - snd->finish_dev = true; - snd->restart_dev = false; - } - #else - snd->device_status = STATUS_CLOSED; - snd->finish_dev = true; - snd->restart_dev = false; - #endif + if (snd_info->source != "alsa") { + return; + } + retcd = snd_pcm_readi(alsa->pcm_dev + , snd_info->buffer, (uint)snd_info->frames); + if (retcd != snd_info->frames) { + MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO + , _("error: read from audio interface failed (%s)") + , snd_strerror((int)retcd)); + device_status = STATUS_CLOSED; + } } -static void snd_alsa_cleanup(ctx_dev *snd) +void cls_sound::alsa_cleanup() { - #ifdef HAVE_ALSA - if (snd->snd_info->snd_alsa->pcm_dev != NULL) { - snd_pcm_close(snd->snd_info->snd_alsa->pcm_dev); - snd_config_update_free_global(); - } - #else - snd->device_status = STATUS_CLOSED; - snd->finish_dev = true; - snd->restart_dev = false; - #endif -} -/************ End ALSA *******************/ - -/************ Start PULSE *******************/ -static void snd_pulse_init(ctx_dev *snd) -{ - #ifdef HAVE_PULSE - ctx_snd_info *info = snd->snd_info; - pa_sample_spec specs; - int errcd; - - specs.format = PA_SAMPLE_S16LE; - specs.rate = (uint32_t)info->sample_rate; - specs.channels = (uint8_t)info->channels; - - snd->snd_info->snd_pulse->dev = NULL; - snd->snd_info->snd_pulse->dev = pa_simple_new( - (info->pulse_server=="" ? NULL : info->pulse_server.c_str()) - , "motionplus", PA_STREAM_RECORD - , (snd->conf->snd_device=="" ? NULL : snd->conf->snd_device.c_str()) - , "motionplus", &specs, NULL, NULL, &errcd); - if (snd->snd_info->snd_pulse->dev == NULL) { - MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO - , _("Error opening pulse (%s)") - , pa_strerror(errcd)); - snd->device_status = STATUS_CLOSED; - snd->finish_dev = true; - snd->restart_dev = false; - return; - } - info->buffer_size = info->frames * 2; - info->buffer = (int16_t*)mymalloc((uint)info->buffer_size * sizeof(int16_t)); - memset(info->buffer, 0x00, (uint)info->buffer_size * sizeof(int16_t)); - - MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Started."); - snd->device_status =STATUS_OPENED; - - #else - snd->device_status = STATUS_CLOSED; - snd->finish_dev = true; - snd->restart_dev = false; - #endif + if (snd_info->source != "alsa") { + return; + } + if (snd_info->snd_alsa->pcm_dev != NULL) { + snd_pcm_close(snd_info->snd_alsa->pcm_dev); + snd_config_update_free_global(); + } } -static void snd_pulse_capture(ctx_dev *snd) -{ - #ifdef HAVE_PULSE - ctx_snd_info *info = snd->snd_info; - ctx_snd_pulse *pulse = snd->snd_info->snd_pulse; - int errcd, retcd; +#endif /************ End ALSA *******************/ + +#ifdef HAVE_PULSE /************ Start PULSE *******************/ + +void cls_sound::pulse_init() +{ + pa_sample_spec specs; + int errcd; + + if (snd_info->source != "pulse") { + return; + } + + specs.format = PA_SAMPLE_S16LE; + specs.rate = (uint32_t)snd_info->sample_rate; + specs.channels = (uint8_t)snd_info->channels; + + snd_info->snd_pulse->dev = NULL; + snd_info->snd_pulse->dev = pa_simple_new( + (snd_info->pulse_server=="" ? NULL : snd_info->pulse_server.c_str()) + , "motionplus", PA_STREAM_RECORD + , (conf->snd_device=="" ? NULL : conf->snd_device.c_str()) + , "motionplus", &specs, NULL, NULL, &errcd); + if (snd_info->snd_pulse->dev == NULL) { + MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO + , _("Error opening pulse (%s)") + , pa_strerror(errcd)); + device_status = STATUS_CLOSED; + return; + } + snd_info->buffer_size = snd_info->frames * 2; + snd_info->buffer = (int16_t*)mymalloc( + (uint)snd_info->buffer_size * sizeof(int16_t)); + memset(snd_info->buffer, 0x00 + , (uint)snd_info->buffer_size * sizeof(int16_t)); + + MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Started."); + device_status =STATUS_OPENED; - retcd = pa_simple_read(pulse->dev, info->buffer - , (uint)info->buffer_size, &errcd); - if (retcd < 0) { - MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO - , _("Error capturing PulseAudio (%s)") - , pa_strerror(errcd)); - snd->device_status = STATUS_CLOSED; - snd->finish_dev = true; - snd->restart_dev = false; - } - #else - snd->device_status = STATUS_CLOSED; - snd->finish_dev = true; - snd->restart_dev = false; - #endif } -static void snd_pulse_cleanup(ctx_dev *snd) +void cls_sound::pulse_capture() { - #ifdef HAVE_PULSE - if (snd->snd_info->snd_pulse->dev != NULL) { - pa_simple_free(snd->snd_info->snd_pulse->dev); - } - #else - snd->device_status = STATUS_CLOSED; - snd->finish_dev = true; - snd->restart_dev = false; - #endif + ctx_snd_pulse *pulse = snd_info->snd_pulse; + int errcd, retcd; + + if (snd_info->source != "pulse") { + return; + } + + retcd = pa_simple_read(pulse->dev, snd_info->buffer + , (uint)snd_info->buffer_size, &errcd); + if (retcd < 0) { + MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO + , _("Error capturing PulseAudio (%s)") + , pa_strerror(errcd)); + device_status = STATUS_CLOSED; + } } -/************ End PULSE *******************/ - - -static void snd_fftw_open(ctx_dev *snd) +void cls_sound::pulse_cleanup() { - ctx_snd_fftw *fftw = snd->snd_info->snd_fftw; - ctx_snd_info *info = snd->snd_info; + if (snd_info->source != "pulse") { + return; + } + + if (snd_info->snd_pulse->dev != NULL) { + pa_simple_free(snd_info->snd_pulse->dev); + } +} + +#endif /************ End PULSE *******************/ + +#ifdef HAVE_FFTW3 /************ Start FFTW3 *******************/ + +void cls_sound::fftw_open() +{ + ctx_snd_fftw *fftw = snd_info->snd_fftw; int indx; - if (snd->device_status == STATUS_CLOSED) { - snd->finish_dev = true; - snd->restart_dev = false; + if (device_status == STATUS_CLOSED) { return; } @@ -656,95 +618,31 @@ static void snd_fftw_open(ctx_dev *snd) , _("Opening FFTW plan")); fftw->ff_in = (double*) fftw_malloc( - sizeof(fftw_complex) * (uint)info->frames); + sizeof(fftw_complex) * (uint)snd_info->frames); fftw->ff_out = (fftw_complex*) fftw_malloc( - sizeof(fftw_complex) * (uint)info->frames); + sizeof(fftw_complex) * (uint)snd_info->frames); fftw->ff_plan = fftw_plan_dft_r2c_1d( - info->frames, fftw->ff_in, fftw->ff_out, FFTW_MEASURE); + snd_info->frames, fftw->ff_in, fftw->ff_out, FFTW_MEASURE); - for (indx=0; indxframes; indx++) { + for (indx=0; indxframes; indx++) { fftw->ff_in[indx] = 0; } fftw->bin_min = 1; - fftw->bin_max = (info->frames / 2); - fftw->bin_size = ((float)info->sample_rate / (float)info->frames); + fftw->bin_max = (snd_info->frames / 2); + fftw->bin_size = ((float)snd_info->sample_rate / (float)snd_info->frames); } -static void slp_capture(ctx_dev *snd) -{ - if (snd->device_status == STATUS_CLOSED) { - snd->finish_dev = true; - snd->restart_dev = false; - return; - } - - if (snd->snd_info->source == "alsa") { - snd_alsa_capture(snd); - } else if (snd->snd_info->source == "pulse") { - snd_pulse_capture(snd); - } +float cls_sound::HammingWindow(int n1, int N2){ + return 0.54F - 0.46F * (float)(cos((2 * M_PI * n1)) / (N2 - 1)); } -void snd_cleanup(ctx_dev *snd) -{ - if (snd->snd_info->source == "alsa") { - snd_alsa_cleanup(snd); - } else if (snd->snd_info->source == "pulse") { - snd_pulse_cleanup(snd); - } - - if (snd->snd_info->buffer != NULL) { - free(snd->snd_info->buffer); - snd->snd_info->buffer = NULL; - } - - fftw_destroy_plan(snd->snd_info->snd_fftw->ff_plan); - fftw_free(snd->snd_info->snd_fftw->ff_in); - fftw_free(snd->snd_info->snd_fftw->ff_out); - - MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Stopped."); - +float cls_sound::HannWindow(int n1, int N2){ + return 0.5F * (float)(1 - (cos(2 * M_PI * n1 * N2))); } -static void slp_init(ctx_dev *snd) +void cls_sound::check_alerts() { - - if ((snd->device_status != STATUS_INIT) && - (snd->device_status != STATUS_RESET)) { - return; - } - - if (snd->device_status == STATUS_RESET) { - snd_cleanup(snd); - } - - MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO,_("Initialize")); - - snd_init_values(snd); - snd_load_params(snd); - snd_load_alerts(snd); - - if (snd->snd_info->source == "alsa") { - snd_alsa_init(snd); - } else if (snd->snd_info->source == "pulse") { - snd_pulse_init(snd); - } else { - MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO,_("Invalid sound source.")); - snd->finish_dev = true; - snd->device_status = STATUS_CLOSED; - return; - } - - snd_fftw_open(snd); - - MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Detecting")); - -} - -static void snd_check_alerts(ctx_dev *snd) -{ - ctx_snd_info *info = snd->snd_info; double freq_value; int indx, chkval, chkcnt; double pMaxIntensity; @@ -756,24 +654,27 @@ static void snd_check_alerts(ctx_dev *snd) std::list::iterator it; struct timespec trig_ts; - for (indx=0;indx frames;indx++){ - if (snd->conf->snd_window == "hamming") { - snd->snd_info->snd_fftw->ff_in[indx] = info->buffer[indx] * HammingWindow(indx, info->frames); - } else if (snd->conf->snd_window == "hann") { - snd->snd_info->snd_fftw->ff_in[indx] = info->buffer[indx] * HannWindow(indx, info->frames); + for (indx=0;indx frames;indx++){ + if (conf->snd_window == "hamming") { + snd_info->snd_fftw->ff_in[indx] = + snd_info->buffer[indx] * HammingWindow(indx, snd_info->frames); + } else if (conf->snd_window == "hann") { + snd_info->snd_fftw->ff_in[indx] = + snd_info->buffer[indx] * HannWindow(indx, snd_info->frames); } else { - snd->snd_info->snd_fftw->ff_in[indx] = info->buffer[indx]; + snd_info->snd_fftw->ff_in[indx] = snd_info->buffer[indx]; } } - fftw_execute(snd->snd_info->snd_fftw->ff_plan); + fftw_execute(snd_info->snd_fftw->ff_plan); pMaxIntensity = 0; pMaxBinIndex = 0; - for (indx = snd->snd_info->snd_fftw->bin_min; indx <= snd->snd_info->snd_fftw->bin_max; indx++){ - pRealNbr = snd->snd_info->snd_fftw->ff_out[indx][0]; - pImaginaryNbr = snd->snd_info->snd_fftw->ff_out[indx][1]; + for (indx = snd_info->snd_fftw->bin_min; + indx <= snd_info->snd_fftw->bin_max; indx++) { + pRealNbr = snd_info->snd_fftw->ff_out[indx][0]; + pImaginaryNbr = snd_info->snd_fftw->ff_out[indx][1]; pIntensity = pRealNbr * pRealNbr + pImaginaryNbr * pImaginaryNbr; if (pIntensity > pMaxIntensity){ pMaxIntensity = pIntensity; @@ -781,21 +682,21 @@ static void snd_check_alerts(ctx_dev *snd) } } - freq_value = (snd->snd_info->snd_fftw->bin_size * pMaxBinIndex * info->channels); + freq_value = (snd_info->snd_fftw->bin_size * pMaxBinIndex * snd_info->channels); - if (snd->conf->snd_show) { + if (conf->snd_show) { MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO , _("Freq: %.4f threshold: %d count: %d maximum: %d") - , freq_value, info->vol_min - , info->vol_count, info->vol_max); + , freq_value, snd_info->vol_min + , snd_info->vol_count, snd_info->vol_max); } - for (it=info->alerts.begin(); it!=info->alerts.end(); it++) { + for (it=snd_info->alerts.begin(); it!=snd_info->alerts.end(); it++) { trigger = false; if ((freq_value >= it->freq_low) && (freq_value <= it->freq_high)) { chkcnt = 0; - for(indx=0; indx < info->frames; indx++) { - chkval = abs((int)info->buffer[indx] / 256); + for(indx=0; indx < snd_info->frames; indx++) { + chkval = abs((int)snd_info->buffer[indx] / 256); if (chkval >= it->volume_level) { chkcnt++; } @@ -818,12 +719,12 @@ static void snd_check_alerts(ctx_dev *snd) , _("Sound Alert %d-%s : level %d count %d max vol %d") , it->alert_id ,it->alert_nm.c_str() , it->volume_level, chkcnt - , info->vol_max); - if (snd->conf->on_sound_alert != "") { - info->trig_freq =std::to_string(freq_value); - info->trig_nbr = std::to_string(it->alert_id); - info->trig_nm = it->alert_nm; - util_exec_command(snd, snd->conf->on_sound_alert.c_str(), NULL); + , snd_info->vol_max); + if (conf->on_sound_alert != "") { + snd_info->trig_freq =std::to_string(freq_value); + snd_info->trig_nbr = std::to_string(it->alert_id); + snd_info->trig_nm = it->alert_nm; + util_exec_command(this, conf->on_sound_alert); } } } @@ -831,94 +732,196 @@ static void snd_check_alerts(ctx_dev *snd) } -static void snd_check_levels(ctx_dev *snd) -{ - ctx_snd_info *info = snd->snd_info; - int indx, chkval; +#endif /************ End FFTW3 *******************/ - if (snd->device_status == STATUS_CLOSED) { - snd->finish_dev = true; - snd->restart_dev = false; +void cls_sound::capture() +{ + if (device_status == STATUS_CLOSED) { + return; + } + #ifdef HAVE_ALSA + alsa_capture(); + #endif + #ifdef HAVE_PULSE + pulse_capture(); + #endif +} + +void cls_sound::cleanup() +{ + #ifdef HAVE_ALSA + alsa_cleanup(); + #endif + #ifdef HAVE_PULSE + pulse_cleanup(); + #endif + #ifdef HAVE_FFTW3 + fftw_destroy_plan(snd_info->snd_fftw->ff_plan); + fftw_free(snd_info->snd_fftw->ff_in); + fftw_free(snd_info->snd_fftw->ff_out); + #endif + if (snd_info->buffer != NULL) { + free(snd_info->buffer); + snd_info->buffer = NULL; + } + + mydelete(snd_info->snd_alsa); + mydelete(snd_info->snd_fftw); + mydelete(snd_info->snd_pulse); + mydelete(snd_info->params); + mydelete(snd_info); + + device_status = STATUS_CLOSED; + + MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, "Stopped."); + +} + +void cls_sound::init() +{ + if ((device_status != STATUS_INIT) && (restart == false)) { return; } - info->vol_max = 0; - info->vol_count = 0; - - for(indx=0; indx < info->frames; indx++) { - chkval = abs((int)info->buffer[indx] / 256); - if (chkval > info->vol_max) info->vol_max = chkval ; - if (chkval > info->vol_min) info->vol_count++; + if (restart == true) { + cleanup(); + restart = false; } - if (info->vol_count > 0) { - snd_check_alerts(snd); + MOTPLS_LOG(INF, TYPE_ALL, NO_ERRNO,_("Initialize")); + snd_info = new ctx_snd_info; + snd_info->params = new ctx_params; + snd_info->snd_fftw = new ctx_snd_fftw; + snd_info->snd_alsa = new ctx_snd_alsa; + snd_info->snd_pulse = new ctx_snd_pulse; + + init_values(); + load_params(); + load_alerts(); + + if ((snd_info->source != "alsa") && + (snd_info->source != "pulse")) { + MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO,_("Invalid sound source.")); + device_status = STATUS_CLOSED; + return; } + #ifdef HAVE_ALSA + alsa_init(); + #endif + #ifdef HAVE_PULSE + pulse_init(); + #endif + #ifdef HAVE_FFTW3 + fftw_open(); + #endif + + MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Detecting")); + +} + +void cls_sound::check_levels() +{ + #ifdef HAVE_FFTW3 + int indx, chkval; + + if (device_status == STATUS_CLOSED) { + return; + } + + snd_info->vol_max = 0; + snd_info->vol_count = 0; + + for(indx=0; indx < snd_info->frames; indx++) { + chkval = abs((int)snd_info->buffer[indx] / 256); + if (chkval > snd_info->vol_max) snd_info->vol_max = chkval ; + if (chkval > snd_info->vol_min) snd_info->vol_count++; + } + + if (snd_info->vol_count > 0) { + check_alerts(); + } + #endif } -void *snd_loop(void *arg) +void cls_sound::handler() { - ctx_dev *snd = (ctx_dev *)arg; + pthread_mutex_lock(&motapp->global_lock); + motapp->threads_running++; + pthread_mutex_unlock(&motapp->global_lock); - pthread_mutex_lock(&snd->motapp->global_lock); - snd->motapp->threads_running++; - pthread_mutex_unlock(&snd->motapp->global_lock); + mythreadname_set("sl", threadnr, conf->device_name.c_str()); - mythreadname_set("sl", snd->threadnr, snd->conf->device_name.c_str()); - pthread_setspecific(tls_key_threadnr, (void *)((unsigned long)snd->threadnr)); + device_status = STATUS_INIT; - snd->snd_info = new ctx_snd_info; - snd->snd_info->params = new ctx_params; - snd->snd_info->snd_fftw = new ctx_snd_fftw; - snd->snd_info->snd_alsa = new ctx_snd_alsa; - snd->snd_info->snd_pulse = new ctx_snd_pulse; - snd->running_dev = true; - snd->finish_dev = false; - snd->restart_dev = false; - snd->device_status = STATUS_INIT; + handler_finished = false; + handler_stop = false; - while (snd->finish_dev == false) { - slp_init(snd); - slp_capture(snd); - snd_check_levels(snd); + while (handler_stop == false) { + init(); + capture(); + check_levels(); + if (device_status == STATUS_CLOSED) { + handler_stop = true; + } } - MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Capture loop finished")); + cleanup(); - snd_cleanup(snd); + pthread_mutex_lock(&motapp->global_lock); + motapp->threads_running--; + pthread_mutex_unlock(&motapp->global_lock); - pthread_mutex_lock(&snd->motapp->global_lock); - snd->motapp->threads_running--; - pthread_mutex_unlock(&snd->motapp->global_lock); - - snd->finish_dev = true; - snd->running_dev = false; - delete snd->snd_info->snd_alsa; - delete snd->snd_info->snd_fftw; - delete snd->snd_info->snd_pulse; - delete snd->snd_info->params; - delete snd->snd_info; - - MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Exiting")); - - pthread_exit(NULL); + MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Sound exiting")); + handler_finished = true; } -#else - -void *snd_loop(void *arg) +void cls_sound::start() { - ctx_dev *snd =(ctx_dev *) arg; + #if !defined(HAVE_FFTW3) || (!defined(HAVE_ALSA) && !defined(HAVE_PULSE)) + MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Required packages not installed")); + device_status = STATUS_CLOSED; + return; + #endif - snd->restart_dev = false; - snd->finish_dev = true; - snd->running_dev = false; - - MOTPLS_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Sound detection functionality not supported")); - - pthread_exit(NULL); + if (handler_finished == true) { + handler_thread = std::thread(&cls_sound::handler, this); + handler_thread.detach(); + } +} + +void cls_sound::stop() +{ + int waitcnt = 0; + + if (handler_finished == false) { + handler_stop = true; + while ((handler_finished == false) && (waitcnt <10)){ + SLEEP(1,0) + waitcnt++; + } + if (waitcnt == 10) { + MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO + ,_("Shutdown of sound frequency detection failed")); + pthread_kill(handler_thread.native_handle(), SIGVTALRM); + pthread_mutex_lock(&motapp->global_lock); + motapp->threads_running--; + pthread_mutex_unlock(&motapp->global_lock); + } + } + +} + +cls_sound::cls_sound(ctx_motapp *p_motapp) +{ + motapp = p_motapp; + handler_finished = true; + restart = false; +} + +cls_sound::~cls_sound() +{ + mydelete(conf); } -#endif diff --git a/src/sound.hpp b/src/sound.hpp index 2fc21256..4d7c731a 100644 --- a/src/sound.hpp +++ b/src/sound.hpp @@ -19,7 +19,129 @@ #ifndef _INCLUDE_SOUND_HPP_ #define _INCLUDE_SOUND_HPP_ - void *snd_loop(void *arg); - void snd_cleanup(ctx_dev *snd); +struct ctx_snd_alert { + int alert_id; /* Id number for the alert*/ + std::string alert_nm; /* Name of the alert*/ + int volume_level; /* Volume level required to consider the sample*/ + int volume_count; /* For each sample, number of times required to exceed volumne level*/ + double freq_low; /* Lowest frequency for detecting this alert*/ + double freq_high; /* Highest frequency for detecting this alert*/ + int trigger_count; /* Count of how many times it has been triggered so far*/ + int trigger_threshold; /* How many times does it need to be triggered before an event*/ + timespec trigger_time; /* The last time the trigger was invoked */ + int trigger_duration; /* Min. duration to trigger a new /event */ +}; + +struct ctx_snd_alsa { + #ifdef HAVE_ALSA + int device_id; + std::string device_nm; + snd_pcm_t *pcm_dev; + snd_pcm_info_t *pcm_info; + int card_id; + snd_ctl_card_info_t *card_info; + snd_ctl_t *ctl_hdl; + #else + int dummy; + #endif +}; + +struct ctx_snd_pulse { + #ifdef HAVE_PULSE + pa_simple *dev; + #else + int dummy; + #endif +}; + +struct ctx_snd_fftw { + #ifdef HAVE_FFTW3 + fftw_plan ff_plan; + double *ff_in; + fftw_complex *ff_out; + int bin_max; + int bin_min; + double bin_size; + #else + int dummy; + #endif +}; + +struct ctx_snd_info { + std::string source; /* Source string in ALSA format e.g. hw:1,0*/ + int sample_rate; /* Sample rate of sound source*/ + int channels; /* Number of audio channels */ + std::list alerts; /* list of sound alert criteria */ + int vol_min; /* The minimum volume from alerts*/ + int vol_max; /* Maximum volume of sample*/ + int vol_count; /* Number of times volumne exceeded user specified volume level */ + int16_t *buffer; + int buffer_size; + int frames; + std::string pulse_server; + std::string trig_freq; + std::string trig_nbr; + std::string trig_nm; + ctx_params *params; /* Device parameters*/ + ctx_snd_fftw *snd_fftw; /* fftw for sound*/ + ctx_snd_alsa *snd_alsa; /* Alsa device for sound*/ + ctx_snd_pulse *snd_pulse; /* PulseAudio for sound*/ +}; + +class cls_sound { + public: + cls_sound(ctx_motapp *p_motapp); + ~cls_sound(); + void start(); + void stop(); + + enum DEVICE_STATUS device_status; + + cls_config *conf; + int device_id; + std::string device_name; + ctx_snd_info *snd_info; + int threadnr; + bool restart; + bool handler_stop; + bool handler_finished; + + private: + ctx_motapp *motapp; + std::thread handler_thread; + + void cleanup(); + void handler(); + void init_values(); + void init_alerts(ctx_snd_alert *tmp_alert); + void edit_alerts(); + void load_alerts(); + void load_params(); + void capture(); + void init(); + void check_levels(); + + #ifdef HAVE_ALSA + void alsa_list_subdev(); + void alsa_list_card(); + void alsa_list(); + void alsa_start(); + void alsa_init(); + void alsa_capture(); + void alsa_cleanup(); + #endif + #ifdef HAVE_PULSE + void pulse_init(); + void pulse_capture(); + void pulse_cleanup(); + #endif + #ifdef HAVE_FFTW3 + void fftw_open(); + float HammingWindow(int n1, int N2); + float HannWindow(int n1, int N2); + void check_alerts(); + #endif + +}; #endif /* _INCLUDE_SOUND_HPP_ */ diff --git a/src/util.cpp b/src/util.cpp index b272213d..24371ac5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -21,7 +21,8 @@ #include "conf.hpp" #include "util.hpp" #include "logger.hpp" -#include "alg_sec.hpp" /* For sec detect in format output */ +#include "alg_sec.hpp" +#include "sound.hpp" /** Non case sensitive equality check for strings*/ @@ -280,7 +281,6 @@ static void mystrftime_long (const ctx_dev *cam, sprintf(out, "%*s", width, cam->action_user); return; } - if (SPECIFIERWORD("secdetect")) { if (cam->algsec->method != "none") { if (cam->algsec->detected) { @@ -294,27 +294,6 @@ static void mystrftime_long (const ctx_dev *cam, return; } - if (SPECIFIERWORD("trig_freq")) { - if (cam->snd_info != NULL) { - snprintf (out, PATH_MAX, "%*s", width, cam->snd_info->trig_freq.c_str() ); - } - return; - } - - if (SPECIFIERWORD("trig_nbr")) { - if (cam->snd_info != NULL) { - snprintf (out, PATH_MAX, "%*s", width, cam->snd_info->trig_nbr.c_str() ); - } - return; - } - - if (SPECIFIERWORD("trig_nm")) { - if (cam->snd_info != NULL) { - snprintf (out, PATH_MAX, "%*s", width, cam->snd_info->trig_nm.c_str() ); - } - return; - } - // Not a valid modifier keyword. Log the error and ignore. MOTPLS_LOG(ERR, TYPE_ALL, NO_ERRNO @@ -327,6 +306,53 @@ static void mystrftime_long (const ctx_dev *cam, out[0] = '~'; out[1] = 0; } +void mystrftime(cls_sound *snd, std::string &dst, std::string fmt) +{ + char tmp[PATH_MAX]; + struct tm timestamp_tm; + timespec curr_ts; + std::string user_fmt; + uint indx; + + clock_gettime(CLOCK_REALTIME, &curr_ts); + localtime_r(&curr_ts.tv_sec, ×tamp_tm); + + if (fmt == "") { + dst = ""; + return; + } + + user_fmt = ""; + for (indx=0;indxdevice_id); + user_fmt.append(tmp); + indx++; + } else if (fmt.substr(indx,2) == "%$") { + user_fmt.append(snd->device_name); + indx++; + } else if (fmt.substr(indx,strlen("%{ver}")) == "%{ver}") { + user_fmt.append(VERSION); + indx += (strlen("%{ver}")-1); + } else if (fmt.substr(indx,strlen("%{trig_freq}")) == "%{trig_freq}") { + user_fmt.append(snd->snd_info->trig_freq); + indx += (strlen("%{trig_freq}")-1); + } else if (fmt.substr(indx,strlen("%{trig_nbr}")) == "%{trig_nbr}") { + user_fmt.append(snd->snd_info->trig_nbr); + indx += (strlen("%{trig_nbr}")-1); + } else if (fmt.substr(indx,strlen("%{trig_nm}")) == "%{trig_nm}") { + user_fmt.append(snd->snd_info->trig_nm); + indx += (strlen("%{trig_nm}")-1); + } else { + user_fmt.append(fmt.substr(indx,1)); + } + } + memset(tmp, 0, sizeof(tmp)); + strftime(tmp, sizeof(tmp),user_fmt.c_str(), ×tamp_tm); + dst.assign(tmp); +} + size_t mystrftime_base(ctx_dev *cam, char *s, size_t max , const char *userformat, const char *filename) { @@ -684,15 +710,6 @@ AVPacket *mypacket_alloc(AVPacket *pkt) } -/*********************************************/ -/** - * util_exec_command - * Execute 'command' with 'arg' as its argument. - * if !arg command is started with no arguments - * Before we call execl we need to close all the file handles - * that the fork inherited from the parent in order not to pass - * the open handles on to the shell - */ void util_exec_command(ctx_dev *cam, const char *command, const char *filename) { char stamp[PATH_MAX]; @@ -725,6 +742,38 @@ void util_exec_command(ctx_dev *cam, const char *command, const char *filename) ,_("Executing external command '%s'"), stamp); } +void util_exec_command(cls_sound *snd, std::string cmd) +{ + std::string dst; + int pid; + + mystrftime(snd, dst, cmd); + + pid = fork(); + if (!pid) { + /* Detach from parent */ + setsid(); + + execl("/bin/sh", "sh", "-c", dst.c_str(), " &",(char*)NULL); + + /* if above function succeeds the program never reach here */ + MOTPLS_LOG(ALR, TYPE_EVENTS, SHOW_ERRNO + ,_("Unable to start external command '%s'"),dst.c_str()); + + exit(1); + } + + if (pid > 0) { + waitpid(pid, NULL, 0); + } else { + MOTPLS_LOG(ALR, TYPE_EVENTS, SHOW_ERRNO + ,_("Unable to start external command '%s'"), dst.c_str()); + } + + MOTPLS_LOG(DBG, TYPE_EVENTS, NO_ERRNO + ,_("Executing external command '%s'"), dst.c_str()); +} + /*********************************************/ static void util_parms_file(ctx_params *params, std::string params_file) { diff --git a/src/util.hpp b/src/util.hpp index 57454750..d0ebda33 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -87,7 +87,9 @@ , const char *usrfmt, const char *fname); void mystrftime(ctx_dev *cam, std::string &rslt , std::string usrfmt, std::string fname); + void mystrftime(cls_sound *snd, std::string &dst, std::string fmt); void util_exec_command(ctx_dev *cam, const char *command, const char *filename); + void util_exec_command(cls_sound *snd, std::string cmd); void mythreadname_set(const char *abbr, int threadnbr, const char *threadname); void mythreadname_get(char *threadname);