34 Commits

Author SHA1 Message Date
marmei
c1970a8393 v2.1.2.0120 2020-02-15 09:01:25 +01:00
marmei
493d612d52 Merge branch 'beta' 2020-02-14 20:02:28 +01:00
marmei
4fc4330a94 FFmpeg changed: user-agent to user_agent 2020-02-08 11:10:14 +01:00
marmei
a683533824 Update changelog-beta.md 2020-01-24 2020-01-24 19:58:00 +01:00
marmei
4b9f5826cf If no user agent is specified, the default FFmpeg or VLC user agent is used. 2020-01-24 19:48:29 +01:00
marmei
ca49d70910 Update changelog-beta.md 2020-01-13 2020-01-13 23:17:55 +01:00
marmei
1b425018d4 v2.1.1.0115-beta 2020-01-13 23:04:34 +01:00
marmei
87b36c283b URL format removed from the settings 2020-01-04 17:17:28 +01:00
marmei
6da26ff4fb Merge branch 'pr/76' into beta 2020-01-04 17:01:32 +01:00
marmei
cd08985e79 Set global domain for /web 2020-01-04 17:00:58 +01:00
Thomas Dall'Agnese
dc04519229 Use relative path when posting HTML forms 2019-12-29 20:03:37 +01:00
Thomas Dall'Agnese
c4ad96b715 Use relative path when posting HTML forms 2019-12-28 18:55:46 +01:00
Thomas Dall'Agnese
45b5e602bb Revert "Use relative path when posting HTML forms"
This reverts commit d5328f6b1a.
2019-12-28 18:43:48 +01:00
marmei
1cefbf022d Workaround for IPTVX content-type bug 2019-12-28 12:28:33 +01:00
Thomas Dall'Agnese
d5328f6b1a Use relative path when posting HTML forms 2019-12-28 10:23:54 +01:00
marmei
91b80bc8bb Add xteve.xml GZIP 2019-12-16 20:23:05 +01:00
marmei
aa763726a3 Fixed broken merge 2019-12-14 10:17:42 +01:00
marmei
66c01dd1fb Missing placeholder 2019-12-13 21:05:14 +01:00
marmei
03e1abbe90 v2.1.1.0110 2019-12-13 20:31:23 +01:00
marmei
469581e280 Add mapping desc. function 2019-12-13 19:01:18 +01:00
marmei
019c98996a Update changelog-beta.md 2019-12-08 2019-12-08 17:49:50 +01:00
marmei
36db927794 v2.1.0.0106 2019-12-08 17:47:54 +01:00
marmei
f0a49788cc User-Agent for FFmpeg and VLC 2019-12-08 17:33:46 +01:00
marmei
72767d7dbd Update changelog-beta.md 2019-12-06 2019-12-06 21:00:44 +01:00
marmei
8eecbf2b78 Update changelog-beta.md 2019-12-06 2019-12-06 20:57:26 +01:00
marmei
1a1e37fe15 v2.1.0.0105: Settings for URI scheme 2019-12-06 20:48:59 +01:00
marmei
08f6fb60e3 Fix log entry, wrong buffer value 2019-11-15 10:09:19 +01:00
marmei
eded490ac7 Update changelog-beta.md 2019-11-06 2019-11-06 18:16:14 +01:00
marmei
ed770b9dbc Merge remote-tracking branch 'origin/master' 2019-11-06 18:11:21 +01:00
marmei
6129b4911a Merge pull request #53 from taeram/patch-1
Small spelling / grammar fixes.
2019-11-05 20:29:12 +01:00
Jesse Patching
477c5f30c1 Small spelling / grammar fixes. 2019-11-04 20:28:45 -07:00
marmei
65ddc6f301 v2.1.2.0101-beta 2019-11-04 18:28:41 +01:00
marmei
3ef95c1950 RV Proxy 2019-11-04 18:23:20 +01:00
marmei
3a3798cd2d WiteHeader 2019-10-23 19:02:54 +02:00
20 changed files with 206 additions and 63 deletions

