void App::openTree(int index, const QString &file) { // no file selected if (index == -1) return; // new data file if (index == -2) { newFile(); return; } createNotes(); if (!openTree(file)) { destroyNotes(); return; } currentFile = file; setModified(false); foreignDeletedNode = !notes->isClipboardEmpty(); if (preferences.showReminder) notes->showReminder(false); notes->repaint(); }
void App::newFile() { if (!closeFile()) return; createNotes(); if (!openTree("#init_file#")) { destroyNotes(); return; } currentFile = ""; setModified(false); #ifndef DEMO setCaption("IQNotes :: (untitled)"); #else setCaption("IQNotes :: DEMO"); #endif foreignDeletedNode = !notes->isClipboardEmpty(); }
Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap ) : monitor( p_monitor ), start_time( p_start_time ), cause( p_cause ), noteSetMap( p_noteSetMap ) { if ( !initialised ) Initialise(); std::string notes; createNotes( notes ); bool untimedEvent = false; if ( !start_time.tv_sec ) { untimedEvent = true; gettimeofday( &start_time, 0 ); } static char sql[ZM_SQL_MED_BUFSIZ]; struct tm *stime = localtime( &start_time.tv_sec ); snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, Name, StartTime, Width, Height, Cause, Notes ) values ( %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s' )", monitor->Id(), start_time.tv_sec, monitor->Width(), monitor->Height(), cause.c_str(), notes.c_str() ); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't insert event: %s", mysql_error( &dbconn ) ); exit( mysql_errno( &dbconn ) ); } id = mysql_insert_id( &dbconn ); if ( untimedEvent ) { Warning( "Event %d has zero time, setting to current", id ); } end_time.tv_sec = 0; frames = 0; alarm_frames = 0; tot_score = 0; max_score = 0; if ( config.use_deep_storage ) { char *path_ptr = path; path_ptr += snprintf( path_ptr, sizeof(path), "%s/%d", config.dir_events, monitor->Id() ); int dt_parts[6]; dt_parts[0] = stime->tm_year-100; dt_parts[1] = stime->tm_mon+1; dt_parts[2] = stime->tm_mday; dt_parts[3] = stime->tm_hour; dt_parts[4] = stime->tm_min; dt_parts[5] = stime->tm_sec; char date_path[PATH_MAX] = ""; char time_path[PATH_MAX] = ""; char *time_path_ptr = time_path; for ( unsigned int i = 0; i < sizeof(dt_parts)/sizeof(*dt_parts); i++ ) { path_ptr += snprintf( path_ptr, sizeof(path)-(path_ptr-path), "/%02d", dt_parts[i] ); struct stat statbuf; errno = 0; stat( path, &statbuf ); if ( errno == ENOENT || errno == ENOTDIR ) { if ( mkdir( path, 0755 ) ) { Fatal( "Can't mkdir %s: %s", path, strerror(errno)); } } if ( i == 2 ) strncpy( date_path, path, sizeof(date_path) ); else if ( i >= 3 ) time_path_ptr += snprintf( time_path_ptr, sizeof(time_path)-(time_path_ptr-time_path), "%s%02d", i>3?"/":"", dt_parts[i] ); } char id_file[PATH_MAX]; // Create event id symlink snprintf( id_file, sizeof(id_file), "%s/.%d", date_path, id ); if ( symlink( time_path, id_file ) < 0 ) Fatal( "Can't symlink %s -> %s: %s", id_file, path, strerror(errno)); // Create empty id tag file snprintf( id_file, sizeof(id_file), "%s/.%d", path, id ); if ( FILE *id_fp = fopen( id_file, "w" ) ) fclose( id_fp ); else Fatal( "Can't fopen %s: %s", id_file, strerror(errno)); } else { snprintf( path, sizeof(path), "%s/%d/%d", config.dir_events, monitor->Id(), id ); struct stat statbuf; errno = 0; stat( path, &statbuf ); if ( errno == ENOENT || errno == ENOTDIR ) { if ( mkdir( path, 0755 ) ) { Error( "Can't mkdir %s: %s", path, strerror(errno)); } } char id_file[PATH_MAX]; // Create empty id tag file snprintf( id_file, sizeof(id_file), "%s/.%d", path, id ); if ( FILE *id_fp = fopen( id_file, "w" ) ) fclose( id_fp ); else Fatal( "Can't fopen %s: %s", id_file, strerror(errno)); } last_db_frame = 0; }
void Event::updateNotes( const StringSetMap &newNoteSetMap ) { bool update = false; //Info( "Checking notes, %d <> %d", noteSetMap.size(), newNoteSetMap.size() ); if ( newNoteSetMap.size() > 0 ) { if ( noteSetMap.size() == 0 ) { noteSetMap = newNoteSetMap; update = true; } else { for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); newNoteSetMapIter++ ) { const std::string &newNoteGroup = newNoteSetMapIter->first; const StringSet &newNoteSet = newNoteSetMapIter->second; //Info( "Got %d new strings", newNoteSet.size() ); if ( newNoteSet.size() > 0 ) { StringSetMap::iterator noteSetMapIter = noteSetMap.find( newNoteGroup ); if ( noteSetMapIter == noteSetMap.end() ) { //Info( "Can't find note group %s, copying %d strings", newNoteGroup.c_str(), newNoteSet.size() ); noteSetMap.insert( StringSetMap::value_type( newNoteGroup, newNoteSet ) ); update = true; } else { StringSet ¬eSet = noteSetMapIter->second; //Info( "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size() ); for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); newNoteSetIter++ ) { const std::string &newNote = *newNoteSetIter; StringSet::iterator noteSetIter = noteSet.find( newNote ); if ( noteSetIter == noteSet.end() ) { noteSet.insert( newNote ); update = true; } } } } } } } if ( update ) { std::string notes; createNotes( notes ); Debug( 2, "Updating notes for event %d, '%s'", id, notes.c_str() ); static char sql[ZM_SQL_MED_BUFSIZ]; #if USE_PREPARED_SQL static MYSQL_STMT *stmt = 0; char notesStr[ZM_SQL_MED_BUFSIZ] = ""; unsigned long notesLen = 0; if ( !stmt ) { const char *sql = "update Events set Notes = ? where Id = ?"; stmt = mysql_stmt_init( &dbconn ); if ( mysql_stmt_prepare( stmt, sql, strlen(sql) ) ) { Fatal( "Unable to prepare sql '%s': %s", sql, mysql_stmt_error(stmt) ); } /* Get the parameter count from the statement */ if ( mysql_stmt_param_count( stmt ) != 2 ) { Fatal( "Unexpected parameter count %ld in sql '%s'", mysql_stmt_param_count( stmt ), sql ); } MYSQL_BIND bind[2]; memset(bind, 0, sizeof(bind)); /* STRING PARAM */ bind[0].buffer_type = MYSQL_TYPE_STRING; bind[0].buffer = (char *)notesStr; bind[0].buffer_length = sizeof(notesStr); bind[0].is_null = 0; bind[0].length = ¬esLen; bind[1].buffer_type= MYSQL_TYPE_LONG; bind[1].buffer= (char *)&id; bind[1].is_null= 0; bind[1].length= 0; /* Bind the buffers */ if ( mysql_stmt_bind_param( stmt, bind ) ) { Fatal( "Unable to bind sql '%s': %s", sql, mysql_stmt_error(stmt) ); } } strncpy( notesStr, notes.c_str(), sizeof(notesStr) ); notesLen = notes.length(); if ( mysql_stmt_execute( stmt ) ) { Fatal( "Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt) ); } #else static char escapedNotes[ZM_SQL_MED_BUFSIZ]; mysql_real_escape_string( &dbconn, escapedNotes, notes.c_str(), notes.length() ); snprintf( sql, sizeof(sql), "update Events set Notes = '%s' where Id = %d", escapedNotes, id ); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't insert event: %s", mysql_error( &dbconn ) ); } #endif } }
Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap, bool p_videoEvent ) : monitor(p_monitor), start_time(p_start_time), cause(p_cause), noteSetMap(p_noteSetMap), videoEvent(p_videoEvent), videowriter(NULL) { std::string notes; createNotes(notes); struct timeval now; gettimeofday(&now, 0); bool untimedEvent = false; if ( !start_time.tv_sec ) { untimedEvent = true; start_time = now; } else if ( start_time.tv_sec > now.tv_sec ) { Error( "StartTime in the future %u.%u > %u.%u", start_time.tv_sec, start_time.tv_usec, now.tv_sec, now.tv_usec ); start_time = now; } Storage * storage = monitor->getStorage(); scheme = storage->Scheme(); unsigned int state_id = 0; zmDbRow dbrow; if ( dbrow.fetch("SELECT Id FROM States WHERE IsActive=1") ) { state_id = atoi(dbrow[0]); } char sql[ZM_SQL_MED_BUFSIZ]; struct tm *stime = localtime(&start_time.tv_sec); snprintf( sql, sizeof(sql), "INSERT INTO Events ( MonitorId, StorageId, Name, StartTime, Width, Height, Cause, Notes, StateId, Orientation, Videoed, DefaultVideo, SaveJPEGs, Scheme ) values ( %d, %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s', %d, %d, %d, '', %d, '%s' )", monitor->Id(), storage->Id(), start_time.tv_sec, monitor->Width(), monitor->Height(), cause.c_str(), notes.c_str(), state_id, monitor->getOrientation(), videoEvent, monitor->GetOptSaveJPEGs(), storage->SchemeString().c_str() ); db_mutex.lock(); if ( mysql_query(&dbconn, sql) ) { Error("Can't insert event: %s. sql was (%s)", mysql_error(&dbconn), sql); db_mutex.unlock(); return; } id = mysql_insert_id(&dbconn); db_mutex.unlock(); if ( untimedEvent ) { Warning("Event %d has zero time, setting to current", id); } end_time.tv_sec = 0; frames = 0; alarm_frames = 0; tot_score = 0; max_score = 0; alarm_frame_written = false; char id_file[PATH_MAX]; char *path_ptr = path; path_ptr += snprintf(path_ptr, sizeof(path), "%s/%d", storage->Path(), monitor->Id()); // Try to make the Monitor Dir. Normally this would exist, but in odd cases might not. if ( mkdir(path, 0755) ) { if ( errno != EEXIST ) Error("Can't mkdir %s: %s", path, strerror(errno)); } if ( storage->Scheme() == Storage::DEEP ) { int dt_parts[6]; dt_parts[0] = stime->tm_year-100; dt_parts[1] = stime->tm_mon+1; dt_parts[2] = stime->tm_mday; dt_parts[3] = stime->tm_hour; dt_parts[4] = stime->tm_min; dt_parts[5] = stime->tm_sec; char date_path[PATH_MAX] = ""; char time_path[PATH_MAX] = ""; char *time_path_ptr = time_path; for ( unsigned int i = 0; i < sizeof(dt_parts)/sizeof(*dt_parts); i++ ) { path_ptr += snprintf(path_ptr, sizeof(path)-(path_ptr-path), "/%02d", dt_parts[i]); errno = 0; if ( mkdir(path, 0755) ) { // FIXME This should not be fatal. Should probably move to a different storage area. if ( errno != EEXIST ) Error("Can't mkdir %s: %s", path, strerror(errno)); } if ( i == 2 ) strncpy(date_path, path, sizeof(date_path)); else if ( i >= 3 ) time_path_ptr += snprintf(time_path_ptr, sizeof(time_path)-(time_path_ptr-time_path), "%s%02d", i>3?"/":"", dt_parts[i]); } // Create event id symlink snprintf(id_file, sizeof(id_file), "%s/.%" PRIu64, date_path, id); if ( symlink(time_path, id_file) < 0 ) Error("Can't symlink %s -> %s: %s", id_file, path, strerror(errno)); } else if ( storage->Scheme() == Storage::MEDIUM ) { path_ptr += snprintf( path_ptr, sizeof(path), "/%04d-%02d-%02d", stime->tm_year+1900, stime->tm_mon+1, stime->tm_mday ); if ( mkdir(path, 0755) ) { if ( errno != EEXIST ) Error("Can't mkdir %s: %s", path, strerror(errno)); } path_ptr += snprintf(path_ptr, sizeof(path), "/%" PRIu64, id); if ( mkdir(path, 0755) ) { if ( errno != EEXIST ) Error("Can't mkdir %s: %s", path, strerror(errno)); } } else { path_ptr += snprintf(path_ptr, sizeof(path), "/%" PRIu64, id); if ( mkdir(path, 0755) ) { if ( errno != EEXIST ) Error("Can't mkdir %s: %s", path, strerror(errno)); } // Create empty id tag file snprintf(id_file, sizeof(id_file), "%s/.%" PRIu64, path, id); if ( FILE *id_fp = fopen(id_file, "w") ) fclose(id_fp); else Error("Can't fopen %s: %s", id_file, strerror(errno)); } // deep storage or not last_db_frame = 0; video_name[0] = 0; /* Save as video */ if ( monitor->GetOptVideoWriter() != 0 ) { snprintf(video_name, sizeof(video_name), "%" PRIu64 "-%s", id, "video.mp4"); snprintf(video_file, sizeof(video_file), staticConfig.video_file_format, path, video_name); Debug(1,"Writing video file to %s", video_file ); /* X264 MP4 video writer */ if ( monitor->GetOptVideoWriter() == Monitor::X264ENCODE ) { #if ZM_HAVE_VIDEOWRITER_X264MP4 videowriter = new X264MP4Writer(video_file, monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder(), monitor->GetOptEncoderParams()); #else Error("ZoneMinder was not compiled with the X264 MP4 video writer, check dependencies (x264 and mp4v2)"); #endif } if ( videowriter != NULL ) { /* Open the video stream */ int nRet = videowriter->Open(); if ( nRet != 0 ) { Error("Failed opening video stream"); delete videowriter; videowriter = NULL; } } } else { /* No video object */ videowriter = NULL; } } // Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap, bool p_videoEvent )