v2.0.0.0009

This commit is contained in:
marmei
2019-08-09 18:02:24 +02:00
21 changed files with 439 additions and 153 deletions

View File

@@ -81,6 +81,11 @@ Including:
- Crond: Daemon to execute scheduled commands - Crond: Daemon to execute scheduled commands
- Perl: Programming language - Perl: Programming language
## Beta version
New features are first available in the beta version and will be added to the master branch after successful testing
If you prefer to use the beta version, you can always switch between master and beta branch.
--- ---
### xTeVe Beta branch ### xTeVe Beta branch

View File

@@ -1,7 +1,10 @@
<<<<<<< HEAD
#### 2.0.0.0008-beta #### 2.0.0.0008-beta
##### Fixes ##### Fixes
- Pull request #6 [Error in http/https detection] window.location.protocol return "https:", not "https://" - Pull request #6 [Error in http/https detection] window.location.protocol return "https:", not "https://"
=======
>>>>>>> beta
#### 2.0.0.0007-beta #### 2.0.0.0007-beta
```diff ```diff
+ Buffer HLS: Add VOD tag from M3U8 + Buffer HLS: Add VOD tag from M3U8

View File

@@ -299,6 +299,8 @@ tbody {
#content_table input[type=text]{ #content_table input[type=text]{
width: 80%; width: 80%;
min-width: 35px;
max-width: 60px;
border: 0px; border: 0px;
background-color: #333; background-color: #333;
margin-left: 5px; margin-left: 5px;

View File

@@ -1,3 +0,0 @@
h1 {
color: green;
}

View File

@@ -583,7 +583,7 @@ var ShowContent = /** @class */ (function (_super) {
return; return;
break; break;
case "log": case "log":
var input = this.createInput("button", menuKey, "{{.button.resetlogs}}"); var input = this.createInput("button", menuKey, "{{.button.resetLogs}}");
input.setAttribute("onclick", 'javascript: resetLogs();'); input.setAttribute("onclick", 'javascript: resetLogs();');
interaction.appendChild(input); interaction.appendChild(input);
var wrapper = document.createElement("DIV"); var wrapper = document.createElement("DIV");
@@ -1252,6 +1252,7 @@ function openPopUp(dataType, element) {
input.setAttribute("readonly", "true"); input.setAttribute("readonly", "true");
} }
content.appendRow("{{.mapping.channelName.title}}", input); content.appendRow("{{.mapping.channelName.title}}", input);
content.description(data["name"]);
// Aktualisierung des Kanalnamens // Aktualisierung des Kanalnamens
if (data.hasOwnProperty("_uuid.key")) { if (data.hasOwnProperty("_uuid.key")) {
if (data["_uuid.key"] != "") { if (data["_uuid.key"] != "") {

View File

@@ -45,7 +45,7 @@
"search": "Search", "search": "Search",
"update": "Update", "update": "Update",
"craeteAccount": "Create Account", "craeteAccount": "Create Account",
"resetlogs": "Reset Logs", "resetLogs": "Reset Logs",
"uploadLogo": "Upload Logo" "uploadLogo": "Upload Logo"
}, },
"filter": { "filter": {
@@ -243,7 +243,7 @@
}, },
"password": { "password": {
"title": "Password", "title": "Password",
"placeholder": "Passoword", "placeholder": "Password",
"description": "" "description": ""
}, },
"confirm": { "confirm": {
@@ -320,7 +320,7 @@
}, },
"streamBuffering": { "streamBuffering": {
"title": "Stream Buffer", "title": "Stream Buffer",
"description": "- The stream is passed from xTeVe to Plex / Emby / M3U Player<br>- Small jerking of the streams can be compensated<br>- HLS / M3U8 support" "description": "- The stream is passed from xTeVe to Plex / Emby / M3U Player<br>- Small jerking of the streams can be compensated<br>- HLS / M3U8 support<br>- Re-streaming<br>- Separate tuner limit for each playlist"
}, },
"bufferSize": { "bufferSize": {
"title": "Buffer Size", "title": "Buffer Size",

View File

@@ -2,6 +2,7 @@ package src
import ( import (
b64 "encoding/base64" b64 "encoding/base64"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
@@ -124,35 +125,44 @@ func xteveBackup() (archiv string, err error) {
return return
} }
func xteveRestore(input string) (newWebURL string, err error) { func xteveRestore(archive string) (newWebURL string, err error) {
var newPort, oldPort string var newPort, oldPort, backupVersion, tmpRestore string
// Base64 Json String in base64 umwandeln tmpRestore = System.Folder.Temp + "restore" + string(os.PathSeparator)
b64data := input[strings.IndexByte(input, ',')+1:]
// Base64 in bytes umwandeln und speichern
sDec, err := b64.StdEncoding.DecodeString(b64data)
err = checkFolder(tmpRestore)
if err != nil { if err != nil {
return return
} }
var archive = System.Folder.Temp + "restore.zip" // Zip Archiv in tmp entpacken
err = extractZIP(archive, tmpRestore)
err = writeByteToFile(archive, sDec)
if err != nil { if err != nil {
return return
} }
// Zip Archiv entpacken // Neue Config laden um den Port und die Version zu überprüfen
newConfig, err := loadJSONFileToMap(tmpRestore + "settings.json")
if err != nil {
ShowError(err, 0)
return
}
backupVersion = newConfig["version"].(string)
if backupVersion < System.Compatibility {
err = errors.New(getErrMsg(1013))
return
}
// Zip Archiv in den Config Ordner entpacken
err = extractZIP(archive, System.Folder.Config) err = extractZIP(archive, System.Folder.Config)
if err != nil { if err != nil {
return return
} }
// Neue Config laden um den Port zu überprüfen // Neue Config laden um den Port und die Version zu überprüfen
newConfig, err := loadJSONFileToMap(System.Folder.Config + "settings.json") newConfig, err = loadJSONFileToMap(System.Folder.Config + "settings.json")
if err != nil { if err != nil {
ShowError(err, 0) ShowError(err, 0)
return return
@@ -187,5 +197,78 @@ func xteveRestore(input string) (newWebURL string, err error) {
var url = System.URLBase + "/web/" var url = System.URLBase + "/web/"
newWebURL = strings.Replace(url, ":"+oldPort, ":"+newPort, 1) newWebURL = strings.Replace(url, ":"+oldPort, ":"+newPort, 1)
os.RemoveAll(tmpRestore)
return
}
func xteveRestoreFromWeb(input string) (newWebURL string, err error) {
// Base64 Json String in base64 umwandeln
b64data := input[strings.IndexByte(input, ',')+1:]
// Base64 in bytes umwandeln und speichern
sDec, err := b64.StdEncoding.DecodeString(b64data)
if err != nil {
return
}
var archive = System.Folder.Temp + "restore.zip"
err = writeByteToFile(archive, sDec)
if err != nil {
return
}
newWebURL, err = xteveRestore(archive)
return
}
// XteveRestoreFromCLI : Wiederherstellung über die Kommandozeile
func XteveRestoreFromCLI(archive string) (err error) {
var confirm string
println()
showInfo(fmt.Sprintf("Version:%s Build: %s", System.Version, System.Build))
showInfo(fmt.Sprintf("Backup File:%s", archive))
showInfo(fmt.Sprintf("System Folder:%s", getPlatformPath(System.Folder.Config)))
println()
fmt.Print("All data will be replaced with those from the backup. Should the files be restored? [yes|no]:")
fmt.Scanln(&confirm)
switch strings.ToLower(confirm) {
case "yes":
break
case "no":
return
default:
fmt.Println("Invalid input")
return
}
if len(System.Folder.Config) > 0 {
err = checkFilePermission(System.Folder.Config)
if err != nil {
return
}
_, err = xteveRestore(archive)
if err != nil {
return
}
showHighlight(fmt.Sprintf("Restor:Backup was successfully restored. %s can now be started normally", System.Name))
}
return return
} }

View File

@@ -709,7 +709,7 @@ InitBuffer:
if resp.StatusCode != http.StatusOK { if resp.StatusCode != http.StatusOK {
showInfo("Content type:" + contentType) showInfo("Content Type:" + contentType)
showInfo("Streaming Status:" + httpStatusInfo) showInfo("Streaming Status:" + httpStatusInfo)
showInfo("Error with this URL:" + currentURL) showInfo("Error with this URL:" + currentURL)
@@ -754,7 +754,7 @@ InitBuffer:
showDebug(debug, 1) showDebug(debug, 1)
showInfo("Streaming Status:" + "HTTP Response Status [" + strconv.Itoa(resp.StatusCode) + "] " + http.StatusText(resp.StatusCode)) showInfo("Streaming Status:" + "HTTP Response Status [" + strconv.Itoa(resp.StatusCode) + "] " + http.StatusText(resp.StatusCode))
showInfo("Content type:" + contentType) showInfo("Content Type:" + contentType)
} else { } else {
@@ -790,7 +790,7 @@ InitBuffer:
} }
// Video Stream (TS) // Video Stream (TS)
case "video/mpeg", "video/mp4", "video/mp2t", "application/octet-stream": case "video/mpeg", "video/mp4", "video/mp2t", "application/octet-stream", "binary/octet-stream", "application/mp2t":
var fileSize int var fileSize int
@@ -931,7 +931,7 @@ InitBuffer:
// Umbekanntes Format // Umbekanntes Format
default: default:
showInfo("Content type:" + resp.Header.Get("Content-Type")) showInfo("Content Type:" + resp.Header.Get("Content-Type"))
err = errors.New("Streaming error") err = errors.New("Streaming error")
ShowError(err, 4003) ShowError(err, 4003)
@@ -1027,7 +1027,7 @@ func parseM3U8(stream *ThisStream) (err error) {
line = strings.Trim(line, "\r\n") line = strings.Trim(line, "\r\n")
var parameters = []string{"#EXT-X-VERSION:", "#EXT-X-MEDIA-SEQUENCE:", "#EXT-X-STREAM-INF:", "#EXTINF:"} var parameters = []string{"#EXT-X-VERSION:", "#EXT-X-PLAYLIST-TYPE:", "#EXT-X-MEDIA-SEQUENCE:", "#EXT-X-STREAM-INF:", "#EXTINF:"}
for _, parameter := range parameters { for _, parameter := range parameters {
@@ -1043,6 +1043,9 @@ func parseM3U8(stream *ThisStream) (err error) {
segment.Version = version segment.Version = version
} }
case "#EXT-X-PLAYLIST-TYPE:":
segment.PlaylistType = value
case "#EXT-X-MEDIA-SEQUENCE:": case "#EXT-X-MEDIA-SEQUENCE:":
n, err := strconv.ParseInt(value, 10, 64) n, err := strconv.ParseInt(value, 10, 64)
if err == nil { if err == nil {
@@ -1194,6 +1197,11 @@ func parseM3U8(stream *ThisStream) (err error) {
noNewSegment = false noNewSegment = false
stream.LastSequence = segment.Sequence stream.LastSequence = segment.Sequence
// Stream ist vom Typ VOD. Es muss das erste Segment der M3U8 Playlist verwendet werden.
if strings.ToUpper(segment.PlaylistType) == "VOD" {
break
}
} else { } else {
if segment.Sequence > stream.LastSequence { if segment.Sequence > stream.LastSequence {

View File

@@ -83,6 +83,11 @@ func Init() (err error) {
return return
} }
if len(System.Flag.Restore) > 0 {
// Einstellungen werden über CLI wiederhergestellt. Weitere Initialisierung ist nicht notwendig.
return
}
System.File.XML = getPlatformFile(fmt.Sprintf("%s%s.xml", System.Folder.Data, System.AppName)) System.File.XML = getPlatformFile(fmt.Sprintf("%s%s.xml", System.Folder.Data, System.AppName))
System.File.M3U = getPlatformFile(fmt.Sprintf("%s%s.m3u", System.Folder.Data, System.AppName)) System.File.M3U = getPlatformFile(fmt.Sprintf("%s%s.m3u", System.Folder.Data, System.AppName))
@@ -161,9 +166,6 @@ func Init() (err error) {
return return
} }
// DLNA Server starten
go SSDP()
// Branch festlegen // Branch festlegen
System.Branch = Settings.Branch System.Branch = Settings.Branch
@@ -194,6 +196,13 @@ func Init() (err error) {
} }
// DLNA Server starten
err = SSDP()
if err != nil {
return
}
// HTML Datein laden
loadHTMLMap() loadHTMLMap()
return return

99
src/info.go Normal file
View File

@@ -0,0 +1,99 @@
package src
import (
"fmt"
"strings"
)
// ShowSystemInfo : Systeminformationen anzeigen
func ShowSystemInfo() {
fmt.Print("Creating the information takes a moment...")
err := buildDatabaseDVR()
if err != nil {
ShowError(err, 0)
return
}
buildXEPG(false)
fmt.Println("OK")
println()
fmt.Println(fmt.Sprintf("Version: %s %s.%s", System.Name, System.Version, System.Build))
fmt.Println(fmt.Sprintf("Branch: %s", System.Branch))
fmt.Println(fmt.Sprintf("GitHub: %s/%s | Git update = %t", System.GitHub.User, System.GitHub.Repo, System.GitHub.Update))
fmt.Println(fmt.Sprintf("Folder (config): %s", System.Folder.Config))
fmt.Println(fmt.Sprintf("Streams: %d / %d", len(Data.Streams.Active), len(Data.Streams.All)))
fmt.Println(fmt.Sprintf("Filter: %d", len(Data.Filter)))
fmt.Println(fmt.Sprintf("XEPG Chanels: %d", int(Data.XEPG.XEPGCount)))
println()
fmt.Println(fmt.Sprintf("IPv4 Addresses:"))
for i, ipv4 := range System.IPAddressesV4 {
switch count := i; {
case count < 10:
fmt.Println(fmt.Sprintf(" %d. %s", count, ipv4))
break
case count < 100:
fmt.Println(fmt.Sprintf(" %d. %s", count, ipv4))
break
}
}
println()
fmt.Println(fmt.Sprintf("IPv6 Addresses:"))
for i, ipv4 := range System.IPAddressesV6 {
switch count := i; {
case count < 10:
fmt.Println(fmt.Sprintf(" %d. %s", count, ipv4))
break
case count < 100:
fmt.Println(fmt.Sprintf(" %d. %s", count, ipv4))
break
}
}
println("---")
fmt.Println("Settings [General]")
fmt.Println(fmt.Sprintf("xTeVe Update: %t", Settings.XteveAutoUpdate))
fmt.Println(fmt.Sprintf("UUID: %s", Settings.UUID))
fmt.Println(fmt.Sprintf("Tuner (Plex / Emby): %d", Settings.Tuner))
fmt.Println(fmt.Sprintf("EPG Source: %s", Settings.EpgSource))
println("---")
fmt.Println("Settings [Files]")
fmt.Println(fmt.Sprintf("Schedule: %s", strings.Join(Settings.Update, ",")))
fmt.Println(fmt.Sprintf("Files Update: %t", Settings.FilesUpdate))
fmt.Println(fmt.Sprintf("Folder (tmp): %s", Settings.TempPath))
fmt.Println(fmt.Sprintf("Image Chaching: %t", Settings.CacheImages))
fmt.Println(fmt.Sprintf("Replace EPG Image: %t", Settings.XepgReplaceMissingImages))
println("---")
fmt.Println("Settings [Streaming]")
fmt.Println(fmt.Sprintf("Buffer: %t", Settings.Buffer))
fmt.Println(fmt.Sprintf("Buffer Size: %d KB", Settings.BufferSize))
fmt.Println(fmt.Sprintf("Timeout: %d ms", int(Settings.BufferTimeout)))
fmt.Println(fmt.Sprintf("User Agent: %s", Settings.UserAgent))
println("---")
fmt.Println("Settings [Backup]")
fmt.Println(fmt.Sprintf("Folder (backup): %s", Settings.BackupPath))
fmt.Println(fmt.Sprintf("Backup Keep: %d", Settings.BackupKeep))
}

View File

@@ -12,6 +12,10 @@ import (
func showInfo(str string) { func showInfo(str string) {
if System.Flag.Info == true {
return
}
var max = 22 var max = 22
var msg = strings.SplitN(str, ":", 2) var msg = strings.SplitN(str, ":", 2)
var length = len(msg[0]) var length = len(msg[0])
@@ -240,7 +244,7 @@ func getErrMsg(errCode int) (errMsg string) {
case 1012: case 1012:
errMsg = fmt.Sprintf("Invalid formatting of the time") errMsg = fmt.Sprintf("Invalid formatting of the time")
case 1013: case 1013:
errMsg = fmt.Sprintf("Invalid settings file (%s), file must be at least version %s", System.File.Settings, System.Compatibility) errMsg = fmt.Sprintf("Invalid settings file (settings.json), file must be at least version %s", System.Compatibility)
case 1020: case 1020:
errMsg = fmt.Sprintf("Data could not be saved, invalid keyword") errMsg = fmt.Sprintf("Data could not be saved, invalid keyword")

View File

@@ -11,24 +11,26 @@ import (
) )
// SSDP : SSPD / DLNA Server // SSDP : SSPD / DLNA Server
func SSDP() { func SSDP() (err error) {
showInfo(fmt.Sprintf("SSDP / DLNA:%t", Settings.SSDP)) if Settings.SSDP == false || System.Flag.Info == true {
if Settings.SSDP == false {
return return
} }
time.Sleep(10 * time.Second) showInfo(fmt.Sprintf("SSDP / DLNA:%t", Settings.SSDP))
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
ad, err := ssdp.Advertise( ad, err := ssdp.Advertise(
"upnp:"+System.AppName, // send as "ST" fmt.Sprintf("upnp:rootdevice"), // send as "ST"
System.DeviceID+"::upnp:"+System.AppName, // send as "USN" fmt.Sprintf("uuid:%s::upnp:rootdevice", System.DeviceID), // send as "USN"
System.URLBase+"/device.xml", // send as "LOCATION" fmt.Sprintf("%s/device.xml", System.URLBase), // send as "LOCATION"
System.AppName, // send as "SERVER" System.AppName, // send as "SERVER"
1800) // send as "maxAge" in "CACHE-CONTROL" 1800) // send as "maxAge" in "CACHE-CONTROL"
if err != nil { if err != nil {
ShowError(err, 000) return
} }
// Debug SSDP // Debug SSDP
@@ -36,27 +38,27 @@ func SSDP() {
ssdp.Logger = log.New(os.Stderr, "[SSDP] ", log.LstdFlags) ssdp.Logger = log.New(os.Stderr, "[SSDP] ", log.LstdFlags)
} }
var aliveTick <-chan time.Time go func(adv *ssdp.Advertiser) {
var ai = 10
if ai > 0 { aliveTick := time.Tick(300 * time.Second)
aliveTick = time.Tick(time.Duration(ai) * time.Second)
} else {
aliveTick = make(chan time.Time)
}
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt)
loop: loop:
for { for {
select { select {
case <-aliveTick: case <-aliveTick:
ad.Alive() err = adv.Alive()
if err != nil {
ShowError(err, 0)
adv.Bye()
adv.Close()
break loop
}
case <-quit: case <-quit:
adv.Bye()
adv.Close()
os.Exit(0) os.Exit(0)
break loop break loop
@@ -64,6 +66,7 @@ loop:
} }
ad.Bye() }(ad)
ad.Close()
return
} }

View File

@@ -70,6 +70,7 @@ type ThisStream struct {
type Segment struct { type Segment struct {
Duration float64 Duration float64
Info bool Info bool
PlaylistType string
Sequence int64 Sequence int64
URL string URL string
Version int Version int

View File

@@ -34,7 +34,9 @@ type SystemStruct struct {
Flag struct { Flag struct {
Branch string Branch string
Debug int Debug int
Info bool
Port string Port string
Restore string
SSDP bool SSDP bool
} }

View File

@@ -117,7 +117,7 @@ func loadSettings() (settings SettingsStrcut, err error) {
defaults["buffer.size.kb"] = 1024 defaults["buffer.size.kb"] = 1024
defaults["buffer.timeout"] = 500 defaults["buffer.timeout"] = 500
defaults["cache.images"] = false defaults["cache.images"] = false
defaults["epgSource"] = "XEPG" defaults["epgSource"] = "PMS"
defaults["files"] = dataMap defaults["files"] = dataMap
defaults["files.update"] = true defaults["files.update"] = true
defaults["filter"] = make(map[string]interface{}) defaults["filter"] = make(map[string]interface{})

File diff suppressed because one or more lines are too long

View File

@@ -34,8 +34,20 @@ func StartWebserver() (err error) {
showInfo("DVR IP:" + System.IPAddress + ":" + Settings.Port) showInfo("DVR IP:" + System.IPAddress + ":" + Settings.Port)
var ips = len(System.IPAddressesV4) + len(System.IPAddressesV6) - 1
switch ips {
case 0:
showHighlight(fmt.Sprintf("Web Interface:%s://%s:%s/web/", System.ServerProtocol.WEB, System.IPAddress, Settings.Port)) showHighlight(fmt.Sprintf("Web Interface:%s://%s:%s/web/", System.ServerProtocol.WEB, System.IPAddress, Settings.Port))
case 1:
showHighlight(fmt.Sprintf("Web Interface:%s://%s:%s/web/ | xTeVe is also available via the other %d IP.", System.ServerProtocol.WEB, System.IPAddress, Settings.Port, ips))
default:
showHighlight(fmt.Sprintf("Web Interface:%s://%s:%s/web/ | xTeVe is also available via the other %d IP's.", System.ServerProtocol.WEB, System.IPAddress, Settings.Port, len(System.IPAddressesV4)+len(System.IPAddressesV6)-1))
}
if err = http.ListenAndServe(":"+port, nil); err != nil { if err = http.ListenAndServe(":"+port, nil); err != nil {
ShowError(err, 1001) ShowError(err, 1001)
return return
@@ -147,7 +159,8 @@ func Stream(w http.ResponseWriter, r *http.Request) {
showInfo("Streaming URL:" + streamInfo.URL) showInfo("Streaming URL:" + streamInfo.URL)
http.Redirect(w, r, streamInfo.URL, 302) http.Redirect(w, r, streamInfo.URL, 302)
showInfo("Streaming Info:URL was passed to the client") showInfo("Streaming Info:URL was passed to the client.")
showInfo("Streaming Info:xTeVe is no longer involved, the client connects directly to the streaming server.")
} }
@@ -302,6 +315,8 @@ func WS(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Could not open websocket connection", http.StatusBadRequest) http.Error(w, "Could not open websocket connection", http.StatusBadRequest)
} }
setGlobalDomain(r.Host)
for { for {
err = conn.ReadJSON(&request) err = conn.ReadJSON(&request)
@@ -447,7 +462,7 @@ func WS(w http.ResponseWriter, r *http.Request) {
file, errNew := xteveBackup() file, errNew := xteveBackup()
err = errNew err = errNew
if err == nil { if err == nil {
response.OpenLink = System.URLBase + "/download/" + file response.OpenLink = fmt.Sprintf("%s://%s/download/%s", System.ServerProtocol.WEB, System.Domain, file)
} }
case "xteveRestore": case "xteveRestore":
@@ -457,9 +472,10 @@ func WS(w http.ResponseWriter, r *http.Request) {
if len(request.Base64) > 0 { if len(request.Base64) > 0 {
newWebURL, err := xteveRestore(request.Base64) newWebURL, err := xteveRestoreFromWeb(request.Base64)
if err != nil { if err != nil {
ShowError(err, 000) ShowError(err, 000)
response.Alert = err.Error()
} }
if err == nil { if err == nil {
@@ -528,7 +544,6 @@ func WS(w http.ResponseWriter, r *http.Request) {
response.Settings = Settings response.Settings = Settings
} }
setGlobalDomain(r.Host)
response = setDefaultResponseData(response, true) response = setDefaultResponseData(response, true)
if System.ConfigurationWizard == true { if System.ConfigurationWizard == true {
response.ConfigurationWizard = System.ConfigurationWizard response.ConfigurationWizard = System.ConfigurationWizard
@@ -582,10 +597,14 @@ func Web(w http.ResponseWriter, r *http.Request) {
if getFilenameFromPath(requestFile) == "html" { if getFilenameFromPath(requestFile) == "html" {
if len(Data.Streams.All) == 0 && System.ScanInProgress == 0 { if System.ScanInProgress == 0 {
if len(Settings.Files.M3U) == 0 || len(Settings.Files.HDHR) == 0 {
System.ConfigurationWizard = true System.ConfigurationWizard = true
} }
}
switch System.ConfigurationWizard { switch System.ConfigurationWizard {
case true: case true:
@@ -867,8 +886,6 @@ func API(w http.ResponseWriter, r *http.Request) {
case "status": case "status":
fmt.Println("-----------------------------")
os.Exit(0)
response.VersionXteve = System.Version response.VersionXteve = System.Version
response.VersionAPI = System.APIVersion response.VersionAPI = System.APIVersion
response.StreamsActive = int64(len(Data.Streams.Active)) response.StreamsActive = int64(len(Data.Streams.Active))

View File

@@ -174,9 +174,7 @@ func createXEPGMapping() {
return return
} }
if len(Data.XMLTV.Files) == 0 { if len(Data.XMLTV.Files) > 0 {
return
}
for i := len(Data.XMLTV.Files) - 1; i >= 0; i-- { for i := len(Data.XMLTV.Files) - 1; i >= 0; i-- {
@@ -221,6 +219,17 @@ func createXEPGMapping() {
} }
Data.XMLTV.Mapping = tmpMap
tmpMap = make(map[string]interface{})
} else {
if System.ConfigurationWizard == false {
showWarning(1007)
}
}
// Auswahl für den Dummy erstellen // Auswahl für den Dummy erstellen
var dummy = make(map[string]interface{}) var dummy = make(map[string]interface{})
var times = []string{"30", "60", "90", "120"} var times = []string{"30", "60", "90", "120"}
@@ -236,11 +245,8 @@ func createXEPGMapping() {
} }
Data.XMLTV.Mapping = tmpMap
Data.XMLTV.Mapping["xTeVe Dummy"] = dummy Data.XMLTV.Mapping["xTeVe Dummy"] = dummy
tmpMap = make(map[string]interface{})
return return
} }
@@ -583,7 +589,12 @@ func createXMLTVFile() (err error) {
var xepgXML XMLTV var xepgXML XMLTV
xepgXML.Generator = System.Name xepgXML.Generator = System.Name
if System.Branch == "master" {
xepgXML.Source = fmt.Sprintf("%s - %s", System.Name, System.Version) xepgXML.Source = fmt.Sprintf("%s - %s", System.Name, System.Version)
} else {
xepgXML.Source = fmt.Sprintf("%s - %s.%s", System.Name, System.Version, System.Build)
}
var tmpProgram = &XMLTV{} var tmpProgram = &XMLTV{}
@@ -749,7 +760,9 @@ func createDummyProgram(xepgChannel XEPGChannelStruct) (dummyXMLTV XMLTV) {
epg.Poster = append(epg.Poster, poster) epg.Poster = append(epg.Poster, poster)
} }
if xepgChannel.XCategory != "Movie" {
epg.EpisodeNum = append(epg.EpisodeNum, &EpisodeNum{Value: epgStartTime.Format("2006-01-02 15:04:05"), System: "original-air-date"}) epg.EpisodeNum = append(epg.EpisodeNum, &EpisodeNum{Value: epgStartTime.Format("2006-01-02 15:04:05"), System: "original-air-date"})
}
epg.New = &New{Value: ""} epg.New = &New{Value: ""}
@@ -812,10 +825,10 @@ func getEpisodeNum(program *Program, xmltvProgram *Program, xepgChannel XEPGChan
program.EpisodeNum = xmltvProgram.EpisodeNum program.EpisodeNum = xmltvProgram.EpisodeNum
if len(xepgChannel.XCategory) > 0 { if len(xepgChannel.XCategory) > 0 && xepgChannel.XCategory != "Movie" {
if len(xmltvProgram.EpisodeNum) == 0 { if len(xmltvProgram.EpisodeNum) == 0 {
program.EpisodeNum = append(program.EpisodeNum, &EpisodeNum{Value: time.Now().Format("2006-01-02"), System: "original-air-date"}) program.EpisodeNum = append(program.EpisodeNum, &EpisodeNum{Value: time.Now().Format("2006-01-02 15:04:05"), System: "original-air-date"})
} }
} }

View File

@@ -714,7 +714,7 @@ class ShowContent extends Content {
break break
case "log": case "log":
var input = this.createInput("button", menuKey, "{{.button.resetlogs}}") var input = this.createInput("button", menuKey, "{{.button.resetLogs}}")
input.setAttribute("onclick", 'javascript: resetLogs();') input.setAttribute("onclick", 'javascript: resetLogs();')
interaction.appendChild(input) interaction.appendChild(input)
@@ -1530,6 +1530,8 @@ function openPopUp(dataType, element) {
} }
content.appendRow("{{.mapping.channelName.title}}", input) content.appendRow("{{.mapping.channelName.title}}", input)
content.description(data["name"])
// Aktualisierung des Kanalnamens // Aktualisierung des Kanalnamens
if (data.hasOwnProperty("_uuid.key")) { if (data.hasOwnProperty("_uuid.key")) {
if (data["_uuid.key"] != "") { if (data["_uuid.key"] != "") {

View File

@@ -24,7 +24,7 @@ class Server {
case "http:": case "http:":
this.protocol = "ws://" this.protocol = "ws://"
break break
case "https://": case "https:":
this.protocol = "wss://" this.protocol = "wss://"
break break
} }

View File

@@ -39,7 +39,7 @@ var GitHub = GitHubStruct{Branch: "master", User: "xteve-project", Repo: "xTeVe-
const Name = "xTeVe" const Name = "xTeVe"
// Version : Version, die Build Nummer wird in der main func geparst. // Version : Version, die Build Nummer wird in der main func geparst.
const Version = "2.0.0.0001" const Version = "2.0.0.0008"
// DBVersion : Datanbank Version // DBVersion : Datanbank Version
const DBVersion = "2.0.0" const DBVersion = "2.0.0"
@@ -52,12 +52,15 @@ const Dev = false
var homeDirectory = fmt.Sprintf("%s%s.%s%s", src.GetUserHomeDirectory(), string(os.PathSeparator), strings.ToLower(Name), string(os.PathSeparator)) var homeDirectory = fmt.Sprintf("%s%s.%s%s", src.GetUserHomeDirectory(), string(os.PathSeparator), strings.ToLower(Name), string(os.PathSeparator))
var samplePath = fmt.Sprintf("%spath%sto%sxteve%s", string(os.PathSeparator), string(os.PathSeparator), string(os.PathSeparator), string(os.PathSeparator)) var samplePath = fmt.Sprintf("%spath%sto%sxteve%s", string(os.PathSeparator), string(os.PathSeparator), string(os.PathSeparator), string(os.PathSeparator))
var sampleRestore = fmt.Sprintf("%spath%sto%sfile%s", string(os.PathSeparator), string(os.PathSeparator), string(os.PathSeparator), string(os.PathSeparator))
var configFolder = flag.String("config", "", ": Config Folder ["+samplePath+"] (default: "+homeDirectory+")") var configFolder = flag.String("config", "", ": Config Folder ["+samplePath+"] (default: "+homeDirectory+")")
var port = flag.String("port", "", ": Server port [34400] (default: 34400)") var port = flag.String("port", "", ": Server port [34400] (default: 34400)")
var restore = flag.String("restore", "", ": Restore from backup ["+sampleRestore+"xteve_backup.zip]")
var gitBranch = flag.String("branch", "", ": Git Branch [master|beta] (default: master)") var gitBranch = flag.String("branch", "", ": Git Branch [master|beta] (default: master)")
var debug = flag.Int("debug", 0, ": Debug level [0 - 3] (default: 0)") var debug = flag.Int("debug", 0, ": Debug level [0 - 3] (default: 0)")
var info = flag.Bool("info", false, ": Show system info")
var h = flag.Bool("h", false, ": Show help") var h = flag.Bool("h", false, ": Show help")
func main() { func main() {
@@ -119,6 +122,22 @@ func main() {
return return
} }
// Systeminformationen anzeigen
if *info {
system.Flag.Info = true
err := src.Init()
if err != nil {
src.ShowError(err, 0)
os.Exit(0)
}
src.ShowSystemInfo()
return
}
// Webserver Port // Webserver Port
if len(*port) > 0 { if len(*port) > 0 {
system.Flag.Port = *port system.Flag.Port = *port
@@ -142,6 +161,25 @@ func main() {
system.Folder.Config = *configFolder system.Folder.Config = *configFolder
} }
// Backup wiederherstellen
if len(*restore) > 0 {
system.Flag.Restore = *restore
err := src.Init()
if err != nil {
src.ShowError(err, 0)
os.Exit(0)
}
err = src.XteveRestoreFromCLI(*restore)
if err != nil {
src.ShowError(err, 0)
}
os.Exit(0)
}
err := src.Init() err := src.Init()
if err != nil { if err != nil {
src.ShowError(err, 0) src.ShowError(err, 0)