Merge branch 'development' into LTS_development
# Conflicts: # lib/stream.cpp
This commit is contained in:
commit
0e1a18986a
6 changed files with 358 additions and 250 deletions
|
@ -472,7 +472,7 @@ static std::string strftime_now(const std::string& format) {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Util::getStreamStatus(std::string & streamname){
|
uint8_t Util::getStreamStatus(const std::string & streamname){
|
||||||
char pageName[NAME_BUFFER_SIZE];
|
char pageName[NAME_BUFFER_SIZE];
|
||||||
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamname.c_str());
|
snprintf(pageName, NAME_BUFFER_SIZE, SHM_STREAM_STATE, streamname.c_str());
|
||||||
IPC::sharedPage streamStatus(pageName, 1, false, false);
|
IPC::sharedPage streamStatus(pageName, 1, false, false);
|
||||||
|
|
|
@ -13,6 +13,6 @@ namespace Util {
|
||||||
bool startInput(std::string streamname, std::string filename = "", bool forkFirst = true, bool isProvider = false);
|
bool startInput(std::string streamname, std::string filename = "", bool forkFirst = true, bool isProvider = false);
|
||||||
int startPush(const std::string & streamname, std::string & target);
|
int startPush(const std::string & streamname, std::string & target);
|
||||||
JSON::Value getStreamConfig(std::string streamname);
|
JSON::Value getStreamConfig(std::string streamname);
|
||||||
uint8_t getStreamStatus(std::string & streamname);
|
uint8_t getStreamStatus(const std::string & streamname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
143
lib/util.cpp
143
lib/util.cpp
|
@ -2,11 +2,16 @@
|
||||||
#define _FILE_OFFSET_BITS 64
|
#define _FILE_OFFSET_BITS 64
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "timing.h"
|
|
||||||
#include "defines.h"
|
|
||||||
#include "bitfields.h"
|
#include "bitfields.h"
|
||||||
#include <stdio.h>
|
#include "defines.h"
|
||||||
|
#include "timing.h"
|
||||||
|
#include <errno.h> // errno, ENOENT, EEXIST
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h> // stat
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <direct.h> // _mkdir
|
||||||
|
#endif
|
||||||
|
|
||||||
#define RECORD_POINTER p + getOffset() + (getRecordPosition(recordNo) * getRSize()) + fd.offset
|
#define RECORD_POINTER p + getOffset() + (getRecordPosition(recordNo) * getRSize()) + fd.offset
|
||||||
#define RAXHDR_FIELDOFFSET p[1]
|
#define RAXHDR_FIELDOFFSET p[1]
|
||||||
|
@ -19,7 +24,85 @@
|
||||||
#define RAX_REQDFIELDS_LEN 28
|
#define RAX_REQDFIELDS_LEN 28
|
||||||
|
|
||||||
namespace Util{
|
namespace Util{
|
||||||
bool stringScan(const std::string & src, const std::string & pattern, std::deque<std::string> & result){
|
/// Helper function that cross-platform checks if a given directory exists.
|
||||||
|
bool isDirectory(const std::string &path){
|
||||||
|
#if defined(_WIN32)
|
||||||
|
struct _stat info;
|
||||||
|
if (_stat(path.c_str(), &info) != 0){return false;}
|
||||||
|
return (info.st_mode & _S_IFDIR) != 0;
|
||||||
|
#else
|
||||||
|
struct stat info;
|
||||||
|
if (stat(path.c_str(), &info) != 0){return false;}
|
||||||
|
return (info.st_mode & S_IFDIR) != 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool createPathFor(const std::string &file){
|
||||||
|
int pos = file.find_last_of('/');
|
||||||
|
#if defined(_WIN32)
|
||||||
|
// Windows also supports backslashes as directory separator
|
||||||
|
if (pos == std::string::npos){pos = file.find_last_of('\\');}
|
||||||
|
#endif
|
||||||
|
if (pos == std::string::npos){
|
||||||
|
return true; // There is no parent
|
||||||
|
}
|
||||||
|
// Fail if we cannot create a parent
|
||||||
|
return createPath(file.substr(0, pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function that will attempt to create the given path if it not yet exists.
|
||||||
|
/// Returns true if path exists or was successfully created, false otherwise.
|
||||||
|
bool createPath(const std::string &path){
|
||||||
|
#if defined(_WIN32)
|
||||||
|
int ret = _mkdir(path.c_str());
|
||||||
|
#else
|
||||||
|
mode_t mode = 0755;
|
||||||
|
int ret = mkdir(path.c_str(), mode);
|
||||||
|
#endif
|
||||||
|
if (ret == 0){// Success!
|
||||||
|
INFO_MSG("Created directory: %s", path.c_str());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (errno){
|
||||||
|
case ENOENT:{// Parent does not exist
|
||||||
|
int pos = path.find_last_of('/');
|
||||||
|
#if defined(_WIN32)
|
||||||
|
// Windows also supports backslashes as directory separator
|
||||||
|
if (pos == std::string::npos){pos = path.find_last_of('\\');}
|
||||||
|
#endif
|
||||||
|
if (pos == std::string::npos){
|
||||||
|
// fail if there is no parent
|
||||||
|
// Theoretically cannot happen, but who knows
|
||||||
|
FAIL_MSG("Could not create %s: %s", path.c_str(), strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Fail if we cannot create a parent
|
||||||
|
if (!createPath(path.substr(0, pos))) return false;
|
||||||
|
#if defined(_WIN32)
|
||||||
|
ret = _mkdir(path.c_str());
|
||||||
|
#else
|
||||||
|
ret = mkdir(path.c_str(), mode);
|
||||||
|
#endif
|
||||||
|
if (ret){FAIL_MSG("Could not create %s: %s", path.c_str(), strerror(errno));}
|
||||||
|
return (ret == 0);
|
||||||
|
}
|
||||||
|
case EEXIST: // Is a file or directory
|
||||||
|
if (isDirectory(path)){
|
||||||
|
return true; // All good, already exists
|
||||||
|
}else{
|
||||||
|
FAIL_MSG("Not a directory: %s", path.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: // Generic failure
|
||||||
|
FAIL_MSG("Could not create %s: %s", path.c_str(), strerror(errno));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool stringScan(const std::string &src, const std::string &pattern,
|
||||||
|
std::deque<std::string> &result){
|
||||||
result.clear();
|
result.clear();
|
||||||
std::deque<size_t> positions;
|
std::deque<size_t> positions;
|
||||||
size_t pos = pattern.find("%", 0);
|
size_t pos = pattern.find("%", 0);
|
||||||
|
@ -27,15 +110,14 @@ namespace Util{
|
||||||
positions.push_back(pos);
|
positions.push_back(pos);
|
||||||
pos = pattern.find("%", pos + 1);
|
pos = pattern.find("%", pos + 1);
|
||||||
}
|
}
|
||||||
if (positions.size() == 0){
|
if (positions.size() == 0){return false;}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
size_t sourcePos = 0;
|
size_t sourcePos = 0;
|
||||||
size_t patternPos = 0;
|
size_t patternPos = 0;
|
||||||
std::deque<size_t>::iterator posIter = positions.begin();
|
std::deque<size_t>::iterator posIter = positions.begin();
|
||||||
while (sourcePos != std::string::npos){
|
while (sourcePos != std::string::npos){
|
||||||
// Match first part of the string
|
// Match first part of the string
|
||||||
if (pattern.substr(patternPos, *posIter - patternPos) != src.substr(sourcePos, *posIter - patternPos)){
|
if (pattern.substr(patternPos, *posIter - patternPos) !=
|
||||||
|
src.substr(sourcePos, *posIter - patternPos)){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sourcePos += *posIter - patternPos;
|
sourcePos += *posIter - patternPos;
|
||||||
|
@ -108,16 +190,13 @@ namespace Util{
|
||||||
// Simple sizes in bytes
|
// Simple sizes in bytes
|
||||||
case 2: size = p[offset + 1 + nameLen + 1]; break;
|
case 2: size = p[offset + 1 + nameLen + 1]; break;
|
||||||
case 3: size = *(uint16_t *)(p + offset + 1 + nameLen + 1); break;
|
case 3: size = *(uint16_t *)(p + offset + 1 + nameLen + 1); break;
|
||||||
case 4:
|
case 4: size = Bit::btoh24(p + offset + 1 + nameLen + 1); break;
|
||||||
size = Bit::btoh24(p+offset+1+nameLen+1);
|
|
||||||
break;
|
|
||||||
case 5: size = *(uint32_t *)(p + offset + 1 + nameLen + 1); break;
|
case 5: size = *(uint32_t *)(p + offset + 1 + nameLen + 1); break;
|
||||||
default:
|
default: WARN_MSG("Unhandled field data size!"); break;
|
||||||
WARN_MSG("Unhandled field data size!");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
fields[fieldName] = RelAccXFieldData(fieldType, size, dataOffset);
|
fields[fieldName] = RelAccXFieldData(fieldType, size, dataOffset);
|
||||||
DONTEVEN_MSG("Field %s: type %u, size %lu, offset %lu", fieldName.c_str(), fieldType, size, dataOffset);
|
DONTEVEN_MSG("Field %s: type %u, size %lu, offset %lu", fieldName.c_str(), fieldType, size,
|
||||||
|
dataOffset);
|
||||||
dataOffset += size;
|
dataOffset += size;
|
||||||
offset += nameLen + typeLen + 1;
|
offset += nameLen + typeLen + 1;
|
||||||
}
|
}
|
||||||
|
@ -138,7 +217,9 @@ namespace Util{
|
||||||
|
|
||||||
/// Gets the number of records present
|
/// Gets the number of records present
|
||||||
/// Defaults to the record count if set to zero.
|
/// Defaults to the record count if set to zero.
|
||||||
uint32_t RelAccX::getPresent() const{return (RAXHDR_PRESENT ? RAXHDR_PRESENT : RAXHDR_RECORDCNT);}
|
uint32_t RelAccX::getPresent() const{
|
||||||
|
return (RAXHDR_PRESENT ? RAXHDR_PRESENT : RAXHDR_RECORDCNT);
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the offset from the structure start where records begin.
|
/// Gets the offset from the structure start where records begin.
|
||||||
uint16_t RelAccX::getOffset() const{return *(uint16_t *)(p + 26);}
|
uint16_t RelAccX::getOffset() const{return *(uint16_t *)(p + 26);}
|
||||||
|
@ -162,8 +243,10 @@ namespace Util{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the given record number into an offset of records after getOffset()'s offset.
|
/// Converts the given record number into an offset of records after getOffset()'s offset.
|
||||||
///Does no bounds checking whatsoever, allowing access to not-yet-created or already-deleted records.
|
/// Does no bounds checking whatsoever, allowing access to not-yet-created or already-deleted
|
||||||
///This access method is stable with changing start/end positions and present record counts, because it only
|
/// records.
|
||||||
|
/// This access method is stable with changing start/end positions and present record counts,
|
||||||
|
/// because it only
|
||||||
/// depends on the record count, which may not change for ring buffers.
|
/// depends on the record count, which may not change for ring buffers.
|
||||||
uint32_t RelAccX::getRecordPosition(uint64_t recordNo) const{
|
uint32_t RelAccX::getRecordPosition(uint64_t recordNo) const{
|
||||||
if (getRCount()){
|
if (getRCount()){
|
||||||
|
@ -224,15 +307,16 @@ namespace Util{
|
||||||
return 0; // Not an integer type, or not implemented
|
return 0; // Not an integer type, or not implemented
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string RelAccX::toPrettyString() const{
|
std::string RelAccX::toPrettyString() const{
|
||||||
std::stringstream r;
|
std::stringstream r;
|
||||||
uint64_t delled = getDeleted();
|
uint64_t delled = getDeleted();
|
||||||
uint64_t max = delled + getRCount();
|
uint64_t max = delled + getRCount();
|
||||||
r << "RelAccX: " << getRCount() << " x " << getRSize() << "b @" << getOffset() << " (#" << getDeleted() << " - #" << (getDeleted()+getPresent()-1) << ")" << std::endl;
|
r << "RelAccX: " << getRCount() << " x " << getRSize() << "b @" << getOffset() << " (#"
|
||||||
|
<< getDeleted() << " - #" << (getDeleted() + getPresent() - 1) << ")" << std::endl;
|
||||||
for (uint64_t i = delled; i < max; ++i){
|
for (uint64_t i = delled; i < max; ++i){
|
||||||
r << " #" << i << ":" << std::endl;
|
r << " #" << i << ":" << std::endl;
|
||||||
for (std::map<std::string, RelAccXFieldData>::const_iterator it = fields.begin(); it != fields.end(); ++it){
|
for (std::map<std::string, RelAccXFieldData>::const_iterator it = fields.begin();
|
||||||
|
it != fields.end(); ++it){
|
||||||
r << " " << it->first << ": ";
|
r << " " << it->first << ": ";
|
||||||
switch (it->second.type & 0xF0){
|
switch (it->second.type & 0xF0){
|
||||||
case RAX_INT: r << (int64_t)getInt(it->first, i) << std::endl; break;
|
case RAX_INT: r << (int64_t)getInt(it->first, i) << std::endl; break;
|
||||||
|
@ -267,7 +351,8 @@ namespace Util{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!name.size() || name.size() > 31){
|
if (!name.size() || name.size() > 31){
|
||||||
WARN_MSG("Attempting to add a field with illegal name: %s (%u chars)", name.c_str(), name.size());
|
WARN_MSG("Attempting to add a field with illegal name: %s (%u chars)", name.c_str(),
|
||||||
|
name.size());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// calculate fLen if missing
|
// calculate fLen if missing
|
||||||
|
@ -326,7 +411,6 @@ namespace Util{
|
||||||
/// Defaults to the record count if set to zero.
|
/// Defaults to the record count if set to zero.
|
||||||
void RelAccX::setPresent(uint32_t n){RAXHDR_PRESENT = n;}
|
void RelAccX::setPresent(uint32_t n){RAXHDR_PRESENT = n;}
|
||||||
|
|
||||||
|
|
||||||
/// Sets the ready flag.
|
/// Sets the ready flag.
|
||||||
/// After calling this function, addField() may no longer be called.
|
/// After calling this function, addField() may no longer be called.
|
||||||
/// Fails if exit, reload or ready are (already) set.
|
/// Fails if exit, reload or ready are (already) set.
|
||||||
|
@ -396,8 +480,10 @@ namespace Util{
|
||||||
WARN_MSG("Setting non-integer %s", name.c_str());
|
WARN_MSG("Setting non-integer %s", name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
///Updates the deleted record counter, the start position and the present record counter, shifting the ring buffer start position forward without moving the ring buffer end position.
|
/// Updates the deleted record counter, the start position and the present record counter,
|
||||||
///If the records present counter would be pushed into the negative by this function, sets it to zero, defaulting it to the record count for all relevant purposes.
|
/// shifting the ring buffer start position forward without moving the ring buffer end position.
|
||||||
|
/// If the records present counter would be pushed into the negative by this function, sets it to
|
||||||
|
/// zero, defaulting it to the record count for all relevant purposes.
|
||||||
void RelAccX::deleteRecords(uint32_t amount){
|
void RelAccX::deleteRecords(uint32_t amount){
|
||||||
uint32_t &startPos = RAXHDR_STARTPOS;
|
uint32_t &startPos = RAXHDR_STARTPOS;
|
||||||
uint64_t &deletedRecs = RAXHDR_DELETED;
|
uint64_t &deletedRecs = RAXHDR_DELETED;
|
||||||
|
@ -411,8 +497,10 @@ namespace Util{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///Updates the present record counter, shifting the ring buffer end position forward without moving the ring buffer start position.
|
/// Updates the present record counter, shifting the ring buffer end position forward without
|
||||||
///If the records present counter would be pushed past the record counter by this function, sets it to zero, defaulting it to the record count for all relevant purposes.
|
/// moving the ring buffer start position.
|
||||||
|
/// If the records present counter would be pushed past the record counter by this function, sets
|
||||||
|
/// it to zero, defaulting it to the record count for all relevant purposes.
|
||||||
void RelAccX::addRecords(uint32_t amount){
|
void RelAccX::addRecords(uint32_t amount){
|
||||||
uint32_t &recsPresent = RAXHDR_PRESENT;
|
uint32_t &recsPresent = RAXHDR_PRESENT;
|
||||||
uint32_t &recordsCount = RAXHDR_RECORDCNT;
|
uint32_t &recordsCount = RAXHDR_RECORDCNT;
|
||||||
|
@ -422,6 +510,5 @@ namespace Util{
|
||||||
recsPresent += amount;
|
recsPresent += amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
lib/util.h
27
lib/util.h
|
@ -1,10 +1,14 @@
|
||||||
#include <string>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace Util{
|
namespace Util{
|
||||||
bool stringScan(const std::string & src, const std::string & pattern, std::deque<std::string> & result);
|
bool isDirectory(const std::string &path);
|
||||||
|
bool createPathFor(const std::string &file);
|
||||||
|
bool createPath(const std::string &path);
|
||||||
|
bool stringScan(const std::string &src, const std::string &pattern,
|
||||||
|
std::deque<std::string> &result);
|
||||||
uint64_t ftell(FILE *stream);
|
uint64_t ftell(FILE *stream);
|
||||||
uint64_t fseek(FILE *stream, uint64_t offset, int whence);
|
uint64_t fseek(FILE *stream, uint64_t offset, int whence);
|
||||||
|
|
||||||
|
@ -41,8 +45,10 @@ namespace Util {
|
||||||
#define RAX_512RAW 0x45
|
#define RAX_512RAW 0x45
|
||||||
|
|
||||||
/// Reliable Access class.
|
/// Reliable Access class.
|
||||||
/// Provides reliable access to memory data structures, using dynamic static offsets and a status field.
|
/// Provides reliable access to memory data structures, using dynamic static offsets and a status
|
||||||
/// All internal fields are host byte order (since no out-of-machine accesses happen), except 24 bit fields, which are network byte order.
|
/// field.
|
||||||
|
/// All internal fields are host byte order (since no out-of-machine accesses happen), except 24
|
||||||
|
/// bit fields, which are network byte order.
|
||||||
/// Data structure:
|
/// Data structure:
|
||||||
/// 1 byte status bit fields (1 = ready, 2 = exit, 4 = reload)
|
/// 1 byte status bit fields (1 = ready, 2 = exit, 4 = reload)
|
||||||
/// 1 byte field_offset (where the field description starts)
|
/// 1 byte field_offset (where the field description starts)
|
||||||
|
@ -55,7 +61,8 @@ namespace Util {
|
||||||
/// @field_offset: offset-field_offset bytes fields:
|
/// @field_offset: offset-field_offset bytes fields:
|
||||||
/// 5 bits field name len (< 32), 3 bits type len (1-5)
|
/// 5 bits field name len (< 32), 3 bits type len (1-5)
|
||||||
/// len bytes field name string (< 32 bytes)
|
/// len bytes field name string (< 32 bytes)
|
||||||
/// 1 byte field type (0x01 = RelAccX, 0x1X = uint, 0x2X = int, 0x3X = string, 0x4X = binary)
|
/// 1 byte field type (0x01 = RelAccX, 0x1X = uint, 0x2X = int, 0x3X = string, 0x4X =
|
||||||
|
/// binary)
|
||||||
/// if type-len > 1: rest-of-type-len bytes max len
|
/// if type-len > 1: rest-of-type-len bytes max len
|
||||||
/// else, for 0xYX:
|
/// else, for 0xYX:
|
||||||
/// Y=1/2: X+1 bytes maxlen (1-16b)
|
/// Y=1/2: X+1 bytes maxlen (1-16b)
|
||||||
|
@ -65,9 +72,11 @@ namespace Util {
|
||||||
/// 0x1X/2X: X+1 bytes (u)int data
|
/// 0x1X/2X: X+1 bytes (u)int data
|
||||||
/// 0x3X: max maxlen bytes string data, zero term'd
|
/// 0x3X: max maxlen bytes string data, zero term'd
|
||||||
/// 0x4X: maxlen bytes binary data
|
/// 0x4X: maxlen bytes binary data
|
||||||
/// Setting ready means the record size, offset and fields will no longer change. Count may still go up (not down)
|
/// Setting ready means the record size, offset and fields will no longer change. Count may still
|
||||||
|
/// go up (not down)
|
||||||
/// Setting exit means the writer has exited, and readers should exit too.
|
/// Setting exit means the writer has exited, and readers should exit too.
|
||||||
/// Setting reload means the writer needed to change fields, and the pointer should be closed and re-opened through outside means (e.g. closing and re-opening the containing shm page).
|
/// Setting reload means the writer needed to change fields, and the pointer should be closed and
|
||||||
|
/// re-opened through outside means (e.g. closing and re-opening the containing shm page).
|
||||||
class RelAccX{
|
class RelAccX{
|
||||||
public:
|
public:
|
||||||
RelAccX(char *data, bool waitReady = true);
|
RelAccX(char *data, bool waitReady = true);
|
||||||
|
@ -100,11 +109,13 @@ namespace Util {
|
||||||
void setInt(const std::string &name, uint64_t val, uint64_t recordNo = 0);
|
void setInt(const std::string &name, uint64_t val, uint64_t recordNo = 0);
|
||||||
void deleteRecords(uint32_t amount);
|
void deleteRecords(uint32_t amount);
|
||||||
void addRecords(uint32_t amount);
|
void addRecords(uint32_t amount);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static uint32_t getDefaultSize(uint8_t fType);
|
static uint32_t getDefaultSize(uint8_t fType);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char *p;
|
char *p;
|
||||||
std::map<std::string, RelAccXFieldData> fields;
|
std::map<std::string, RelAccXFieldData> fields;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -571,13 +571,16 @@ namespace Mist {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateMeta();
|
updateMeta();
|
||||||
|
if (config->is_active){
|
||||||
if (streamStatus){streamStatus.mapped[0] = hasPush ? STRMSTAT_READY : STRMSTAT_WAIT;}
|
if (streamStatus){streamStatus.mapped[0] = hasPush ? STRMSTAT_READY : STRMSTAT_WAIT;}
|
||||||
|
}
|
||||||
static bool everHadPush = false;
|
static bool everHadPush = false;
|
||||||
if (hasPush) {
|
if (hasPush) {
|
||||||
hasPush = false;
|
hasPush = false;
|
||||||
everHadPush = true;
|
everHadPush = true;
|
||||||
} else if (everHadPush && !resumeMode && config->is_active) {
|
} else if (everHadPush && !resumeMode && config->is_active) {
|
||||||
INFO_MSG("Shutting down buffer because resume mode is disabled and the source disconnected");
|
INFO_MSG("Shutting down buffer because resume mode is disabled and the source disconnected");
|
||||||
|
if (streamStatus){streamStatus.mapped[0] = STRMSTAT_SHUTDOWN;}
|
||||||
config->is_active = false;
|
config->is_active = false;
|
||||||
userPage.finishEach();
|
userPage.finishEach();
|
||||||
}
|
}
|
||||||
|
@ -818,6 +821,8 @@ namespace Mist {
|
||||||
if (!myMeta.tracks.count(finalMap)) {
|
if (!myMeta.tracks.count(finalMap)) {
|
||||||
DEBUG_MSG(DLVL_MEDIUM, "Inserting metadata for track number %d", finalMap);
|
DEBUG_MSG(DLVL_MEDIUM, "Inserting metadata for track number %d", finalMap);
|
||||||
myMeta.tracks[finalMap] = trackMeta.tracks.begin()->second;
|
myMeta.tracks[finalMap] = trackMeta.tracks.begin()->second;
|
||||||
|
myMeta.tracks[finalMap].firstms = 0;
|
||||||
|
myMeta.tracks[finalMap].lastms = 0;
|
||||||
myMeta.tracks[finalMap].trackID = finalMap;
|
myMeta.tracks[finalMap].trackID = finalMap;
|
||||||
}
|
}
|
||||||
//Write the final mapped track number and keyframe number to the user page element
|
//Write the final mapped track number and keyframe number to the user page element
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <mist/defines.h>
|
#include <mist/defines.h>
|
||||||
#include <mist/http_parser.h>
|
#include <mist/http_parser.h>
|
||||||
#include <mist/timing.h>
|
#include <mist/timing.h>
|
||||||
|
#include <mist/util.h>
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
|
|
||||||
/*LTS-START*/
|
/*LTS-START*/
|
||||||
|
@ -553,7 +554,7 @@ namespace Mist{
|
||||||
VERYHIGH_MSG("Loading track %lu, containing key %lld", trackId, keyNum);
|
VERYHIGH_MSG("Loading track %lu, containing key %lld", trackId, keyNum);
|
||||||
unsigned int timeout = 0;
|
unsigned int timeout = 0;
|
||||||
unsigned long pageNum = pageNumForKey(trackId, keyNum);
|
unsigned long pageNum = pageNumForKey(trackId, keyNum);
|
||||||
while (pageNum == -1){
|
while (config->is_active && myConn && pageNum == -1){
|
||||||
if (!timeout){
|
if (!timeout){
|
||||||
HIGH_MSG("Requesting page with key %lu:%lld", trackId, keyNum);
|
HIGH_MSG("Requesting page with key %lu:%lld", trackId, keyNum);
|
||||||
}
|
}
|
||||||
|
@ -1274,6 +1275,10 @@ namespace Mist{
|
||||||
bool Output::connectToFile(std::string file){
|
bool Output::connectToFile(std::string file){
|
||||||
int flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
int flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||||
int mode = O_RDWR | O_CREAT | O_TRUNC;
|
int mode = O_RDWR | O_CREAT | O_TRUNC;
|
||||||
|
if (!Util::createPathFor(file)){
|
||||||
|
ERROR_MSG("Cannot not create file %s: could not create parent folder", file.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int outFile = open(file.c_str(), mode, flags);
|
int outFile = open(file.c_str(), mode, flags);
|
||||||
if (outFile < 0){
|
if (outFile < 0){
|
||||||
ERROR_MSG("Failed to open file %s, error: %s", file.c_str(), strerror(errno));
|
ERROR_MSG("Failed to open file %s, error: %s", file.c_str(), strerror(errno));
|
||||||
|
|
Loading…
Add table
Reference in a new issue