View File

@@ -31,7 +31,7 @@ Documentation for setup and configuration is [here](https://github.com/xteve-pro
* Merge external M3U files * Merge external M3U files
* Merge external XMLTV files * Merge external XMLTV files
* Automatic M3U and XMLTV update * Automatic M3U and XMLTV update
* M3U und XMLTV export * M3U and XMLTV export
#### Channel management #### Channel management
* Filtering streams * Filtering streams
@@ -84,7 +84,7 @@ Including:
--- ---
### xTeVe Beta branch ### xTeVe Beta branch
New features and bug fixes are only available in beta brunch. Only after successful testing, they are merged into the master branch. New features and bug fixes are only available in beta branch. Only after successful testing are they are merged into the master branch.
**It is not recommended to use the beta version in a production system.** **It is not recommended to use the beta version in a production system.**

View File

@@ -1,3 +1,29 @@
#### 2.1.1.0116-beta
If no user agent is specified, the default FFmpeg or VLC user agent is used.
#### 2.1.1.0115-beta
```diff
+ GZIP compression for xteve.xml file. (http://xteve.ip:34400/xmltv/xteve.xml.gz)
- Removed protocol setting for reverse proxy. HTTPS can also be configured in the proxy, where it makes more sense.
```
#### 2.1.0.0106-beta
```diff
+ User-Agent is now also used by VLC and FFmpeg.
```
#### 2.1.0.0105-beta
```diff
+ Fixed wrong buffer value in log
+ New setting: URL protocol for M3U and XML file
+ Add xml tag premiere to xteve.xml
```
#### 2.1.0.0101-beta
```diff
+ Reverse proxy fix
```
#### 2.0.3.0042-beta #### 2.0.3.0042-beta
**Version 2.0.3.0042 changes the settings.json.** **Version 2.0.3.0042 changes the settings.json.**
Settings from the current beta can not be used for the current master version 2.0.3 Settings from the current beta can not be used for the current master version 2.0.3

View File

@@ -24,7 +24,7 @@
<div id="content"> <div id="content">
<form id="authentication" action="/web/" method="post"> <form id="authentication" action="" method="post">
<h5>{{.account.username.title}}:</h5> <h5>{{.account.username.title}}:</h5>
<input id="username" type="text" name="username" placeholder="Username" value=""> <input id="username" type="text" name="username" placeholder="Username" value="">

View File

@@ -1253,6 +1253,12 @@ function openPopUp(dataType, element) {
} }
content.appendRow("{{.mapping.channelName.title}}", input); content.appendRow("{{.mapping.channelName.title}}", input);
content.description(data["name"]); content.description(data["name"]);
// Beschreibung
var dbKey = "x-description";
var input = content.createInput("text", dbKey, data[dbKey]);
input.setAttribute("placeholder", "{{.mapping.description.placeholder}}");
input.setAttribute("onchange", "javascript: this.className = 'changed'");
content.appendRow("{{.mapping.description.title}}", input);
// 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

