15 changed files with 423 additions and 196 deletions
-
46kplayer.xcodeproj/project.pbxproj
-
1kplayer/AppDelegate.swift
-
60kplayer/core/ItemType.swift
-
97kplayer/core/MediaItem.swift
-
19kplayer/core/MediaModel.swift
-
33kplayer/core/NetworkManager.swift
-
80kplayer/detail/DetailViewController.swift
-
4kplayer/detail/VideoController.swift
-
77kplayer/master/MasterViewController.swift
-
105kplayer/master/NetworkDelegate.swift
-
15kplayer/photo/PhotoController.swift
-
34kplayer/readme.md
-
22kplayer/util/FileHelper.swift
-
10kplayer/video/BMPlayer.swift
-
14kplayerTests/kplayerTests.swift
@ -0,0 +1,60 @@ |
|||
// |
|||
// Created by Marco Schmickler on 29.04.21. |
|||
// Copyright (c) 2021 Marco Schmickler. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
|
|||
enum ItemType: String, Codable, CustomStringConvertible { |
|||
/** |
|||
Repräsentiert eine Wurzel, in der nur Bilder angezeigt werden. |
|||
*/ |
|||
case PICROOT = "root" |
|||
|
|||
/** |
|||
Repräsentiert eine Wurzel, in der nur Videos angezeigt werden. |
|||
*/ |
|||
case VIDEOROOT = "videoroot" |
|||
|
|||
case FAVROOT = "favroot" |
|||
|
|||
/** |
|||
Repräsentiert eine Wurzel, in der nur Webseiten angezeigt werden. |
|||
*/ |
|||
case WEBROOT = "webroot" |
|||
|
|||
/** |
|||
Repräsentiert einen Ordner. Darin sind weitere Ordner enthalten. |
|||
*/ |
|||
case FOLDER = "folder" |
|||
|
|||
/** |
|||
Repräsentiert ein Video. Hat keine Unterordner. Die Children sind Snapshots. |
|||
*/ |
|||
case VIDEO = "video" |
|||
|
|||
/** |
|||
Web-Browser |
|||
*/ |
|||
case WEB = "web" |
|||
|
|||
/** |
|||
Snapshots eines Videos. |
|||
*/ |
|||
case SNAPSHOT = "snapshot" |
|||
|
|||
/** |
|||
Repräsentiert einen Bilder-Ordner. |
|||
*/ |
|||
case PICS = "pics" |
|||
|
|||
/** |
|||
Repräsentiert einen Ordner, der Videos oder Bilder-Ordner enthält. Wird im DetailViewController angezeigt. |
|||
*/ |
|||
case DETAILS = "details" |
|||
|
|||
var description: String { |
|||
return self.rawValue |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,19 @@ |
|||
// |
|||
// Created by Marco Schmickler on 29.04.21. |
|||
// Copyright (c) 2021 Marco Schmickler. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
|
|||
public struct MediaModel : Codable { |
|||
let name: String |
|||
let path: String |
|||
let root: String |
|||
|
|||
var time = 0.0 |
|||
var length = 0.0 |
|||
var loop = false |
|||
|
|||
var children: [MediaModel] |
|||
let type: ItemType |
|||
} |
|||
@ -0,0 +1,105 @@ |
|||
// |
|||
// Created by Marco Schmickler on 29.04.21. |
|||
// Copyright (c) 2021 Marco Schmickler. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
|
|||
class NetworkDelegate: MasterDelegate, DetailDelegate { |
|||
func loadItem(selectedItem: MediaItem, completionHandler: @escaping Weiter) { |
|||
let p = selectedItem.superRoot() |
|||
let dir = selectedItem.encodedDir! |
|||
|
|||
if p.type == ItemType.FAVROOT { |
|||
NetworkManager.sharedInstance.loadFavDirs(dir, completionHandler: completionHandler) |
|||
} |
|||
else if p.type == ItemType.VIDEOROOT { |
|||
NetworkManager.sharedInstance.loadVideoDirs(dir, completionHandler: completionHandler) |
|||
} |
|||
else if p.type == ItemType.WEBROOT { |
|||
completionHandler(p.children) |
|||
} |
|||
else { |
|||
NetworkManager.sharedInstance.loadPicDirs(dir, completionHandler: completionHandler) |
|||
} |
|||
} |
|||
|
|||
func loadFolder(selectedItem: MediaItem, completionHandler: @escaping (MediaItem) -> Void) -> Void { |
|||
|
|||
NetworkManager.sharedInstance.listDirs(selectedItem.encodedDir!) { |
|||
(i, leaf) in |
|||
|
|||
let details = MediaItem(name: selectedItem.name, path: selectedItem.path, root: selectedItem.root, type: ItemType.DETAILS) |
|||
let neu = MediaItem(name: selectedItem.name, path: "", root: "", type: ItemType.FOLDER) |
|||
let newFolder = MediaItem(name: ".", path: "", root: selectedItem.root, type: ItemType.DETAILS) |
|||
newFolder.loaded = true |
|||
|
|||
var hasDetails = false |
|||
|
|||
for item in i { |
|||
if item.type != ItemType.FOLDER && item.isVideo() { |
|||
item.parent = newFolder |
|||
newFolder.children.append(item) |
|||
} else { |
|||
if item.path == "" { |
|||
item.path = item.name |
|||
item.name = "" |
|||
} |
|||
|
|||
if item.type == ItemType.PICS { |
|||
if !hasDetails { |
|||
neu.children.append(details) |
|||
hasDetails = true |
|||
} |
|||
} else { |
|||
// item.type = ItemType.FOLDER |
|||
item.parent = selectedItem |
|||
neu.children.append(item) |
|||
} |
|||
} |
|||
} |
|||
|
|||
if newFolder.children.count > 0 { |
|||
newFolder.parent = selectedItem |
|||
neu.children.append(newFolder) |
|||
} |
|||
|
|||
let isVideo = selectedItem.parent != nil && selectedItem.parent!.type == ItemType.VIDEOROOT |
|||
if leaf || isVideo { |
|||
selectedItem.type = ItemType.DETAILS |
|||
completionHandler(selectedItem) |
|||
} |
|||
else { |
|||
completionHandler(neu) |
|||
} |
|||
} |
|||
} |
|||
|
|||
func loadDetails(selectedItem: MediaItem, completionHandler: @escaping () -> ()) { |
|||
|
|||
if selectedItem.isPic() { |
|||
NetworkManager.sharedInstance.loadPicDetails(items: selectedItem, result: { (im: [MediaItem]) in |
|||
selectedItem.children = im |
|||
completionHandler() |
|||
}) |
|||
} |
|||
else { |
|||
completionHandler() |
|||
} |
|||
} |
|||
|
|||
func deleteThumb(selectedItem c: MediaItem) { |
|||
if let t = c.time { |
|||
let ms = Int(t * 1000) |
|||
let p = c.snapshotDirPathForVideo + "\(ms).jpg" |
|||
let pt = c.snapshotDirPathForVideo + "\(ms)_thumb.jpg" |
|||
|
|||
// NetworkManager.sharedInstance.deleteThumb(p) |
|||
NetworkManager.sharedInstance.deleteThumb(pt) |
|||
} |
|||
} |
|||
|
|||
func saveItem(selectedItem: MediaItem) { |
|||
NetworkManager.sharedInstance.saveItem(selectedItem) |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
KPlayer verwaltet MediaItems |
|||
|
|||
Ein MediaItem ist |
|||
|
|||
ein Root |
|||
ein Folder |
|||
ein Detail |
|||
|
|||
Ein Root kann Children vom Server oder lokal laden. |
|||
|
|||
Ein Folder ist eine Zwischenebene unter Root (optional) |
|||
|
|||
Ein Detail ist |
|||
- ein Video |
|||
- eine Bilderserie |
|||
- eine Webseitensammlung |
|||
|
|||
|
|||
Ein Detail hat Children, davon ein ausgewähltes. |
|||
Ein Video-Detail enthält Snapshots. |
|||
Ein Picture-Detail enthält Bilder. |
|||
Ein Web-Detail enthält Bookmarks. |
|||
|
|||
Der MasterViewController enthält eine Liste von Roots. |
|||
Wird ein Root ausgewählt, werden die Children geladen. |
|||
Gibt es Folder, wird die nächste Ebene eingeblendet. |
|||
Die Details-Liste wird im Details-Controller dargestellt. |
|||
|
|||
Der DetailsViewController zeigt die selektierte Details-Liste. |
|||
Jede Section zeigt ein Detail, die einzelnen Children werden mit Bild dargestellt. |
|||
Beim Klick auf das Bild wird ein Controller angezeigt für die verschiedenen Typen. |
|||
|
|||
|
|||
|
|||
@ -0,0 +1,22 @@ |
|||
// |
|||
// Created by Marco Schmickler on 29.04.21. |
|||
// Copyright (c) 2021 Marco Schmickler. All rights reserved. |
|||
// |
|||
|
|||
import Foundation |
|||
|
|||
struct FileHelper { |
|||
static func getDocumentsDirectory() -> URL { |
|||
// find all possible documents directories for this user |
|||
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) |
|||
|
|||
// just send back the first one, which ought to be the only one |
|||
return paths[0] |
|||
} |
|||
|
|||
static func getData(name: String) throws -> Data { |
|||
let url = getDocumentsDirectory().appendingPathComponent(name) |
|||
print(url) |
|||
return try Data(contentsOf: url) |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue