mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-23 15:30:34 -04:00
Creating bases api calls for playback.
This commit is contained in:
parent
3096249eef
commit
2462d3ad7f
@ -159,6 +159,7 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="Stream.h" />
|
||||
<ClInclude Include="Transcoder.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -13,6 +13,9 @@
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Models">
|
||||
<UniqueIdentifier>{a553acdb-cb65-47bc-8809-c5374fe91cae}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h">
|
||||
@ -24,6 +27,9 @@
|
||||
<ClInclude Include="Transcoder.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Stream.h">
|
||||
<Filter>Models</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
|
28
Kyoo.Transcoder/Stream.h
Normal file
28
Kyoo.Transcoder/Stream.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#ifdef TRANSCODER_EXPORTS
|
||||
#define API __declspec(dllexport)
|
||||
#else
|
||||
#define API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
extern "C" API struct Video
|
||||
{
|
||||
std::string title;
|
||||
Audio* audios;
|
||||
Subtitle* subtitles;
|
||||
long duration;
|
||||
};
|
||||
|
||||
extern "C" API struct Audio
|
||||
{
|
||||
std::string title;
|
||||
std::string languageCode;
|
||||
};
|
||||
|
||||
extern "C" API struct Subtitle
|
||||
{
|
||||
std::string title;
|
||||
std::string languageCode;
|
||||
};
|
@ -5,3 +5,8 @@ int Init()
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
Video ScanVideo(std::string path)
|
||||
{
|
||||
|
||||
}
|
@ -1,9 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef TRANSCODER_EXPORTS
|
||||
#define API __declspec(dllexport)
|
||||
#else
|
||||
#define API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include "Stream.h"
|
||||
|
||||
|
||||
extern "C" API int Init();
|
||||
|
||||
extern "C" API Video ScanVideo(std::string path);
|
||||
|
@ -9,5 +9,6 @@
|
||||
|
||||
// add headers that you want to pre-compile here
|
||||
#include "framework.h"
|
||||
#include <iostream>
|
||||
|
||||
#endif //PCH_H
|
||||
|
35
Kyoo/Controllers/VideoController.cs
Normal file
35
Kyoo/Controllers/VideoController.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using Kyoo.InternalAPI;
|
||||
using Kyoo.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class VideoController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager libraryManager;
|
||||
private readonly ITranscoder transcoder;
|
||||
|
||||
public VideoController(ILibraryManager libraryManager, ITranscoder transcoder)
|
||||
{
|
||||
this.libraryManager = libraryManager;
|
||||
this.transcoder = transcoder;
|
||||
}
|
||||
|
||||
[HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public IActionResult Index(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
WatchItem episode = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
|
||||
if (System.IO.File.Exists(episode.Path))
|
||||
{
|
||||
//Should check if video is playable on the client and transcode if needed.
|
||||
//Should use the right mime type
|
||||
return new PhysicalFileResult(episode.Path, "video/mp4");
|
||||
}
|
||||
else
|
||||
return NotFound();
|
||||
}
|
||||
}
|
||||
}
|
@ -8,29 +8,25 @@ using System.Diagnostics;
|
||||
namespace Kyoo.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
public class WatchController : Controller
|
||||
[ApiController]
|
||||
public class WatchController : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager libraryManager;
|
||||
private readonly ITranscoder transcoder;
|
||||
|
||||
public WatchController(ILibraryManager libraryManager, ITranscoder transcoder)
|
||||
public WatchController(ILibraryManager libraryManager)
|
||||
{
|
||||
this.libraryManager = libraryManager;
|
||||
this.transcoder = transcoder;
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("{showSlug}-s{seasonNumber}e{episodeNumber}")]
|
||||
public IActionResult Index(string showSlug, long seasonNumber, long episodeNumber)
|
||||
public ActionResult<WatchItem> Index(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
Debug.WriteLine("&Trying to watch " + showSlug + " season " + seasonNumber + " episode " + episodeNumber);
|
||||
|
||||
Episode episode = libraryManager.GetEpisode(showSlug, seasonNumber, episodeNumber);
|
||||
|
||||
Debug.WriteLine("&Transcoding at: " + episode.Path);
|
||||
transcoder.GetVideo(episode.Path);
|
||||
WatchItem item = libraryManager.GetWatchItem(showSlug, seasonNumber, episodeNumber);
|
||||
|
||||
if(item == null)
|
||||
return NotFound();
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Watch;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Kyoo.InternalAPI
|
||||
@ -13,6 +14,7 @@ namespace Kyoo.InternalAPI
|
||||
List<People> GetPeople(long showID);
|
||||
List<Genre> GetGenreForShow(long showID);
|
||||
List<Season> GetSeasons(long showID);
|
||||
(VideoStream video, List<Stream> audios, List<Stream> subtitles) GetStreams(long episodeID);
|
||||
|
||||
//Public read
|
||||
IEnumerable<Library> GetLibraries();
|
||||
@ -20,6 +22,7 @@ namespace Kyoo.InternalAPI
|
||||
Season GetSeason(string showSlug, long seasonNumber);
|
||||
List<Episode> GetEpisodes(string showSlug, long seasonNumber);
|
||||
Episode GetEpisode(string showSlug, long seasonNumber, long episodeNumber);
|
||||
WatchItem GetWatchItem(string showSlug, long seasonNumber, long episodeNumber);
|
||||
People GetPeopleBySlug(string slug);
|
||||
Genre GetGenreBySlug(string slug);
|
||||
Studio GetStudioBySlug(string slug);
|
||||
|
@ -1,9 +1,9 @@
|
||||
using Kyoo.Models;
|
||||
using Kyoo.Models.Watch;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.SQLite;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace Kyoo.InternalAPI
|
||||
{
|
||||
@ -17,7 +17,7 @@ namespace Kyoo.InternalAPI
|
||||
string databasePath = configuration.GetValue<string>("databasePath");
|
||||
|
||||
Debug.WriteLine("&Library Manager init, databasePath: " + databasePath);
|
||||
if (!File.Exists(databasePath))
|
||||
if (!System.IO.File.Exists(databasePath))
|
||||
{
|
||||
Debug.WriteLine("&Database doesn't exist, creating one.");
|
||||
|
||||
@ -303,6 +303,43 @@ namespace Kyoo.InternalAPI
|
||||
}
|
||||
}
|
||||
|
||||
public WatchItem GetWatchItem(string showSlug, long seasonNumber, long episodeNumber)
|
||||
{
|
||||
string query = "SELECT episodes.id, shows.title as showTitle, seasonNumber, episodeNumber, episodes.title, releaseDate, episodes.path FROM episodes JOIN shows ON shows.id = episodes.showID WHERE shows.slug = $showSlug AND episodes.seasonNumber = $seasonNumber AND episodes.episodeNumber = $episodeNumber;";
|
||||
|
||||
using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("$showSlug", showSlug);
|
||||
cmd.Parameters.AddWithValue("$seasonNumber", seasonNumber);
|
||||
cmd.Parameters.AddWithValue("$episodeNumber", episodeNumber);
|
||||
SQLiteDataReader reader = cmd.ExecuteReader();
|
||||
|
||||
if (reader.Read())
|
||||
return WatchItem.FromReader(reader).SetStreams(this);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public (VideoStream video, List<Stream> audios, List<Stream> subtitles) GetStreams(long episodeID)
|
||||
{
|
||||
return (new VideoStream(), null, null);
|
||||
//string query = "SELECT genres.id, genres.slug, genres.name FROM genres JOIN genresLinks l ON l.genreID = genres.id WHERE l.showID = $showID;";
|
||||
|
||||
//using (SQLiteCommand cmd = new SQLiteCommand(query, sqlConnection))
|
||||
//{
|
||||
// cmd.Parameters.AddWithValue("$episodeID", episodeID);
|
||||
// SQLiteDataReader reader = cmd.ExecuteReader();
|
||||
|
||||
// List<Genre> genres = new List<Genre>();
|
||||
|
||||
// while (reader.Read())
|
||||
// genres.Add(Stream.FromReader(reader));
|
||||
|
||||
// return genres;
|
||||
//}
|
||||
}
|
||||
|
||||
public List<People> GetPeople(long showID)
|
||||
{
|
||||
string query = "SELECT people.id, people.slug, people.name, people.imgPrimary, people.externalIDs, l.role, l.type FROM people JOIN peopleLinks l ON l.peopleID = people.id WHERE l.showID = $showID;";
|
||||
|
@ -3,5 +3,7 @@ namespace Kyoo.InternalAPI
|
||||
public interface ITranscoder
|
||||
{
|
||||
void GetVideo(string Path);
|
||||
|
||||
dynamic ScanVideo(string Path);
|
||||
}
|
||||
}
|
||||
|
@ -17,5 +17,10 @@ namespace Kyoo.InternalAPI
|
||||
{
|
||||
Debug.WriteLine("&Getting video...");
|
||||
}
|
||||
|
||||
public dynamic ScanVideo(string path)
|
||||
{
|
||||
return TranscoderAPI.ScanVideo(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,12 @@ namespace Kyoo.InternalAPI.TranscoderLink
|
||||
{
|
||||
public class TranscoderAPI
|
||||
{
|
||||
[DllImport(@"C:\Projects\Kyoo\Debug\Kyoo.Transcoder.dll", CallingConvention = CallingConvention.Cdecl)]
|
||||
private const string TranscoderPath = @"C:\Projects\Kyoo\Debug\Kyoo.Transcoder.dll";
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static int Init();
|
||||
|
||||
[DllImport(TranscoderPath, CallingConvention = CallingConvention.Cdecl)]
|
||||
public extern static dynamic ScanVideo(string path);
|
||||
}
|
||||
}
|
||||
|
@ -16,21 +16,13 @@ namespace Kyoo.Models
|
||||
public string Overview;
|
||||
public DateTime? ReleaseDate;
|
||||
|
||||
public long Runtime; //This runtime variable should be in seconds (used by the video manager so we need precisions)
|
||||
public long Runtime; //This runtime variable should be in minutes
|
||||
|
||||
[JsonIgnore] public string ImgPrimary;
|
||||
public string ExternalIDs;
|
||||
|
||||
public string Thumb; //Used in the API response only
|
||||
|
||||
public long RuntimeInMinutes
|
||||
{
|
||||
get
|
||||
{
|
||||
return Runtime / 60;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Episode() { }
|
||||
|
||||
|
17
Kyoo/Models/Stream.cs
Normal file
17
Kyoo/Models/Stream.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace Kyoo.Models.Watch
|
||||
{
|
||||
public struct Stream
|
||||
{
|
||||
public string Title;
|
||||
public string Language;
|
||||
public bool IsDefault;
|
||||
public bool IsForced;
|
||||
public string Format;
|
||||
}
|
||||
|
||||
public struct VideoStream
|
||||
{
|
||||
public string Title;
|
||||
public string Language;
|
||||
}
|
||||
}
|
63
Kyoo/Models/WatchItem.cs
Normal file
63
Kyoo/Models/WatchItem.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using Kyoo.InternalAPI;
|
||||
using Kyoo.Models.Watch;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Kyoo.Models
|
||||
{
|
||||
public class WatchItem
|
||||
{
|
||||
[JsonIgnore] public readonly long episodeID;
|
||||
|
||||
public string ShowTitle;
|
||||
public long seasonNumber;
|
||||
public long episodeNumber;
|
||||
public string Title;
|
||||
public DateTime? ReleaseDate;
|
||||
[JsonIgnore] public string Path;
|
||||
|
||||
[JsonIgnore] public VideoStream video;
|
||||
public IEnumerable<Stream> audios;
|
||||
public IEnumerable<Stream> subtitles;
|
||||
|
||||
public WatchItem() { }
|
||||
|
||||
public WatchItem(long episodeID, string showTitle, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path)
|
||||
{
|
||||
this.episodeID = episodeID;
|
||||
ShowTitle = showTitle;
|
||||
this.seasonNumber = seasonNumber;
|
||||
this.episodeNumber = episodeNumber;
|
||||
Title = title;
|
||||
ReleaseDate = releaseDate;
|
||||
Path = path;
|
||||
}
|
||||
|
||||
public WatchItem(long episodeID, string showTitle, long seasonNumber, long episodeNumber, string title, DateTime? releaseDate, string path, Stream[] audios, Stream[] subtitles) : this(episodeID, showTitle, seasonNumber, episodeNumber, title, releaseDate, path)
|
||||
{
|
||||
this.audios = audios;
|
||||
this.subtitles = subtitles;
|
||||
}
|
||||
|
||||
public static WatchItem FromReader(System.Data.SQLite.SQLiteDataReader reader)
|
||||
{
|
||||
return new WatchItem((long)reader["id"],
|
||||
reader["showTitle"] as string,
|
||||
(long)reader["seasonNumber"],
|
||||
(long)reader["episodeNumber"],
|
||||
reader["title"] as string,
|
||||
reader["releaseDate"] as DateTime?,
|
||||
reader["path"] as string);
|
||||
}
|
||||
|
||||
public WatchItem SetStreams(ILibraryManager libraryManager)
|
||||
{
|
||||
(VideoStream video, IEnumerable<Stream> audios, IEnumerable<Stream> subtitles) streams = libraryManager.GetStreams(episodeID);
|
||||
video = streams.video;
|
||||
audios = streams.audios;
|
||||
subtitles = streams.subtitles;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
@page
|
||||
@model ErrorModel
|
||||
@{
|
||||
ViewData["Title"] = "Error";
|
||||
}
|
||||
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (Model.ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Development environment should not be enabled in deployed applications</strong>, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>, and restarting the application.
|
||||
</p>
|
@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace Kyoo.Pages
|
||||
{
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public class ErrorModel : PageModel
|
||||
{
|
||||
public string RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
public void OnGet()
|
||||
{
|
||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
@using Kyoo
|
||||
@namespace Kyoo.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
Loading…
x
Reference in New Issue
Block a user