@@ -190,6 +190,11 @@
"placeholder": "", "placeholder": "",
"description": "" "description": ""
}, },
"description": {
"title": "Channel Description",
"placeholder": "Used by the Dummy as an XML description",
"description": ""
},
"updateChannelName": { "updateChannelName": {
"title": "Update Channel Name", "title": "Update Channel Name",
"placeholder": "", "placeholder": "",
@@ -358,7 +363,7 @@
}, },
"userAgent": { "userAgent": {
"title": "User Agent", "title": "User Agent",
"description": "User Agent for HTTP requests. Only used if xTeVe is selected as the buffer.", "description": "User Agent for HTTP requests. For every HTTP connection, this value is used for the user agent. Should only be changed if xTeVe is blocked.",
"placeholder": "xTeVe" "placeholder": "xTeVe"
}, },
"backupPath": { "backupPath": {

View File

@@ -24,7 +24,7 @@
<div id="content"> <div id="content">
<form id="authentication" action="/web/" method="post"> <form id="authentication" action="" method="post">
<h5>{{.login.username.title}}:</h5> <h5>{{.login.username.title}}:</h5>
<input id="username" type="text" name="username" placeholder="Username" value=""> <input id="username" type="text" name="username" placeholder="Username" value="">

View File

@@ -1,8 +1,8 @@
package src package src
/* /*
Tuner-Limit Bild als Video rendern [ffmpeg] Tuner-Limit Bild als Video rendern [ffmpeg]
-loop 1 -i stream-limit.jpg -c:v libx264 -t 1 -pix_fmt yuv420p -vf scale=1920:1080 stream-limit.ts -loop 1 -i stream-limit.jpg -c:v libx264 -t 1 -pix_fmt yuv420p -vf scale=1920:1080 stream-limit.ts
*/ */
import ( import (
@@ -261,7 +261,9 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon
var oldSegments []string var oldSegments []string
for { // Loop 2: Temporäre Datein sind vorhanden, Daten können zum Client gesendet werden for { // Loop 2: Temporäre Datein sind vorhanden, Daten können zum Client gesendet werden
// HTTP Clientverbindung überwachen // HTTP Clientverbindung überwachen
cn, ok := w.(http.CloseNotifier) cn, ok := w.(http.CloseNotifier)
if ok { if ok {
@@ -340,10 +342,10 @@ func bufferingStream(playlistID, streamingURL, channelName string, w http.Respon
} }
/* /*
// HDHR Header // HDHR Header
w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Pragma", "no-cache") w.Header().Set("Pragma", "no-cache")
w.Header().Set("transferMode.dlna.org", "Streaming") w.Header().Set("transferMode.dlna.org", "Streaming")
*/ */
_, err := w.Write(buffer) _, err := w.Write(buffer)
@@ -449,6 +451,9 @@ func getTmpFiles(stream *ThisStream) (tmpFiles []string) {
func killClientConnection(streamID int, playlistID string, force bool) { func killClientConnection(streamID int, playlistID string, force bool) {
Lock.Lock()
defer Lock.Unlock()
if p, ok := BufferInformation.Load(playlistID); ok { if p, ok := BufferInformation.Load(playlistID); ok {
var playlist = p.(Playlist) var playlist = p.(Playlist)
@@ -493,6 +498,8 @@ func killClientConnection(streamID int, playlistID string, force bool) {
func clientConnection(stream ThisStream) (status bool) { func clientConnection(stream ThisStream) (status bool) {
status = true status = true
Lock.Lock()
defer Lock.Unlock()
if _, ok := BufferClients.Load(stream.PlaylistID + stream.MD5); !ok { if _, ok := BufferClients.Load(stream.PlaylistID + stream.MD5); !ok {
@@ -901,6 +908,8 @@ func connectToStreamingServer(streamID int, playlistID string) {
// Buffer auf die Festplatte speichern // Buffer auf die Festplatte speichern
if fileSize >= tmpFileSize/2 || n == 0 { if fileSize >= tmpFileSize/2 || n == 0 {
Lock.Lock()
bandwidth.Stop = time.Now() bandwidth.Stop = time.Now()
bandwidth.Size += fileSize bandwidth.Size += fileSize
@@ -919,6 +928,7 @@ func connectToStreamingServer(streamID int, playlistID string) {
stream.Status = true stream.Status = true
playlist.Streams[streamID] = stream playlist.Streams[streamID] = stream
BufferInformation.Store(playlistID, playlist) BufferInformation.Store(playlistID, playlist)
Lock.Unlock()
tmpSegment++ tmpSegment++
@@ -1408,8 +1418,42 @@ func thirdPartyBuffer(streamID int, playlistID string) {
return return
} }
var args = strings.Replace(options, "[URL]", url, -1) //args = strings.Replace(args, "[USER-AGENT]", Settings.UserAgent, -1)
var cmd = exec.Command(path, strings.Split(args, " ")...)
// User-Agent setzen
var args []string
for i, a := range strings.Split(options, " ") {
switch bufferType {
case "FFMPEG":
a = strings.Replace(a, "[URL]", url, -1)
if i == 0 {
if len(Settings.UserAgent) != 0 {
args = []string{"-user_agent", Settings.UserAgent}
}
}
args = append(args, a)
case "VLC":
if a == "[URL]" {
a = strings.Replace(a, "[URL]", url, -1)
args = append(args, a)
if len(Settings.UserAgent) != 0 {
args = append(args, fmt.Sprintf(":http-user-agent=%s", Settings.UserAgent))
}
} else {
args = append(args, a)
}
}
}
var cmd = exec.Command(path, args...)
debug = fmt.Sprintf("%s:%s %s", bufferType, path, args) debug = fmt.Sprintf("%s:%s %s", bufferType, path, args)
showDebug(debug, 1) showDebug(debug, 1)
@@ -1551,9 +1595,11 @@ func thirdPartyBuffer(streamID int, playlistID string) {
tmpSegment++ tmpSegment++
if stream.Status == false { if stream.Status == false {
Lock.Lock()
stream.Status = true stream.Status = true
playlist.Streams[streamID] = stream playlist.Streams[streamID] = stream
BufferInformation.Store(playlistID, playlist) BufferInformation.Store(playlistID, playlist)
Lock.Unlock()
} }
tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment) tmpFile = fmt.Sprintf("%s%d.ts", tmpFolder, tmpSegment)

View File

@@ -146,3 +146,20 @@ func extractGZIP(gzipBody []byte, fileSource string) (body []byte, err error) {
body = resB.Bytes() body = resB.Bytes()
return return
} }
func compressGZIP(data *[]byte, file string) (err error) {
if len(file) != 0 {
f, err := os.Create(file)
if err != nil {
return err
}
w := gzip.NewWriter(f)
w.Write(*data)
w.Close()
}
return
}

View File

@@ -29,6 +29,9 @@ var BufferInformation sync.Map
// BufferClients : Anzahl der Clients die einen Stream über den Buffer abspielen // BufferClients : Anzahl der Clients die einen Stream über den Buffer abspielen
var BufferClients sync.Map var BufferClients sync.Map
// Lock : Lock Map
var Lock = sync.RWMutex{}
// Init : Systeminitialisierung // Init : Systeminitialisierung
func Init() (err error) { func Init() (err error) {
@@ -95,6 +98,8 @@ func Init() (err error) {
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))
System.Compressed.GZxml = getPlatformFile(fmt.Sprintf("%s%s.xml.gz", System.Folder.Data, System.AppName))
err = activatedSystemAuthentication() err = activatedSystemAuthentication()
if err != nil { if err != nil {
return return

View File

@@ -56,6 +56,10 @@ func updateServerSettings(request RequestStruct) (settings SettingsStrcut, err e
} }
if len(newUpdateTimes) == 0 {
newUpdateTimes = append(newUpdateTimes, "0000")
}
value = newUpdateTimes value = newUpdateTimes
case "cache.images": case "cache.images":
@@ -107,6 +111,9 @@ func updateServerSettings(request RequestStruct) (settings SettingsStrcut, err e
} }
case "scheme.m3u", "scheme.xml":
createXEPGFiles = true
} }
oldSettings[key] = value oldSettings[key] = value
@@ -505,7 +512,7 @@ func saveXEpgMapping(request RequestStruct) (err error) {
System.ScanInProgress = 1 System.ScanInProgress = 1
cleanupXEPG() cleanupXEPG()
//buildXEPG(true) buildXEPG(true)
go func() { go func() {
@@ -540,8 +547,7 @@ func saveXEpgMapping(request RequestStruct) (err error) {
System.ScanInProgress = 1 System.ScanInProgress = 1
cleanupXEPG() cleanupXEPG()
//buildXEPG(false) buildXEPG(false)
createXMLTVFile() createXMLTVFile()
createM3UFile() createM3UFile()
showInfo("XEPG:" + fmt.Sprintf("Ready to use")) showInfo("XEPG:" + fmt.Sprintf("Ready to use"))

View File

@@ -45,7 +45,7 @@ func getCacheImageURL(imageURL string) (cacheImageURL string) {
if indexOfString(urlMD5+fileExtension, Data.Cache.ImagesCache) != -1 { if indexOfString(urlMD5+fileExtension, Data.Cache.ImagesCache) != -1 {
cacheImageURL = fmt.Sprintf("%s://%s/images/%s%s", System.ServerProtocol.WEB, System.Domain, urlMD5, fileExtension) cacheImageURL = fmt.Sprintf("%s://%s/images/%s%s", System.ServerProtocol.XML, System.Domain, urlMD5, fileExtension)
} else { } else {
@@ -163,7 +163,7 @@ func uploadLogo(input, filename string) (logoURL string, err error) {
return return
} }
logoURL = fmt.Sprintf("%s://%s/data_images/%s", System.ServerProtocol.WEB, System.Domain, filename) logoURL = fmt.Sprintf("%s://%s/data_images/%s", System.ServerProtocol.XML, System.Domain, filename)
return return

View File

@@ -42,6 +42,10 @@ type SystemStruct struct {
XML string XML string
} }
Compressed struct {
GZxml string
}
Flag struct { Flag struct {
Branch string Branch string
Debug int Debug int
@@ -187,6 +191,7 @@ type XEPGChannelStruct struct {
XName string `json:"x-name,required"` XName string `json:"x-name,required"`
XUpdateChannelIcon bool `json:"x-update-channel-icon,required"` XUpdateChannelIcon bool `json:"x-update-channel-icon,required"`
XUpdateChannelName bool `json:"x-update-channel-name,required"` XUpdateChannelName bool `json:"x-update-channel-name,required"`
XDescription string `json:"x-description,required"`
} }
// M3UChannelStructXEPG : M3U Struktur für XEPG // M3UChannelStructXEPG : M3U Struktur für XEPG

View File

@@ -41,6 +41,8 @@ type RequestStruct struct {
UserAgent *string `json:"user.agent,omitempty"` UserAgent *string `json:"user.agent,omitempty"`
XepgReplaceMissingImages *bool `json:"xepg.replace.missing.images,omitempty"` XepgReplaceMissingImages *bool `json:"xepg.replace.missing.images,omitempty"`
XteveAutoUpdate *bool `json:"xteveAutoUpdate,omitempty"` XteveAutoUpdate *bool `json:"xteveAutoUpdate,omitempty"`
SchemeM3U *string `json:"scheme.m3u,omitempty"`
SchemeXML *string `json:"scheme.xml,omitempty"`
} `json:"settings,omitempty"` } `json:"settings,omitempty"`
// Upload Logo // Upload Logo

View File

@@ -48,6 +48,7 @@ type Program struct {
PreviouslyShown *PreviouslyShown `xml:"previously-shown"` PreviouslyShown *PreviouslyShown `xml:"previously-shown"`
New *New `xml:"new"` New *New `xml:"new"`
Live *Live `xml:"live"` Live *Live `xml:"live"`
Premiere *Live `xml:"premiere"`
} }
// Title : Programmtitel // Title : Programmtitel

File diff suppressed because one or more lines are too long

View File

@@ -132,7 +132,7 @@ func Stream(w http.ResponseWriter, r *http.Request) {
switch Settings.Buffer { switch Settings.Buffer {
case "-": case "-":
showInfo(fmt.Sprintf("Buffer:false", Settings.Buffer)) showInfo(fmt.Sprintf("Buffer:false [%s]", Settings.Buffer))
case "xteve": case "xteve":
if strings.Index(streamInfo.URL, "rtsp://") != -1 || strings.Index(streamInfo.URL, "rtp://") != -1 { if strings.Index(streamInfo.URL, "rtsp://") != -1 || strings.Index(streamInfo.URL, "rtp://") != -1 {
@@ -206,7 +206,7 @@ func Auto(w http.ResponseWriter, r *http.Request) {
// xTeVe : Web Server /xmltv/ und /m3u/ // xTeVe : Web Server /xmltv/ und /m3u/
func xTeVe(w http.ResponseWriter, r *http.Request) { func xTeVe(w http.ResponseWriter, r *http.Request) {
var requestType, groupTitle, file, content string var requestType, groupTitle, file, content, contentType string
var err error var err error
var path = strings.TrimPrefix(r.URL.Path, "/") var path = strings.TrimPrefix(r.URL.Path, "/")
var groups = []string{} var groups = []string{}
@@ -216,7 +216,6 @@ func xTeVe(w http.ResponseWriter, r *http.Request) {
// XMLTV Datei // XMLTV Datei
if strings.Contains(path, "xmltv/") { if strings.Contains(path, "xmltv/") {
w.Header().Set("Content-Type", "application/xml")
requestType = "xml" requestType = "xml"
file = System.Folder.Data + getFilenameFromPath(path) file = System.Folder.Data + getFilenameFromPath(path)
@@ -260,6 +259,13 @@ func xTeVe(w http.ResponseWriter, r *http.Request) {
return return
} }
contentType = http.DetectContentType([]byte(content))
if strings.Contains(strings.ToLower(contentType), "xml") {
contentType = "application/xml; charset=utf-8"
}
w.Header().Set("Content-Type", contentType)
if err == nil { if err == nil {
w.Write([]byte(content)) w.Write([]byte(content))
} }
@@ -316,10 +322,12 @@ func WS(w http.ResponseWriter, r *http.Request) {
var newToken string var newToken string
if r.Header.Get("Origin") != "http://"+r.Host { /*
httpStatusError(w, r, 403) if r.Header.Get("Origin") != "http://"+r.Host {
return httpStatusError(w, r, 403)
} return
}
*/
conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024) conn, err := websocket.Upgrade(w, r, w.Header(), 1024, 1024)
if err != nil { if err != nil {
@@ -583,6 +591,8 @@ func Web(w http.ResponseWriter, r *http.Request) {
var language LanguageUI var language LanguageUI
setGlobalDomain(r.Host)
if System.Dev == true { if System.Dev == true {
lang, err = loadJSONFileToMap(fmt.Sprintf("html/lang/%s.json", Settings.Language)) lang, err = loadJSONFileToMap(fmt.Sprintf("html/lang/%s.json", Settings.Language))

View File

@@ -641,9 +641,10 @@ func createXMLTVFile() (err error) {
var xmlOutput = []byte(xml.Header + string(content)) var xmlOutput = []byte(xml.Header + string(content))
writeByteToFile(System.File.XML, xmlOutput) writeByteToFile(System.File.XML, xmlOutput)
xepgXML = XMLTV{} showInfo("XEPG:" + fmt.Sprintf("Compress XMLTV file (%s)", System.Compressed.GZxml))
err = compressGZIP(&xmlOutput, System.Compressed.GZxml)
//saveMapToJSONFile(System.File.Images, Data.Cache.ImageCache) xepgXML = XMLTV{}
return return
} }
@@ -717,6 +718,9 @@ func getProgramData(xepgChannel XEPGChannelStruct) (xepgXML XMLTV, err error) {
// Live // Live
program.Live = xmltvProgram.Live program.Live = xmltvProgram.Live
// Premiere
program.Premiere = xmltvProgram.Premiere
xepgXML.Program = append(xepgXML.Program, program) xepgXML.Program = append(xepgXML.Program, program)
} }
@@ -759,7 +763,12 @@ func createDummyProgram(xepgChannel XEPGChannelStruct) (dummyXMLTV XMLTV) {
epg.Start = epgStartTime.Format("20060102150405") + offset epg.Start = epgStartTime.Format("20060102150405") + offset
epg.Stop = epgStopTime.Format("20060102150405") + offset epg.Stop = epgStopTime.Format("20060102150405") + offset
epg.Title = append(epg.Title, &Title{Value: xepgChannel.XName + " (" + epgStartTime.Weekday().String()[0:2] + ". " + epgStartTime.Format("15:04") + " - " + epgStopTime.Format("15:04") + ")", Lang: "en"}) epg.Title = append(epg.Title, &Title{Value: xepgChannel.XName + " (" + epgStartTime.Weekday().String()[0:2] + ". " + epgStartTime.Format("15:04") + " - " + epgStopTime.Format("15:04") + ")", Lang: "en"})
epg.Desc = append(epg.Desc, &Desc{Value: "xTeVe: (" + strconv.Itoa(dummyLength) + " Minutes) " + epgStartTime.Weekday().String() + " " + epgStartTime.Format("15:04") + " - " + epgStopTime.Format("15:04"), Lang: "en"})
if len(xepgChannel.XDescription) == 0 {
epg.Desc = append(epg.Desc, &Desc{Value: "xTeVe: (" + strconv.Itoa(dummyLength) + " Minutes) " + epgStartTime.Weekday().String() + " " + epgStartTime.Format("15:04") + " - " + epgStopTime.Format("15:04"), Lang: "en"})
} else {
epg.Desc = append(epg.Desc, &Desc{Value: xepgChannel.XDescription, Lang: "en"})
}
if Settings.XepgReplaceMissingImages == true { if Settings.XepgReplaceMissingImages == true {
poster.Src = getCacheImageURL(xepgChannel.TvgLogo) poster.Src = getCacheImageURL(xepgChannel.TvgLogo)

View File

@@ -21,8 +21,7 @@ menuItems.push(new MainMenuItem("logout", "{{.mainMenu.item.logout}}", "logout.p
// Kategorien für die Einstellungen // Kategorien für die Einstellungen
var settingsCategory = new Array() var settingsCategory = new Array()
settingsCategory.push(new SettingsCategoryItem("{{.settings.category.general}}", "xteveAutoUpdate,tuner,epgSource,api")) settingsCategory.push(new SettingsCategoryItem("{{.settings.category.general}}", "xteveAutoUpdate,tuner,epgSource,api"));settingsCategory.push(new SettingsCategoryItem("{{.settings.category.files}}", "update,files.update,temp.path,cache.images,xepg.replace.missing.images"))
settingsCategory.push(new SettingsCategoryItem("{{.settings.category.files}}", "update,files.update,temp.path,cache.images,xepg.replace.missing.images"))
settingsCategory.push(new SettingsCategoryItem("{{.settings.category.streaming}}", "buffer,buffer.size.kb,buffer.timeout,user.agent,ffmpeg.path,ffmpeg.options,vlc.path,vlc.options")) settingsCategory.push(new SettingsCategoryItem("{{.settings.category.streaming}}", "buffer,buffer.size.kb,buffer.timeout,user.agent,ffmpeg.path,ffmpeg.options,vlc.path,vlc.options"))
settingsCategory.push(new SettingsCategoryItem("{{.settings.category.backup}}", "backup.path,backup.keep")) settingsCategory.push(new SettingsCategoryItem("{{.settings.category.backup}}", "backup.path,backup.keep"))
settingsCategory.push(new SettingsCategoryItem("{{.settings.category.authentication}}", "authentication.web,authentication.pms,authentication.m3u,authentication.xml,authentication.api")) settingsCategory.push(new SettingsCategoryItem("{{.settings.category.authentication}}", "authentication.web,authentication.pms,authentication.m3u,authentication.xml,authentication.api"))

View File

@@ -1532,6 +1532,13 @@ function openPopUp(dataType, element) {
content.description(data["name"]) content.description(data["name"])
// Beschreibung
var dbKey:string = "x-description"
var input = content.createInput("text", dbKey, data[dbKey])
input.setAttribute("placeholder", "{{.mapping.description.placeholder}}")
input.setAttribute("onchange", "javascript: this.className = 'changed'")
content.appendRow("{{.mapping.description.title}}", input)
// 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

@@ -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.1.0.0100" const Version = "2.1.2.0120"
// DBVersion : Datanbank Version // DBVersion : Datanbank Version
const DBVersion = "2.1.0" const DBVersion = "2.1.0"