media_streaming_loader_local.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "media/streaming/media_streaming_loader_local.h"
  8. #include "storage/cache/storage_cache_types.h"
  9. #include <QtCore/QBuffer>
  10. namespace Media {
  11. namespace Streaming {
  12. namespace {
  13. // This is the maximum file size in Telegram API.
  14. constexpr auto kMaxFileSize = 8000 * int64(512 * 1024);
  15. [[nodiscard]] int64 ValidateLocalSize(int64 size) {
  16. return (size > 0 && size <= kMaxFileSize) ? size : 0;
  17. }
  18. } // namespace
  19. LoaderLocal::LoaderLocal(std::unique_ptr<QIODevice> device)
  20. : _device(std::move(device))
  21. , _size(ValidateLocalSize(_device->size())) {
  22. Expects(_device != nullptr);
  23. if (!_size || !_device->open(QIODevice::ReadOnly)) {
  24. fail();
  25. }
  26. }
  27. Storage::Cache::Key LoaderLocal::baseCacheKey() const {
  28. return {};
  29. }
  30. int64 LoaderLocal::size() const {
  31. return _size;
  32. }
  33. void LoaderLocal::load(int64 offset) {
  34. if (_device->pos() != offset && !_device->seek(offset)) {
  35. fail();
  36. return;
  37. }
  38. auto result = _device->read(kPartSize);
  39. if (result.isEmpty()
  40. || ((result.size() != kPartSize)
  41. && (offset + result.size() != size()))) {
  42. fail();
  43. return;
  44. }
  45. crl::on_main(this, [=, result = std::move(result)]() mutable {
  46. _parts.fire({ offset, std::move(result) });
  47. });
  48. }
  49. void LoaderLocal::fail() {
  50. crl::on_main(this, [=] {
  51. _parts.fire({ LoadedPart::kFailedOffset });
  52. });
  53. }
  54. void LoaderLocal::cancel(int64 offset) {
  55. }
  56. void LoaderLocal::resetPriorities() {
  57. }
  58. void LoaderLocal::setPriority(int priority) {
  59. }
  60. void LoaderLocal::stop() {
  61. }
  62. void LoaderLocal::tryRemoveFromQueue() {
  63. }
  64. rpl::producer<LoadedPart> LoaderLocal::parts() const {
  65. return _parts.events();
  66. }
  67. rpl::producer<SpeedEstimate> LoaderLocal::speedEstimate() const {
  68. return rpl::never<SpeedEstimate>();
  69. }
  70. void LoaderLocal::attachDownloader(
  71. not_null<Storage::StreamedFileDownloader*> downloader) {
  72. Unexpected("Downloader attached to a local streaming loader.");
  73. }
  74. void LoaderLocal::clearAttachedDownloader() {
  75. Unexpected("Downloader detached from a local streaming loader.");
  76. }
  77. std::unique_ptr<LoaderLocal> MakeFileLoader(const QString &path) {
  78. return std::make_unique<LoaderLocal>(std::make_unique<QFile>(path));
  79. }
  80. std::unique_ptr<LoaderLocal> MakeBytesLoader(const QByteArray &bytes) {
  81. auto device = std::make_unique<QBuffer>();
  82. auto copy = new QByteArray(bytes);
  83. QObject::connect(device.get(), &QBuffer::destroyed, [=] {
  84. delete copy;
  85. });
  86. device->setBuffer(copy);
  87. return std::make_unique<LoaderLocal>(std::move(device));
  88. }
  89. } // namespace Streaming
  90. } // namespace Media