aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/stale.yml29
-rw-r--r--.github/workflows/repo-stale.yaml27
-rw-r--r--BannedSymbols.txt1
-rw-r--r--Directory.Build.props4
-rw-r--r--Dockerfile2
-rw-r--r--Dockerfile.arm2
-rw-r--r--Dockerfile.arm642
-rw-r--r--Emby.Dlna/ContentDirectory/ControlHandler.cs104
-rw-r--r--Emby.Dlna/DlnaManager.cs3
-rw-r--r--Emby.Dlna/Emby.Dlna.csproj4
-rw-r--r--Emby.Dlna/PlayTo/PlayToController.cs10
-rw-r--r--Emby.Drawing/Emby.Drawing.csproj4
-rw-r--r--Emby.Drawing/NullImageEncoder.cs6
-rw-r--r--Emby.Naming/Common/NamingOptions.cs145
-rw-r--r--Emby.Naming/Emby.Naming.csproj4
-rw-r--r--Emby.Notifications/Emby.Notifications.csproj4
-rw-r--r--Emby.Photos/Emby.Photos.csproj4
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs6
-rw-r--r--Emby.Server.Implementations/Channels/ChannelManager.cs38
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs21
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs24
-rw-r--r--Emby.Server.Implementations/Emby.Server.Implementations.csproj6
-rw-r--r--Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs4
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs24
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs10
-rw-r--r--Emby.Server.Implementations/Library/SearchEngine.cs10
-rw-r--r--Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs79
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs20
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs126
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs64
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs5
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs18
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs2
-rw-r--r--Emby.Server.Implementations/Localization/Core/cs.json2
-rw-r--r--Emby.Server.Implementations/Localization/Core/fr.json2
-rw-r--r--Emby.Server.Implementations/Localization/Core/ro.json4
-rw-r--r--Emby.Server.Implementations/Localization/Core/th.json3
-rw-r--r--Emby.Server.Implementations/Localization/Core/ug.json9
-rw-r--r--Emby.Server.Implementations/Net/UdpSocket.cs4
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs4
-rw-r--r--Emby.Server.Implementations/TV/TVSeriesManager.cs9
-rw-r--r--Jellyfin.Api/Controllers/ApiKeyController.cs6
-rw-r--r--Jellyfin.Api/Controllers/ArtistsController.cs18
-rw-r--r--Jellyfin.Api/Controllers/DynamicHlsController.cs173
-rw-r--r--Jellyfin.Api/Controllers/ImageController.cs231
-rw-r--r--Jellyfin.Api/Controllers/InstantMixController.cs10
-rw-r--r--Jellyfin.Api/Controllers/ItemLookupController.cs3
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs17
-rw-r--r--Jellyfin.Api/Controllers/LibraryController.cs18
-rw-r--r--Jellyfin.Api/Controllers/LiveTvController.cs19
-rw-r--r--Jellyfin.Api/Controllers/PersonsController.cs6
-rw-r--r--Jellyfin.Api/Controllers/PlaylistsController.cs9
-rw-r--r--Jellyfin.Api/Controllers/SuggestionsController.cs9
-rw-r--r--Jellyfin.Api/Controllers/TvShowsController.cs33
-rw-r--r--Jellyfin.Api/Controllers/UserLibraryController.cs19
-rw-r--r--Jellyfin.Api/Controllers/UserViewsController.cs6
-rw-r--r--Jellyfin.Api/Controllers/VideosController.cs7
-rw-r--r--Jellyfin.Api/Controllers/YearsController.cs8
-rw-r--r--Jellyfin.Api/Helpers/RequestHelpers.cs9
-rw-r--r--Jellyfin.Api/Jellyfin.Api.csproj5
-rw-r--r--Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs10
-rw-r--r--Jellyfin.Data/Jellyfin.Data.csproj4
-rw-r--r--Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj4
-rw-r--r--Jellyfin.Drawing.Skia/SkiaEncoder.cs8
-rw-r--r--Jellyfin.Drawing.Skia/SkiaHelper.cs37
-rw-r--r--Jellyfin.Drawing.Skia/SplashscreenBuilder.cs148
-rw-r--r--Jellyfin.Drawing.Skia/StripCollageBuilder.cs32
-rw-r--r--Jellyfin.Networking/Jellyfin.Networking.csproj4
-rw-r--r--Jellyfin.Server.Implementations/Activity/ActivityManager.cs11
-rw-r--r--Jellyfin.Server.Implementations/Devices/DeviceManager.cs20
-rw-r--r--Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj6
-rw-r--r--Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs14
-rw-r--r--Jellyfin.Server/Jellyfin.Server.csproj9
-rw-r--r--Jellyfin.Server/Program.cs27
-rw-r--r--Jellyfin.Server/Startup.cs3
-rw-r--r--Jellyfin.sln32
-rw-r--r--MediaBrowser.Common/Extensions/ProcessExtensions.cs2
-rw-r--r--MediaBrowser.Common/MediaBrowser.Common.csproj4
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs2
-rw-r--r--MediaBrowser.Controller/Drawing/IImageEncoder.cs7
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs38
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs13
-rw-r--r--MediaBrowser.Controller/Entities/Movies/Movie.cs1
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs26
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs2
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs2
-rw-r--r--MediaBrowser.Controller/Library/IMetadataFileSaver.cs5
-rw-r--r--MediaBrowser.Controller/Library/IMetadataSaver.cs6
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs2
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj4
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs6
-rw-r--r--MediaBrowser.Controller/Providers/IProviderManager.cs6
-rw-r--r--MediaBrowser.Controller/Providers/ImageRefreshOptions.cs5
-rw-r--r--MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs1
-rw-r--r--MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs43
-rw-r--r--MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj4
-rw-r--r--MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs284
-rw-r--r--MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs6
-rw-r--r--MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs9
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs3
-rw-r--r--MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj4
-rw-r--r--MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs12
-rw-r--r--MediaBrowser.Model/Branding/BrandingOptions.cs43
-rw-r--r--MediaBrowser.Model/Configuration/EncodingOptions.cs5
-rw-r--r--MediaBrowser.Model/Dto/BaseItemDto.cs8
-rw-r--r--MediaBrowser.Model/Dto/BaseItemPerson.cs3
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj4
-rw-r--r--MediaBrowser.Model/Querying/QueryResult.cs7
-rw-r--r--MediaBrowser.Providers/Books/AudioBookMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Books/BookMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Channels/ChannelMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Folders/FolderMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Folders/UserViewMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Genres/GenreMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/LiveTv/LiveTvMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Manager/ItemImageProvider.cs123
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs347
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs22
-rw-r--r--MediaBrowser.Providers/Manager/ProviderUtils.cs295
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj6
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs35
-rw-r--r--MediaBrowser.Providers/Movies/MovieMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Movies/TrailerMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Music/AlbumMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Music/ArtistMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Music/AudioMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Music/MusicVideoMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/People/PersonMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Photos/PhotoMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Configuration/PluginConfiguration.cs10
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Configuration/config.html14
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieImageProvider.cs7
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs5
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs7
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs16
-rw-r--r--MediaBrowser.Providers/Studios/StudioMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Subtitles/SubtitleManager.cs7
-rw-r--r--MediaBrowser.Providers/TV/EpisodeMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/TV/SeasonMetadataService.cs6
-rw-r--r--MediaBrowser.Providers/TV/SeriesMetadataService.cs2
-rw-r--r--MediaBrowser.Providers/Videos/VideoMetadataService.cs7
-rw-r--r--MediaBrowser.Providers/Years/YearMetadataService.cs7
-rw-r--r--MediaBrowser.XbmcMetadata/EntryPoint.cs6
-rw-r--r--MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj4
-rw-r--r--MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs13
-rw-r--r--MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs15
-rw-r--r--RSSDP/DeviceAvailableEventArgs.cs2
-rw-r--r--RSSDP/DeviceUnavailableEventArgs.cs2
-rw-r--r--RSSDP/ISsdpCommunicationsServer.cs4
-rw-r--r--RSSDP/RequestReceivedEventArgs.cs2
-rw-r--r--RSSDP/ResponseReceivedEventArgs.cs2
-rw-r--r--RSSDP/SsdpCommunicationsServer.cs4
-rw-r--r--RSSDP/SsdpDeviceLocator.cs2
-rw-r--r--jellyfin.ruleset5
-rw-r--r--src/Jellyfin.Extensions/Jellyfin.Extensions.csproj4
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Cache/CacheDecorator.cs96
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Extensions/MediaEncodingHlsServiceCollectionExtensions.cs36
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Extractors/FfProbeKeyframeExtractor.cs58
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs24
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Extractors/MatroskaKeyframeExtractor.cs48
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj35
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Playlist/CreateMainPlaylistRequest.cs56
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs207
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/Playlist/IDynamicHlsPlaylistGenerator.cs14
-rw-r--r--src/Jellyfin.MediaEncoding.Hls/ScheduledTasks/KeyframeExtractionScheduledTask.cs111
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs94
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/FfTool/FfToolKeyframeExtractor.cs17
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj33
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/KeyframeData.cs30
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/Matroska/Extensions/EbmlReaderExtensions.cs177
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaConstants.cs30
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs87
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/Matroska/Models/Info.cs28
-rw-r--r--src/Jellyfin.MediaEncoding.Keyframes/Matroska/Models/SeekHead.cs35
-rw-r--r--tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj6
-rw-r--r--tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj6
-rw-r--r--tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj6
-rw-r--r--tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj6
-rw-r--r--tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj6
-rw-r--r--tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj37
-rw-r--r--tests/Jellyfin.MediaEncoding.Hls.Tests/Playlist/DynamicHlsPlaylistGeneratorTests.cs101
-rw-r--r--tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/FfProbeKeyframeExtractorTests.cs28
-rw-r--r--tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes.txt16937
-rw-r--r--tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_result.json1
-rw-r--r--tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_streamduration.txt2398
-rw-r--r--tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_streamduration_result.json1
-rw-r--r--tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj53
-rw-r--r--tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj6
-rw-r--r--tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj6
-rw-r--r--tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj6
-rw-r--r--tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj6
-rw-r--r--tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj6
-rw-r--r--tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs189
-rw-r--r--tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs378
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj6
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs46
-rw-r--r--tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs34
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj6
-rw-r--r--tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj6
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj6
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs14
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Test Data/Sonarr-Thumb.nfo34
212 files changed, 23382 insertions, 1659 deletions
diff --git a/.github/stale.yml b/.github/stale.yml
deleted file mode 100644
index cba9c33b2..000000000
--- a/.github/stale.yml
+++ /dev/null
@@ -1,29 +0,0 @@
-# Number of days of inactivity before an issue becomes stale
-daysUntilStale: 120
-# Number of days of inactivity before a stale issue is closed
-daysUntilClose: 21
-# Issues with these labels will never be considered stale
-exemptLabels:
- - regression
- - security
- - dotnet-3.0-future
- - roadmap
- - future
- - feature
- - enhancement
- - confirmed
-# Label to use when marking an issue as stale
-staleLabel: stale
-# Comment to post when marking an issue as stale. Set to `false` to disable
-markComment: >
- This issue has gone 120 days without comment. To avoid abandoned issues, it will be closed in 21 days if there are no new comments.
-
- If you're the original submitter of this issue, please comment confirming if this issue still affects you in the latest release or nightlies, or close the issue if it has been fixed. If you're another user also affected by this bug, please comment confirming so. Either action will remove the stale label.
-
- This bot exists to prevent issues from becoming stale and forgotten. Jellyfin is always moving forward, and bugs are often fixed as side effects of other changes. We therefore ask that bug report authors remain vigilant about their issues to ensure they are closed if fixed, or re-confirmed - perhaps with fresh logs or reproduction examples - regularly. If you have any questions you can reach us on [Matrix or Social Media](https://docs.jellyfin.org/general/getting-help.html).
-# Comment to post when closing a stale issue. Set to `false` to disable
-closeComment: false
-
-# Disable automatic closing of pull requests
-pulls:
- daysUntilClose: false
diff --git a/.github/workflows/repo-stale.yaml b/.github/workflows/repo-stale.yaml
new file mode 100644
index 000000000..63ded4140
--- /dev/null
+++ b/.github/workflows/repo-stale.yaml
@@ -0,0 +1,27 @@
+name: Issue Stale Check
+
+on:
+ schedule:
+ - cron: '30 1 * * *'
+ workflow_dispatch:
+
+jobs:
+ stale:
+ runs-on: ubuntu-latest
+ if: ${{ contains(github.repository, 'jellyfin/') }}
+ steps:
+ - uses: actions/stale@v4.1.0
+ with:
+ repo-token: ${{ secrets.JF_BOT_TOKEN }}
+ days-before-stale: 120
+ days-before-pr-stale: -1
+ days-before-close: 21
+ days-before-pr-close: -1
+ exempt-issue-labels: regression,security,roadmap,future,feature,enhancement,confirmed
+ stale-issue-label: stale
+ stale-issue-message: |-
+ This issue has gone 120 days without comment. To avoid abandoned issues, it will be closed in 21 days if there are no new comments.
+
+ If you're the original submitter of this issue, please comment confirming if this issue still affects you in the latest release or master branch, or close the issue if it has been fixed. If you're another user also affected by this bug, please comment confirming so. Either action will remove the stale label.
+
+ This bot exists to prevent issues from becoming stale and forgotten. Jellyfin is always moving forward, and bugs are often fixed as side effects of other changes. We therefore ask that bug report authors remain vigilant about their issues to ensure they are closed if fixed, or re-confirmed - perhaps with fresh logs or reproduction examples - regularly. If you have any questions you can reach us on [Matrix or Social Media](https://docs.jellyfin.org/general/getting-help.html).
diff --git a/BannedSymbols.txt b/BannedSymbols.txt
new file mode 100644
index 000000000..dc291e22a
--- /dev/null
+++ b/BannedSymbols.txt
@@ -0,0 +1 @@
+P:System.Threading.Tasks.Task`1.Result
diff --git a/Directory.Build.props b/Directory.Build.props
index b27782918..efcfb7224 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -14,4 +14,8 @@
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
</PropertyGroup>
+ <ItemGroup>
+ <AdditionalFiles Include="$(SolutionDir)/BannedSymbols.txt" />
+ </ItemGroup>
+
</Project>
diff --git a/Dockerfile b/Dockerfile
index e133c0819..f0090889f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -83,7 +83,7 @@ COPY --from=builder /jellyfin /jellyfin
COPY --from=web-builder /dist /jellyfin/jellyfin-web
EXPOSE 8096
-VOLUME /cache /config /media
+VOLUME /cache /config
ENTRYPOINT ["./jellyfin/jellyfin", \
"--datadir", "/config", \
"--cachedir", "/cache", \
diff --git a/Dockerfile.arm b/Dockerfile.arm
index a46fa331d..b25e6039f 100644
--- a/Dockerfile.arm
+++ b/Dockerfile.arm
@@ -74,7 +74,7 @@ COPY --from=builder /jellyfin /jellyfin
COPY --from=web-builder /dist /jellyfin/jellyfin-web
EXPOSE 8096
-VOLUME /cache /config /media
+VOLUME /cache /config
ENTRYPOINT ["./jellyfin/jellyfin", \
"--datadir", "/config", \
"--cachedir", "/cache", \
diff --git a/Dockerfile.arm64 b/Dockerfile.arm64
index 1279c47f8..d0be834dd 100644
--- a/Dockerfile.arm64
+++ b/Dockerfile.arm64
@@ -65,7 +65,7 @@ COPY --from=builder /jellyfin /jellyfin
COPY --from=web-builder /dist /jellyfin/jellyfin-web
EXPOSE 8096
-VOLUME /cache /config /media
+VOLUME /cache /config
ENTRYPOINT ["./jellyfin/jellyfin", \
"--datadir", "/config", \
"--cachedir", "/cache", \
diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs
index 0cd1a0daf..57170bb31 100644
--- a/Emby.Dlna/ContentDirectory/ControlHandler.cs
+++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs
@@ -619,7 +619,7 @@ namespace Emby.Dlna.ContentDirectory
var queryResult = folder.GetItems(query);
- return ToResult(queryResult);
+ return ToResult(startIndex, queryResult);
}
/// <summary>
@@ -642,7 +642,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
- return ToResult(result);
+ return ToResult(startIndex, result);
}
/// <summary>
@@ -707,11 +707,10 @@ namespace Emby.Dlna.ContentDirectory
serverItems = serverItems[..limit.Value];
}
- return new QueryResult<ServerItem>
- {
- Items = serverItems,
- TotalRecordCount = serverItems.Length
- };
+ return new QueryResult<ServerItem>(
+ startIndex,
+ serverItems.Length,
+ serverItems);
}
/// <summary>
@@ -764,11 +763,10 @@ namespace Emby.Dlna.ContentDirectory
array = array[..limit.Value];
}
- return new QueryResult<ServerItem>
- {
- Items = array,
- TotalRecordCount = array.Length
- };
+ return new QueryResult<ServerItem>(
+ startIndex,
+ array.Length,
+ array);
}
/// <summary>
@@ -790,11 +788,10 @@ namespace Emby.Dlna.ContentDirectory
.Select(i => new ServerItem(i, StubType.Folder))
.ToArray();
- return new QueryResult<ServerItem>
- {
- Items = items,
- TotalRecordCount = totalRecordCount
- };
+ return new QueryResult<ServerItem>(
+ startIndex,
+ totalRecordCount,
+ items);
}
/// <summary>
@@ -850,11 +847,10 @@ namespace Emby.Dlna.ContentDirectory
serverItems = serverItems[..limit.Value];
}
- return new QueryResult<ServerItem>
- {
- Items = serverItems,
- TotalRecordCount = serverItems.Length
- };
+ return new QueryResult<ServerItem>(
+ startIndex,
+ serverItems.Length,
+ serverItems);
}
/// <summary>
@@ -879,7 +875,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
- return ToResult(result);
+ return ToResult(query.StartIndex, result);
}
/// <summary>
@@ -894,7 +890,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
- return ToResult(result);
+ return ToResult(query.StartIndex, result);
}
/// <summary>
@@ -914,7 +910,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
- return ToResult(result);
+ return ToResult(query.StartIndex, result);
}
/// <summary>
@@ -931,7 +927,7 @@ namespace Emby.Dlna.ContentDirectory
query.AncestorIds = new[] { parent.Id };
var genresResult = _libraryManager.GetGenres(query);
- return ToResult(genresResult);
+ return ToResult(query.StartIndex, genresResult);
}
/// <summary>
@@ -947,7 +943,7 @@ namespace Emby.Dlna.ContentDirectory
query.AncestorIds = new[] { parent.Id };
var genresResult = _libraryManager.GetMusicGenres(query);
- return ToResult(genresResult);
+ return ToResult(query.StartIndex, genresResult);
}
/// <summary>
@@ -963,7 +959,7 @@ namespace Emby.Dlna.ContentDirectory
query.AncestorIds = new[] { parent.Id };
var artists = _libraryManager.GetAlbumArtists(query);
- return ToResult(artists);
+ return ToResult(query.StartIndex, artists);
}
/// <summary>
@@ -978,7 +974,7 @@ namespace Emby.Dlna.ContentDirectory
query.OrderBy = Array.Empty<(string, SortOrder)>();
query.AncestorIds = new[] { parent.Id };
var artists = _libraryManager.GetArtists(query);
- return ToResult(artists);
+ return ToResult(query.StartIndex, artists);
}
/// <summary>
@@ -994,7 +990,7 @@ namespace Emby.Dlna.ContentDirectory
query.AncestorIds = new[] { parent.Id };
query.IsFavorite = true;
var artists = _libraryManager.GetArtists(query);
- return ToResult(artists);
+ return ToResult(query.StartIndex, artists);
}
/// <summary>
@@ -1010,7 +1006,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
- return ToResult(result);
+ return ToResult(query.StartIndex, result);
}
/// <summary>
@@ -1034,7 +1030,7 @@ namespace Emby.Dlna.ContentDirectory
new[] { parent },
query.DtoOptions);
- return ToResult(result);
+ return ToResult(query.StartIndex, result);
}
/// <summary>
@@ -1060,7 +1056,7 @@ namespace Emby.Dlna.ContentDirectory
},
query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null).ToArray();
- return ToResult(items);
+ return ToResult(query.StartIndex, items);
}
/// <summary>
@@ -1087,7 +1083,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
- return ToResult(result);
+ return ToResult(startIndex, result);
}
/// <summary>
@@ -1118,7 +1114,7 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
- return ToResult(result);
+ return ToResult(startIndex, result);
}
/// <summary>
@@ -1145,33 +1141,34 @@ namespace Emby.Dlna.ContentDirectory
var result = _libraryManager.GetItemsResult(query);
- return ToResult(result);
+ return ToResult(startIndex, result);
}
/// <summary>
/// Converts <see cref="IReadOnlyCollection{BaseItem}"/> into a <see cref="QueryResult{ServerItem}"/>.
/// </summary>
+ /// <param name="startIndex">The start index.</param>
/// <param name="result">An array of <see cref="BaseItem"/>.</param>
/// <returns>A <see cref="QueryResult{ServerItem}"/>.</returns>
- private static QueryResult<ServerItem> ToResult(IReadOnlyCollection<BaseItem> result)
+ private static QueryResult<ServerItem> ToResult(int? startIndex, IReadOnlyCollection<BaseItem> result)
{
var serverItems = result
.Select(i => new ServerItem(i, null))
.ToArray();
- return new QueryResult<ServerItem>
- {
- TotalRecordCount = result.Count,
- Items = serverItems
- };
+ return new QueryResult<ServerItem>(
+ startIndex,
+ result.Count,
+ serverItems);
}
/// <summary>
/// Converts a <see cref="QueryResult{BaseItem}"/> to a <see cref="QueryResult{ServerItem}"/>.
/// </summary>
+ /// <param name="startIndex">The index the result started at.</param>
/// <param name="result">A <see cref="QueryResult{BaseItem}"/>.</param>
/// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns>
- private static QueryResult<ServerItem> ToResult(QueryResult<BaseItem> result)
+ private static QueryResult<ServerItem> ToResult(int? startIndex, QueryResult<BaseItem> result)
{
var length = result.Items.Count;
var serverItems = new ServerItem[length];
@@ -1180,19 +1177,19 @@ namespace Emby.Dlna.ContentDirectory
serverItems[i] = new ServerItem(result.Items[i], null);
}
- return new QueryResult<ServerItem>
- {
- TotalRecordCount = result.TotalRecordCount,
- Items = serverItems
- };
+ return new QueryResult<ServerItem>(
+ startIndex,
+ result.TotalRecordCount,
+ serverItems);
}
/// <summary>
/// Converts a query result to a <see cref="QueryResult{ServerItem}"/>.
/// </summary>
+ /// <param name="startIndex">The start index.</param>
/// <param name="result">A <see cref="QueryResult{BaseItem}"/>.</param>
/// <returns>The <see cref="QueryResult{ServerItem}"/>.</returns>
- private static QueryResult<ServerItem> ToResult(QueryResult<(BaseItem Item, ItemCounts ItemCounts)> result)
+ private static QueryResult<ServerItem> ToResult(int? startIndex, QueryResult<(BaseItem Item, ItemCounts ItemCounts)> result)
{
var length = result.Items.Count;
var serverItems = new ServerItem[length];
@@ -1201,11 +1198,10 @@ namespace Emby.Dlna.ContentDirectory
serverItems[i] = new ServerItem(result.Items[i].Item, null);
}
- return new QueryResult<ServerItem>
- {
- TotalRecordCount = result.TotalRecordCount,
- Items = serverItems
- };
+ return new QueryResult<ServerItem>(
+ startIndex,
+ result.TotalRecordCount,
+ serverItems);
}
/// <summary>
diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs
index f2a0548c2..192128c7e 100644
--- a/Emby.Dlna/DlnaManager.cs
+++ b/Emby.Dlna/DlnaManager.cs
@@ -343,7 +343,8 @@ namespace Emby.Dlna
var fileOptions = AsyncFile.WriteOptions;
fileOptions.Mode = FileMode.Create;
fileOptions.PreallocationSize = length;
- using (var fileStream = new FileStream(path, fileOptions))
+ var fileStream = new FileStream(path, fileOptions);
+ await using (fileStream.ConfigureAwait(false))
{
await stream.CopyToAsync(fileStream).ConfigureAwait(false);
}
diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj
index fd95041fe..bf0272e83 100644
--- a/Emby.Dlna/Emby.Dlna.csproj
+++ b/Emby.Dlna/Emby.Dlna.csproj
@@ -28,6 +28,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs
index d0c9df68e..23f2456ac 100644
--- a/Emby.Dlna/PlayTo/PlayToController.cs
+++ b/Emby.Dlna/PlayTo/PlayToController.cs
@@ -180,7 +180,7 @@ namespace Emby.Dlna.PlayTo
_currentPlaylistIndex = currentItemIndex;
}
- await SendNextTrackMessage(currentItemIndex, CancellationToken.None);
+ await SendNextTrackMessage(currentItemIndex, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -453,7 +453,7 @@ namespace Emby.Dlna.PlayTo
// Send a message to the DLNA device to notify what is the next track in the play list.
var newItemIndex = _playlist.FindIndex(item => item.StreamUrl == newItem.StreamUrl);
- await SendNextTrackMessage(newItemIndex, CancellationToken.None);
+ await SendNextTrackMessage(newItemIndex, CancellationToken.None).ConfigureAwait(false);
return;
}
@@ -654,7 +654,7 @@ namespace Emby.Dlna.PlayTo
await _device.SetAvTransport(currentitem.StreamUrl, GetDlnaHeaders(currentitem), currentitem.Didl, cancellationToken).ConfigureAwait(false);
// Send a message to the DLNA device to notify what is the next track in the play list.
- await SendNextTrackMessage(index, cancellationToken);
+ await SendNextTrackMessage(index, cancellationToken).ConfigureAwait(false);
var streamInfo = currentitem.StreamInfo;
if (streamInfo.StartPositionTicks > 0 && EnableClientSideSeek(streamInfo))
@@ -771,7 +771,7 @@ namespace Emby.Dlna.PlayTo
// Send a message to the DLNA device to notify what is the next track in the play list.
var newItemIndex = _playlist.FindIndex(item => item.StreamUrl == newItem.StreamUrl);
- await SendNextTrackMessage(newItemIndex, CancellationToken.None);
+ await SendNextTrackMessage(newItemIndex, CancellationToken.None).ConfigureAwait(false);
if (EnableClientSideSeek(newItem.StreamInfo))
{
@@ -800,7 +800,7 @@ namespace Emby.Dlna.PlayTo
// Send a message to the DLNA device to notify what is the next track in the play list.
var newItemIndex = _playlist.FindIndex(item => item.StreamUrl == newItem.StreamUrl);
- await SendNextTrackMessage(newItemIndex, CancellationToken.None);
+ await SendNextTrackMessage(newItemIndex, CancellationToken.None).ConfigureAwait(false);
if (EnableClientSideSeek(newItem.StreamInfo) && newPosition > 0)
{
diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj
index b9a2c5d5d..9bcf6b2ea 100644
--- a/Emby.Drawing/Emby.Drawing.csproj
+++ b/Emby.Drawing/Emby.Drawing.csproj
@@ -27,6 +27,10 @@
<!-- Code analysers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs
index 1c05aa916..d0a26b713 100644
--- a/Emby.Drawing/NullImageEncoder.cs
+++ b/Emby.Drawing/NullImageEncoder.cs
@@ -44,6 +44,12 @@ namespace Emby.Drawing
}
/// <inheritdoc />
+ public void CreateSplashscreen(IReadOnlyList<string> posters, IReadOnlyList<string> backdrops)
+ {
+ throw new NotImplementedException();
+ }
+
+ /// <inheritdoc />
public string GetImageBlurHash(int xComp, int yComp, string path)
{
throw new NotImplementedException();
diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs
index c0be0b7c6..eb211050f 100644
--- a/Emby.Naming/Common/NamingOptions.cs
+++ b/Emby.Naming/Common/NamingOptions.cs
@@ -411,6 +411,66 @@ namespace Emby.Naming.Common
MediaType.Video),
new ExtraRule(
+ ExtraType.ThemeVideo,
+ ExtraRuleType.DirectoryName,
+ "backdrops",
+ MediaType.Video),
+
+ new ExtraRule(
+ ExtraType.ThemeSong,
+ ExtraRuleType.DirectoryName,
+ "theme-music",
+ MediaType.Audio),
+
+ new ExtraRule(
+ ExtraType.BehindTheScenes,
+ ExtraRuleType.DirectoryName,
+ "behind the scenes",
+ MediaType.Video),
+
+ new ExtraRule(
+ ExtraType.DeletedScene,
+ ExtraRuleType.DirectoryName,
+ "deleted scenes",
+ MediaType.Video),
+
+ new ExtraRule(
+ ExtraType.Interview,
+ ExtraRuleType.DirectoryName,
+ "interviews",
+ MediaType.Video),
+
+ new ExtraRule(
+ ExtraType.Scene,
+ ExtraRuleType.DirectoryName,
+ "scenes",
+ MediaType.Video),
+
+ new ExtraRule(
+ ExtraType.Sample,
+ ExtraRuleType.DirectoryName,
+ "samples",
+ MediaType.Video),
+
+ new ExtraRule(
+ ExtraType.Clip,
+ ExtraRuleType.DirectoryName,
+ "shorts",
+ MediaType.Video),
+
+ new ExtraRule(
+ ExtraType.Clip,
+ ExtraRuleType.DirectoryName,
+ "featurettes",
+ MediaType.Video),
+
+ new ExtraRule(
+ ExtraType.Unknown,
+ ExtraRuleType.DirectoryName,
+ "extras",
+ MediaType.Video),
+
+ new ExtraRule(
ExtraType.Trailer,
ExtraRuleType.Filename,
"trailer",
@@ -471,24 +531,12 @@ namespace Emby.Naming.Common
MediaType.Video),
new ExtraRule(
- ExtraType.ThemeVideo,
- ExtraRuleType.DirectoryName,
- "backdrops",
- MediaType.Video),
-
- new ExtraRule(
ExtraType.ThemeSong,
ExtraRuleType.Filename,
"theme",
MediaType.Audio),
new ExtraRule(
- ExtraType.ThemeSong,
- ExtraRuleType.DirectoryName,
- "theme-music",
- MediaType.Audio),
-
- new ExtraRule(
ExtraType.Scene,
ExtraRuleType.Suffix,
"-scene",
@@ -537,54 +585,16 @@ namespace Emby.Naming.Common
MediaType.Video),
new ExtraRule(
- ExtraType.BehindTheScenes,
- ExtraRuleType.DirectoryName,
- "behind the scenes",
- MediaType.Video),
-
- new ExtraRule(
- ExtraType.DeletedScene,
- ExtraRuleType.DirectoryName,
- "deleted scenes",
- MediaType.Video),
-
- new ExtraRule(
- ExtraType.Interview,
- ExtraRuleType.DirectoryName,
- "interviews",
- MediaType.Video),
-
- new ExtraRule(
- ExtraType.Scene,
- ExtraRuleType.DirectoryName,
- "scenes",
- MediaType.Video),
-
- new ExtraRule(
- ExtraType.Sample,
- ExtraRuleType.DirectoryName,
- "samples",
- MediaType.Video),
-
- new ExtraRule(
- ExtraType.Clip,
- ExtraRuleType.DirectoryName,
- "shorts",
- MediaType.Video),
-
- new ExtraRule(
- ExtraType.Clip,
- ExtraRuleType.DirectoryName,
- "featurettes",
- MediaType.Video),
-
- new ExtraRule(
ExtraType.Unknown,
- ExtraRuleType.DirectoryName,
- "extras",
+ ExtraRuleType.Suffix,
+ "-extra",
MediaType.Video)
};
+ AllExtrasTypesFolderNames = VideoExtraRules
+ .Where(i => i.RuleType == ExtraRuleType.DirectoryName)
+ .ToDictionary(i => i.Token, i => i.ExtraType, StringComparer.OrdinalIgnoreCase);
+
Format3DRules = new[]
{
// Kodi rules:
@@ -673,6 +683,10 @@ namespace Emby.Naming.Common
".mxf"
});
+ VideoFileExtensions = extensions
+ .Distinct(StringComparer.OrdinalIgnoreCase)
+ .ToArray();
+
MultipleEpisodeExpressions = new[]
{
@".*(\\|\/)[sS]?(?<seasonnumber>[0-9]{1,4})[xX](?<epnumber>[0-9]{1,3})((-| - )[0-9]{1,4}[eExX](?<endingepnumber>[0-9]{1,3}))+[^\\\/]*$",
@@ -690,25 +704,6 @@ namespace Emby.Naming.Common
IsNamed = true
}).ToArray();
- VideoFileExtensions = extensions
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .ToArray();
-
- AllExtrasTypesFolderNames = new Dictionary<string, ExtraType>(StringComparer.OrdinalIgnoreCase)
- {
- ["trailers"] = ExtraType.Trailer,
- ["theme-music"] = ExtraType.ThemeSong,
- ["backdrops"] = ExtraType.ThemeVideo,
- ["extras"] = ExtraType.Unknown,
- ["behind the scenes"] = ExtraType.BehindTheScenes,
- ["deleted scenes"] = ExtraType.DeletedScene,
- ["interviews"] = ExtraType.Interview,
- ["scenes"] = ExtraType.Scene,
- ["samples"] = ExtraType.Sample,
- ["shorts"] = ExtraType.Clip,
- ["featurettes"] = ExtraType.Clip
- };
-
Compile();
}
diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj
index 433ad137b..781c99ae2 100644
--- a/Emby.Naming/Emby.Naming.csproj
+++ b/Emby.Naming/Emby.Naming.csproj
@@ -47,6 +47,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj
index 7fd2e9bb4..fa7709f2a 100644
--- a/Emby.Notifications/Emby.Notifications.csproj
+++ b/Emby.Notifications/Emby.Notifications.csproj
@@ -23,6 +23,10 @@
<!-- Code analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj
index 4964265c9..36419decf 100644
--- a/Emby.Photos/Emby.Photos.csproj
+++ b/Emby.Photos/Emby.Photos.csproj
@@ -26,6 +26,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 8ed51a194..e7efc81d7 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -47,6 +47,7 @@ using Emby.Server.Implementations.TV;
using Emby.Server.Implementations.Udp;
using Emby.Server.Implementations.Updates;
using Jellyfin.Api.Helpers;
+using Jellyfin.MediaEncoding.Hls.Playlist;
using Jellyfin.Networking.Configuration;
using Jellyfin.Networking.Manager;
using MediaBrowser.Common;
@@ -973,7 +974,7 @@ namespace Emby.Server.Implementations
yield return typeof(IServerApplicationHost).Assembly;
// Include composable parts in the Providers assembly
- yield return typeof(ProviderUtils).Assembly;
+ yield return typeof(ProviderManager).Assembly;
// Include composable parts in the Photos assembly
yield return typeof(PhotoProvider).Assembly;
@@ -999,6 +1000,9 @@ namespace Emby.Server.Implementations
// Network
yield return typeof(NetworkManager).Assembly;
+ // Hls
+ yield return typeof(DynamicHlsPlaylistGenerator).Assembly;
+
foreach (var i in GetAssembliesWithPartsInternal())
{
yield return i;
diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs
index 43c8a451b..a107e7a52 100644
--- a/Emby.Server.Implementations/Channels/ChannelManager.cs
+++ b/Emby.Server.Implementations/Channels/ChannelManager.cs
@@ -264,11 +264,10 @@ namespace Emby.Server.Implementations.Channels
}
}
- return new QueryResult<Channel>
- {
- Items = all,
- TotalRecordCount = totalCount
- };
+ return new QueryResult<Channel>(
+ query.StartIndex,
+ totalCount,
+ all);
}
/// <inheritdoc />
@@ -285,11 +284,10 @@ namespace Emby.Server.Implementations.Channels
// TODO Fix The co-variant conversion (internalResult.Items) between Folder[] and BaseItem[], this can generate runtime issues.
var returnItems = _dtoService.GetBaseItemDtos(internalResult.Items, dtoOptions, user);
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnItems,
- TotalRecordCount = internalResult.TotalRecordCount
- };
+ var result = new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ internalResult.TotalRecordCount,
+ returnItems);
return result;
}
@@ -333,7 +331,7 @@ namespace Emby.Server.Implementations.Channels
private Channel GetChannelEntity(IChannel channel)
{
- return GetChannel(GetInternalChannelId(channel.Name)) ?? GetChannel(channel, CancellationToken.None).Result;
+ return GetChannel(GetInternalChannelId(channel.Name)) ?? GetChannel(channel, CancellationToken.None).GetAwaiter().GetResult();
}
private MediaSourceInfo[] GetSavedMediaSources(BaseItem item)
@@ -620,11 +618,10 @@ namespace Emby.Server.Implementations.Channels
var returnItems = _dtoService.GetBaseItemDtos(items, query.DtoOptions, query.User);
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnItems,
- TotalRecordCount = totalRecordCount
- };
+ var result = new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ totalRecordCount,
+ returnItems);
return result;
}
@@ -786,11 +783,10 @@ namespace Emby.Server.Implementations.Channels
var returnItems = _dtoService.GetBaseItemDtos(internalResult.Items, query.DtoOptions, query.User);
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnItems,
- TotalRecordCount = internalResult.TotalRecordCount
- };
+ var result = new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ internalResult.TotalRecordCount,
+ returnItems);
return result;
}
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index 5ab9e02fe..1da9b4650 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -2810,11 +2810,10 @@ namespace Emby.Server.Implementations.Data
if (!query.EnableTotalRecordCount || (!query.Limit.HasValue && (query.StartIndex ?? 0) == 0))
{
var returnList = GetItemList(query);
- return new QueryResult<BaseItem>
- {
- Items = returnList,
- TotalRecordCount = returnList.Count
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ returnList.Count,
+ returnList);
}
var now = DateTime.UtcNow;
@@ -2978,6 +2977,7 @@ namespace Emby.Server.Implementations.Data
ReadTransactionMode);
}
+ result.StartIndex = query.StartIndex ?? 0;
result.Items = list;
return result;
}
@@ -3265,11 +3265,10 @@ namespace Emby.Server.Implementations.Data
if (!query.EnableTotalRecordCount || (!query.Limit.HasValue && (query.StartIndex ?? 0) == 0))
{
var returnList = GetItemIdsList(query);
- return new QueryResult<Guid>
- {
- Items = returnList,
- TotalRecordCount = returnList.Count
- };
+ return new QueryResult<Guid>(
+ query.StartIndex,
+ returnList.Count,
+ returnList);
}
var now = DateTime.UtcNow;
@@ -3395,6 +3394,7 @@ namespace Emby.Server.Implementations.Data
LogQueryTime("GetItemIds", commandText, now);
+ result.StartIndex = query.StartIndex ?? 0;
result.Items = list;
return result;
}
@@ -5599,6 +5599,7 @@ AND Type = @InternalPersonType)");
result.TotalRecordCount = list.Count;
}
+ result.StartIndex = query.StartIndex ?? 0;
result.Items = list;
return result;
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index 7ba34e74a..f5ca006dd 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -458,11 +458,6 @@ namespace Emby.Server.Implementations.Dto
}
}
- private string GetDtoId(BaseItem item)
- {
- return item.Id.ToString("N", CultureInfo.InvariantCulture);
- }
-
private void SetMusicVideoProperties(BaseItemDto dto, MusicVideo item)
{
if (!string.IsNullOrEmpty(item.Album))
@@ -584,7 +579,7 @@ namespace Emby.Server.Implementations.Dto
if (dictionary.TryGetValue(person.Name, out Person entity))
{
baseItemPerson.PrimaryImageTag = GetTagAndFillBlurhash(dto, entity, ImageType.Primary);
- baseItemPerson.Id = entity.Id.ToString("N", CultureInfo.InvariantCulture);
+ baseItemPerson.Id = entity.Id;
if (dto.ImageBlurHashes != null)
{
// Only add BlurHash for the person's image.
@@ -1102,12 +1097,13 @@ namespace Emby.Server.Implementations.Dto
if (options.ContainsField(ItemFields.LocalTrailerCount))
{
- allExtras ??= item.GetExtras().ToArray();
- dto.LocalTrailerCount = allExtras.Count(i => i.ExtraType == ExtraType.Trailer);
-
if (item is IHasTrailers hasTrailers)
{
- dto.LocalTrailerCount += hasTrailers.GetTrailerCount();
+ dto.LocalTrailerCount = hasTrailers.GetTrailerCount();
+ }
+ else
+ {
+ dto.LocalTrailerCount = (allExtras ?? item.GetExtras()).Count(i => i.ExtraType == ExtraType.Trailer);
}
}
@@ -1323,7 +1319,7 @@ namespace Emby.Server.Implementations.Dto
if (image != null)
{
- dto.ParentLogoItemId = GetDtoId(parent);
+ dto.ParentLogoItemId = parent.Id;
dto.ParentLogoImageTag = GetTagAndFillBlurhash(dto, parent, image);
}
}
@@ -1334,7 +1330,7 @@ namespace Emby.Server.Implementations.Dto
if (image != null)
{
- dto.ParentArtItemId = GetDtoId(parent);
+ dto.ParentArtItemId = parent.Id;
dto.ParentArtImageTag = GetTagAndFillBlurhash(dto, parent, image);
}
}
@@ -1345,7 +1341,7 @@ namespace Emby.Server.Implementations.Dto
if (image != null)
{
- dto.ParentThumbItemId = GetDtoId(parent);
+ dto.ParentThumbItemId = parent.Id;
dto.ParentThumbImageTag = GetTagAndFillBlurhash(dto, parent, image);
}
}
@@ -1356,7 +1352,7 @@ namespace Emby.Server.Implementations.Dto
if (images.Count > 0)
{
- dto.ParentBackdropItemId = GetDtoId(parent);
+ dto.ParentBackdropItemId = parent.Id;
dto.ParentBackdropImageTags = GetTagsAndFillBlurhashes(dto, parent, ImageType.Backdrop, images);
}
}
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 1e09a98cf..3226a3b19 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -31,7 +31,7 @@
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.1" />
<PackageReference Include="Mono.Nat" Version="3.0.2" />
- <PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.2" />
+ <PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.3" />
<PackageReference Include="sharpcompress" Version="0.30.1" />
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="3.1.0" />
<PackageReference Include="DotNet.Glob" Version="3.1.3" />
@@ -55,6 +55,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs
index 7958eb8f5..8a0e627b9 100644
--- a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs
+++ b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs
@@ -42,6 +42,10 @@ namespace Emby.Server.Implementations.Images
{
includeItemTypes = new[] { BaseItemKind.MusicAlbum };
}
+ else if (string.Equals(viewType, CollectionType.MusicVideos, StringComparison.Ordinal))
+ {
+ includeItemTypes = new[] { BaseItemKind.MusicVideo };
+ }
else if (string.Equals(viewType, CollectionType.Books, StringComparison.Ordinal))
{
includeItemTypes = new[] { BaseItemKind.Book, BaseItemKind.AudioBook };
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index bd0c178fd..064fd2372 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1360,10 +1360,10 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetItems(query);
}
- return new QueryResult<BaseItem>
- {
- Items = _itemRepository.GetItemList(query)
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ null,
+ _itemRepository.GetItemList(query));
}
public List<Guid> GetItemIds(InternalItemsQuery query)
@@ -1493,10 +1493,10 @@ namespace Emby.Server.Implementations.Library
return _itemRepository.GetItems(query);
}
- return new QueryResult<BaseItem>
- {
- Items = _itemRepository.GetItemList(query)
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ null,
+ _itemRepository.GetItemList(query));
}
private void SetTopParentIdsOrAncestors(InternalItemsQuery query, List<BaseItem> parents)
@@ -2014,16 +2014,16 @@ namespace Emby.Server.Implementations.Library
public Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken)
=> UpdateItemsAsync(new[] { item }, parent, updateReason, cancellationToken);
- public Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason)
+ public async Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason)
{
if (item.IsFileProtocol)
{
- ProviderManager.SaveMetadata(item, updateReason);
+ await ProviderManager.SaveMetadataAsync(item, updateReason).ConfigureAwait(false);
}
item.DateLastSaved = DateTime.UtcNow;
- return UpdateImagesAsync(item, updateReason >= ItemUpdateType.ImageUpdate);
+ await UpdateImagesAsync(item, updateReason >= ItemUpdateType.ImageUpdate).ConfigureAwait(false);
}
/// <summary>
@@ -2686,7 +2686,7 @@ namespace Emby.Server.Implementations.Library
};
}
- public IEnumerable<BaseItem> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
+ public IEnumerable<BaseItem> FindExtras(BaseItem owner, IReadOnlyList<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
{
var ownerVideoInfo = VideoResolver.Resolve(owner.Path, owner.IsFolder, _namingOptions);
if (ownerVideoInfo == null)
diff --git a/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
index 3d06ceb5e..807913b5d 100644
--- a/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs
@@ -20,7 +20,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
private readonly IItemResolver[] _videoResolvers;
/// <summary>
- /// Initializes an new instance of the <see cref="ExtraResolver"/> class.
+ /// Initializes a new instance of the <see cref="ExtraResolver"/> class.
/// </summary>
/// <param name="namingOptions">An instance of <see cref="NamingOptions"/>.</param>
public ExtraResolver(NamingOptions namingOptions)
diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 1a9295dc8..be1460928 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
CollectionType.Movies,
CollectionType.HomeVideos,
CollectionType.MusicVideos,
- CollectionType.Movies,
+ CollectionType.TvShows,
CollectionType.Photos
};
@@ -128,10 +128,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return movie?.ExtraType == null ? movie : null;
}
- // Owned items will be caught by the video extra resolver
if (args.Parent == null)
{
- return null;
+ return base.Resolve(args);
}
if (IsInvalid(args.Parent, collectionType))
@@ -222,6 +221,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
return ResolveVideos<Movie>(parent, files, true, collectionType, true);
}
+ if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
+ {
+ return ResolveVideos<Episode>(parent, files, true, collectionType, true);
+ }
+
return null;
}
diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs
index 55911933a..70d9cbc98 100644
--- a/Emby.Server.Implementations/Library/SearchEngine.cs
+++ b/Emby.Server.Implementations/Library/SearchEngine.cs
@@ -48,12 +48,10 @@ namespace Emby.Server.Implementations.Library
results = results.GetRange(0, Math.Min(query.Limit.Value, results.Count));
}
- return new QueryResult<SearchHintInfo>
- {
- TotalRecordCount = totalRecordCount,
-
- Items = results
- };
+ return new QueryResult<SearchHintInfo>(
+ query.StartIndex,
+ totalRecordCount,
+ results);
}
private static void AddIfMissing(List<BaseItemKind> list, BaseItemKind value)
diff --git a/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs b/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs
new file mode 100644
index 000000000..320685b1f
--- /dev/null
+++ b/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Querying;
+using Microsoft.Extensions.Logging;
+
+namespace Emby.Server.Implementations.Library;
+
+/// <summary>
+/// The splashscreen post scan task.
+/// </summary>
+public class SplashscreenPostScanTask : ILibraryPostScanTask
+{
+ private readonly IItemRepository _itemRepository;
+ private readonly IImageEncoder _imageEncoder;
+ private readonly ILogger<SplashscreenPostScanTask> _logger;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SplashscreenPostScanTask"/> class.
+ /// </summary>
+ /// <param name="itemRepository">Instance of the <see cref="IItemRepository"/> interface.</param>
+ /// <param name="imageEncoder">Instance of the <see cref="IImageEncoder"/> interface.</param>
+ /// <param name="logger">Instance of the <see cref="ILogger{SplashscreenPostScanTask}"/> interface.</param>
+ public SplashscreenPostScanTask(
+ IItemRepository itemRepository,
+ IImageEncoder imageEncoder,
+ ILogger<SplashscreenPostScanTask> logger)
+ {
+ _itemRepository = itemRepository;
+ _imageEncoder = imageEncoder;
+ _logger = logger;
+ }
+
+ /// <inheritdoc />
+ public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
+ {
+ var posters = GetItemsWithImageType(ImageType.Primary).Select(x => x.GetImages(ImageType.Primary).First().Path).ToList();
+ var backdrops = GetItemsWithImageType(ImageType.Thumb).Select(x => x.GetImages(ImageType.Thumb).First().Path).ToList();
+ if (backdrops.Count == 0)
+ {
+ // Thumb images fit better because they include the title in the image but are not provided with TMDb.
+ // Using backdrops as a fallback to generate an image at all
+ _logger.LogDebug("No thumb images found. Using backdrops to generate splashscreen");
+ backdrops = GetItemsWithImageType(ImageType.Backdrop).Select(x => x.GetImages(ImageType.Backdrop).First().Path).ToList();
+ }
+
+ _imageEncoder.CreateSplashscreen(posters, backdrops);
+ return Task.CompletedTask;
+ }
+
+ private IReadOnlyList<BaseItem> GetItemsWithImageType(ImageType imageType)
+ {
+ // TODO make included libraries configurable
+ return _itemRepository.GetItemList(new InternalItemsQuery
+ {
+ CollapseBoxSetItems = false,
+ Recursive = true,
+ DtoOptions = new DtoOptions(false),
+ ImageTypes = new[] { imageType },
+ Limit = 30,
+ // TODO max parental rating configurable
+ MaxParentalRating = 10,
+ OrderBy = new[]
+ {
+ (ItemSortBy.Random, SortOrder.Ascending)
+ },
+ IncludeItemTypes = new[] { BaseItemKind.Movie, BaseItemKind.Series }
+ });
+ }
+}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
index 6937cc097..b2d25fdae 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
@@ -46,7 +46,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
Directory.CreateDirectory(Path.GetDirectoryName(targetFile) ?? throw new ArgumentException("Path can't be a root directory.", nameof(targetFile)));
- using (var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
+ await using (var output = new FileStream(targetFile, FileMode.CreateNew, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
{
onStarted();
@@ -56,14 +56,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
using var durationToken = new CancellationTokenSource(duration);
using var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token);
var linkedCancellationToken = cancellationTokenSource.Token;
-
- await using var fileStream = new ProgressiveFileStream(directStreamProvider.GetStream());
- await _streamHelper.CopyToAsync(
- fileStream,
- output,
- IODefaults.CopyToBufferSize,
- 1000,
- linkedCancellationToken).ConfigureAwait(false);
+ var fileStream = new ProgressiveFileStream(directStreamProvider.GetStream());
+ await using (fileStream.ConfigureAwait(false))
+ {
+ await _streamHelper.CopyToAsync(
+ fileStream,
+ output,
+ IODefaults.CopyToBufferSize,
+ 1000,
+ linkedCancellationToken).ConfigureAwait(false);
+ }
}
_logger.LogInformation("Recording completed: {FilePath}", targetFile);
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index e7834ffd6..bba584854 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -1819,16 +1819,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (timer.IsProgramSeries)
{
- SaveSeriesNfo(timer, seriesPath);
- SaveVideoNfo(timer, recordingPath, program, false);
+ await SaveSeriesNfoAsync(timer, seriesPath).ConfigureAwait(false);
+ await SaveVideoNfoAsync(timer, recordingPath, program, false).ConfigureAwait(false);
}
else if (!timer.IsMovie || timer.IsSports || timer.IsNews)
{
- SaveVideoNfo(timer, recordingPath, program, true);
+ await SaveVideoNfoAsync(timer, recordingPath, program, true).ConfigureAwait(false);
}
else
{
- SaveVideoNfo(timer, recordingPath, program, false);
+ await SaveVideoNfoAsync(timer, recordingPath, program, false).ConfigureAwait(false);
}
await SaveRecordingImages(recordingPath, program).ConfigureAwait(false);
@@ -1839,7 +1839,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
- private void SaveSeriesNfo(TimerInfo timer, string seriesPath)
+ private async Task SaveSeriesNfoAsync(TimerInfo timer, string seriesPath)
{
var nfoPath = Path.Combine(seriesPath, "tvshow.nfo");
@@ -1848,61 +1848,62 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return;
}
- using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
+ await using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
var settings = new XmlWriterSettings
{
Indent = true,
- Encoding = Encoding.UTF8
+ Encoding = Encoding.UTF8,
+ Async = true
};
- using (var writer = XmlWriter.Create(stream, settings))
+ await using (var writer = XmlWriter.Create(stream, settings))
{
- writer.WriteStartDocument(true);
- writer.WriteStartElement("tvshow");
+ await writer.WriteStartDocumentAsync(true).ConfigureAwait(false);
+ await writer.WriteStartElementAsync(null, "tvshow", null).ConfigureAwait(false);
string id;
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(), out id))
{
- writer.WriteElementString("id", id);
+ await writer.WriteElementStringAsync(null, "id", null, id).ConfigureAwait(false);
}
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Imdb.ToString(), out id))
{
- writer.WriteElementString("imdb_id", id);
+ await writer.WriteElementStringAsync(null, "imdb_id", null, id).ConfigureAwait(false);
}
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Tmdb.ToString(), out id))
{
- writer.WriteElementString("tmdbid", id);
+ await writer.WriteElementStringAsync(null, "tmdbid", null, id).ConfigureAwait(false);
}
if (timer.SeriesProviderIds.TryGetValue(MetadataProvider.Zap2It.ToString(), out id))
{
- writer.WriteElementString("zap2itid", id);
+ await writer.WriteElementStringAsync(null, "zap2itid", null, id).ConfigureAwait(false);
}
if (!string.IsNullOrWhiteSpace(timer.Name))
{
- writer.WriteElementString("title", timer.Name);
+ await writer.WriteElementStringAsync(null, "title", null, timer.Name).ConfigureAwait(false);
}
if (!string.IsNullOrWhiteSpace(timer.OfficialRating))
{
- writer.WriteElementString("mpaa", timer.OfficialRating);
+ await writer.WriteElementStringAsync(null, "mpaa", null, timer.OfficialRating).ConfigureAwait(false);
}
foreach (var genre in timer.Genres)
{
- writer.WriteElementString("genre", genre);
+ await writer.WriteElementStringAsync(null, "genre", null, genre).ConfigureAwait(false);
}
- writer.WriteEndElement();
- writer.WriteEndDocument();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
+ await writer.WriteEndDocumentAsync().ConfigureAwait(false);
}
}
}
- private void SaveVideoNfo(TimerInfo timer, string recordingPath, BaseItem item, bool lockData)
+ private async Task SaveVideoNfoAsync(TimerInfo timer, string recordingPath, BaseItem item, bool lockData)
{
var nfoPath = Path.ChangeExtension(recordingPath, ".nfo");
@@ -1911,29 +1912,30 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
return;
}
- using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
+ await using (var stream = new FileStream(nfoPath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
var settings = new XmlWriterSettings
{
Indent = true,
- Encoding = Encoding.UTF8
+ Encoding = Encoding.UTF8,
+ Async = true
};
var options = _config.GetNfoConfiguration();
var isSeriesEpisode = timer.IsProgramSeries;
- using (var writer = XmlWriter.Create(stream, settings))
+ await using (var writer = XmlWriter.Create(stream, settings))
{
- writer.WriteStartDocument(true);
+ await writer.WriteStartDocumentAsync(true).ConfigureAwait(false);
if (isSeriesEpisode)
{
- writer.WriteStartElement("episodedetails");
+ await writer.WriteStartElementAsync(null, "episodedetails", null).ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(timer.EpisodeTitle))
{
- writer.WriteElementString("title", timer.EpisodeTitle);
+ await writer.WriteElementStringAsync(null, "title", null, timer.EpisodeTitle).ConfigureAwait(false);
}
var premiereDate = item.PremiereDate ?? (!timer.IsRepeat ? DateTime.UtcNow : null);
@@ -1942,76 +1944,84 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
var formatString = options.ReleaseDateFormat;
- writer.WriteElementString(
+ await writer.WriteElementStringAsync(
+ null,
"aired",
- premiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture));
+ null,
+ premiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (item.IndexNumber.HasValue)
{
- writer.WriteElementString("episode", item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "episode", null, item.IndexNumber.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (item.ParentIndexNumber.HasValue)
{
- writer.WriteElementString("season", item.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "season", null, item.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
}
else
{
- writer.WriteStartElement("movie");
+ await writer.WriteStartElementAsync(null, "movie", null);
if (!string.IsNullOrWhiteSpace(item.Name))
{
- writer.WriteElementString("title", item.Name);
+ await writer.WriteElementStringAsync(null, "title", null, item.Name).ConfigureAwait(false);
}
if (!string.IsNullOrWhiteSpace(item.OriginalTitle))
{
- writer.WriteElementString("originaltitle", item.OriginalTitle);
+ await writer.WriteElementStringAsync(null, "originaltitle", null, item.OriginalTitle).ConfigureAwait(false);
}
if (item.PremiereDate.HasValue)
{
var formatString = options.ReleaseDateFormat;
- writer.WriteElementString(
+ await writer.WriteElementStringAsync(
+ null,
"premiered",
- item.PremiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture));
- writer.WriteElementString(
+ null,
+ item.PremiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture)).ConfigureAwait(false);
+ await writer.WriteElementStringAsync(
+ null,
"releasedate",
- item.PremiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture));
+ null,
+ item.PremiereDate.Value.ToLocalTime().ToString(formatString, CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
}
- writer.WriteElementString(
+ await writer.WriteElementStringAsync(
+ null,
"dateadded",
- DateTime.Now.ToString(DateAddedFormat, CultureInfo.InvariantCulture));
+ null,
+ DateTime.Now.ToString(DateAddedFormat, CultureInfo.InvariantCulture)).ConfigureAwait(false);
if (item.ProductionYear.HasValue)
{
- writer.WriteElementString("year", item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "year", null, item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (!string.IsNullOrEmpty(item.OfficialRating))
{
- writer.WriteElementString("mpaa", item.OfficialRating);
+ await writer.WriteElementStringAsync(null, "mpaa", null, item.OfficialRating).ConfigureAwait(false);
}
var overview = (item.Overview ?? string.Empty)
.StripHtml()
.Replace("&quot;", "'", StringComparison.Ordinal);
- writer.WriteElementString("plot", overview);
+ await writer.WriteElementStringAsync(null, "plot", null, overview).ConfigureAwait(false);
if (item.CommunityRating.HasValue)
{
- writer.WriteElementString("rating", item.CommunityRating.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "rating", null, item.CommunityRating.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
foreach (var genre in item.Genres)
{
- writer.WriteElementString("genre", genre);
+ await writer.WriteElementStringAsync(null, "genre", null, genre).ConfigureAwait(false);
}
var people = item.Id.Equals(Guid.Empty) ? new List<PersonInfo>() : _libraryManager.GetPeople(item);
@@ -2023,7 +2033,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
foreach (var person in directors)
{
- writer.WriteElementString("director", person);
+ await writer.WriteElementStringAsync(null, "director", null, person).ConfigureAwait(false);
}
var writers = people
@@ -2034,19 +2044,19 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
foreach (var person in writers)
{
- writer.WriteElementString("writer", person);
+ await writer.WriteElementStringAsync(null, "writer", null, person).ConfigureAwait(false);
}
foreach (var person in writers)
{
- writer.WriteElementString("credits", person);
+ await writer.WriteElementStringAsync(null, "credits", null, person).ConfigureAwait(false);
}
var tmdbCollection = item.GetProviderId(MetadataProvider.TmdbCollection);
if (!string.IsNullOrEmpty(tmdbCollection))
{
- writer.WriteElementString("collectionnumber", tmdbCollection);
+ await writer.WriteElementStringAsync(null, "collectionnumber", null, tmdbCollection).ConfigureAwait(false);
}
var imdb = item.GetProviderId(MetadataProvider.Imdb);
@@ -2054,10 +2064,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
if (!isSeriesEpisode)
{
- writer.WriteElementString("id", imdb);
+ await writer.WriteElementStringAsync(null, "id", null, imdb).ConfigureAwait(false);
}
- writer.WriteElementString("imdbid", imdb);
+ await writer.WriteElementStringAsync(null, "imdbid", null, imdb).ConfigureAwait(false);
// No need to lock if we have identified the content already
lockData = false;
@@ -2066,7 +2076,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var tvdb = item.GetProviderId(MetadataProvider.Tvdb);
if (!string.IsNullOrEmpty(tvdb))
{
- writer.WriteElementString("tvdbid", tvdb);
+ await writer.WriteElementStringAsync(null, "tvdbid", null, tvdb).ConfigureAwait(false);
// No need to lock if we have identified the content already
lockData = false;
@@ -2075,7 +2085,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var tmdb = item.GetProviderId(MetadataProvider.Tmdb);
if (!string.IsNullOrEmpty(tmdb))
{
- writer.WriteElementString("tmdbid", tmdb);
+ await writer.WriteElementStringAsync(null, "tmdbid", null, tmdb).ConfigureAwait(false);
// No need to lock if we have identified the content already
lockData = false;
@@ -2083,26 +2093,26 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (lockData)
{
- writer.WriteElementString("lockdata", true.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
+ await writer.WriteElementStringAsync(null, "lockdata", null, "true").ConfigureAwait(false);
}
if (item.CriticRating.HasValue)
{
- writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "criticrating", null, item.CriticRating.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (!string.IsNullOrWhiteSpace(item.Tagline))
{
- writer.WriteElementString("tagline", item.Tagline);
+ await writer.WriteElementStringAsync(null, "tagline", null, item.Tagline).ConfigureAwait(false);
}
foreach (var studio in item.Studios)
{
- writer.WriteElementString("studio", studio);
+ await writer.WriteElementStringAsync(null, "studio", null, studio).ConfigureAwait(false);
}
- writer.WriteEndElement();
- writer.WriteEndDocument();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
+ await writer.WriteEndDocumentAsync().ConfigureAwait(false);
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index 7fa47e7db..f1d4b6097 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -29,7 +29,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
private readonly ILogger _logger;
private readonly IMediaEncoder _mediaEncoder;
private readonly IServerApplicationPaths _appPaths;
- private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
+ private readonly TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
private bool _hasExited;
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
index 323b96021..fbce7af2d 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -176,7 +176,7 @@ namespace Emby.Server.Implementations.LiveTv
try
{
dto.ParentThumbImageTag = _imageProcessor.GetImageCacheTag(librarySeries, image);
- dto.ParentThumbItemId = librarySeries.Id.ToString("N", CultureInfo.InvariantCulture);
+ dto.ParentThumbItemId = librarySeries.Id;
}
catch (Exception ex)
{
@@ -193,7 +193,7 @@ namespace Emby.Server.Implementations.LiveTv
{
_imageProcessor.GetImageCacheTag(librarySeries, image)
};
- dto.ParentBackdropItemId = librarySeries.Id.ToString("N", CultureInfo.InvariantCulture);
+ dto.ParentBackdropItemId = librarySeries.Id;
}
catch (Exception ex)
{
@@ -240,7 +240,7 @@ namespace Emby.Server.Implementations.LiveTv
_imageProcessor.GetImageCacheTag(program, image)
};
- dto.ParentBackdropItemId = program.Id.ToString("N", CultureInfo.InvariantCulture);
+ dto.ParentBackdropItemId = program.Id;
}
catch (Exception ex)
{
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index aa3598c8b..6a9a3077c 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -857,11 +857,10 @@ namespace Emby.Server.Implementations.LiveTv
var returnArray = _dtoService.GetBaseItemDtos(queryResult.Items, options, user);
- return new QueryResult<BaseItemDto>
- {
- Items = returnArray,
- TotalRecordCount = queryResult.TotalRecordCount
- };
+ return new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ queryResult.TotalRecordCount,
+ returnArray);
}
public QueryResult<BaseItem> GetRecommendedProgramsInternal(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken)
@@ -910,29 +909,27 @@ namespace Emby.Server.Implementations.LiveTv
programs = programs.Take(query.Limit.Value);
}
- return new QueryResult<BaseItem>
- {
- Items = programs.ToArray(),
- TotalRecordCount = totalCount
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ totalCount,
+ programs.ToArray());
}
- public QueryResult<BaseItemDto> GetRecommendedPrograms(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken)
+ public Task<QueryResult<BaseItemDto>> GetRecommendedProgramsAsync(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken)
{
if (!(query.IsAiring ?? false))
{
- return GetPrograms(query, options, cancellationToken).Result;
+ return GetPrograms(query, options, cancellationToken);
}
RemoveFields(options);
var internalResult = GetRecommendedProgramsInternal(query, options, cancellationToken);
- return new QueryResult<BaseItemDto>
- {
- Items = _dtoService.GetBaseItemDtos(internalResult.Items, options, query.User),
- TotalRecordCount = internalResult.TotalRecordCount
- };
+ return Task.FromResult(new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ internalResult.TotalRecordCount,
+ _dtoService.GetBaseItemDtos(internalResult.Items, options, query.User)));
}
private int GetRecommendationScore(LiveTvProgram program, User user, bool factorChannelWatchCount)
@@ -1541,11 +1538,10 @@ namespace Emby.Server.Implementations.LiveTv
var returnArray = _dtoService.GetBaseItemDtos(internalResult.Items, options, user);
- return new QueryResult<BaseItemDto>
- {
- Items = returnArray,
- TotalRecordCount = internalResult.TotalRecordCount
- };
+ return new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ internalResult.TotalRecordCount,
+ returnArray);
}
private async Task<QueryResult<TimerInfo>> GetTimersInternal(TimerQuery query, CancellationToken cancellationToken)
@@ -1615,11 +1611,7 @@ namespace Emby.Server.Implementations.LiveTv
.OrderBy(i => i.StartDate)
.ToArray();
- return new QueryResult<TimerInfo>
- {
- Items = returnArray,
- TotalRecordCount = returnArray.Length
- };
+ return new QueryResult<TimerInfo>(returnArray);
}
public async Task<QueryResult<TimerInfoDto>> GetTimers(TimerQuery query, CancellationToken cancellationToken)
@@ -1701,11 +1693,7 @@ namespace Emby.Server.Implementations.LiveTv
.OrderBy(i => i.StartDate)
.ToArray();
- return new QueryResult<TimerInfoDto>
- {
- Items = returnArray,
- TotalRecordCount = returnArray.Length
- };
+ return new QueryResult<TimerInfoDto>(returnArray);
}
public async Task CancelTimer(string id)
@@ -1801,11 +1789,7 @@ namespace Emby.Server.Implementations.LiveTv
.Select(i => i.Item1)
.ToArray();
- return new QueryResult<SeriesTimerInfo>
- {
- Items = returnArray,
- TotalRecordCount = returnArray.Length
- };
+ return new QueryResult<SeriesTimerInfo>(returnArray);
}
public async Task<QueryResult<SeriesTimerInfoDto>> GetSeriesTimers(SeriesTimerQuery query, CancellationToken cancellationToken)
@@ -1855,11 +1839,7 @@ namespace Emby.Server.Implementations.LiveTv
})
.ToArray();
- return new QueryResult<SeriesTimerInfoDto>
- {
- Items = returnArray,
- TotalRecordCount = returnArray.Length
- };
+ return new QueryResult<SeriesTimerInfoDto>(returnArray);
}
public BaseItem GetLiveTvChannel(TimerInfo timer, ILiveTvService service)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
index a5edd35cc..6195c7648 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
@@ -133,7 +133,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
}
}
- var taskCompletionSource = new TaskCompletionSource<bool>();
+ var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
_ = StartStreaming(
udpClient,
@@ -186,7 +186,8 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
var resolved = false;
- using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read))
+ var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read);
+ await using (fileStream.ConfigureAwait(false))
{
while (true)
{
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
index 5581ba87c..2748794b3 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
@@ -97,7 +97,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
public Stream GetStream()
{
- var stream = GetInputStream(TempFilePath);
+ var stream = new FileStream(
+ TempFilePath,
+ FileMode.Open,
+ FileAccess.Read,
+ FileShare.ReadWrite,
+ IODefaults.FileStreamBufferSize,
+ FileOptions.SequentialScan | FileOptions.Asynchronous);
+
bool seekFile = (DateTime.UtcNow - DateOpened).TotalSeconds > 10;
if (seekFile)
{
@@ -107,15 +114,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
return stream;
}
- protected FileStream GetInputStream(string path)
- => new FileStream(
- path,
- FileMode.Open,
- FileAccess.Read,
- FileShare.ReadWrite,
- IODefaults.FileStreamBufferSize,
- FileOptions.SequentialScan | FileOptions.Asynchronous);
-
protected async Task DeleteTempFiles(string path, int retryCount = 0)
{
if (retryCount == 0)
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
index ab4beb15b..e84e1e074 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
@@ -73,7 +73,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
SetTempFilePath("ts");
- var taskCompletionSource = new TaskCompletionSource<bool>();
+ var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
_ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);
diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json
index 25f51db16..65a31e676 100644
--- a/Emby.Server.Implementations/Localization/Core/cs.json
+++ b/Emby.Server.Implementations/Localization/Core/cs.json
@@ -23,7 +23,7 @@
"HeaderFavoriteShows": "Oblíbené seriály",
"HeaderFavoriteSongs": "Oblíbená hudba",
"HeaderLiveTV": "Televize",
- "HeaderNextUp": "Nadcházející",
+ "HeaderNextUp": "Další díly",
"HeaderRecordingGroups": "Skupiny nahrávek",
"HomeVideos": "Domácí videa",
"Inherit": "Zdědit",
diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json
index bfafe7650..e56ae6071 100644
--- a/Emby.Server.Implementations/Localization/Core/fr.json
+++ b/Emby.Server.Implementations/Localization/Core/fr.json
@@ -1,7 +1,7 @@
{
"Albums": "Albums",
"AppDeviceValues": "Application : {0}, Appareil : {1}",
- "Application": "Applications",
+ "Application": "Application",
"Artists": "Artistes",
"AuthenticationSucceededWithUserName": "{0} authentifié avec succès",
"Books": "Livres",
diff --git a/Emby.Server.Implementations/Localization/Core/ro.json b/Emby.Server.Implementations/Localization/Core/ro.json
index f8fad7b63..8af5449a7 100644
--- a/Emby.Server.Implementations/Localization/Core/ro.json
+++ b/Emby.Server.Implementations/Localization/Core/ro.json
@@ -117,5 +117,7 @@
"TaskCleanActivityLog": "Curăță Jurnalul de Activitate",
"Undefined": "Nedefinit",
"Forced": "Forțat",
- "Default": "Implicit"
+ "Default": "Implicit",
+ "TaskOptimizeDatabaseDescription": "Compactează baza de date și trunchiază spațiul liber. Rularea acestei sarcini după scanarea bibliotecii sau după efectuarea altor modificări care implică modificări ale bazei de date poate îmbunătăți performanța.",
+ "TaskOptimizeDatabase": "Optimizează baza de date"
}
diff --git a/Emby.Server.Implementations/Localization/Core/th.json b/Emby.Server.Implementations/Localization/Core/th.json
index 89fbb84b6..bed67fa4f 100644
--- a/Emby.Server.Implementations/Localization/Core/th.json
+++ b/Emby.Server.Implementations/Localization/Core/th.json
@@ -118,5 +118,6 @@
"TaskCleanActivityLog": "ล้างบันทึกกิจกรรม",
"Undefined": "ไม่ได้กำหนด",
"Forced": "บังคับใช้",
- "TaskOptimizeDatabase": "ปรับฐานข้อมูลให้เหมาะสม"
+ "TaskOptimizeDatabase": "ปรับปรุงประสิทธิภาพฐานข้อมูล",
+ "TaskOptimizeDatabaseDescription": "ลดขนาดการจัดเก็บฐานข้อมูล ใช้งานคำสั่งนี้หลังจากสแกนไลบรารีหรือหลังจากการเปลี่ยนแปลงฐานข้อมูล อาจจะทำให้ระบบทำงานเร็วขึ้น"
}
diff --git a/Emby.Server.Implementations/Localization/Core/ug.json b/Emby.Server.Implementations/Localization/Core/ug.json
new file mode 100644
index 000000000..aea93c7fa
--- /dev/null
+++ b/Emby.Server.Implementations/Localization/Core/ug.json
@@ -0,0 +1,9 @@
+{
+ "ChapterNameValue": "باب {0}",
+ "Channels": "قانال",
+ "CameraImageUploadedFrom": "{0} ئورۇندىن يېڭى سۈرەت چىقىرىلدى",
+ "Books": "كىتاب",
+ "AuthenticationSucceededWithUserName": "تىزىملىتىش مۇۋەپپەقىيەتلىك بول",
+ "Artists": "سەنئەتكار",
+ "Albums": "پىلاستىنكا"
+}
diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs
index 0c451ccb6..bbbca4fc0 100644
--- a/Emby.Server.Implementations/Net/UdpSocket.cs
+++ b/Emby.Server.Implementations/Net/UdpSocket.cs
@@ -159,7 +159,7 @@ namespace Emby.Server.Implementations.Net
{
ThrowIfDisposed();
- var taskCompletion = new TaskCompletionSource<SocketReceiveResult>();
+ var taskCompletion = new TaskCompletionSource<SocketReceiveResult>(TaskCreationOptions.RunContinuationsAsynchronously);
bool isResultSet = false;
Action<IAsyncResult> callback = callbackResult =>
@@ -195,7 +195,7 @@ namespace Emby.Server.Implementations.Net
{
ThrowIfDisposed();
- var taskCompletion = new TaskCompletionSource<int>();
+ var taskCompletion = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
bool isResultSet = false;
Action<IAsyncResult> callback = callbackResult =>
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
index f7b3cfedc..7c27ae384 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
@@ -25,8 +25,8 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
/// <summary>
/// Initializes a new instance of the <see cref="RefreshMediaLibraryTask" /> class.
/// </summary>
- /// <param name="libraryManager">The library manager.</param>
- /// <param name="localization">The localization manager.</param>
+ /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
+ /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param>
public RefreshMediaLibraryTask(ILibraryManager libraryManager, ILocalizationManager localization)
{
_libraryManager = libraryManager;
diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs
index c994ffc90..a18af27f3 100644
--- a/Emby.Server.Implementations/TV/TVSeriesManager.cs
+++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs
@@ -304,11 +304,10 @@ namespace Emby.Server.Implementations.TV
items = items.Take(query.Limit.Value);
}
- return new QueryResult<BaseItem>
- {
- TotalRecordCount = totalCount,
- Items = items.ToArray()
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ totalCount,
+ items.ToArray());
}
}
}
diff --git a/Jellyfin.Api/Controllers/ApiKeyController.cs b/Jellyfin.Api/Controllers/ApiKeyController.cs
index 8e0332d3e..593846adc 100644
--- a/Jellyfin.Api/Controllers/ApiKeyController.cs
+++ b/Jellyfin.Api/Controllers/ApiKeyController.cs
@@ -38,11 +38,7 @@ namespace Jellyfin.Api.Controllers
{
var keys = await _authenticationManager.GetApiKeys();
- return new QueryResult<AuthenticationInfo>
- {
- Items = keys,
- TotalRecordCount = keys.Count
- };
+ return new QueryResult<AuthenticationInfo>(keys);
}
/// <summary>
diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs
index 3df975563..b54825775 100644
--- a/Jellyfin.Api/Controllers/ArtistsController.cs
+++ b/Jellyfin.Api/Controllers/ArtistsController.cs
@@ -243,11 +243,10 @@ namespace Jellyfin.Api.Controllers
return dto;
});
- return new QueryResult<BaseItemDto>
- {
- Items = dtos.ToArray(),
- TotalRecordCount = result.TotalRecordCount
- };
+ return new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ result.TotalRecordCount,
+ dtos.ToArray());
}
/// <summary>
@@ -447,11 +446,10 @@ namespace Jellyfin.Api.Controllers
return dto;
});
- return new QueryResult<BaseItemDto>
- {
- Items = dtos.ToArray(),
- TotalRecordCount = result.TotalRecordCount
- };
+ return new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ result.TotalRecordCount,
+ dtos.ToArray());
}
/// <summary>
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index 6ef3a2ff9..f2fdeeea5 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -13,6 +13,7 @@ using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
using Jellyfin.Api.Models.PlaybackDtos;
using Jellyfin.Api.Models.StreamingDtos;
+using Jellyfin.MediaEncoding.Hls.Playlist;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Devices;
@@ -28,7 +29,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
-using Microsoft.Net.Http.Headers;
namespace Jellyfin.Api.Controllers
{
@@ -55,6 +55,7 @@ namespace Jellyfin.Api.Controllers
private readonly TranscodingJobHelper _transcodingJobHelper;
private readonly ILogger<DynamicHlsController> _logger;
private readonly EncodingHelper _encodingHelper;
+ private readonly IDynamicHlsPlaylistGenerator _dynamicHlsPlaylistGenerator;
private readonly DynamicHlsHelper _dynamicHlsHelper;
private readonly EncodingOptions _encodingOptions;
@@ -74,6 +75,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="logger">Instance of the <see cref="ILogger{DynamicHlsController}"/> interface.</param>
/// <param name="dynamicHlsHelper">Instance of <see cref="DynamicHlsHelper"/>.</param>
/// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
+ /// <param name="dynamicHlsPlaylistGenerator">Instance of <see cref="IDynamicHlsPlaylistGenerator"/>.</param>
public DynamicHlsController(
ILibraryManager libraryManager,
IUserManager userManager,
@@ -87,7 +89,8 @@ namespace Jellyfin.Api.Controllers
TranscodingJobHelper transcodingJobHelper,
ILogger<DynamicHlsController> logger,
DynamicHlsHelper dynamicHlsHelper,
- EncodingHelper encodingHelper)
+ EncodingHelper encodingHelper,
+ IDynamicHlsPlaylistGenerator dynamicHlsPlaylistGenerator)
{
_libraryManager = libraryManager;
_userManager = userManager;
@@ -102,6 +105,7 @@ namespace Jellyfin.Api.Controllers
_logger = logger;
_dynamicHlsHelper = dynamicHlsHelper;
_encodingHelper = encodingHelper;
+ _dynamicHlsPlaylistGenerator = dynamicHlsPlaylistGenerator;
_encodingOptions = serverConfigurationManager.GetEncodingOptions();
}
@@ -385,6 +389,8 @@ namespace Jellyfin.Api.Controllers
/// <param name="startTimeTicks">Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.</param>
/// <param name="width">Optional. The fixed horizontal resolution of the encoded video.</param>
/// <param name="height">Optional. The fixed vertical resolution of the encoded video.</param>
+ /// <param name="maxWidth">Optional. The maximum horizontal resolution of the encoded video.</param>
+ /// <param name="maxHeight">Optional. The maximum vertical resolution of the encoded video.</param>
/// <param name="videoBitRate">Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults.</param>
/// <param name="subtitleStreamIndex">Optional. The index of the subtitle stream to use. If omitted no subtitles will be used.</param>
/// <param name="subtitleMethod">Optional. Specify the subtitle delivery method.</param>
@@ -441,6 +447,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] long? startTimeTicks,
[FromQuery] int? width,
[FromQuery] int? height,
+ [FromQuery] int? maxWidth,
+ [FromQuery] int? maxHeight,
[FromQuery] int? videoBitRate,
[FromQuery] int? subtitleStreamIndex,
[FromQuery] SubtitleDeliveryMethod? subtitleMethod,
@@ -493,6 +501,8 @@ namespace Jellyfin.Api.Controllers
StartTimeTicks = startTimeTicks,
Width = width,
Height = height,
+ MaxWidth = maxWidth,
+ MaxHeight = maxHeight,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
@@ -717,6 +727,8 @@ namespace Jellyfin.Api.Controllers
/// <param name="startTimeTicks">Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.</param>
/// <param name="width">Optional. The fixed horizontal resolution of the encoded video.</param>
/// <param name="height">Optional. The fixed vertical resolution of the encoded video.</param>
+ /// <param name="maxWidth">Optional. The maximum horizontal resolution of the encoded video.</param>
+ /// <param name="maxHeight">Optional. The maximum vertical resolution of the encoded video.</param>
/// <param name="videoBitRate">Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults.</param>
/// <param name="subtitleStreamIndex">Optional. The index of the subtitle stream to use. If omitted no subtitles will be used.</param>
/// <param name="subtitleMethod">Optional. Specify the subtitle delivery method.</param>
@@ -771,6 +783,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] long? startTimeTicks,
[FromQuery] int? width,
[FromQuery] int? height,
+ [FromQuery] int? maxWidth,
+ [FromQuery] int? maxHeight,
[FromQuery] int? videoBitRate,
[FromQuery] int? subtitleStreamIndex,
[FromQuery] SubtitleDeliveryMethod? subtitleMethod,
@@ -823,6 +837,8 @@ namespace Jellyfin.Api.Controllers
StartTimeTicks = startTimeTicks,
Width = width,
Height = height,
+ MaxWidth = maxWidth,
+ MaxHeight = maxHeight,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
@@ -844,7 +860,7 @@ namespace Jellyfin.Api.Controllers
StreamOptions = streamOptions
};
- return await GetVariantPlaylistInternal(streamingRequest, "main", cancellationTokenSource)
+ return await GetVariantPlaylistInternal(streamingRequest, cancellationTokenSource)
.ConfigureAwait(false);
}
@@ -1009,7 +1025,7 @@ namespace Jellyfin.Api.Controllers
StreamOptions = streamOptions
};
- return await GetVariantPlaylistInternal(streamingRequest, "main", cancellationTokenSource)
+ return await GetVariantPlaylistInternal(streamingRequest, cancellationTokenSource)
.ConfigureAwait(false);
}
@@ -1020,13 +1036,15 @@ namespace Jellyfin.Api.Controllers
/// <param name="playlistId">The playlist id.</param>
/// <param name="segmentId">The segment id.</param>
/// <param name="container">The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, mpg, avi, 3gp, wmv, wtv, m2ts, mov, iso, flv. </param>
+ /// <param name="runtimeTicks">The position of the requested segment in ticks.</param>
+ /// <param name="actualSegmentLengthTicks">The length of the requested segment in ticks.</param>
/// <param name="static">Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false.</param>
/// <param name="params">The streaming parameters.</param>
/// <param name="tag">The tag.</param>
/// <param name="deviceProfileId">Optional. The dlna device profile id to utilize.</param>
/// <param name="playSessionId">The play session id.</param>
/// <param name="segmentContainer">The segment container.</param>
- /// <param name="segmentLength">The segment lenght.</param>
+ /// <param name="segmentLength">The desired segment length.</param>
/// <param name="minSegments">The minimum number of segments.</param>
/// <param name="mediaSourceId">The media version id, if playing an alternate version.</param>
/// <param name="deviceId">The device id of the client requesting. Used to stop encoding processes when needed.</param>
@@ -1048,6 +1066,8 @@ namespace Jellyfin.Api.Controllers
/// <param name="startTimeTicks">Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms.</param>
/// <param name="width">Optional. The fixed horizontal resolution of the encoded video.</param>
/// <param name="height">Optional. The fixed vertical resolution of the encoded video.</param>
+ /// <param name="maxWidth">Optional. The maximum horizontal resolution of the encoded video.</param>
+ /// <param name="maxHeight">Optional. The maximum vertical resolution of the encoded video.</param>
/// <param name="videoBitRate">Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults.</param>
/// <param name="subtitleStreamIndex">Optional. The index of the subtitle stream to use. If omitted no subtitles will be used.</param>
/// <param name="subtitleMethod">Optional. Specify the subtitle delivery method.</param>
@@ -1078,6 +1098,8 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] string playlistId,
[FromRoute, Required] int segmentId,
[FromRoute, Required] string container,
+ [FromQuery, Required] long runtimeTicks,
+ [FromQuery, Required] long actualSegmentLengthTicks,
[FromQuery] bool? @static,
[FromQuery] string? @params,
[FromQuery] string? tag,
@@ -1106,6 +1128,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] long? startTimeTicks,
[FromQuery] int? width,
[FromQuery] int? height,
+ [FromQuery] int? maxWidth,
+ [FromQuery] int? maxHeight,
[FromQuery] int? videoBitRate,
[FromQuery] int? subtitleStreamIndex,
[FromQuery] SubtitleDeliveryMethod? subtitleMethod,
@@ -1129,6 +1153,8 @@ namespace Jellyfin.Api.Controllers
var streamingRequest = new VideoRequestDto
{
Id = itemId,
+ CurrentRuntimeTicks = runtimeTicks,
+ ActualSegmentLengthTicks = actualSegmentLengthTicks,
Container = container,
Static = @static ?? false,
Params = @params,
@@ -1158,6 +1184,8 @@ namespace Jellyfin.Api.Controllers
StartTimeTicks = startTimeTicks,
Width = width,
Height = height,
+ MaxWidth = maxWidth,
+ MaxHeight = maxHeight,
VideoBitRate = videoBitRate,
SubtitleStreamIndex = subtitleStreamIndex,
SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode,
@@ -1190,6 +1218,8 @@ namespace Jellyfin.Api.Controllers
/// <param name="playlistId">The playlist id.</param>
/// <param name="segmentId">The segment id.</param>
/// <param name="container">The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, mpg, avi, 3gp, wmv, wtv, m2ts, mov, iso, flv. </param>
+ /// <param name="runtimeTicks">The position of the requested segment in ticks.</param>
+ /// <param name="actualSegmentLengthTicks">The length of the requested segment in ticks.</param>
/// <param name="static">Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false.</param>
/// <param name="params">The streaming parameters.</param>
/// <param name="tag">The tag.</param>
@@ -1249,6 +1279,8 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] string playlistId,
[FromRoute, Required] int segmentId,
[FromRoute, Required] string container,
+ [FromQuery, Required] long runtimeTicks,
+ [FromQuery, Required] long actualSegmentLengthTicks,
[FromQuery] bool? @static,
[FromQuery] string? @params,
[FromQuery] string? tag,
@@ -1302,6 +1334,8 @@ namespace Jellyfin.Api.Controllers
{
Id = itemId,
Container = container,
+ CurrentRuntimeTicks = runtimeTicks,
+ ActualSegmentLengthTicks = actualSegmentLengthTicks,
Static = @static ?? false,
Params = @params,
Tag = tag,
@@ -1355,7 +1389,7 @@ namespace Jellyfin.Api.Controllers
.ConfigureAwait(false);
}
- private async Task<ActionResult> GetVariantPlaylistInternal(StreamingRequestDto streamingRequest, string name, CancellationTokenSource cancellationTokenSource)
+ private async Task<ActionResult> GetVariantPlaylistInternal(StreamingRequestDto streamingRequest, CancellationTokenSource cancellationTokenSource)
{
using var state = await StreamingHelpers.GetStreamingState(
streamingRequest,
@@ -1374,60 +1408,16 @@ namespace Jellyfin.Api.Controllers
cancellationTokenSource.Token)
.ConfigureAwait(false);
- Response.Headers.Add(HeaderNames.Expires, "0");
-
- var segmentLengths = GetSegmentLengths(state);
-
- var segmentContainer = state.Request.SegmentContainer ?? "ts";
-
- // http://ffmpeg.org/ffmpeg-all.html#toc-hls-2
- var isHlsInFmp4 = string.Equals(segmentContainer, "mp4", StringComparison.OrdinalIgnoreCase);
- var hlsVersion = isHlsInFmp4 ? "7" : "3";
-
- var builder = new StringBuilder(128);
-
- builder.AppendLine("#EXTM3U")
- .AppendLine("#EXT-X-PLAYLIST-TYPE:VOD")
- .Append("#EXT-X-VERSION:")
- .Append(hlsVersion)
- .AppendLine()
- .Append("#EXT-X-TARGETDURATION:")
- .Append(Math.Ceiling(segmentLengths.Length > 0 ? segmentLengths.Max() : state.SegmentLength))
- .AppendLine()
- .AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
+ var request = new CreateMainPlaylistRequest(
+ state.MediaPath,
+ state.SegmentLength * 1000,
+ state.RunTimeTicks ?? 0,
+ state.Request.SegmentContainer ?? string.Empty,
+ "hls1/main/",
+ Request.QueryString.ToString());
+ var playlist = _dynamicHlsPlaylistGenerator.CreateMainPlaylist(request);
- var index = 0;
- var segmentExtension = EncodingHelper.GetSegmentFileExtension(streamingRequest.SegmentContainer);
- var queryString = Request.QueryString;
-
- if (isHlsInFmp4)
- {
- builder.Append("#EXT-X-MAP:URI=\"")
- .Append("hls1/")
- .Append(name)
- .Append("/-1")
- .Append(segmentExtension)
- .Append(queryString)
- .Append('"')
- .AppendLine();
- }
-
- foreach (var length in segmentLengths)
- {
- builder.Append("#EXTINF:")
- .Append(length.ToString("0.0000", CultureInfo.InvariantCulture))
- .AppendLine(", nodesc")
- .Append("hls1/")
- .Append(name)
- .Append('/')
- .Append(index++)
- .Append(segmentExtension)
- .Append(queryString)
- .AppendLine();
- }
-
- builder.AppendLine("#EXT-X-ENDLIST");
- return new FileContentResult(Encoding.UTF8.GetBytes(builder.ToString()), MimeTypes.GetMimeType("playlist.m3u8"));
+ return new FileContentResult(Encoding.UTF8.GetBytes(playlist), MimeTypes.GetMimeType("playlist.m3u8"));
}
private async Task<ActionResult> GetDynamicSegment(StreamingRequestDto streamingRequest, int segmentId)
@@ -1528,7 +1518,7 @@ namespace Jellyfin.Api.Controllers
DeleteLastFile(playlistPath, segmentExtension, 0);
}
- streamingRequest.StartTimeTicks = GetStartPositionTicks(state, segmentId);
+ streamingRequest.StartTimeTicks = streamingRequest.CurrentRuntimeTicks;
state.WaitForPath = segmentPath;
job = await _transcodingJobHelper.StartFfMpeg(
@@ -1879,7 +1869,7 @@ namespace Jellyfin.Api.Controllers
{
// Transcoding job is over, so assume all existing files are ready
_logger.LogDebug("serving up {0} as transcode is over", segmentPath);
- return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
+ return GetSegmentResult(state, segmentPath, transcodingJob);
}
var currentTranscodingIndex = GetCurrentTranscodingIndex(playlistPath, segmentExtension);
@@ -1888,7 +1878,7 @@ namespace Jellyfin.Api.Controllers
if (segmentIndex < currentTranscodingIndex)
{
_logger.LogDebug("serving up {0} as transcode index {1} is past requested point {2}", segmentPath, currentTranscodingIndex, segmentIndex);
- return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
+ return GetSegmentResult(state, segmentPath, transcodingJob);
}
}
@@ -1903,8 +1893,8 @@ namespace Jellyfin.Api.Controllers
{
if (transcodingJob.HasExited || System.IO.File.Exists(nextSegmentPath))
{
- _logger.LogDebug("serving up {0} as it deemed ready", segmentPath);
- return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
+ _logger.LogDebug("Serving up {SegmentPath} as it deemed ready", segmentPath);
+ return GetSegmentResult(state, segmentPath, transcodingJob);
}
}
else
@@ -1935,16 +1925,16 @@ namespace Jellyfin.Api.Controllers
_logger.LogWarning("cannot serve {0} as it doesn't exist and no transcode is running", segmentPath);
}
- return GetSegmentResult(state, segmentPath, segmentIndex, transcodingJob);
+ return GetSegmentResult(state, segmentPath, transcodingJob);
}
- private ActionResult GetSegmentResult(StreamState state, string segmentPath, int index, TranscodingJobDto? transcodingJob)
+ private ActionResult GetSegmentResult(StreamState state, string segmentPath, TranscodingJobDto? transcodingJob)
{
- var segmentEndingPositionTicks = GetEndPositionTicks(state, index);
+ var segmentEndingPositionTicks = state.Request.CurrentRuntimeTicks + state.Request.ActualSegmentLengthTicks;
Response.OnCompleted(() =>
{
- _logger.LogDebug("finished serving {0}", segmentPath);
+ _logger.LogDebug("Finished serving {SegmentPath}", segmentPath);
if (transcodingJob != null)
{
transcodingJob.DownloadPositionTicks = Math.Max(transcodingJob.DownloadPositionTicks ?? segmentEndingPositionTicks, segmentEndingPositionTicks);
@@ -1957,29 +1947,6 @@ namespace Jellyfin.Api.Controllers
return FileStreamResponseHelpers.GetStaticFileResult(segmentPath, MimeTypes.GetMimeType(segmentPath), false, HttpContext);
}
- private long GetEndPositionTicks(StreamState state, int requestedIndex)
- {
- double startSeconds = 0;
- var lengths = GetSegmentLengths(state);
-
- if (requestedIndex >= lengths.Length)
- {
- var msg = string.Format(
- CultureInfo.InvariantCulture,
- "Invalid segment index requested: {0} - Segment count: {1}",
- requestedIndex,
- lengths.Length);
- throw new ArgumentException(msg);
- }
-
- for (var i = 0; i <= requestedIndex; i++)
- {
- startSeconds += lengths[i];
- }
-
- return TimeSpan.FromSeconds(startSeconds).Ticks;
- }
-
private int? GetCurrentTranscodingIndex(string playlist, string segmentExtension)
{
var job = _transcodingJobHelper.GetTranscodingJob(playlist, TranscodingJobType);
@@ -2058,29 +2025,5 @@ namespace Jellyfin.Api.Controllers
_logger.LogError(ex, "Error deleting partial stream file(s) {Path}", path);
}
}
-
- private long GetStartPositionTicks(StreamState state, int requestedIndex)
- {
- double startSeconds = 0;
- var lengths = GetSegmentLengths(state);
-
- if (requestedIndex >= lengths.Length)
- {
- var msg = string.Format(
- CultureInfo.InvariantCulture,
- "Invalid segment index requested: {0} - Segment count: {1}",
- requestedIndex,
- lengths.Length);
- throw new ArgumentException(msg);
- }
-
- for (var i = 0; i < requestedIndex; i++)
- {
- startSeconds += lengths[i];
- }
-
- var position = TimeSpan.FromSeconds(startSeconds).Ticks;
- return position;
- }
}
}
diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs
index e72589cfa..aafffc2a1 100644
--- a/Jellyfin.Api/Controllers/ImageController.cs
+++ b/Jellyfin.Api/Controllers/ImageController.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
@@ -11,12 +12,14 @@ using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Helpers;
+using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Branding;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@@ -44,6 +47,8 @@ namespace Jellyfin.Api.Controllers
private readonly IAuthorizationContext _authContext;
private readonly ILogger<ImageController> _logger;
private readonly IServerConfigurationManager _serverConfigurationManager;
+ private readonly IApplicationPaths _appPaths;
+ private readonly IImageEncoder _imageEncoder;
/// <summary>
/// Initializes a new instance of the <see cref="ImageController"/> class.
@@ -56,6 +61,8 @@ namespace Jellyfin.Api.Controllers
/// <param name="authContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{ImageController}"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
+ /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
+ /// <param name="imageEncoder">Instance of the <see cref="IImageEncoder"/> interface.</param>
public ImageController(
IUserManager userManager,
ILibraryManager libraryManager,
@@ -64,7 +71,9 @@ namespace Jellyfin.Api.Controllers
IFileSystem fileSystem,
IAuthorizationContext authContext,
ILogger<ImageController> logger,
- IServerConfigurationManager serverConfigurationManager)
+ IServerConfigurationManager serverConfigurationManager,
+ IApplicationPaths appPaths,
+ IImageEncoder imageEncoder)
{
_userManager = userManager;
_libraryManager = libraryManager;
@@ -74,6 +83,8 @@ namespace Jellyfin.Api.Controllers
_authContext = authContext;
_logger = logger;
_serverConfigurationManager = serverConfigurationManager;
+ _appPaths = appPaths;
+ _imageEncoder = imageEncoder;
}
/// <summary>
@@ -1692,6 +1703,130 @@ namespace Jellyfin.Api.Controllers
.ConfigureAwait(false);
}
+ /// <summary>
+ /// Generates or gets the splashscreen.
+ /// </summary>
+ /// <param name="tag">Supply the cache tag from the item object to receive strong caching headers.</param>
+ /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
+ /// <param name="maxWidth">The maximum image width to return.</param>
+ /// <param name="maxHeight">The maximum image height to return.</param>
+ /// <param name="width">The fixed image width to return.</param>
+ /// <param name="height">The fixed image height to return.</param>
+ /// <param name="fillWidth">Width of box to fill.</param>
+ /// <param name="fillHeight">Height of box to fill.</param>
+ /// <param name="blur">Blur image.</param>
+ /// <param name="backgroundColor">Apply a background color for transparent images.</param>
+ /// <param name="foregroundLayer">Apply a foreground layer on top of the image.</param>
+ /// <param name="quality">Quality setting, from 0-100.</param>
+ /// <response code="200">Splashscreen returned successfully.</response>
+ /// <returns>The splashscreen.</returns>
+ [HttpGet("Branding/Splashscreen")]
+ [ProducesResponseType(StatusCodes.Status200OK)]
+ [ProducesImageFile]
+ public async Task<ActionResult> GetSplashscreen(
+ [FromQuery] string? tag,
+ [FromQuery] ImageFormat? format,
+ [FromQuery] int? maxWidth,
+ [FromQuery] int? maxHeight,
+ [FromQuery] int? width,
+ [FromQuery] int? height,
+ [FromQuery] int? fillWidth,
+ [FromQuery] int? fillHeight,
+ [FromQuery] int? blur,
+ [FromQuery] string? backgroundColor,
+ [FromQuery] string? foregroundLayer,
+ [FromQuery, Range(0, 100)] int quality = 90)
+ {
+ var brandingOptions = _serverConfigurationManager.GetConfiguration<BrandingOptions>("branding");
+ string splashscreenPath;
+
+ if (!string.IsNullOrWhiteSpace(brandingOptions.SplashscreenLocation)
+ && System.IO.File.Exists(brandingOptions.SplashscreenLocation))
+ {
+ splashscreenPath = brandingOptions.SplashscreenLocation;
+ }
+ else
+ {
+ splashscreenPath = Path.Combine(_appPaths.DataPath, "splashscreen.png");
+ if (!System.IO.File.Exists(splashscreenPath))
+ {
+ return NotFound();
+ }
+ }
+
+ var outputFormats = GetOutputFormats(format);
+
+ TimeSpan? cacheDuration = null;
+ if (!string.IsNullOrEmpty(tag))
+ {
+ cacheDuration = TimeSpan.FromDays(365);
+ }
+
+ var options = new ImageProcessingOptions
+ {
+ Image = new ItemImageInfo
+ {
+ Path = splashscreenPath
+ },
+ Height = height,
+ MaxHeight = maxHeight,
+ MaxWidth = maxWidth,
+ FillHeight = fillHeight,
+ FillWidth = fillWidth,
+ Quality = quality,
+ Width = width,
+ Blur = blur,
+ BackgroundColor = backgroundColor,
+ ForegroundLayer = foregroundLayer,
+ SupportedOutputFormats = outputFormats
+ };
+
+ return await GetImageResult(
+ options,
+ cacheDuration,
+ ImmutableDictionary<string, string>.Empty,
+ Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ .ConfigureAwait(false);
+ }
+
+ /// <summary>
+ /// Uploads a custom splashscreen.
+ /// </summary>
+ /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
+ /// <response code="204">Successfully uploaded new splashscreen.</response>
+ /// <response code="400">Error reading MimeType from uploaded image.</response>
+ /// <response code="403">User does not have permission to upload splashscreen..</response>
+ /// <exception cref="ArgumentException">Error reading the image format.</exception>
+ [HttpPost("Branding/Splashscreen")]
+ [Authorize(Policy = Policies.RequiresElevation)]
+ [ProducesResponseType(StatusCodes.Status204NoContent)]
+ [ProducesResponseType(StatusCodes.Status400BadRequest)]
+ [ProducesResponseType(StatusCodes.Status403Forbidden)]
+ [AcceptsImageFile]
+ public async Task<ActionResult> UploadCustomSplashscreen()
+ {
+ await using var memoryStream = await GetMemoryStream(Request.Body).ConfigureAwait(false);
+
+ var mimeType = MediaTypeHeaderValue.Parse(Request.ContentType).MediaType;
+
+ if (!mimeType.HasValue)
+ {
+ return BadRequest("Error reading mimetype from uploaded image");
+ }
+
+ var filePath = Path.Combine(_appPaths.DataPath, "splashscreen-upload" + MimeTypes.ToExtension(mimeType.Value));
+ var brandingOptions = _serverConfigurationManager.GetConfiguration<BrandingOptions>("branding");
+ brandingOptions.SplashscreenLocation = filePath;
+ _serverConfigurationManager.SaveConfiguration("branding", brandingOptions);
+
+ await using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
+ {
+ await memoryStream.CopyToAsync(fs, CancellationToken.None).ConfigureAwait(false);
+ }
+
+ return NoContent();
+ }
+
private static async Task<MemoryStream> GetMemoryStream(Stream inputStream)
{
using var reader = new StreamReader(inputStream);
@@ -1823,25 +1958,35 @@ namespace Jellyfin.Api.Controllers
{ "realTimeInfo.dlna.org", "DLNA.ORG_TLAG=*" }
};
+ if (!imageInfo.IsLocalFile && item != null)
+ {
+ imageInfo = await _libraryManager.ConvertImageToLocal(item, imageInfo, imageIndex ?? 0).ConfigureAwait(false);
+ }
+
+ var options = new ImageProcessingOptions
+ {
+ Height = height,
+ ImageIndex = imageIndex ?? 0,
+ Image = imageInfo,
+ Item = item,
+ ItemId = itemId,
+ MaxHeight = maxHeight,
+ MaxWidth = maxWidth,
+ FillHeight = fillHeight,
+ FillWidth = fillWidth,
+ Quality = quality ?? 100,
+ Width = width,
+ AddPlayedIndicator = addPlayedIndicator ?? false,
+ PercentPlayed = percentPlayed ?? 0,
+ UnplayedCount = unplayedCount,
+ Blur = blur,
+ BackgroundColor = backgroundColor,
+ ForegroundLayer = foregroundLayer,
+ SupportedOutputFormats = outputFormats
+ };
+
return await GetImageResult(
- item,
- itemId,
- imageIndex,
- width,
- height,
- maxWidth,
- maxHeight,
- fillWidth,
- fillHeight,
- quality,
- addPlayedIndicator,
- percentPlayed,
- unplayedCount,
- blur,
- backgroundColor,
- foregroundLayer,
- imageInfo,
- outputFormats,
+ options,
cacheDuration,
responseHeaders,
isHeadRequest).ConfigureAwait(false);
@@ -1921,56 +2066,12 @@ namespace Jellyfin.Api.Controllers
}
private async Task<ActionResult> GetImageResult(
- BaseItem? item,
- Guid itemId,
- int? index,
- int? width,
- int? height,
- int? maxWidth,
- int? maxHeight,
- int? fillWidth,
- int? fillHeight,
- int? quality,
- bool? addPlayedIndicator,
- double? percentPlayed,
- int? unplayedCount,
- int? blur,
- string? backgroundColor,
- string? foregroundLayer,
- ItemImageInfo imageInfo,
- IReadOnlyCollection<ImageFormat> supportedFormats,
+ ImageProcessingOptions imageProcessingOptions,
TimeSpan? cacheDuration,
IDictionary<string, string> headers,
bool isHeadRequest)
{
- if (!imageInfo.IsLocalFile && item != null)
- {
- imageInfo = await _libraryManager.ConvertImageToLocal(item, imageInfo, index ?? 0).ConfigureAwait(false);
- }
-
- var options = new ImageProcessingOptions
- {
- Height = height,
- ImageIndex = index ?? 0,
- Image = imageInfo,
- Item = item,
- ItemId = itemId,
- MaxHeight = maxHeight,
- MaxWidth = maxWidth,
- FillHeight = fillHeight,
- FillWidth = fillWidth,
- Quality = quality ?? 100,
- Width = width,
- AddPlayedIndicator = addPlayedIndicator ?? false,
- PercentPlayed = percentPlayed ?? 0,
- UnplayedCount = unplayedCount,
- Blur = blur,
- BackgroundColor = backgroundColor,
- ForegroundLayer = foregroundLayer,
- SupportedOutputFormats = supportedFormats
- };
-
- var (imagePath, imageContentType, dateImageModified) = await _imageProcessor.ProcessImage(options).ConfigureAwait(false);
+ var (imagePath, imageContentType, dateImageModified) = await _imageProcessor.ProcessImage(imageProcessingOptions).ConfigureAwait(false);
var disableCaching = Request.Headers[HeaderNames.CacheControl].Contains("no-cache");
var parsingSuccessful = DateTime.TryParse(Request.Headers[HeaderNames.IfModifiedSince], out var ifModifiedSinceHeader);
diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs
index a6c2e07c9..e9d48b624 100644
--- a/Jellyfin.Api/Controllers/InstantMixController.cs
+++ b/Jellyfin.Api/Controllers/InstantMixController.cs
@@ -341,10 +341,7 @@ namespace Jellyfin.Api.Controllers
{
var list = items;
- var result = new QueryResult<BaseItemDto>
- {
- TotalRecordCount = list.Count
- };
+ var totalCount = list.Count;
if (limit.HasValue && limit < list.Count)
{
@@ -353,7 +350,10 @@ namespace Jellyfin.Api.Controllers
var returnList = _dtoService.GetBaseItemDtos(list, dtoOptions, user);
- result.Items = returnList;
+ var result = new QueryResult<BaseItemDto>(
+ 0,
+ totalCount,
+ returnList);
return result;
}
diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs
index 4161e43f6..c49f85616 100644
--- a/Jellyfin.Api/Controllers/ItemLookupController.cs
+++ b/Jellyfin.Api/Controllers/ItemLookupController.cs
@@ -263,7 +263,8 @@ namespace Jellyfin.Api.Controllers
ImageRefreshMode = MetadataRefreshMode.FullRefresh,
ReplaceAllMetadata = true,
ReplaceAllImages = replaceAllImages,
- SearchResult = searchResult
+ SearchResult = searchResult,
+ RemoveOldMetadata = true
},
CancellationToken.None).ConfigureAwait(false);
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index f8192955e..dc7af0a20 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -491,10 +491,13 @@ namespace Jellyfin.Api.Controllers
else
{
var itemsArray = folder.GetChildren(user, true);
- result = new QueryResult<BaseItem> { Items = itemsArray, TotalRecordCount = itemsArray.Count, StartIndex = 0 };
+ result = new QueryResult<BaseItem>(itemsArray);
}
- return new QueryResult<BaseItemDto> { StartIndex = startIndex.GetValueOrDefault(), TotalRecordCount = result.TotalRecordCount, Items = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user) };
+ return new QueryResult<BaseItemDto>(
+ startIndex,
+ result.TotalRecordCount,
+ _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user));
}
/// <summary>
@@ -836,12 +839,10 @@ namespace Jellyfin.Api.Controllers
var returnItems = _dtoService.GetBaseItemDtos(itemsResult.Items, dtoOptions, user);
- return new QueryResult<BaseItemDto>
- {
- StartIndex = startIndex.GetValueOrDefault(),
- TotalRecordCount = itemsResult.TotalRecordCount,
- Items = returnItems
- };
+ return new QueryResult<BaseItemDto>(
+ startIndex,
+ itemsResult.TotalRecordCount,
+ returnItems);
}
}
}
diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs
index f1b9c2f67..c65462ab5 100644
--- a/Jellyfin.Api/Controllers/LibraryController.cs
+++ b/Jellyfin.Api/Controllers/LibraryController.cs
@@ -506,13 +506,8 @@ namespace Jellyfin.Api.Controllers
}
var dtoOptions = new DtoOptions().AddClientFields(Request);
- var result = new QueryResult<BaseItemDto>
- {
- TotalRecordCount = items.Count,
- Items = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions)).ToArray()
- };
-
- return result;
+ var resultArray = _dtoService.GetBaseItemDtos(items, dtoOptions);
+ return new QueryResult<BaseItemDto>(resultArray);
}
/// <summary>
@@ -759,11 +754,10 @@ namespace Jellyfin.Api.Controllers
var returnList = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user);
- return new QueryResult<BaseItemDto>
- {
- Items = returnList,
- TotalRecordCount = itemsResult.Count
- };
+ return new QueryResult<BaseItemDto>(
+ query.StartIndex,
+ itemsResult.Count,
+ returnList);
}
/// <summary>
diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs
index 9e2ef8c60..484b0a974 100644
--- a/Jellyfin.Api/Controllers/LiveTvController.cs
+++ b/Jellyfin.Api/Controllers/LiveTvController.cs
@@ -193,11 +193,10 @@ namespace Jellyfin.Api.Controllers
dtoOptions.AddCurrentProgram = addCurrentProgram;
var returnArray = _dtoService.GetBaseItemDtos(channelResult.Items, dtoOptions, user);
- return new QueryResult<BaseItemDto>
- {
- Items = returnArray,
- TotalRecordCount = channelResult.TotalRecordCount
- };
+ return new QueryResult<BaseItemDto>(
+ startIndex,
+ channelResult.TotalRecordCount,
+ returnArray);
}
/// <summary>
@@ -390,11 +389,7 @@ namespace Jellyfin.Api.Controllers
var returnArray = _dtoService.GetBaseItemDtos(folders, new DtoOptions(), user);
- return new QueryResult<BaseItemDto>
- {
- Items = returnArray,
- TotalRecordCount = returnArray.Count
- };
+ return new QueryResult<BaseItemDto>(returnArray);
}
/// <summary>
@@ -687,7 +682,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("Programs/Recommended")]
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status200OK)]
- public ActionResult<QueryResult<BaseItemDto>> GetRecommendedPrograms(
+ public async Task<ActionResult<QueryResult<BaseItemDto>>> GetRecommendedPrograms(
[FromQuery] Guid? userId,
[FromQuery] int? limit,
[FromQuery] bool? isAiring,
@@ -726,7 +721,7 @@ namespace Jellyfin.Api.Controllers
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
- return _liveTvManager.GetRecommendedPrograms(query, dtoOptions, CancellationToken.None);
+ return await _liveTvManager.GetRecommendedProgramsAsync(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
}
/// <summary>
diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs
index cb4894d77..ffc748a6e 100644
--- a/Jellyfin.Api/Controllers/PersonsController.cs
+++ b/Jellyfin.Api/Controllers/PersonsController.cs
@@ -101,11 +101,7 @@ namespace Jellyfin.Api.Controllers
Limit = limit ?? 0
});
- return new QueryResult<BaseItemDto>
- {
- Items = peopleItems.Select(person => _dtoService.GetItemByNameDto(person, dtoOptions, null, user)).ToArray(),
- TotalRecordCount = peopleItems.Count
- };
+ return new QueryResult<BaseItemDto>(peopleItems.Select(person => _dtoService.GetItemByNameDto(person, dtoOptions, null, user)).ToArray());
}
/// <summary>
diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs
index 1667d6ede..c18f1b427 100644
--- a/Jellyfin.Api/Controllers/PlaylistsController.cs
+++ b/Jellyfin.Api/Controllers/PlaylistsController.cs
@@ -208,11 +208,10 @@ namespace Jellyfin.Api.Controllers
dtos[index].PlaylistItemId = items[index].Item1.Id;
}
- var result = new QueryResult<BaseItemDto>
- {
- Items = dtos,
- TotalRecordCount = count
- };
+ var result = new QueryResult<BaseItemDto>(
+ startIndex,
+ count,
+ dtos);
return result;
}
diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs
index af77c801f..73be26bb2 100644
--- a/Jellyfin.Api/Controllers/SuggestionsController.cs
+++ b/Jellyfin.Api/Controllers/SuggestionsController.cs
@@ -81,11 +81,10 @@ namespace Jellyfin.Api.Controllers
var dtoList = _dtoService.GetBaseItemDtos(result.Items, dtoOptions, user);
- return new QueryResult<BaseItemDto>
- {
- TotalRecordCount = result.TotalRecordCount,
- Items = dtoList
- };
+ return new QueryResult<BaseItemDto>(
+ startIndex,
+ result.TotalRecordCount,
+ dtoList);
}
}
}
diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs
index e20bcd7a7..9425fe519 100644
--- a/Jellyfin.Api/Controllers/TvShowsController.cs
+++ b/Jellyfin.Api/Controllers/TvShowsController.cs
@@ -110,11 +110,10 @@ namespace Jellyfin.Api.Controllers
var returnItems = _dtoService.GetBaseItemDtos(result.Items, options, user);
- return new QueryResult<BaseItemDto>
- {
- TotalRecordCount = result.TotalRecordCount,
- Items = returnItems
- };
+ return new QueryResult<BaseItemDto>(
+ startIndex,
+ result.TotalRecordCount,
+ returnItems);
}
/// <summary>
@@ -169,11 +168,10 @@ namespace Jellyfin.Api.Controllers
var returnItems = _dtoService.GetBaseItemDtos(itemsResult, options, user);
- return new QueryResult<BaseItemDto>
- {
- TotalRecordCount = itemsResult.Count,
- Items = returnItems
- };
+ return new QueryResult<BaseItemDto>(
+ startIndex,
+ itemsResult.Count,
+ returnItems);
}
/// <summary>
@@ -296,11 +294,10 @@ namespace Jellyfin.Api.Controllers
var dtos = _dtoService.GetBaseItemDtos(returnItems, dtoOptions, user);
- return new QueryResult<BaseItemDto>
- {
- TotalRecordCount = episodes.Count,
- Items = dtos
- };
+ return new QueryResult<BaseItemDto>(
+ startIndex,
+ episodes.Count,
+ dtos);
}
/// <summary>
@@ -354,11 +351,7 @@ namespace Jellyfin.Api.Controllers
var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user);
- return new QueryResult<BaseItemDto>
- {
- TotalRecordCount = returnItems.Count,
- Items = returnItems
- };
+ return new QueryResult<BaseItemDto>(returnItems);
}
/// <summary>
diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs
index 8b99170d9..008d2f176 100644
--- a/Jellyfin.Api/Controllers/UserLibraryController.cs
+++ b/Jellyfin.Api/Controllers/UserLibraryController.cs
@@ -124,11 +124,7 @@ namespace Jellyfin.Api.Controllers
var dtoOptions = new DtoOptions().AddClientFields(Request);
var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray();
- return new QueryResult<BaseItemDto>
- {
- Items = dtos,
- TotalRecordCount = dtos.Length
- };
+ return new QueryResult<BaseItemDto>(dtos);
}
/// <summary>
@@ -206,21 +202,16 @@ namespace Jellyfin.Api.Controllers
: _libraryManager.GetItemById(itemId);
var dtoOptions = new DtoOptions().AddClientFields(Request);
- var dtosExtras = item.GetExtras(new[] { ExtraType.Trailer })
- .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))
- .ToArray();
if (item is IHasTrailers hasTrailers)
{
var trailers = hasTrailers.LocalTrailers;
- var dtosTrailers = _dtoService.GetBaseItemDtos(trailers, dtoOptions, user, item);
- var allTrailers = new BaseItemDto[dtosExtras.Length + dtosTrailers.Count];
- dtosExtras.CopyTo(allTrailers, 0);
- dtosTrailers.CopyTo(allTrailers, dtosExtras.Length);
- return allTrailers;
+ return Ok(_dtoService.GetBaseItemDtos(trailers, dtoOptions, user, item));
}
- return dtosExtras;
+ return Ok(item.GetExtras()
+ .Where(e => e.ExtraType == ExtraType.Trailer)
+ .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)));
}
/// <summary>
diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs
index 3d27371f6..04171da8a 100644
--- a/Jellyfin.Api/Controllers/UserViewsController.cs
+++ b/Jellyfin.Api/Controllers/UserViewsController.cs
@@ -108,11 +108,7 @@ namespace Jellyfin.Api.Controllers
var dtos = folders.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user))
.ToArray();
- return new QueryResult<BaseItemDto>
- {
- Items = dtos,
- TotalRecordCount = dtos.Length
- };
+ return new QueryResult<BaseItemDto>(dtos);
}
/// <summary>
diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs
index 3c079a71d..89b150598 100644
--- a/Jellyfin.Api/Controllers/VideosController.cs
+++ b/Jellyfin.Api/Controllers/VideosController.cs
@@ -134,12 +134,7 @@ namespace Jellyfin.Api.Controllers
items = Array.Empty<BaseItemDto>();
}
- var result = new QueryResult<BaseItemDto>
- {
- Items = items,
- TotalRecordCount = items.Length
- };
-
+ var result = new QueryResult<BaseItemDto>(items);
return result;
}
diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs
index 8be6fd1b5..bac77d43b 100644
--- a/Jellyfin.Api/Controllers/YearsController.cs
+++ b/Jellyfin.Api/Controllers/YearsController.cs
@@ -136,8 +136,6 @@ namespace Jellyfin.Api.Controllers
IEnumerable<BaseItem> ibnItems = ibnItemsArray;
- var result = new QueryResult<BaseItemDto> { TotalRecordCount = ibnItemsArray.Count };
-
if (startIndex.HasValue || limit.HasValue)
{
if (startIndex.HasValue)
@@ -155,8 +153,10 @@ namespace Jellyfin.Api.Controllers
var dtos = tuples.Select(i => _dtoService.GetItemByNameDto(i.Item1, dtoOptions, i.Item2, user));
- result.Items = dtos.Where(i => i != null).ToArray();
-
+ var result = new QueryResult<BaseItemDto>(
+ startIndex,
+ ibnItemsArray.Count,
+ dtos.Where(i => i != null).ToArray());
return result;
}
diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs
index 2cfd36d00..20427d7fa 100644
--- a/Jellyfin.Api/Helpers/RequestHelpers.cs
+++ b/Jellyfin.Api/Helpers/RequestHelpers.cs
@@ -131,11 +131,10 @@ namespace Jellyfin.Api.Helpers
return dto;
});
- return new QueryResult<BaseItemDto>
- {
- Items = dtos.ToArray(),
- TotalRecordCount = result.TotalRecordCount
- };
+ return new QueryResult<BaseItemDto>(
+ result.StartIndex,
+ result.TotalRecordCount,
+ dtos.ToArray());
}
}
}
diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj
index b5af07408..3a7d39365 100644
--- a/Jellyfin.Api/Jellyfin.Api.csproj
+++ b/Jellyfin.Api/Jellyfin.Api.csproj
@@ -26,10 +26,15 @@
<ItemGroup>
<ProjectReference Include="..\Emby.Dlna\Emby.Dlna.csproj" />
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />
+ <ProjectReference Include="..\src\Jellyfin.MediaEncoding.Hls\Jellyfin.MediaEncoding.Hls.csproj" />
</ItemGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs b/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs
index 1791b0370..f8b0212b6 100644
--- a/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs
+++ b/Jellyfin.Api/Models/StreamingDtos/StreamingRequestDto.cs
@@ -41,5 +41,15 @@ namespace Jellyfin.Api.Models.StreamingDtos
/// Gets or sets the min segments.
/// </summary>
public int? MinSegments { get; set; }
+
+ /// <summary>
+ /// Gets or sets the position of the requested segment in ticks.
+ /// </summary>
+ public long CurrentRuntimeTicks { get; set; }
+
+ /// <summary>
+ /// Gets or sets the actual segment length in ticks.
+ /// </summary>
+ public long ActualSegmentLengthTicks { get; set; }
}
}
diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj
index f2779d8f2..c35778065 100644
--- a/Jellyfin.Data/Jellyfin.Data.csproj
+++ b/Jellyfin.Data/Jellyfin.Data.csproj
@@ -29,6 +29,10 @@
<!-- Code analysers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
index 4cc215903..44631327e 100644
--- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
+++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj
@@ -30,6 +30,10 @@
<!-- Code analysers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs
index 6d0a5ac2b..1fa8e570d 100644
--- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs
+++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs
@@ -492,6 +492,14 @@ namespace Jellyfin.Drawing.Skia
}
}
+ /// <inheritdoc />
+ public void CreateSplashscreen(IReadOnlyList<string> posters, IReadOnlyList<string> backdrops)
+ {
+ var splashBuilder = new SplashscreenBuilder(this);
+ var outputPath = Path.Combine(_appPaths.DataPath, "splashscreen.png");
+ splashBuilder.GenerateSplash(posters, backdrops, outputPath);
+ }
+
private void DrawIndicator(SKCanvas canvas, int imageWidth, int imageHeight, ImageProcessingOptions options)
{
try
diff --git a/Jellyfin.Drawing.Skia/SkiaHelper.cs b/Jellyfin.Drawing.Skia/SkiaHelper.cs
index f9c79c855..35dcebdab 100644
--- a/Jellyfin.Drawing.Skia/SkiaHelper.cs
+++ b/Jellyfin.Drawing.Skia/SkiaHelper.cs
@@ -1,3 +1,4 @@
+using System.Collections.Generic;
using SkiaSharp;
namespace Jellyfin.Drawing.Skia
@@ -19,5 +20,41 @@ namespace Jellyfin.Drawing.Skia
throw new SkiaCodecException(result);
}
}
+
+ /// <summary>
+ /// Gets the next valid image as a bitmap.
+ /// </summary>
+ /// <param name="skiaEncoder">The current skia encoder.</param>
+ /// <param name="paths">The list of image paths.</param>
+ /// <param name="currentIndex">The current checked indes.</param>
+ /// <param name="newIndex">The new index.</param>
+ /// <returns>A valid bitmap, or null if no bitmap exists after <c>currentIndex</c>.</returns>
+ public static SKBitmap? GetNextValidImage(SkiaEncoder skiaEncoder, IReadOnlyList<string> paths, int currentIndex, out int newIndex)
+ {
+ var imagesTested = new Dictionary<int, int>();
+ SKBitmap? bitmap = null;
+
+ while (imagesTested.Count < paths.Count)
+ {
+ if (currentIndex >= paths.Count)
+ {
+ currentIndex = 0;
+ }
+
+ bitmap = skiaEncoder.Decode(paths[currentIndex], false, null, out _);
+
+ imagesTested[currentIndex] = 0;
+
+ currentIndex++;
+
+ if (bitmap != null)
+ {
+ break;
+ }
+ }
+
+ newIndex = currentIndex;
+ return bitmap;
+ }
}
}
diff --git a/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs b/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs
new file mode 100644
index 000000000..e5fa6c2bd
--- /dev/null
+++ b/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs
@@ -0,0 +1,148 @@
+using System;
+using System.Collections.Generic;
+using SkiaSharp;
+
+namespace Jellyfin.Drawing.Skia
+{
+ /// <summary>
+ /// Used to build the splashscreen.
+ /// </summary>
+ public class SplashscreenBuilder
+ {
+ private const int FinalWidth = 1920;
+ private const int FinalHeight = 1080;
+ // generated collage resolution should be higher than the final resolution
+ private const int WallWidth = FinalWidth * 3;
+ private const int WallHeight = FinalHeight * 2;
+ private const int Rows = 6;
+ private const int Spacing = 20;
+
+ private readonly SkiaEncoder _skiaEncoder;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SplashscreenBuilder"/> class.
+ /// </summary>
+ /// <param name="skiaEncoder">The SkiaEncoder.</param>
+ public SplashscreenBuilder(SkiaEncoder skiaEncoder)
+ {
+ _skiaEncoder = skiaEncoder;
+ }
+
+ /// <summary>
+ /// Generate a splashscreen.
+ /// </summary>
+ /// <param name="posters">The poster paths.</param>
+ /// <param name="backdrops">The landscape paths.</param>
+ /// <param name="outputPath">The output path.</param>
+ public void GenerateSplash(IReadOnlyList<string> posters, IReadOnlyList<string> backdrops, string outputPath)
+ {
+ using var wall = GenerateCollage(posters, backdrops);
+ using var transformed = Transform3D(wall);
+
+ using var outputStream = new SKFileWStream(outputPath);
+ using var pixmap = new SKPixmap(new SKImageInfo(FinalWidth, FinalHeight), transformed.GetPixels());
+ pixmap.Encode(outputStream, StripCollageBuilder.GetEncodedFormat(outputPath), 90);
+ }
+
+ /// <summary>
+ /// Generates a collage of posters and landscape pictures.
+ /// </summary>
+ /// <param name="posters">The poster paths.</param>
+ /// <param name="backdrops">The landscape paths.</param>
+ /// <returns>The created collage as a bitmap.</returns>
+ private SKBitmap GenerateCollage(IReadOnlyList<string> posters, IReadOnlyList<string> backdrops)
+ {
+ var posterIndex = 0;
+ var backdropIndex = 0;
+
+ var bitmap = new SKBitmap(WallWidth, WallHeight);
+ using var canvas = new SKCanvas(bitmap);
+ canvas.Clear(SKColors.Black);
+
+ int posterHeight = WallHeight / 6;
+
+ for (int i = 0; i < Rows; i++)
+ {
+ int imageCounter = Random.Shared.Next(0, 5);
+ int currentWidthPos = i * 75;
+ int currentHeight = i * (posterHeight + Spacing);
+
+ while (currentWidthPos < WallWidth)
+ {
+ SKBitmap? currentImage;
+
+ switch (imageCounter)
+ {
+ case 0:
+ case 2:
+ case 3:
+ currentImage = SkiaHelper.GetNextValidImage(_skiaEncoder, posters, posterIndex, out int newPosterIndex);
+ posterIndex = newPosterIndex;
+ break;
+ default:
+ currentImage = SkiaHelper.GetNextValidImage(_skiaEncoder, backdrops, backdropIndex, out int newBackdropIndex);
+ backdropIndex = newBackdropIndex;
+ break;
+ }
+
+ if (currentImage == null)
+ {
+ throw new ArgumentException("Not enough valid pictures provided to create a splashscreen!");
+ }
+
+ // resize to the same aspect as the original
+ var imageWidth = Math.Abs(posterHeight * currentImage.Width / currentImage.Height);
+ using var resizedBitmap = new SKBitmap(imageWidth, posterHeight);
+ currentImage.ScalePixels(resizedBitmap, SKFilterQuality.High);
+
+ // draw on canvas
+ canvas.DrawBitmap(resizedBitmap, currentWidthPos, currentHeight);
+
+ currentWidthPos += imageWidth + Spacing;
+
+ currentImage.Dispose();
+
+ if (imageCounter >= 4)
+ {
+ imageCounter = 0;
+ }
+ else
+ {
+ imageCounter++;
+ }
+ }
+ }
+
+ return bitmap;
+ }
+
+ /// <summary>
+ /// Transform the collage in 3D space.
+ /// </summary>
+ /// <param name="input">The bitmap to transform.</param>
+ /// <returns>The transformed image.</returns>
+ private SKBitmap Transform3D(SKBitmap input)
+ {
+ var bitmap = new SKBitmap(FinalWidth, FinalHeight);
+ using var canvas = new SKCanvas(bitmap);
+ canvas.Clear(SKColors.Black);
+ var matrix = new SKMatrix
+ {
+ ScaleX = 0.324108899f,
+ ScaleY = 0.563934922f,
+ SkewX = -0.244337708f,
+ SkewY = 0.0377609022f,
+ TransX = 42.0407715f,
+ TransY = -198.104706f,
+ Persp0 = -9.08959337E-05f,
+ Persp1 = 6.85242048E-05f,
+ Persp2 = 0.988209724f
+ };
+
+ canvas.SetMatrix(matrix);
+ canvas.DrawBitmap(input, 0, 0);
+
+ return bitmap;
+ }
+ }
+}
diff --git a/Jellyfin.Drawing.Skia/StripCollageBuilder.cs b/Jellyfin.Drawing.Skia/StripCollageBuilder.cs
index d1cc2255d..6bece9db6 100644
--- a/Jellyfin.Drawing.Skia/StripCollageBuilder.cs
+++ b/Jellyfin.Drawing.Skia/StripCollageBuilder.cs
@@ -99,7 +99,7 @@ namespace Jellyfin.Drawing.Skia
using var canvas = new SKCanvas(bitmap);
canvas.Clear(SKColors.Black);
- using var backdrop = GetNextValidImage(paths, 0, out _);
+ using var backdrop = SkiaHelper.GetNextValidImage(_skiaEncoder, paths, 0, out _);
if (backdrop == null)
{
return bitmap;
@@ -152,34 +152,6 @@ namespace Jellyfin.Drawing.Skia
return bitmap;
}
- private SKBitmap? GetNextValidImage(IReadOnlyList<string> paths, int currentIndex, out int newIndex)
- {
- var imagesTested = new Dictionary<int, int>();
- SKBitmap? bitmap = null;
-
- while (imagesTested.Count < paths.Count)
- {
- if (currentIndex >= paths.Count)
- {
- currentIndex = 0;
- }
-
- bitmap = _skiaEncoder.Decode(paths[currentIndex], false, null, out _);
-
- imagesTested[currentIndex] = 0;
-
- currentIndex++;
-
- if (bitmap != null)
- {
- break;
- }
- }
-
- newIndex = currentIndex;
- return bitmap;
- }
-
private SKBitmap BuildSquareCollageBitmap(IReadOnlyList<string> paths, int width, int height)
{
var bitmap = new SKBitmap(width, height);
@@ -192,7 +164,7 @@ namespace Jellyfin.Drawing.Skia
{
for (var y = 0; y < 2; y++)
{
- using var currentBitmap = GetNextValidImage(paths, imageIndex, out int newIndex);
+ using var currentBitmap = SkiaHelper.GetNextValidImage(_skiaEncoder, paths, imageIndex, out int newIndex);
imageIndex = newIndex;
if (currentBitmap == null)
diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj
index a6af8566c..ef8ef700f 100644
--- a/Jellyfin.Networking/Jellyfin.Networking.csproj
+++ b/Jellyfin.Networking/Jellyfin.Networking.csproj
@@ -11,6 +11,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs
index ba2c8b54f..4447b212d 100644
--- a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs
+++ b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs
@@ -59,17 +59,16 @@ namespace Jellyfin.Server.Implementations.Activity
entries = entries.Where(entry => entry.UserId != Guid.Empty == query.HasUserId.Value );
}
- return new QueryResult<ActivityLogEntry>
- {
- Items = await entries
+ return new QueryResult<ActivityLogEntry>(
+ query.Skip,
+ await entries.CountAsync().ConfigureAwait(false),
+ await entries
.Skip(query.Skip ?? 0)
.Take(query.Limit ?? 100)
.AsAsyncEnumerable()
.Select(ConvertToOldModel)
.ToListAsync()
- .ConfigureAwait(false),
- TotalRecordCount = await entries.CountAsync().ConfigureAwait(false)
- };
+ .ConfigureAwait(false));
}
/// <inheritdoc />
diff --git a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs
index 6c77421c7..b5fc96079 100644
--- a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs
+++ b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs
@@ -145,12 +145,10 @@ namespace Jellyfin.Server.Implementations.Devices
devices = devices.Take(query.Limit.Value);
}
- return new QueryResult<Device>
- {
- Items = await devices.ToListAsync().ConfigureAwait(false),
- StartIndex = query.Skip ?? 0,
- TotalRecordCount = count
- };
+ return new QueryResult<Device>(
+ query.Skip,
+ count,
+ await devices.ToListAsync().ConfigureAwait(false));
}
/// <inheritdoc />
@@ -158,12 +156,10 @@ namespace Jellyfin.Server.Implementations.Devices
{
var devices = await GetDevices(query).ConfigureAwait(false);
- return new QueryResult<DeviceInfo>
- {
- Items = devices.Items.Select(device => ToDeviceInfo(device)).ToList(),
- StartIndex = devices.StartIndex,
- TotalRecordCount = devices.TotalRecordCount
- };
+ return new QueryResult<DeviceInfo>(
+ devices.StartIndex,
+ devices.TotalRecordCount,
+ devices.Items.Select(device => ToDeviceInfo(device)).ToList());
}
/// <inheritdoc />
diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
index 86aec1399..027b3afad 100644
--- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
+++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj
@@ -12,6 +12,10 @@
<!-- Code analysers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
@@ -22,7 +26,7 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="System.Linq.Async" Version="5.1.0" />
+ <PackageReference Include="System.Linq.Async" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.1">
diff --git a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs
index 73a619b8d..7e7e4ca95 100644
--- a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs
+++ b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs
@@ -125,18 +125,20 @@ namespace Jellyfin.Server.Infrastructure
// Copied from SendFileFallback.SendFileAsync
const int BufferSize = 1024 * 16;
- await using var fileStream = new FileStream(
+ var fileStream = new FileStream(
filePath,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite,
bufferSize: BufferSize,
options: FileOptions.Asynchronous | FileOptions.SequentialScan);
-
- fileStream.Seek(offset, SeekOrigin.Begin);
- await StreamCopyOperation
- .CopyToAsync(fileStream, response.Body, count, BufferSize, CancellationToken.None)
- .ConfigureAwait(true);
+ await using (fileStream.ConfigureAwait(false))
+ {
+ fileStream.Seek(offset, SeekOrigin.Begin);
+ await StreamCopyOperation
+ .CopyToAsync(fileStream, response.Body, count, BufferSize, CancellationToken.None)
+ .ConfigureAwait(true);
+ }
}
private static bool IsSymLink(string path) => (File.GetAttributes(path) & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint;
diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj
index 12efa15dd..f4e9f2197 100644
--- a/Jellyfin.Server/Jellyfin.Server.csproj
+++ b/Jellyfin.Server/Jellyfin.Server.csproj
@@ -14,10 +14,6 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
- <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
- </PropertyGroup>
-
<ItemGroup>
<Compile Include="..\SharedVersion.cs" />
</ItemGroup>
@@ -28,6 +24,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
@@ -56,6 +56,7 @@
<ProjectReference Include="..\Emby.Server.Implementations\Emby.Server.Implementations.csproj" />
<ProjectReference Include="..\Jellyfin.Drawing.Skia\Jellyfin.Drawing.Skia.csproj" />
<ProjectReference Include="..\Jellyfin.Server.Implementations\Jellyfin.Server.Implementations.csproj" />
+ <ProjectReference Include="..\src\Jellyfin.MediaEncoding.Hls\Jellyfin.MediaEncoding.Hls.csproj" />
</ItemGroup>
<ItemGroup>
diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs
index f40526e22..ce11c63f9 100644
--- a/Jellyfin.Server/Program.cs
+++ b/Jellyfin.Server/Program.cs
@@ -224,12 +224,16 @@ namespace Jellyfin.Server
}
finally
{
- _logger.LogInformation("Running query planner optimizations in the database... This might take a while");
- // Run before disposing the application
- using var context = appHost.Resolve<JellyfinDbProvider>().CreateContext();
- if (context.Database.IsSqlite())
+ // Don't throw additional exception if startup failed.
+ if (appHost.ServiceProvider != null)
{
- context.Database.ExecuteSqlRaw("PRAGMA optimize");
+ _logger.LogInformation("Running query planner optimizations in the database... This might take a while");
+ // Run before disposing the application
+ using var context = appHost.Resolve<JellyfinDbProvider>().CreateContext();
+ if (context.Database.IsSqlite())
+ {
+ context.Database.ExecuteSqlRaw("PRAGMA optimize");
+ }
}
appHost.Dispose();
@@ -545,12 +549,15 @@ namespace Jellyfin.Server
// Get a stream of the resource contents
// NOTE: The .csproj name is used instead of the assembly name in the resource path
const string ResourcePath = "Jellyfin.Server.Resources.Configuration.logging.json";
- await using Stream resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath)
+ Stream resource = typeof(Program).Assembly.GetManifestResourceStream(ResourcePath)
?? throw new InvalidOperationException($"Invalid resource path: '{ResourcePath}'");
-
- // Copy the resource contents to the expected file path for the config file
- await using Stream dst = new FileStream(configPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
- await resource.CopyToAsync(dst).ConfigureAwait(false);
+ Stream dst = new FileStream(configPath, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
+ await using (resource.ConfigureAwait(false))
+ await using (dst.ConfigureAwait(false))
+ {
+ // Copy the resource contents to the expected file path for the config file
+ await resource.CopyToAsync(dst).ConfigureAwait(false);
+ }
}
/// <summary>
diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs
index 8085c2630..8eb5f2196 100644
--- a/Jellyfin.Server/Startup.cs
+++ b/Jellyfin.Server/Startup.cs
@@ -4,6 +4,7 @@ using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Mime;
using System.Text;
+using Jellyfin.MediaEncoding.Hls.Extensions;
using Jellyfin.Networking.Configuration;
using Jellyfin.Server.Extensions;
using Jellyfin.Server.Implementations;
@@ -104,6 +105,8 @@ namespace Jellyfin.Server
services.AddHealthChecks()
.AddDbContextCheck<JellyfinDb>();
+
+ services.AddHlsPlaylistGenerator();
}
/// <summary>
diff --git a/Jellyfin.sln b/Jellyfin.sln
index 4626601c3..0514b9614 100644
--- a/Jellyfin.sln
+++ b/Jellyfin.sln
@@ -89,6 +89,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Extensions", "src\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Extensions.Tests", "tests\Jellyfin.Extensions.Tests\Jellyfin.Extensions.Tests.csproj", "{332A5C7A-F907-47CA-910E-BE6F7371B9E0}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.MediaEncoding.Keyframes", "src\Jellyfin.MediaEncoding.Keyframes\Jellyfin.MediaEncoding.Keyframes.csproj", "{06535CA1-4097-4360-85EB-5FB875D53239}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.MediaEncoding.Hls", "src\Jellyfin.MediaEncoding.Hls\Jellyfin.MediaEncoding.Hls.csproj", "{DA9FD356-4894-4830-B208-D6BCE3E65B11}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.MediaEncoding.Hls.Tests", "tests\Jellyfin.MediaEncoding.Hls.Tests\Jellyfin.MediaEncoding.Hls.Tests.csproj", "{FE47334C-EFDE-4519-BD50-F24430FF360B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.MediaEncoding.Keyframes.Tests", "tests\Jellyfin.MediaEncoding.Keyframes.Tests\Jellyfin.MediaEncoding.Keyframes.Tests.csproj", "{24960660-DE6C-47BF-AEEF-CEE8F19FE6C2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -219,10 +227,6 @@ Global
{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42816EA8-4511-4CBF-A9C7-7791D5DDDAE6}.Release|Any CPU.Build.0 = Release|Any CPU
- {25E40B0B-7C89-4230-8911-CBBBCE83FC5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {25E40B0B-7C89-4230-8911-CBBBCE83FC5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {25E40B0B-7C89-4230-8911-CBBBCE83FC5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {25E40B0B-7C89-4230-8911-CBBBCE83FC5B}.Release|Any CPU.Build.0 = Release|Any CPU
{3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3ADBCD8C-C0F2-4956-8FDC-35D686B74CF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -243,6 +247,22 @@ Global
{332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{332A5C7A-F907-47CA-910E-BE6F7371B9E0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {06535CA1-4097-4360-85EB-5FB875D53239}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {06535CA1-4097-4360-85EB-5FB875D53239}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {06535CA1-4097-4360-85EB-5FB875D53239}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {06535CA1-4097-4360-85EB-5FB875D53239}.Release|Any CPU.Build.0 = Debug|Any CPU
+ {DA9FD356-4894-4830-B208-D6BCE3E65B11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DA9FD356-4894-4830-B208-D6BCE3E65B11}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DA9FD356-4894-4830-B208-D6BCE3E65B11}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+ {DA9FD356-4894-4830-B208-D6BCE3E65B11}.Release|Any CPU.Build.0 = Debug|Any CPU
+ {FE47334C-EFDE-4519-BD50-F24430FF360B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FE47334C-EFDE-4519-BD50-F24430FF360B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FE47334C-EFDE-4519-BD50-F24430FF360B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FE47334C-EFDE-4519-BD50-F24430FF360B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {24960660-DE6C-47BF-AEEF-CEE8F19FE6C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {24960660-DE6C-47BF-AEEF-CEE8F19FE6C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {24960660-DE6C-47BF-AEEF-CEE8F19FE6C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {24960660-DE6C-47BF-AEEF-CEE8F19FE6C2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -263,6 +283,10 @@ Global
{A964008C-2136-4716-B6CB-B3426C22320A} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
{750B8757-BE3D-4F8C-941A-FBAD94904ADA} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
{332A5C7A-F907-47CA-910E-BE6F7371B9E0} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
+ {06535CA1-4097-4360-85EB-5FB875D53239} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
+ {DA9FD356-4894-4830-B208-D6BCE3E65B11} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C}
+ {FE47334C-EFDE-4519-BD50-F24430FF360B} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
+ {24960660-DE6C-47BF-AEEF-CEE8F19FE6C2} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3448830C-EBDC-426C-85CD-7BBB9651A7FE}
diff --git a/MediaBrowser.Common/Extensions/ProcessExtensions.cs b/MediaBrowser.Common/Extensions/ProcessExtensions.cs
index 08e01bfd6..c3a7cb394 100644
--- a/MediaBrowser.Common/Extensions/ProcessExtensions.cs
+++ b/MediaBrowser.Common/Extensions/ProcessExtensions.cs
@@ -39,7 +39,7 @@ namespace MediaBrowser.Common.Extensions
}
// Add an event handler for the process exit event
- var tcs = new TaskCompletionSource<bool>();
+ var tcs = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
process.Exited += (_, _) => tcs.TrySetResult(true);
// Return immediately if the process has already exited
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index 2a2fffce0..b61e104ce 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -49,6 +49,10 @@
<!-- Code analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index e6923b55c..85a99d62c 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -53,7 +53,7 @@ namespace MediaBrowser.Controller.Channels
query.ChannelIds = new Guid[] { Id };
// Don't blow up here because it could cause parent screens with other content to fail
- return ChannelManager.GetChannelItemsInternal(query, new SimpleProgress<double>(), CancellationToken.None).Result;
+ return ChannelManager.GetChannelItemsInternal(query, new SimpleProgress<double>(), CancellationToken.None).GetAwaiter().GetResult();
}
catch
{
diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
index 4e67cfee4..e5c8ebfaf 100644
--- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs
+++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs
@@ -74,5 +74,12 @@ namespace MediaBrowser.Controller.Drawing
/// <param name="options">The options to use when creating the collage.</param>
/// <param name="libraryName">Optional. </param>
void CreateImageCollage(ImageCollageOptions options, string? libraryName);
+
+ /// <summary>
+ /// Creates a new splashscreen image.
+ /// </summary>
+ /// <param name="posters">The list of poster paths.</param>
+ /// <param name="backdrops">The list of backdrop paths.</param>
+ void CreateSplashscreen(IReadOnlyList<string> posters, IReadOnlyList<string> backdrops);
}
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 915971adc..0f62e8e1e 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
@@ -1286,7 +1287,7 @@ namespace MediaBrowser.Controller.Entities
{
if (IsFileProtocol)
{
- requiresSave = await RefreshedOwnedItems(options, GetFileSystemChildren(options.DirectoryService).ToList(), cancellationToken).ConfigureAwait(false);
+ requiresSave = await RefreshedOwnedItems(options, GetFileSystemChildren(options.DirectoryService), cancellationToken).ConfigureAwait(false);
}
await LibraryManager.UpdateImagesAsync(this).ConfigureAwait(false); // ensure all image properties in DB are fresh
@@ -1363,7 +1364,7 @@ namespace MediaBrowser.Controller.Entities
/// <param name="fileSystemChildren">The list of filesystem children.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns><c>true</c> if any items have changed, else <c>false</c>.</returns>
- protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
+ protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder or UserRootFolder or AggregateFolder || this.GetType() == typeof(Folder))
{
@@ -1380,7 +1381,7 @@ namespace MediaBrowser.Controller.Entities
return directoryService.GetFileSystemEntries(path);
}
- private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
+ private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
var extras = LibraryManager.FindExtras(item, fileSystemChildren, options.DirectoryService).ToArray();
var newExtraIds = extras.Select(i => i.Id).ToArray();
@@ -2041,27 +2042,32 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Validates that images within the item are still on the filesystem.
/// </summary>
- /// <param name="directoryService">The directory service to use.</param>
/// <returns><c>true</c> if the images validate, <c>false</c> if not.</returns>
- public bool ValidateImages(IDirectoryService directoryService)
+ public bool ValidateImages()
{
- var allFiles = ImageInfos
- .Where(i => i.IsLocalFile)
- .Select(i => System.IO.Path.GetDirectoryName(i.Path))
- .Distinct(StringComparer.OrdinalIgnoreCase)
- .SelectMany(path => directoryService.GetFilePaths(path))
- .ToList();
+ List<ItemImageInfo> deletedImages = null;
+ foreach (var imageInfo in ImageInfos)
+ {
+ if (!imageInfo.IsLocalFile)
+ {
+ continue;
+ }
- var deletedImages = ImageInfos
- .Where(image => image.IsLocalFile && !allFiles.Contains(image.Path, StringComparison.OrdinalIgnoreCase))
- .ToList();
+ if (File.Exists(imageInfo.Path))
+ {
+ continue;
+ }
+
+ (deletedImages ??= new List<ItemImageInfo>()).Add(imageInfo);
+ }
- if (deletedImages.Count > 0)
+ var anyImagesRemoved = deletedImages?.Count > 0;
+ if (anyImagesRemoved)
{
RemoveImages(deletedImages);
}
- return deletedImages.Count > 0;
+ return anyImagesRemoved;
}
/// <summary>
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 55551e70e..4d9aac6f9 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -783,11 +783,10 @@ namespace MediaBrowser.Controller.Entities
returnItems = returnItems.Skip(startIndex.Value);
}
- return new QueryResult<BaseItem>
- {
- TotalRecordCount = totalCount,
- Items = returnItems.ToArray()
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ totalCount,
+ returnItems.ToArray());
}
private bool RequiresPostFiltering2(InternalItemsQuery query)
@@ -965,7 +964,7 @@ namespace MediaBrowser.Controller.Entities
query.ChannelIds = new[] { ChannelId };
// Don't blow up here because it could cause parent screens with other content to fail
- return ChannelManager.GetChannelItemsInternal(query, new SimpleProgress<double>(), CancellationToken.None).Result;
+ return ChannelManager.GetChannelItemsInternal(query, new SimpleProgress<double>(), CancellationToken.None).GetAwaiter().GetResult();
}
catch
{
@@ -1586,7 +1585,7 @@ namespace MediaBrowser.Controller.Entities
.Where(i => i.Item2 != null);
}
- protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
+ protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
var changesFound = false;
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index b9455721e..77e70f8fb 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -20,6 +20,7 @@ namespace MediaBrowser.Controller.Entities.Movies
public class Movie : Video, IHasSpecialFeatures, IHasTrailers, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping
{
/// <inheritdoc />
+ [JsonIgnore]
public IReadOnlyList<Guid> SpecialFeatureIds => GetExtras()
.Where(extra => extra.ExtraType != null && extra is Video)
.Select(extra => extra.Id)
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index fe44f1169..279206da4 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -238,12 +238,7 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> ConvertToResult(List<BaseItem> items)
{
- var arr = items.ToArray();
- return new QueryResult<BaseItem>
- {
- Items = arr,
- TotalRecordCount = arr.Length
- };
+ return new QueryResult<BaseItem>(items);
}
private QueryResult<BaseItem> GetMovieGenres(Folder parent, User user, InternalItemsQuery query)
@@ -414,16 +409,6 @@ namespace MediaBrowser.Controller.Entities
return _libraryManager.GetItemsResult(query);
}
- private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result)
- where T : BaseItem
- {
- return new QueryResult<BaseItem>
- {
- Items = result.Items, // TODO Fix The co-variant conversion between T[] and BaseItem[], this can generate runtime issues if T is not BaseItem.
- TotalRecordCount = result.TotalRecordCount
- };
- }
-
private QueryResult<BaseItem> GetResult<T>(
IEnumerable<T> items,
InternalItemsQuery query)
@@ -483,11 +468,10 @@ namespace MediaBrowser.Controller.Entities
itemsArray = itemsArray.Skip(query.StartIndex.Value).ToArray();
}
- return new QueryResult<BaseItem>
- {
- TotalRecordCount = totalCount,
- Items = itemsArray
- };
+ return new QueryResult<BaseItem>(
+ query.StartIndex,
+ totalCount,
+ itemsArray);
}
public static bool Filter(BaseItem item, User user, InternalItemsQuery query, IUserDataManager userDataManager, ILibraryManager libraryManager)
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index 3e125602a..5ab7808c3 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -419,7 +419,7 @@ namespace MediaBrowser.Controller.Entities
return updateType;
}
- protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
+ protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index 8db528330..2b0193771 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -434,7 +434,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="fileSystemChildren">The file system children.</param>
/// <param name="directoryService">An instance of <see cref="IDirectoryService"/>.</param>
/// <returns>IEnumerable&lt;BaseItem&gt;.</returns>
- IEnumerable<BaseItem> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService);
+ IEnumerable<BaseItem> FindExtras(BaseItem owner, IReadOnlyList<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService);
/// <summary>
/// Gets the collection folders.
diff --git a/MediaBrowser.Controller/Library/IMetadataFileSaver.cs b/MediaBrowser.Controller/Library/IMetadataFileSaver.cs
index 9c6f03a23..842c687d1 100644
--- a/MediaBrowser.Controller/Library/IMetadataFileSaver.cs
+++ b/MediaBrowser.Controller/Library/IMetadataFileSaver.cs
@@ -13,9 +13,4 @@ namespace MediaBrowser.Controller.Library
/// <returns>System.String.</returns>
string GetSavePath(BaseItem item);
}
-
- public interface IConfigurableProvider
- {
- bool IsEnabled { get; }
- }
}
diff --git a/MediaBrowser.Controller/Library/IMetadataSaver.cs b/MediaBrowser.Controller/Library/IMetadataSaver.cs
index d963fd249..eed661345 100644
--- a/MediaBrowser.Controller/Library/IMetadataSaver.cs
+++ b/MediaBrowser.Controller/Library/IMetadataSaver.cs
@@ -1,6 +1,5 @@
-#nullable disable
-
using System.Threading;
+using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
@@ -29,6 +28,7 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
- void Save(BaseItem item, CancellationToken cancellationToken);
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ Task SaveAsync(BaseItem item, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index 6dc5665b2..46bdca302 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -188,7 +188,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="options">The options.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Recommended programs.</returns>
- QueryResult<BaseItemDto> GetRecommendedPrograms(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken);
+ Task<QueryResult<BaseItemDto>> GetRecommendedProgramsAsync(InternalItemsQuery query, DtoOptions options, CancellationToken cancellationToken);
/// <summary>
/// Gets the recommended programs internal.
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 432159d5d..e76a478a5 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -52,6 +52,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index fd3eb8105..6bf3e7b46 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -26,6 +26,12 @@ namespace MediaBrowser.Controller.MediaEncoding
string EncoderPath { get; }
/// <summary>
+ /// Gets the probe path.
+ /// </summary>
+ /// <value>The probe path.</value>
+ string ProbePath { get; }
+
+ /// <summary>
/// Gets the version of encoder.
/// </summary>
/// <returns>The version of encoder.</returns>
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index 9f7a76be6..44bc4a50c 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -156,7 +156,8 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
- void SaveMetadata(BaseItem item, ItemUpdateType updateType);
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ Task SaveMetadataAsync(BaseItem item, ItemUpdateType updateType);
/// <summary>
/// Saves the metadata.
@@ -164,7 +165,8 @@ namespace MediaBrowser.Controller.Providers
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <param name="savers">The metadata savers.</param>
- void SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable<string> savers);
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ Task SaveMetadataAsync(BaseItem item, ItemUpdateType updateType, IEnumerable<string> savers);
/// <summary>
/// Gets the metadata options.
diff --git a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs
index 08d129a82..a9d16a49e 100644
--- a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs
+++ b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs
@@ -27,6 +27,11 @@ namespace MediaBrowser.Controller.Providers
public bool IsAutomated { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether old metadata should be removed if it isn't replaced.
+ /// </summary>
+ public bool RemoveOldMetadata { get; set; }
+
public bool IsReplacingImage(ImageType type)
{
return ImageRefreshMode == MetadataRefreshMode.FullRefresh &&
diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
index 90fd6e269..a38bbaf69 100644
--- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
+++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
@@ -30,6 +30,7 @@ namespace MediaBrowser.Controller.Providers
ReplaceAllImages = copy.ReplaceAllImages;
ReplaceImages = copy.ReplaceImages;
SearchResult = copy.SearchResult;
+ RemoveOldMetadata = copy.RemoveOldMetadata;
if (copy.RefreshPaths != null && copy.RefreshPaths.Length > 0)
{
diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
index 7dc6149f4..70fd68129 100644
--- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
+++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs
@@ -291,7 +291,7 @@ namespace MediaBrowser.LocalMetadata.Images
foreach (var name in imageFileNames)
{
- if (AddImage(files, images, imagePrefix + name, ImageType.Primary))
+ if (AddImage(files, images, name, ImageType.Primary, imagePrefix))
{
return;
}
@@ -317,7 +317,7 @@ namespace MediaBrowser.LocalMetadata.Images
if (!string.IsNullOrEmpty(name))
{
- AddImage(files, images, imagePrefix + name + "-fanart", ImageType.Backdrop);
+ AddImage(files, images, name + "-fanart", ImageType.Backdrop, imagePrefix);
// Support without the prefix if it's in it's own folder
if (!isInMixedFolder)
@@ -436,7 +436,7 @@ namespace MediaBrowser.LocalMetadata.Images
private bool AddImage(List<FileSystemMetadata> files, List<LocalImageInfo> images, string name, string imagePrefix, bool isInMixedFolder, ImageType type)
{
- var added = AddImage(files, images, imagePrefix + name, type);
+ var added = AddImage(files, images, name, type, imagePrefix);
if (!isInMixedFolder)
{
@@ -449,32 +449,39 @@ namespace MediaBrowser.LocalMetadata.Images
return added;
}
- private bool AddImage(List<FileSystemMetadata> files, List<LocalImageInfo> images, string name, ImageType type)
+ private static bool AddImage(IReadOnlyList<FileSystemMetadata> files, List<LocalImageInfo> images, string name, ImageType type, string? prefix = null)
{
- var image = GetImage(files, name);
+ var image = GetImage(files, name, prefix);
- if (image != null)
+ if (image == null)
{
- images.Add(new LocalImageInfo
- {
- FileInfo = image,
- Type = type
- });
-
- return true;
+ return false;
}
- return false;
+ images.Add(new LocalImageInfo
+ {
+ FileInfo = image,
+ Type = type
+ });
+
+ return true;
}
- private static FileSystemMetadata? GetImage(IReadOnlyList<FileSystemMetadata> files, string name)
+ private static FileSystemMetadata? GetImage(IReadOnlyList<FileSystemMetadata> files, string name, string? prefix = null)
{
+ var fileNameLength = name.Length + (prefix?.Length ?? 0);
for (var i = 0; i < files.Count; i++)
{
var file = files[i];
- if (!file.IsDirectory
- && file.Length > 0
- && Path.GetFileNameWithoutExtension(file.FullName.AsSpan()).Equals(name, StringComparison.OrdinalIgnoreCase))
+ if (file.IsDirectory || file.Length <= 0)
+ {
+ continue;
+ }
+
+ var fileName = Path.GetFileNameWithoutExtension(file.FullName.AsSpan());
+ if (fileName.Length == fileNameLength
+ && fileName.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)
+ && fileName.EndsWith(name, StringComparison.OrdinalIgnoreCase))
{
return file;
}
diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
index 41c79651d..41ac7038a 100644
--- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
+++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj
@@ -22,6 +22,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
index 1a8b5bb4e..2d94c5de8 100644
--- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs
@@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
+using System.Threading.Tasks;
using System.Xml;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -21,11 +22,6 @@ namespace MediaBrowser.LocalMetadata.Savers
public abstract class BaseXmlSaver : IMetadataFileSaver
{
/// <summary>
- /// Gets the date added format.
- /// </summary>
- public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss";
-
- /// <summary>
/// Initializes a new instance of the <see cref="BaseXmlSaver"/> class.
/// </summary>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
@@ -82,9 +78,7 @@ namespace MediaBrowser.LocalMetadata.Savers
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
protected virtual string GetRootElementName(BaseItem item)
- {
- return "Item";
- }
+ => "Item";
/// <summary>
/// Determines whether [is enabled for] [the specified item].
@@ -95,23 +89,10 @@ namespace MediaBrowser.LocalMetadata.Savers
public abstract bool IsEnabledFor(BaseItem item, ItemUpdateType updateType);
/// <inheritdoc />
- public void Save(BaseItem item, CancellationToken cancellationToken)
+ public async Task SaveAsync(BaseItem item, CancellationToken cancellationToken)
{
var path = GetSavePath(item);
-
- using var memoryStream = new MemoryStream();
- Save(item, memoryStream);
-
- memoryStream.Position = 0;
-
- cancellationToken.ThrowIfCancellationRequested();
-
- SaveToFile(memoryStream, path);
- }
-
- private void SaveToFile(Stream stream, string path)
- {
- var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path));
+ var directory = Path.GetDirectoryName(path) ?? throw new InvalidDataException($"Provided path ({path}) is not valid.");
Directory.CreateDirectory(directory);
// On Windows, savint the file will fail if the file is hidden or readonly
@@ -121,13 +102,41 @@ namespace MediaBrowser.LocalMetadata.Savers
{
Mode = FileMode.Create,
Access = FileAccess.Write,
- Share = FileShare.None,
- PreallocationSize = stream.Length
+ Share = FileShare.None
};
- using (var filestream = new FileStream(path, fileStreamOptions))
+ var filestream = new FileStream(path, fileStreamOptions);
+ await using (filestream.ConfigureAwait(false))
{
- stream.CopyTo(filestream);
+ var settings = new XmlWriterSettings
+ {
+ Indent = true,
+ Encoding = Encoding.UTF8,
+ Async = true
+ };
+
+ var writer = XmlWriter.Create(filestream, settings);
+ await using (writer.ConfigureAwait(false))
+ {
+ var root = GetRootElementName(item);
+
+ await writer.WriteStartDocumentAsync(true).ConfigureAwait(false);
+
+ await writer.WriteStartElementAsync(null, root, null).ConfigureAwait(false);
+
+ var baseItem = item;
+
+ if (baseItem != null)
+ {
+ await AddCommonNodesAsync(baseItem, writer).ConfigureAwait(false);
+ }
+
+ await WriteCustomElementsAsync(item, writer).ConfigureAwait(false);
+
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
+
+ await writer.WriteEndDocumentAsync().ConfigureAwait(false);
+ }
}
if (ConfigurationManager.Configuration.SaveMetadataHidden)
@@ -148,107 +157,76 @@ namespace MediaBrowser.LocalMetadata.Savers
}
}
- private void Save(BaseItem item, Stream stream)
- {
- var settings = new XmlWriterSettings
- {
- Indent = true,
- Encoding = Encoding.UTF8,
- CloseOutput = false
- };
-
- using (var writer = XmlWriter.Create(stream, settings))
- {
- var root = GetRootElementName(item);
-
- writer.WriteStartDocument(true);
-
- writer.WriteStartElement(root);
-
- var baseItem = item;
-
- if (baseItem != null)
- {
- AddCommonNodes(baseItem, writer, LibraryManager);
- }
-
- WriteCustomElements(item, writer);
-
- writer.WriteEndElement();
-
- writer.WriteEndDocument();
- }
- }
-
/// <summary>
/// Write custom elements.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="writer">The xml writer.</param>
- protected abstract void WriteCustomElements(BaseItem item, XmlWriter writer);
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ protected abstract Task WriteCustomElementsAsync(BaseItem item, XmlWriter writer);
/// <summary>
/// Adds the common nodes.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="writer">The xml writer.</param>
- /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
- public static void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManager libraryManager)
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ private async Task AddCommonNodesAsync(BaseItem item, XmlWriter writer)
{
if (!string.IsNullOrEmpty(item.OfficialRating))
{
- writer.WriteElementString("ContentRating", item.OfficialRating);
+ await writer.WriteElementStringAsync(null, "ContentRating", null, item.OfficialRating).ConfigureAwait(false);
}
- writer.WriteElementString("Added", item.DateCreated.ToLocalTime().ToString("G", CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "Added", null, item.DateCreated.ToLocalTime().ToString("G", CultureInfo.InvariantCulture)).ConfigureAwait(false);
- writer.WriteElementString("LockData", item.IsLocked.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
+ await writer.WriteElementStringAsync(null, "LockData", null, item.IsLocked.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()).ConfigureAwait(false);
if (item.LockedFields.Length > 0)
{
- writer.WriteElementString("LockedFields", string.Join('|', item.LockedFields));
+ await writer.WriteElementStringAsync(null, "LockedFields", null, string.Join('|', item.LockedFields)).ConfigureAwait(false);
}
if (item.CriticRating.HasValue)
{
- writer.WriteElementString("CriticRating", item.CriticRating.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "CriticRating", null, item.CriticRating.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (!string.IsNullOrEmpty(item.Overview))
{
- writer.WriteElementString("Overview", item.Overview);
+ await writer.WriteElementStringAsync(null, "Overview", null, item.Overview).ConfigureAwait(false);
}
if (!string.IsNullOrEmpty(item.OriginalTitle))
{
- writer.WriteElementString("OriginalTitle", item.OriginalTitle);
+ await writer.WriteElementStringAsync(null, "OriginalTitle", null, item.OriginalTitle).ConfigureAwait(false);
}
if (!string.IsNullOrEmpty(item.CustomRating))
{
- writer.WriteElementString("CustomRating", item.CustomRating);
+ await writer.WriteElementStringAsync(null, "CustomRating", null, item.CustomRating).ConfigureAwait(false);
}
if (!string.IsNullOrEmpty(item.Name) && item is not Episode)
{
- writer.WriteElementString("LocalTitle", item.Name);
+ await writer.WriteElementStringAsync(null, "LocalTitle", null, item.Name).ConfigureAwait(false);
}
var forcedSortName = item.ForcedSortName;
if (!string.IsNullOrEmpty(forcedSortName))
{
- writer.WriteElementString("SortTitle", forcedSortName);
+ await writer.WriteElementStringAsync(null, "SortTitle", null, forcedSortName).ConfigureAwait(false);
}
if (item.PremiereDate.HasValue)
{
if (item is Person)
{
- writer.WriteElementString("BirthDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "BirthDate", null, item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
else if (item is not Episode)
{
- writer.WriteElementString("PremiereDate", item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "PremiereDate", null, item.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
}
@@ -256,69 +234,69 @@ namespace MediaBrowser.LocalMetadata.Savers
{
if (item is Person)
{
- writer.WriteElementString("DeathDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "DeathDate", null, item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
else if (item is not Episode)
{
- writer.WriteElementString("EndDate", item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "EndDate", null, item.EndDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
}
if (item.RemoteTrailers.Count > 0)
{
- writer.WriteStartElement("Trailers");
+ await writer.WriteStartElementAsync(null, "Trailers", null).ConfigureAwait(false);
foreach (var trailer in item.RemoteTrailers)
{
- writer.WriteElementString("Trailer", trailer.Url);
+ await writer.WriteElementStringAsync(null, "Trailer", null, trailer.Url).ConfigureAwait(false);
}
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
if (item.ProductionLocations.Length > 0)
{
- writer.WriteStartElement("Countries");
+ await writer.WriteStartElementAsync(null, "Countries", null).ConfigureAwait(false);
foreach (var name in item.ProductionLocations)
{
- writer.WriteElementString("Country", name);
+ await writer.WriteElementStringAsync(null, "Country", null, name).ConfigureAwait(false);
}
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
if (item is IHasDisplayOrder hasDisplayOrder && !string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder))
{
- writer.WriteElementString("DisplayOrder", hasDisplayOrder.DisplayOrder);
+ await writer.WriteElementStringAsync(null, "DisplayOrder", null, hasDisplayOrder.DisplayOrder).ConfigureAwait(false);
}
if (item.CommunityRating.HasValue)
{
- writer.WriteElementString("Rating", item.CommunityRating.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "Rating", null, item.CommunityRating.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (item.ProductionYear.HasValue && item is not Person)
{
- writer.WriteElementString("ProductionYear", item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "ProductionYear", null, item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (item is IHasAspectRatio hasAspectRatio)
{
if (!string.IsNullOrEmpty(hasAspectRatio.AspectRatio))
{
- writer.WriteElementString("AspectRatio", hasAspectRatio.AspectRatio);
+ await writer.WriteElementStringAsync(null, "AspectRatio", null, hasAspectRatio.AspectRatio).ConfigureAwait(false);
}
}
if (!string.IsNullOrEmpty(item.PreferredMetadataLanguage))
{
- writer.WriteElementString("Language", item.PreferredMetadataLanguage);
+ await writer.WriteElementStringAsync(null, "Language", null, item.PreferredMetadataLanguage).ConfigureAwait(false);
}
if (!string.IsNullOrEmpty(item.PreferredMetadataCountryCode))
{
- writer.WriteElementString("CountryCode", item.PreferredMetadataCountryCode);
+ await writer.WriteElementStringAsync(null, "CountryCode", null, item.PreferredMetadataCountryCode).ConfigureAwait(false);
}
// Use original runtime here, actual file runtime later in MediaInfo
@@ -328,7 +306,7 @@ namespace MediaBrowser.LocalMetadata.Savers
{
var timespan = TimeSpan.FromTicks(runTimeTicks.Value);
- writer.WriteElementString("RunningTime", Math.Floor(timespan.TotalMinutes).ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "RunningTime", null, Math.Floor(timespan.TotalMinutes).ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
if (item.ProviderIds != null)
@@ -338,94 +316,94 @@ namespace MediaBrowser.LocalMetadata.Savers
var providerId = item.ProviderIds[providerKey];
if (!string.IsNullOrEmpty(providerId))
{
- writer.WriteElementString(providerKey + "Id", providerId);
+ await writer.WriteElementStringAsync(null, providerKey + "Id", null, providerId).ConfigureAwait(false);
}
}
}
if (!string.IsNullOrWhiteSpace(item.Tagline))
{
- writer.WriteStartElement("Taglines");
- writer.WriteElementString("Tagline", item.Tagline);
- writer.WriteEndElement();
+ await writer.WriteStartElementAsync(null, "Taglines", null).ConfigureAwait(false);
+ await writer.WriteElementStringAsync(null, "Tagline", null, item.Tagline).ConfigureAwait(false);
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
if (item.Genres.Length > 0)
{
- writer.WriteStartElement("Genres");
+ await writer.WriteStartElementAsync(null, "Genres", null).ConfigureAwait(false);
foreach (var genre in item.Genres)
{
- writer.WriteElementString("Genre", genre);
+ await writer.WriteElementStringAsync(null, "Genre", null, genre).ConfigureAwait(false);
}
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
if (item.Studios.Length > 0)
{
- writer.WriteStartElement("Studios");
+ await writer.WriteStartElementAsync(null, "Studios", null).ConfigureAwait(false);
foreach (var studio in item.Studios)
{
- writer.WriteElementString("Studio", studio);
+ await writer.WriteElementStringAsync(null, "Studio", null, studio).ConfigureAwait(false);
}
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
if (item.Tags.Length > 0)
{
- writer.WriteStartElement("Tags");
+ await writer.WriteStartElementAsync(null, "Tags", null).ConfigureAwait(false);
foreach (var tag in item.Tags)
{
- writer.WriteElementString("Tag", tag);
+ await writer.WriteElementStringAsync(null, "Tag", null, tag).ConfigureAwait(false);
}
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
- var people = libraryManager.GetPeople(item);
+ var people = LibraryManager.GetPeople(item);
if (people.Count > 0)
{
- writer.WriteStartElement("Persons");
+ await writer.WriteStartElementAsync(null, "Persons", null).ConfigureAwait(false);
foreach (var person in people)
{
- writer.WriteStartElement("Person");
- writer.WriteElementString("Name", person.Name);
- writer.WriteElementString("Type", person.Type);
- writer.WriteElementString("Role", person.Role);
+ await writer.WriteStartElementAsync(null, "Person", null).ConfigureAwait(false);
+ await writer.WriteElementStringAsync(null, "Name", null, person.Name).ConfigureAwait(false);
+ await writer.WriteElementStringAsync(null, "Type", null, person.Type).ConfigureAwait(false);
+ await writer.WriteElementStringAsync(null, "Role", null, person.Role).ConfigureAwait(false);
if (person.SortOrder.HasValue)
{
- writer.WriteElementString("SortOrder", person.SortOrder.Value.ToString(CultureInfo.InvariantCulture));
+ await writer.WriteElementStringAsync(null, "SortOrder", null, person.SortOrder.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
}
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
if (item is BoxSet boxset)
{
- AddLinkedChildren(boxset, writer, "CollectionItems", "CollectionItem");
+ await AddLinkedChildren(boxset, writer, "CollectionItems", "CollectionItem").ConfigureAwait(false);
}
if (item is Playlist playlist && !Playlist.IsPlaylistFile(playlist.Path))
{
- AddLinkedChildren(playlist, writer, "PlaylistItems", "PlaylistItem");
+ await AddLinkedChildren(playlist, writer, "PlaylistItems", "PlaylistItem").ConfigureAwait(false);
}
if (item is IHasShares hasShares)
{
- AddShares(hasShares, writer);
+ await AddSharesAsync(hasShares, writer).ConfigureAwait(false);
}
- AddMediaInfo(item, writer);
+ await AddMediaInfo(item, writer).ConfigureAwait(false);
}
/// <summary>
@@ -433,23 +411,26 @@ namespace MediaBrowser.LocalMetadata.Savers
/// </summary>
/// <param name="item">The item.</param>
/// <param name="writer">The xml writer.</param>
- public static void AddShares(IHasShares item, XmlWriter writer)
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ private static async Task AddSharesAsync(IHasShares item, XmlWriter writer)
{
- writer.WriteStartElement("Shares");
+ await writer.WriteStartElementAsync(null, "Shares", null).ConfigureAwait(false);
foreach (var share in item.Shares)
{
- writer.WriteStartElement("Share");
+ await writer.WriteStartElementAsync(null, "Share", null).ConfigureAwait(false);
- writer.WriteElementString("UserId", share.UserId);
- writer.WriteElementString(
+ await writer.WriteElementStringAsync(null, "UserId", null, share.UserId).ConfigureAwait(false);
+ await writer.WriteElementStringAsync(
+ null,
"CanEdit",
- share.CanEdit.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
+ null,
+ share.CanEdit.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()).ConfigureAwait(false);
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
/// <summary>
@@ -458,33 +439,29 @@ namespace MediaBrowser.LocalMetadata.Savers
/// <param name="item">The item.</param>
/// <param name="writer">The xml writer.</param>
/// <typeparam name="T">Type of item.</typeparam>
- public static void AddMediaInfo<T>(T item, XmlWriter writer)
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ private static Task AddMediaInfo<T>(T item, XmlWriter writer)
where T : BaseItem
{
- if (item is Video video)
+ if (item is Video video && video.Video3DFormat.HasValue)
{
- if (video.Video3DFormat.HasValue)
+ return video.Video3DFormat switch
{
- switch (video.Video3DFormat.Value)
- {
- case Video3DFormat.FullSideBySide:
- writer.WriteElementString("Format3D", "FSBS");
- break;
- case Video3DFormat.FullTopAndBottom:
- writer.WriteElementString("Format3D", "FTAB");
- break;
- case Video3DFormat.HalfSideBySide:
- writer.WriteElementString("Format3D", "HSBS");
- break;
- case Video3DFormat.HalfTopAndBottom:
- writer.WriteElementString("Format3D", "HTAB");
- break;
- case Video3DFormat.MVC:
- writer.WriteElementString("Format3D", "MVC");
- break;
- }
- }
- }
+ Video3DFormat.FullSideBySide =>
+ writer.WriteElementStringAsync(null, "Format3D", null, "FSBS"),
+ Video3DFormat.FullTopAndBottom =>
+ writer.WriteElementStringAsync(null, "Format3D", null, "FTAB"),
+ Video3DFormat.HalfSideBySide =>
+ writer.WriteElementStringAsync(null, "Format3D", null, "HSBS"),
+ Video3DFormat.HalfTopAndBottom =>
+ writer.WriteElementStringAsync(null, "Format3D", null, "HTAB"),
+ Video3DFormat.MVC =>
+ writer.WriteElementStringAsync(null, "Format3D", null, "MVC"),
+ _ => Task.CompletedTask
+ };
+ }
+
+ return Task.CompletedTask;
}
/// <summary>
@@ -494,7 +471,8 @@ namespace MediaBrowser.LocalMetadata.Savers
/// <param name="writer">The xml writer.</param>
/// <param name="pluralNodeName">The plural node name.</param>
/// <param name="singularNodeName">The singular node name.</param>
- public static void AddLinkedChildren(Folder item, XmlWriter writer, string pluralNodeName, string singularNodeName)
+ /// <returns>The task object representing the asynchronous operation.</returns>
+ private static async Task AddLinkedChildren(Folder item, XmlWriter writer, string pluralNodeName, string singularNodeName)
{
var items = item.LinkedChildren
.Where(i => i.Type == LinkedChildType.Manual)
@@ -505,28 +483,28 @@ namespace MediaBrowser.LocalMetadata.Savers
return;
}
- writer.WriteStartElement(pluralNodeName);
+ await writer.WriteStartElementAsync(null, pluralNodeName, null).ConfigureAwait(false);
foreach (var link in items)
{
if (!string.IsNullOrWhiteSpace(link.Path) || !string.IsNullOrWhiteSpace(link.LibraryItemId))
{
- writer.WriteStartElement(singularNodeName);
+ await writer.WriteStartElementAsync(null, singularNodeName, null).ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(link.Path))
{
- writer.WriteElementString("Path", link.Path);
+ await writer.WriteElementStringAsync(null, "Path", null, link.Path).ConfigureAwait(false);
}
if (!string.IsNullOrWhiteSpace(link.LibraryItemId))
{
- writer.WriteElementString("ItemId", link.LibraryItemId);
+ await writer.WriteElementStringAsync(null, "ItemId", null, link.LibraryItemId).ConfigureAwait(false);
}
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
}
- writer.WriteEndElement();
+ await writer.WriteEndElementAsync().ConfigureAwait(false);
}
}
}
diff --git a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
index 8a5da95bf..940f51dac 100644
--- a/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/BoxSetXmlSaver.cs
@@ -1,4 +1,5 @@
using System.IO;
+using System.Threading.Tasks;
using System.Xml;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -38,9 +39,8 @@ namespace MediaBrowser.LocalMetadata.Savers
}
/// <inheritdoc />
- protected override void WriteCustomElements(BaseItem item, XmlWriter writer)
- {
- }
+ protected override Task WriteCustomElementsAsync(BaseItem item, XmlWriter writer)
+ => Task.CompletedTask;
/// <inheritdoc />
protected override string GetLocalSavePath(BaseItem item)
diff --git a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
index 76252bc09..847add07f 100644
--- a/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
+++ b/MediaBrowser.LocalMetadata/Savers/PlaylistXmlSaver.cs
@@ -1,4 +1,5 @@
using System.IO;
+using System.Threading.Tasks;
using System.Xml;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -43,14 +44,16 @@ namespace MediaBrowser.LocalMetadata.Savers
}
/// <inheritdoc />
- protected override void WriteCustomElements(BaseItem item, XmlWriter writer)
+ protected override Task WriteCustomElementsAsync(BaseItem item, XmlWriter writer)
{
var game = (Playlist)item;
- if (!string.IsNullOrEmpty(game.PlaylistMediaType))
+ if (string.IsNullOrEmpty(game.PlaylistMediaType))
{
- writer.WriteElementString("PlaylistMediaType", game.PlaylistMediaType);
+ return Task.CompletedTask;
}
+
+ return writer.WriteElementStringAsync(null, "PlaylistMediaType", null, game.PlaylistMediaType);
}
/// <inheritdoc />
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index e1643ea43..c41ed20cd 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -92,6 +92,9 @@ namespace MediaBrowser.MediaEncoding.Encoder
/// <inheritdoc />
public string EncoderPath => _ffmpegPath;
+ /// <inheritdoc />
+ public string ProbePath => _ffprobePath;
+
public Version EncoderVersion => _ffmpegVersion;
public bool IsVaapiDeviceAmd => _isVaapiDeviceAmd;
diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
index b60ccd2ca..47de4edff 100644
--- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
+++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj
@@ -35,6 +35,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
index 750fd44eb..4c8f19604 100644
--- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
+++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs
@@ -44,9 +44,11 @@ namespace MediaBrowser.MediaEncoding.Probing
private IReadOnlyList<string> SplitWhitelist => _splitWhiteList ??= new string[]
{
"AC/DC",
+ "As/Hi Soundworks",
"Au/Ra",
"Bremer/McCoy",
"이달의 소녀 1/3",
+ "R!N / Gemie",
"LOONA 1/3",
"LOONA / yyxy",
"LOONA / ODD EYE CIRCLE",
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 5b1ec8041..00f51d0eb 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -141,12 +141,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles
var inputFormat = subtitle.Format;
- // Return the original if we don't have any way of converting it
- if (!TryGetWriter(outputFormat, out var writer))
- {
- return subtitle.Stream;
- }
-
// Return the original if the same format is being requested
// Character encoding was already handled in GetSubtitleStream
if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase))
@@ -677,8 +671,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles
if (!string.Equals(text, newText, StringComparison.Ordinal))
{
- using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
- using (var writer = new StreamWriter(fileStream, encoding))
+ var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous);
+ var writer = new StreamWriter(fileStream, encoding);
+ await using (fileStream.ConfigureAwait(false))
+ await using (writer.ConfigureAwait(false))
{
await writer.WriteAsync(newText.AsMemory(), cancellationToken).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Model/Branding/BrandingOptions.cs b/MediaBrowser.Model/Branding/BrandingOptions.cs
index 7f19a5b85..cc42c1718 100644
--- a/MediaBrowser.Model/Branding/BrandingOptions.cs
+++ b/MediaBrowser.Model/Branding/BrandingOptions.cs
@@ -1,19 +1,32 @@
-#pragma warning disable CS1591
+using System.Text.Json.Serialization;
+using System.Xml.Serialization;
-namespace MediaBrowser.Model.Branding
+namespace MediaBrowser.Model.Branding;
+
+/// <summary>
+/// The branding options.
+/// </summary>
+public class BrandingOptions
{
- public class BrandingOptions
- {
- /// <summary>
- /// Gets or sets the login disclaimer.
- /// </summary>
- /// <value>The login disclaimer.</value>
- public string? LoginDisclaimer { get; set; }
+ /// <summary>
+ /// Gets or sets the login disclaimer.
+ /// </summary>
+ /// <value>The login disclaimer.</value>
+ public string? LoginDisclaimer { get; set; }
+
+ /// <summary>
+ /// Gets or sets the custom CSS.
+ /// </summary>
+ /// <value>The custom CSS.</value>
+ public string? CustomCss { get; set; }
- /// <summary>
- /// Gets or sets the custom CSS.
- /// </summary>
- /// <value>The custom CSS.</value>
- public string? CustomCss { get; set; }
- }
+ /// <summary>
+ /// Gets or sets the splashscreen location on disk.
+ /// </summary>
+ /// <remarks>
+ /// Not served via the API.
+ /// Only used to save the custom uploaded user splashscreen in the configuration file.
+ /// </remarks>
+ [JsonIgnore]
+ public string? SplashscreenLocation { get; set; }
}
diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs
index d0ded99ea..51917b50e 100644
--- a/MediaBrowser.Model/Configuration/EncodingOptions.cs
+++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs
@@ -1,3 +1,5 @@
+using System;
+
#nullable disable
#pragma warning disable CS1591
@@ -37,6 +39,7 @@ namespace MediaBrowser.Model.Configuration
EnableHardwareEncoding = true;
AllowHevcEncoding = false;
EnableSubtitleExtraction = true;
+ AllowOnDemandMetadataBasedKeyframeExtractionForExtensions = Array.Empty<string>();
HardwareDecodingCodecs = new string[] { "h264", "vc1" };
}
@@ -115,5 +118,7 @@ namespace MediaBrowser.Model.Configuration
public bool EnableSubtitleExtraction { get; set; }
public string[] HardwareDecodingCodecs { get; set; }
+
+ public string[] AllowOnDemandMetadataBasedKeyframeExtractionForExtensions { get; set; }
}
}
diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs
index a784025e3..094dc73b2 100644
--- a/MediaBrowser.Model/Dto/BaseItemDto.cs
+++ b/MediaBrowser.Model/Dto/BaseItemDto.cs
@@ -297,13 +297,13 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets wether the item has a logo, this will hold the Id of the Parent that has one.
/// </summary>
/// <value>The parent logo item id.</value>
- public string ParentLogoItemId { get; set; }
+ public Guid? ParentLogoItemId { get; set; }
/// <summary>
/// Gets or sets wether the item has any backdrops, this will hold the Id of the Parent that has one.
/// </summary>
/// <value>The parent backdrop item id.</value>
- public string ParentBackdropItemId { get; set; }
+ public Guid? ParentBackdropItemId { get; set; }
/// <summary>
/// Gets or sets the parent backdrop image tags.
@@ -509,7 +509,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets wether the item has fan art, this will hold the Id of the Parent that has one.
/// </summary>
/// <value>The parent art item id.</value>
- public string ParentArtItemId { get; set; }
+ public Guid? ParentArtItemId { get; set; }
/// <summary>
/// Gets or sets the parent art image tag.
@@ -540,7 +540,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the parent thumb item id.
/// </summary>
/// <value>The parent thumb item id.</value>
- public string ParentThumbItemId { get; set; }
+ public Guid? ParentThumbItemId { get; set; }
/// <summary>
/// Gets or sets the parent thumb image tag.
diff --git a/MediaBrowser.Model/Dto/BaseItemPerson.cs b/MediaBrowser.Model/Dto/BaseItemPerson.cs
index ddd7667ef..6b920b0ef 100644
--- a/MediaBrowser.Model/Dto/BaseItemPerson.cs
+++ b/MediaBrowser.Model/Dto/BaseItemPerson.cs
@@ -1,4 +1,5 @@
#nullable disable
+using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using MediaBrowser.Model.Entities;
@@ -20,7 +21,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the identifier.
/// </summary>
/// <value>The identifier.</value>
- public string Id { get; set; }
+ public Guid Id { get; set; }
/// <summary>
/// Gets or sets the role.
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index 63f7ada5c..b54a40b42 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -49,6 +49,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/MediaBrowser.Model/Querying/QueryResult.cs b/MediaBrowser.Model/Querying/QueryResult.cs
index 8ce794800..ea843f34c 100644
--- a/MediaBrowser.Model/Querying/QueryResult.cs
+++ b/MediaBrowser.Model/Querying/QueryResult.cs
@@ -19,6 +19,13 @@ namespace MediaBrowser.Model.Querying
TotalRecordCount = items.Count;
}
+ public QueryResult(int? startIndex, int? totalRecordCount, IReadOnlyList<T> items)
+ {
+ StartIndex = startIndex ?? 0;
+ TotalRecordCount = totalRecordCount ?? items.Count;
+ Items = items;
+ }
+
/// <summary>
/// Gets or sets the items.
/// </summary>
diff --git a/MediaBrowser.Providers/Books/AudioBookMetadataService.cs b/MediaBrowser.Providers/Books/AudioBookMetadataService.cs
index eabc66c6b..96e1165b6 100644
--- a/MediaBrowser.Providers/Books/AudioBookMetadataService.cs
+++ b/MediaBrowser.Providers/Books/AudioBookMetadataService.cs
@@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.Books
bool replaceData,
bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
diff --git a/MediaBrowser.Providers/Books/BookMetadataService.cs b/MediaBrowser.Providers/Books/BookMetadataService.cs
index 3f3782dfb..50b9922c6 100644
--- a/MediaBrowser.Providers/Books/BookMetadataService.cs
+++ b/MediaBrowser.Providers/Books/BookMetadataService.cs
@@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.Books
/// <inheritdoc />
protected override void MergeData(MetadataResult<Book> source, MetadataResult<Book> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
if (replaceData || string.IsNullOrEmpty(target.Item.SeriesName))
{
diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
index 88ce8d087..cbbb343e5 100644
--- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
+++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs
@@ -47,7 +47,7 @@ namespace MediaBrowser.Providers.BoxSets
/// <inheritdoc />
protected override void MergeData(MetadataResult<BoxSet> source, MetadataResult<BoxSet> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
diff --git a/MediaBrowser.Providers/Channels/ChannelMetadataService.cs b/MediaBrowser.Providers/Channels/ChannelMetadataService.cs
index db2213bad..0267fa13f 100644
--- a/MediaBrowser.Providers/Channels/ChannelMetadataService.cs
+++ b/MediaBrowser.Providers/Channels/ChannelMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.Channels
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<Channel> source, MetadataResult<Channel> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs b/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs
index e0f3131fd..0629824d3 100644
--- a/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs
+++ b/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.Folders
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<CollectionFolder> source, MetadataResult<CollectionFolder> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Folders/FolderMetadataService.cs b/MediaBrowser.Providers/Folders/FolderMetadataService.cs
index 998bf4c6a..79d52991a 100644
--- a/MediaBrowser.Providers/Folders/FolderMetadataService.cs
+++ b/MediaBrowser.Providers/Folders/FolderMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -26,11 +25,5 @@ namespace MediaBrowser.Providers.Folders
/// <inheritdoc />
// Make sure the type-specific services get picked first
public override int Order => 10;
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<Folder> source, MetadataResult<Folder> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Folders/UserViewMetadataService.cs b/MediaBrowser.Providers/Folders/UserViewMetadataService.cs
index 2d536f12e..79c5597e5 100644
--- a/MediaBrowser.Providers/Folders/UserViewMetadataService.cs
+++ b/MediaBrowser.Providers/Folders/UserViewMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.Folders
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<UserView> source, MetadataResult<UserView> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Genres/GenreMetadataService.cs b/MediaBrowser.Providers/Genres/GenreMetadataService.cs
index f7ea767e7..4d10d8987 100644
--- a/MediaBrowser.Providers/Genres/GenreMetadataService.cs
+++ b/MediaBrowser.Providers/Genres/GenreMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.Genres
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<Genre> source, MetadataResult<Genre> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/LiveTv/LiveTvMetadataService.cs b/MediaBrowser.Providers/LiveTv/LiveTvMetadataService.cs
index 2e6cf4530..c94d36530 100644
--- a/MediaBrowser.Providers/LiveTv/LiveTvMetadataService.cs
+++ b/MediaBrowser.Providers/LiveTv/LiveTvMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.LiveTv
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<LiveTvChannel> source, MetadataResult<LiveTvChannel> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index 0d1bdec58..bbbbfad54 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -63,6 +63,29 @@ namespace MediaBrowser.Providers.Manager
}
/// <summary>
+ /// Removes all existing images from the provided item.
+ /// </summary>
+ /// <param name="item">The <see cref="BaseItem"/> to remove images from.</param>
+ /// <returns><c>true</c> if changes were made to the item; otherwise <c>false</c>.</returns>
+ public bool RemoveImages(BaseItem item)
+ {
+ var singular = new List<ItemImageInfo>();
+ for (var i = 0; i < _singularImages.Length; i++)
+ {
+ var currentImage = item.GetImageInfo(_singularImages[i], 0);
+ if (currentImage != null)
+ {
+ singular.Add(currentImage);
+ }
+ }
+
+ singular.AddRange(item.GetImages(ImageType.Backdrop));
+ PruneImages(item, singular);
+
+ return singular.Count > 0;
+ }
+
+ /// <summary>
/// Verifies existing images have valid paths and adds any new local images provided.
/// </summary>
/// <param name="item">The <see cref="BaseItem"/> to validate images for.</param>
@@ -100,7 +123,7 @@ namespace MediaBrowser.Providers.Manager
public async Task<RefreshResult> RefreshImages(
BaseItem item,
LibraryOptions libraryOptions,
- List<IImageProvider> providers,
+ IEnumerable<IImageProvider> providers,
ImageRefreshOptions refreshOptions,
CancellationToken cancellationToken)
{
@@ -160,14 +183,14 @@ namespace MediaBrowser.Providers.Manager
foreach (var imageType in images)
{
- if (!IsEnabled(savedOptions, imageType))
+ if (!savedOptions.IsEnabled(imageType))
{
continue;
}
- if (!HasImage(item, imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
+ if (!item.HasImage(imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
{
- _logger.LogDebug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name);
+ _logger.LogDebug("Running {Provider} for {Item}", provider.GetType().Name, item.Path ?? item.Name);
var response = await provider.GetImage(item, imageType, cancellationToken).ConfigureAwait(false);
@@ -183,7 +206,7 @@ namespace MediaBrowser.Providers.Manager
{
if (response.Protocol == MediaProtocol.Http)
{
- _logger.LogDebug("Setting image url into item {0}", item.Id);
+ _logger.LogDebug("Setting image url into item {Item}", item.Id);
var index = item.AllowsMultipleImages(imageType) ? item.GetImages(imageType).Count() : 0;
item.SetImage(
new ItemImageInfo
@@ -220,39 +243,6 @@ namespace MediaBrowser.Providers.Manager
}
}
- private bool HasImage(BaseItem item, ImageType type)
- {
- return item.HasImage(type);
- }
-
- /// <summary>
- /// Determines if an item already contains the given images.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="images">The images.</param>
- /// <param name="savedOptions">The saved options.</param>
- /// <param name="backdropLimit">The backdrop limit.</param>
- /// <returns><c>true</c> if the specified item contains images; otherwise, <c>false</c>.</returns>
- private bool ContainsImages(BaseItem item, List<ImageType> images, TypeOptions savedOptions, int backdropLimit)
- {
- // Using .Any causes the creation of a DisplayClass aka. variable capture
- for (var i = 0; i < _singularImages.Length; i++)
- {
- var type = _singularImages[i];
- if (images.Contains(type) && !HasImage(item, type) && savedOptions.GetLimit(type) > 0)
- {
- return false;
- }
- }
-
- if (images.Contains(ImageType.Backdrop) && item.GetImages(ImageType.Backdrop).Count() < backdropLimit)
- {
- return false;
- }
-
- return true;
- }
-
/// <summary>
/// Refreshes from a remote provider.
/// </summary>
@@ -289,7 +279,7 @@ namespace MediaBrowser.Providers.Manager
return;
}
- _logger.LogDebug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name);
+ _logger.LogDebug("Running {Provider} for {Item}", provider.GetType().Name, item.Path ?? item.Name);
var images = await _providerManager.GetAvailableRemoteImages(
item,
@@ -305,12 +295,12 @@ namespace MediaBrowser.Providers.Manager
foreach (var imageType in _singularImages)
{
- if (!IsEnabled(savedOptions, imageType))
+ if (!savedOptions.IsEnabled(imageType))
{
continue;
}
- if (!HasImage(item, imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
+ if (!item.HasImage(imageType) || (refreshOptions.IsReplacingImage(imageType) && !downloadedImages.Contains(imageType)))
{
minWidth = savedOptions.GetMinWidth(imageType);
var downloaded = await DownloadImage(item, provider, result, list, minWidth, imageType, cancellationToken).ConfigureAwait(false);
@@ -336,14 +326,37 @@ namespace MediaBrowser.Providers.Manager
}
}
- private bool IsEnabled(TypeOptions options, ImageType type)
+ /// <summary>
+ /// Determines if an item already contains the given images.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="images">The images.</param>
+ /// <param name="savedOptions">The saved options.</param>
+ /// <param name="backdropLimit">The backdrop limit.</param>
+ /// <returns><c>true</c> if the specified item contains images; otherwise, <c>false</c>.</returns>
+ private bool ContainsImages(BaseItem item, List<ImageType> images, TypeOptions savedOptions, int backdropLimit)
{
- return options.IsEnabled(type);
+ // Using .Any causes the creation of a DisplayClass aka. variable capture
+ for (var i = 0; i < _singularImages.Length; i++)
+ {
+ var type = _singularImages[i];
+ if (images.Contains(type) && !item.HasImage(type) && savedOptions.GetLimit(type) > 0)
+ {
+ return false;
+ }
+ }
+
+ if (images.Contains(ImageType.Backdrop) && item.GetImages(ImageType.Backdrop).Count() < backdropLimit)
+ {
+ return false;
+ }
+
+ return true;
}
- private void PruneImages(BaseItem item, ItemImageInfo[] images)
+ private void PruneImages(BaseItem item, IReadOnlyList<ItemImageInfo> images)
{
- for (var i = 0; i < images.Length; i++)
+ for (var i = 0; i < images.Count; i++)
{
var image = images[i];
@@ -355,6 +368,11 @@ namespace MediaBrowser.Providers.Manager
}
catch (FileNotFoundException)
{
+ // nothing to do, already gone
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ _logger.LogWarning(ex, "Unable to delete {Image}", image.Path);
}
}
}
@@ -370,7 +388,7 @@ namespace MediaBrowser.Providers.Manager
/// <returns><c>true</c> if changes were made to the item; otherwise <c>false</c>.</returns>
public bool MergeImages(BaseItem item, IReadOnlyList<LocalImageInfo> images)
{
- var changed = item.ValidateImages(new DirectoryService(_fileSystem));
+ var changed = item.ValidateImages();
for (var i = 0; i < _singularImages.Length; i++)
{
@@ -381,12 +399,7 @@ namespace MediaBrowser.Providers.Manager
{
var currentImage = item.GetImageInfo(type, 0);
- if (currentImage == null)
- {
- item.SetImagePath(type, image.FileInfo);
- changed = true;
- }
- else if (!string.Equals(currentImage.Path, image.FileInfo.FullName, StringComparison.OrdinalIgnoreCase))
+ if (currentImage == null || !string.Equals(currentImage.Path, image.FileInfo.FullName, StringComparison.OrdinalIgnoreCase))
{
item.SetImagePath(type, image.FileInfo);
changed = true;
@@ -494,7 +507,7 @@ namespace MediaBrowser.Providers.Manager
await _providerManager.SaveImage(
item,
stream,
- response.Content.Headers.ContentType.MediaType,
+ response.Content.Headers.ContentType?.MediaType,
type,
null,
cancellationToken).ConfigureAwait(false);
@@ -617,11 +630,11 @@ namespace MediaBrowser.Providers.Manager
await _providerManager.SaveImage(
item,
stream,
- response.Content.Headers.ContentType.MediaType,
+ response.Content.Headers.ContentType?.MediaType,
imageType,
null,
cancellationToken).ConfigureAwait(false);
- result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
+ result.UpdateType |= ItemUpdateType.ImageUpdate;
}
catch (HttpRequestException)
{
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index 94045b38b..0c52d2673 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -8,8 +8,10 @@ using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
+using Diacritics.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
@@ -74,14 +76,10 @@ namespace MediaBrowser.Providers.Manager
var itemOfType = (TItemType)item;
var updateType = ItemUpdateType.None;
- var requiresRefresh = false;
var libraryOptions = LibraryManager.GetLibraryOptions(item);
- if (!requiresRefresh && libraryOptions.AutomaticRefreshIntervalDays > 0 && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= libraryOptions.AutomaticRefreshIntervalDays)
- {
- requiresRefresh = true;
- }
+ var requiresRefresh = libraryOptions.AutomaticRefreshIntervalDays > 0 && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= libraryOptions.AutomaticRefreshIntervalDays;
if (!requiresRefresh && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
{
@@ -90,7 +88,7 @@ namespace MediaBrowser.Providers.Manager
if (requiresRefresh)
{
- Logger.LogDebug("Refreshing {0} {1} because item.RequiresRefresh() returned true", typeof(TItemType).Name, item.Path ?? item.Name);
+ Logger.LogDebug("Refreshing {Type} {Item} because item.RequiresRefresh() returned true", typeof(TItemType).Name, item.Path ?? item.Name);
}
}
@@ -98,6 +96,14 @@ namespace MediaBrowser.Providers.Manager
var allImageProviders = ((ProviderManager)ProviderManager).GetImageProviders(item, refreshOptions).ToList();
+ if (refreshOptions.RemoveOldMetadata && refreshOptions.ReplaceAllImages)
+ {
+ if (ImageProvider.RemoveImages(item))
+ {
+ updateType |= ItemUpdateType.ImageUpdate;
+ }
+ }
+
// Start by validating images
try
{
@@ -110,7 +116,7 @@ namespace MediaBrowser.Providers.Manager
catch (Exception ex)
{
localImagesFailed = true;
- Logger.LogError(ex, "Error validating images for {0}", item.Path ?? item.Name ?? "Unknown name");
+ Logger.LogError(ex, "Error validating images for {Item}", item.Path ?? item.Name ?? "Unknown name");
}
var metadataResult = new MetadataResult<TItemType>
@@ -380,8 +386,7 @@ namespace MediaBrowser.Providers.Manager
{
var updateType = ItemUpdateType.None;
- var folder = item as Folder;
- if (folder != null && folder.SupportsDateLastMediaAdded)
+ if (item is Folder folder && folder.SupportsDateLastMediaAdded)
{
var dateLastMediaAdded = DateTime.MinValue;
var any = false;
@@ -668,7 +673,7 @@ namespace MediaBrowser.Providers.Manager
foreach (var provider in providers.OfType<ILocalMetadataProvider<TItemType>>().ToList())
{
var providerName = provider.GetType().Name;
- Logger.LogDebug("Running {0} for {1}", providerName, logName);
+ Logger.LogDebug("Running {Provider} for {Item}", providerName, logName);
var itemInfo = new ItemInfo(item);
@@ -713,7 +718,7 @@ namespace MediaBrowser.Providers.Manager
break;
}
- Logger.LogDebug("{0} returned no metadata for {1}", providerName, logName);
+ Logger.LogDebug("{Provider} returned no metadata for {Item}", providerName, logName);
}
catch (OperationCanceledException)
{
@@ -749,8 +754,11 @@ namespace MediaBrowser.Providers.Manager
}
else
{
- // TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields
- MergeData(metadata, temp, Array.Empty<MetadataField>(), false, false);
+ if (!options.RemoveOldMetadata)
+ {
+ MergeData(metadata, temp, Array.Empty<MetadataField>(), false, false);
+ }
+
MergeData(temp, metadata, item.LockedFields, true, false);
}
}
@@ -780,7 +788,7 @@ namespace MediaBrowser.Providers.Manager
private async Task RunCustomProvider(ICustomMetadataProvider<TItemType> provider, TItemType item, string logName, MetadataRefreshOptions options, RefreshResult refreshResult, CancellationToken cancellationToken)
{
- Logger.LogDebug("Running {0} for {1}", provider.GetType().Name, logName);
+ Logger.LogDebug("Running {Provider} for {Item}", provider.GetType().Name, logName);
try
{
@@ -811,7 +819,7 @@ namespace MediaBrowser.Providers.Manager
foreach (var provider in providers)
{
var providerName = provider.GetType().Name;
- Logger.LogDebug("Running {0} for {1}", providerName, logName);
+ Logger.LogDebug("Running {Provider} for {Item}", providerName, logName);
if (id != null && !tmpDataMerged)
{
@@ -834,7 +842,7 @@ namespace MediaBrowser.Providers.Manager
}
else
{
- Logger.LogDebug("{0} returned no metadata for {1}", providerName, logName);
+ Logger.LogDebug("{Provider} returned no metadata for {Item}", providerName, logName);
}
}
catch (OperationCanceledException)
@@ -867,13 +875,6 @@ namespace MediaBrowser.Providers.Manager
}
}
- protected abstract void MergeData(
- MetadataResult<TItemType> source,
- MetadataResult<TItemType> target,
- MetadataField[] lockedFields,
- bool replaceData,
- bool mergeMetadataSettings);
-
private bool HasChanged(BaseItem item, IHasItemChangeMonitor changeMonitor, IDirectoryService directoryService)
{
try
@@ -882,16 +883,312 @@ namespace MediaBrowser.Providers.Manager
if (hasChanged)
{
- Logger.LogDebug("{0} reports change to {1}", changeMonitor.GetType().Name, item.Path ?? item.Name);
+ Logger.LogDebug("{Monitor} reports change to {Item}", changeMonitor.GetType().Name, item.Path ?? item.Name);
}
return hasChanged;
}
catch (Exception ex)
{
- Logger.LogError(ex, "Error in {0}.HasChanged", changeMonitor.GetType().Name);
+ Logger.LogError(ex, "Error in {Monitor}.HasChanged", changeMonitor.GetType().Name);
return false;
}
}
+
+ /// <summary>
+ /// Merges metadata from source into target.
+ /// </summary>
+ /// <param name="source">The source for new metadata.</param>
+ /// <param name="target">The target to insert new metadata into.</param>
+ /// <param name="lockedFields">The fields that are locked and should not be updated.</param>
+ /// <param name="replaceData"><c>true</c> if existing data should be replaced.</param>
+ /// <param name="mergeMetadataSettings"><c>true</c> if the metadata settings in target should be updated to match source.</param>
+ /// <exception cref="ArgumentException">Thrown if source or target are null.</exception>
+ protected virtual void MergeData(
+ MetadataResult<TItemType> source,
+ MetadataResult<TItemType> target,
+ MetadataField[] lockedFields,
+ bool replaceData,
+ bool mergeMetadataSettings)
+ {
+ MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ }
+
+ internal static void MergeBaseItemData(
+ MetadataResult<TItemType> sourceResult,
+ MetadataResult<TItemType> targetResult,
+ MetadataField[] lockedFields,
+ bool replaceData,
+ bool mergeMetadataSettings)
+ {
+ var source = sourceResult.Item;
+ var target = targetResult.Item;
+
+ if (source == null)
+ {
+ throw new ArgumentException("Item cannot be null.", nameof(sourceResult));
+ }
+
+ if (target == null)
+ {
+ throw new ArgumentException("Item cannot be null.", nameof(targetResult));
+ }
+
+ if (!lockedFields.Contains(MetadataField.Name))
+ {
+ if (replaceData || string.IsNullOrEmpty(target.Name))
+ {
+ // Safeguard against incoming data having an empty name
+ if (!string.IsNullOrWhiteSpace(source.Name))
+ {
+ target.Name = source.Name;
+ }
+ }
+ }
+
+ if (replaceData || string.IsNullOrEmpty(target.OriginalTitle))
+ {
+ // Safeguard against incoming data having an empty name
+ if (!string.IsNullOrWhiteSpace(source.OriginalTitle))
+ {
+ target.OriginalTitle = source.OriginalTitle;
+ }
+ }
+
+ if (replaceData || !target.CommunityRating.HasValue)
+ {
+ target.CommunityRating = source.CommunityRating;
+ }
+
+ if (replaceData || !target.EndDate.HasValue)
+ {
+ target.EndDate = source.EndDate;
+ }
+
+ if (!lockedFields.Contains(MetadataField.Genres))
+ {
+ if (replaceData || target.Genres.Length == 0)
+ {
+ target.Genres = source.Genres;
+ }
+ }
+
+ if (replaceData || !target.IndexNumber.HasValue)
+ {
+ target.IndexNumber = source.IndexNumber;
+ }
+
+ if (!lockedFields.Contains(MetadataField.OfficialRating))
+ {
+ if (replaceData || string.IsNullOrEmpty(target.OfficialRating))
+ {
+ target.OfficialRating = source.OfficialRating;
+ }
+ }
+
+ if (replaceData || string.IsNullOrEmpty(target.CustomRating))
+ {
+ target.CustomRating = source.CustomRating;
+ }
+
+ if (replaceData || string.IsNullOrEmpty(target.Tagline))
+ {
+ target.Tagline = source.Tagline;
+ }
+
+ if (!lockedFields.Contains(MetadataField.Overview))
+ {
+ if (replaceData || string.IsNullOrEmpty(target.Overview))
+ {
+ target.Overview = source.Overview;
+ }
+ }
+
+ if (replaceData || !target.ParentIndexNumber.HasValue)
+ {
+ target.ParentIndexNumber = source.ParentIndexNumber;
+ }
+
+ if (!lockedFields.Contains(MetadataField.Cast))
+ {
+ if (replaceData || targetResult.People == null || targetResult.People.Count == 0)
+ {
+ targetResult.People = sourceResult.People;
+ }
+ else if (targetResult.People != null && sourceResult.People != null)
+ {
+ MergePeople(sourceResult.People, targetResult.People);
+ }
+ }
+
+ if (replaceData || !target.PremiereDate.HasValue)
+ {
+ target.PremiereDate = source.PremiereDate;
+ }
+
+ if (replaceData || !target.ProductionYear.HasValue)
+ {
+ target.ProductionYear = source.ProductionYear;
+ }
+
+ if (!lockedFields.Contains(MetadataField.Runtime))
+ {
+ if (replaceData || !target.RunTimeTicks.HasValue)
+ {
+ if (target is not Audio && target is not Video)
+ {
+ target.RunTimeTicks = source.RunTimeTicks;
+ }
+ }
+ }
+
+ if (!lockedFields.Contains(MetadataField.Studios))
+ {
+ if (replaceData || target.Studios.Length == 0)
+ {
+ target.Studios = source.Studios;
+ }
+ }
+
+ if (!lockedFields.Contains(MetadataField.Tags))
+ {
+ if (replaceData || target.Tags.Length == 0)
+ {
+ target.Tags = source.Tags;
+ }
+ }
+
+ if (!lockedFields.Contains(MetadataField.ProductionLocations))
+ {
+ if (replaceData || target.ProductionLocations.Length == 0)
+ {
+ target.ProductionLocations = source.ProductionLocations;
+ }
+ }
+
+ foreach (var id in source.ProviderIds)
+ {
+ var key = id.Key;
+
+ // Don't replace existing Id's.
+ if (replaceData)
+ {
+ target.ProviderIds[key] = id.Value;
+ }
+ else
+ {
+ target.ProviderIds.TryAdd(key, id.Value);
+ }
+ }
+
+ MergeAlbumArtist(source, target, replaceData);
+ MergeCriticRating(source, target, replaceData);
+ MergeTrailers(source, target, replaceData);
+ MergeVideoInfo(source, target, replaceData);
+ MergeDisplayOrder(source, target, replaceData);
+
+ if (replaceData || string.IsNullOrEmpty(target.ForcedSortName))
+ {
+ var forcedSortName = source.ForcedSortName;
+
+ if (!string.IsNullOrWhiteSpace(forcedSortName))
+ {
+ target.ForcedSortName = forcedSortName;
+ }
+ }
+
+ if (mergeMetadataSettings)
+ {
+ target.LockedFields = source.LockedFields;
+ target.IsLocked = source.IsLocked;
+
+ // Grab the value if it's there, but if not then don't overwrite with the default
+ if (source.DateCreated != default)
+ {
+ target.DateCreated = source.DateCreated;
+ }
+
+ target.PreferredMetadataCountryCode = source.PreferredMetadataCountryCode;
+ target.PreferredMetadataLanguage = source.PreferredMetadataLanguage;
+ }
+ }
+
+ private static void MergePeople(List<PersonInfo> source, List<PersonInfo> target)
+ {
+ foreach (var person in target)
+ {
+ var normalizedName = person.Name.RemoveDiacritics();
+ var personInSource = source.FirstOrDefault(i => string.Equals(i.Name.RemoveDiacritics(), normalizedName, StringComparison.OrdinalIgnoreCase));
+
+ if (personInSource != null)
+ {
+ foreach (var providerId in personInSource.ProviderIds)
+ {
+ person.ProviderIds.TryAdd(providerId.Key, providerId.Value);
+ }
+
+ if (string.IsNullOrWhiteSpace(person.ImageUrl))
+ {
+ person.ImageUrl = personInSource.ImageUrl;
+ }
+ }
+ }
+ }
+
+ private static void MergeDisplayOrder(BaseItem source, BaseItem target, bool replaceData)
+ {
+ if (source is IHasDisplayOrder sourceHasDisplayOrder
+ && target is IHasDisplayOrder targetHasDisplayOrder)
+ {
+ if (replaceData || string.IsNullOrEmpty(targetHasDisplayOrder.DisplayOrder))
+ {
+ var displayOrder = sourceHasDisplayOrder.DisplayOrder;
+
+ if (!string.IsNullOrWhiteSpace(displayOrder))
+ {
+ targetHasDisplayOrder.DisplayOrder = displayOrder;
+ }
+ }
+ }
+ }
+
+ private static void MergeAlbumArtist(BaseItem source, BaseItem target, bool replaceData)
+ {
+ if (source is IHasAlbumArtist sourceHasAlbumArtist
+ && target is IHasAlbumArtist targetHasAlbumArtist)
+ {
+ if (replaceData || targetHasAlbumArtist.AlbumArtists.Count == 0)
+ {
+ targetHasAlbumArtist.AlbumArtists = sourceHasAlbumArtist.AlbumArtists;
+ }
+ }
+ }
+
+ private static void MergeCriticRating(BaseItem source, BaseItem target, bool replaceData)
+ {
+ if (replaceData || !target.CriticRating.HasValue)
+ {
+ target.CriticRating = source.CriticRating;
+ }
+ }
+
+ private static void MergeTrailers(BaseItem source, BaseItem target, bool replaceData)
+ {
+ if (replaceData || target.RemoteTrailers.Count == 0)
+ {
+ target.RemoteTrailers = source.RemoteTrailers;
+ }
+ }
+
+ private static void MergeVideoInfo(BaseItem source, BaseItem target, bool replaceData)
+ {
+ if (source is Video sourceCast && target is Video targetCast)
+ {
+ if (replaceData || targetCast.Video3DFormat == null)
+ {
+ targetCast.Video3DFormat = sourceCast.Video3DFormat;
+ }
+ }
+ }
}
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 0385ce6a7..5281b3721 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -128,9 +128,7 @@ namespace MediaBrowser.Providers.Manager
_metadataProviders = metadataProviders.ToArray();
_externalIds = externalIds.OrderBy(i => i.ProviderName).ToArray();
- _savers = metadataSavers
- .Where(i => i is not IConfigurableProvider configurable || configurable.IsEnabled)
- .ToArray();
+ _savers = metadataSavers.ToArray();
}
/// <inheritdoc/>
@@ -653,16 +651,12 @@ namespace MediaBrowser.Providers.Manager
}
/// <inheritdoc/>
- public void SaveMetadata(BaseItem item, ItemUpdateType updateType)
- {
- SaveMetadata(item, updateType, _savers);
- }
+ public Task SaveMetadataAsync(BaseItem item, ItemUpdateType updateType)
+ => SaveMetadataAsync(item, updateType, _savers);
/// <inheritdoc/>
- public void SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable<string> savers)
- {
- SaveMetadata(item, updateType, _savers.Where(i => savers.Contains(i.Name, StringComparison.OrdinalIgnoreCase)));
- }
+ public Task SaveMetadataAsync(BaseItem item, ItemUpdateType updateType, IEnumerable<string> savers)
+ => SaveMetadataAsync(item, updateType, _savers.Where(i => savers.Contains(i.Name, StringComparison.OrdinalIgnoreCase)));
/// <summary>
/// Saves the metadata.
@@ -670,7 +664,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <param name="savers">The savers.</param>
- private void SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable<IMetadataSaver> savers)
+ private async Task SaveMetadataAsync(BaseItem item, ItemUpdateType updateType, IEnumerable<IMetadataSaver> savers)
{
var libraryOptions = _libraryManager.GetLibraryOptions(item);
@@ -695,7 +689,7 @@ namespace MediaBrowser.Providers.Manager
try
{
_libraryMonitor.ReportFileSystemChangeBeginning(path);
- saver.Save(item, CancellationToken.None);
+ await saver.SaveAsync(item, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -710,7 +704,7 @@ namespace MediaBrowser.Providers.Manager
{
try
{
- saver.Save(item, CancellationToken.None);
+ await saver.SaveAsync(item, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs
deleted file mode 100644
index b90136d50..000000000
--- a/MediaBrowser.Providers/Manager/ProviderUtils.cs
+++ /dev/null
@@ -1,295 +0,0 @@
-#nullable disable
-
-#pragma warning disable CS1591
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Diacritics.Extensions;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-
-namespace MediaBrowser.Providers.Manager
-{
- public static class ProviderUtils
- {
- public static void MergeBaseItemData<T>(
- MetadataResult<T> sourceResult,
- MetadataResult<T> targetResult,
- MetadataField[] lockedFields,
- bool replaceData,
- bool mergeMetadataSettings)
- where T : BaseItem
- {
- var source = sourceResult.Item;
- var target = targetResult.Item;
-
- if (source == null)
- {
- throw new ArgumentException("Item cannot be null.", nameof(sourceResult));
- }
-
- if (target == null)
- {
- throw new ArgumentException("Item cannot be null.", nameof(targetResult));
- }
-
- if (!lockedFields.Contains(MetadataField.Name))
- {
- if (replaceData || string.IsNullOrEmpty(target.Name))
- {
- // Safeguard against incoming data having an empty name
- if (!string.IsNullOrWhiteSpace(source.Name))
- {
- target.Name = source.Name;
- }
- }
- }
-
- if (replaceData || string.IsNullOrEmpty(target.OriginalTitle))
- {
- // Safeguard against incoming data having an empty name
- if (!string.IsNullOrWhiteSpace(source.OriginalTitle))
- {
- target.OriginalTitle = source.OriginalTitle;
- }
- }
-
- if (replaceData || !target.CommunityRating.HasValue)
- {
- target.CommunityRating = source.CommunityRating;
- }
-
- if (replaceData || !target.EndDate.HasValue)
- {
- target.EndDate = source.EndDate;
- }
-
- if (!lockedFields.Contains(MetadataField.Genres))
- {
- if (replaceData || target.Genres.Length == 0)
- {
- target.Genres = source.Genres;
- }
- }
-
- if (replaceData || !target.IndexNumber.HasValue)
- {
- target.IndexNumber = source.IndexNumber;
- }
-
- if (!lockedFields.Contains(MetadataField.OfficialRating))
- {
- if (replaceData || string.IsNullOrEmpty(target.OfficialRating))
- {
- target.OfficialRating = source.OfficialRating;
- }
- }
-
- if (replaceData || string.IsNullOrEmpty(target.CustomRating))
- {
- target.CustomRating = source.CustomRating;
- }
-
- if (replaceData || string.IsNullOrEmpty(target.Tagline))
- {
- target.Tagline = source.Tagline;
- }
-
- if (!lockedFields.Contains(MetadataField.Overview))
- {
- if (replaceData || string.IsNullOrEmpty(target.Overview))
- {
- target.Overview = source.Overview;
- }
- }
-
- if (replaceData || !target.ParentIndexNumber.HasValue)
- {
- target.ParentIndexNumber = source.ParentIndexNumber;
- }
-
- if (!lockedFields.Contains(MetadataField.Cast))
- {
- if (replaceData || targetResult.People == null || targetResult.People.Count == 0)
- {
- targetResult.People = sourceResult.People;
- }
- else if (targetResult.People != null && sourceResult.People != null)
- {
- MergePeople(sourceResult.People, targetResult.People);
- }
- }
-
- if (replaceData || !target.PremiereDate.HasValue)
- {
- target.PremiereDate = source.PremiereDate;
- }
-
- if (replaceData || !target.ProductionYear.HasValue)
- {
- target.ProductionYear = source.ProductionYear;
- }
-
- if (!lockedFields.Contains(MetadataField.Runtime))
- {
- if (replaceData || !target.RunTimeTicks.HasValue)
- {
- if (target is not Audio && target is not Video)
- {
- target.RunTimeTicks = source.RunTimeTicks;
- }
- }
- }
-
- if (!lockedFields.Contains(MetadataField.Studios))
- {
- if (replaceData || target.Studios.Length == 0)
- {
- target.Studios = source.Studios;
- }
- }
-
- if (!lockedFields.Contains(MetadataField.Tags))
- {
- if (replaceData || target.Tags.Length == 0)
- {
- target.Tags = source.Tags;
- }
- }
-
- if (!lockedFields.Contains(MetadataField.ProductionLocations))
- {
- if (replaceData || target.ProductionLocations.Length == 0)
- {
- target.ProductionLocations = source.ProductionLocations;
- }
- }
-
- foreach (var id in source.ProviderIds)
- {
- var key = id.Key;
-
- // Don't replace existing Id's.
- if (replaceData || !target.ProviderIds.ContainsKey(key))
- {
- target.ProviderIds[key] = id.Value;
- }
- }
-
- MergeAlbumArtist(source, target, replaceData);
- MergeCriticRating(source, target, replaceData);
- MergeTrailers(source, target, replaceData);
- MergeVideoInfo(source, target, replaceData);
- MergeDisplayOrder(source, target, replaceData);
-
- if (replaceData || string.IsNullOrEmpty(target.ForcedSortName))
- {
- var forcedSortName = source.ForcedSortName;
-
- if (!string.IsNullOrWhiteSpace(forcedSortName))
- {
- target.ForcedSortName = forcedSortName;
- }
- }
-
- if (mergeMetadataSettings)
- {
- target.LockedFields = source.LockedFields;
- target.IsLocked = source.IsLocked;
-
- // Grab the value if it's there, but if not then don't overwrite the default
- if (source.DateCreated != default)
- {
- target.DateCreated = source.DateCreated;
- }
-
- target.PreferredMetadataCountryCode = source.PreferredMetadataCountryCode;
- target.PreferredMetadataLanguage = source.PreferredMetadataLanguage;
- }
- }
-
- private static void MergePeople(List<PersonInfo> source, List<PersonInfo> target)
- {
- foreach (var person in target)
- {
- var normalizedName = person.Name.RemoveDiacritics();
- var personInSource = source.FirstOrDefault(i => string.Equals(i.Name.RemoveDiacritics(), normalizedName, StringComparison.OrdinalIgnoreCase));
-
- if (personInSource != null)
- {
- foreach (var providerId in personInSource.ProviderIds)
- {
- if (!person.ProviderIds.ContainsKey(providerId.Key))
- {
- person.ProviderIds[providerId.Key] = providerId.Value;
- }
- }
-
- if (string.IsNullOrWhiteSpace(person.ImageUrl))
- {
- person.ImageUrl = personInSource.ImageUrl;
- }
- }
- }
- }
-
- private static void MergeDisplayOrder(BaseItem source, BaseItem target, bool replaceData)
- {
- if (source is IHasDisplayOrder sourceHasDisplayOrder
- && target is IHasDisplayOrder targetHasDisplayOrder)
- {
- if (replaceData || string.IsNullOrEmpty(targetHasDisplayOrder.DisplayOrder))
- {
- var displayOrder = sourceHasDisplayOrder.DisplayOrder;
-
- if (!string.IsNullOrWhiteSpace(displayOrder))
- {
- targetHasDisplayOrder.DisplayOrder = displayOrder;
- }
- }
- }
- }
-
- private static void MergeAlbumArtist(BaseItem source, BaseItem target, bool replaceData)
- {
- if (source is IHasAlbumArtist sourceHasAlbumArtist
- && target is IHasAlbumArtist targetHasAlbumArtist)
- {
- if (replaceData || targetHasAlbumArtist.AlbumArtists.Count == 0)
- {
- targetHasAlbumArtist.AlbumArtists = sourceHasAlbumArtist.AlbumArtists;
- }
- }
- }
-
- private static void MergeCriticRating(BaseItem source, BaseItem target, bool replaceData)
- {
- if (replaceData || !target.CriticRating.HasValue)
- {
- target.CriticRating = source.CriticRating;
- }
- }
-
- private static void MergeTrailers(BaseItem source, BaseItem target, bool replaceData)
- {
- if (replaceData || target.RemoteTrailers.Count == 0)
- {
- target.RemoteTrailers = source.RemoteTrailers;
- }
- }
-
- private static void MergeVideoInfo(BaseItem source, BaseItem target, bool replaceData)
- {
- if (source is Video sourceCast && target is Video targetCast)
- {
- if (replaceData || targetCast.Video3DFormat == null)
- {
- targetCast.Video3DFormat = sourceCast.Video3DFormat;
- }
- }
- }
- }
-}
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 43cf621cd..1851a9e4b 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -22,7 +22,7 @@
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="OptimizedPriorityQueue" Version="5.0.0" />
<PackageReference Include="PlaylistsNET" Version="1.1.3" />
- <PackageReference Include="TMDbLib" Version="1.8.1" />
+ <PackageReference Include="TMDbLib" Version="1.9.1" />
</ItemGroup>
<PropertyGroup>
@@ -38,6 +38,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index 71cdc5bff..d67e83ab4 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -380,11 +380,11 @@ namespace MediaBrowser.Providers.MediaInfo
private void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions refreshOptions, LibraryOptions libraryOptions)
{
- var isFullRefresh = refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
+ var replaceData = refreshOptions.ReplaceAllMetadata;
if (!video.IsLocked && !video.LockedFields.Contains(MetadataField.OfficialRating))
{
- if (!string.IsNullOrWhiteSpace(data.OfficialRating) || isFullRefresh)
+ if (string.IsNullOrWhiteSpace(video.OfficialRating) || replaceData)
{
video.OfficialRating = data.OfficialRating;
}
@@ -392,7 +392,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (!video.IsLocked && !video.LockedFields.Contains(MetadataField.Genres))
{
- if (video.Genres.Length == 0 || isFullRefresh)
+ if (video.Genres.Length == 0 || replaceData)
{
video.Genres = Array.Empty<string>();
@@ -405,21 +405,28 @@ namespace MediaBrowser.Providers.MediaInfo
if (!video.IsLocked && !video.LockedFields.Contains(MetadataField.Studios))
{
- if (video.Studios.Length == 0 || isFullRefresh)
+ if (video.Studios.Length == 0 || replaceData)
{
video.SetStudios(data.Studios);
}
}
- if (video is MusicVideo musicVideo)
+ if (!video.IsLocked && video is MusicVideo musicVideo)
{
- musicVideo.Album = data.Album;
- musicVideo.Artists = data.Artists;
+ if (string.IsNullOrEmpty(musicVideo.Album) || replaceData)
+ {
+ musicVideo.Album = data.Album;
+ }
+
+ if (musicVideo.Artists.Count == 0 || replaceData)
+ {
+ musicVideo.Artists = data.Artists;
+ }
}
if (data.ProductionYear.HasValue)
{
- if (!video.ProductionYear.HasValue || isFullRefresh)
+ if (!video.ProductionYear.HasValue || replaceData)
{
video.ProductionYear = data.ProductionYear;
}
@@ -427,7 +434,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (data.PremiereDate.HasValue)
{
- if (!video.PremiereDate.HasValue || isFullRefresh)
+ if (!video.PremiereDate.HasValue || replaceData)
{
video.PremiereDate = data.PremiereDate;
}
@@ -435,7 +442,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (data.IndexNumber.HasValue)
{
- if (!video.IndexNumber.HasValue || isFullRefresh)
+ if (!video.IndexNumber.HasValue || replaceData)
{
video.IndexNumber = data.IndexNumber;
}
@@ -443,7 +450,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (data.ParentIndexNumber.HasValue)
{
- if (!video.ParentIndexNumber.HasValue || isFullRefresh)
+ if (!video.ParentIndexNumber.HasValue || replaceData)
{
video.ParentIndexNumber = data.ParentIndexNumber;
}
@@ -474,7 +481,7 @@ namespace MediaBrowser.Providers.MediaInfo
if (!video.IsLocked && !video.LockedFields.Contains(MetadataField.Overview))
{
- if (string.IsNullOrWhiteSpace(video.Overview) || isFullRefresh)
+ if (string.IsNullOrWhiteSpace(video.Overview) || replaceData)
{
video.Overview = data.Overview;
}
@@ -483,11 +490,11 @@ namespace MediaBrowser.Providers.MediaInfo
private void FetchPeople(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions options)
{
- var isFullRefresh = options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
+ var replaceData = options.ReplaceAllMetadata;
if (!video.IsLocked && !video.LockedFields.Contains(MetadataField.Cast))
{
- if (isFullRefresh || _libraryManager.GetPeople(video).Count == 0)
+ if (replaceData || _libraryManager.GetPeople(video).Count == 0)
{
var people = new List<PersonInfo>();
diff --git a/MediaBrowser.Providers/Movies/MovieMetadataService.cs b/MediaBrowser.Providers/Movies/MovieMetadataService.cs
index c477fb70f..984a3c122 100644
--- a/MediaBrowser.Providers/Movies/MovieMetadataService.cs
+++ b/MediaBrowser.Providers/Movies/MovieMetadataService.cs
@@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.Movies
/// <inheritdoc />
protected override void MergeData(MetadataResult<Movie> source, MetadataResult<Movie> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
diff --git a/MediaBrowser.Providers/Movies/TrailerMetadataService.cs b/MediaBrowser.Providers/Movies/TrailerMetadataService.cs
index f32d9ec0a..ad0c5aaa7 100644
--- a/MediaBrowser.Providers/Movies/TrailerMetadataService.cs
+++ b/MediaBrowser.Providers/Movies/TrailerMetadataService.cs
@@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.Movies
/// <inheritdoc />
protected override void MergeData(MetadataResult<Trailer> source, MetadataResult<Trailer> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
if (replaceData || target.Item.TrailerTypes.Length == 0)
{
diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
index 7c5b80e1e..7743d3b27 100644
--- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs
+++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs
@@ -114,7 +114,7 @@ namespace MediaBrowser.Providers.Music
bool replaceData,
bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
index e29475dd7..1f342c0db 100644
--- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs
+++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs
@@ -6,7 +6,6 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -39,11 +38,5 @@ namespace MediaBrowser.Providers.Music
})
: item.GetRecursiveChildren(i => i is IHasArtist && !i.IsFolder);
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<MusicArtist> source, MetadataResult<MusicArtist> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Music/AudioMetadataService.cs b/MediaBrowser.Providers/Music/AudioMetadataService.cs
index 8b9fc8a08..4577f7745 100644
--- a/MediaBrowser.Providers/Music/AudioMetadataService.cs
+++ b/MediaBrowser.Providers/Music/AudioMetadataService.cs
@@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.Music
/// <inheritdoc />
protected override void MergeData(MetadataResult<Audio> source, MetadataResult<Audio> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
diff --git a/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs b/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs
index 1d611a746..b97b76630 100644
--- a/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs
+++ b/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs
@@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.Music
bool replaceData,
bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
diff --git a/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs b/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs
index 7dda7e9bf..46eb546c2 100644
--- a/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs
+++ b/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.MusicGenres
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<MusicGenre> source, MetadataResult<MusicGenre> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/People/PersonMetadataService.cs b/MediaBrowser.Providers/People/PersonMetadataService.cs
index fe6d1d4d3..59bf7e4e6 100644
--- a/MediaBrowser.Providers/People/PersonMetadataService.cs
+++ b/MediaBrowser.Providers/People/PersonMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.People
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<Person> source, MetadataResult<Person> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs b/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs
index 60ed96452..f2cccb90f 100644
--- a/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs
+++ b/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.Photos
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<PhotoAlbum> source, MetadataResult<PhotoAlbum> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Photos/PhotoMetadataService.cs b/MediaBrowser.Providers/Photos/PhotoMetadataService.cs
index cbbb433c0..6941401e0 100644
--- a/MediaBrowser.Providers/Photos/PhotoMetadataService.cs
+++ b/MediaBrowser.Providers/Photos/PhotoMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.Photos
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<Photo> source, MetadataResult<Photo> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs
index 5262919d5..1bd000a48 100644
--- a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs
+++ b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs
@@ -41,7 +41,7 @@ namespace MediaBrowser.Providers.Playlists
/// <inheritdoc />
protected override void MergeData(MetadataResult<Playlist> source, MetadataResult<Playlist> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Configuration/PluginConfiguration.cs b/MediaBrowser.Providers/Plugins/Tmdb/Configuration/PluginConfiguration.cs
index dec796148..03aaf380b 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Configuration/PluginConfiguration.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Configuration/PluginConfiguration.cs
@@ -23,6 +23,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
public bool ExcludeTagsMovies { get; set; }
/// <summary>
+ /// Gets or sets a value indicating whether season name should be imported from TMDb.
+ /// </summary>
+ public bool ImportSeasonName { get; set; }
+
+ /// <summary>
/// Gets or sets a value indicating the maximum number of cast members to fetch for an item.
/// </summary>
public int MaxCastMembers { get; set; } = 15;
@@ -38,6 +43,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
public string? BackdropSize { get; set; }
/// <summary>
+ /// Gets or sets a value indicating the logo image size to fetch.
+ /// </summary>
+ public string? LogoSize { get; set; }
+
+ /// <summary>
/// Gets or sets a value indicating the profile image size to fetch.
/// </summary>
public string? ProfileSize { get; set; }
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Configuration/config.html b/MediaBrowser.Providers/Plugins/Tmdb/Configuration/config.html
index 52693795b..48ec0535c 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Configuration/config.html
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Configuration/config.html
@@ -20,6 +20,10 @@
<input is="emby-checkbox" type="checkbox" id="excludeTagsMovies" />
<span>Exclude tags/keywords from metadata fetched for movies.</span>
</label>
+ <label class="checkboxContainer">
+ <input is="emby-checkbox" type="checkbox" id="importSeasonName" />
+ <span>Import season name from metadata fetched for series.</span>
+ </label>
<div class="inputContainer">
<input is="emby-input" type="number" id="maxCastMembers" pattern="[0-9]*" required min="0" max="1000" label="Max Cast Members" />
<div class="fieldDescription">The maximum number of cast members to fetch for an item.</div>
@@ -33,6 +37,9 @@
<select is="emby-select" id="selectBackdropSize" label="Backdrop"></select>
</div>
<div class="selectContainer">
+ <select is="emby-select" id="selectLogoSize" label="Logo"></select>
+ </div>
+ <div class="selectContainer">
<select is="emby-select" id="selectProfileSize" label="Profile"></select>
</div>
<div class="selectContainer">
@@ -72,6 +79,10 @@
selBackdropSize.innerHTML = clientConfig.BackdropSizes.map(sizeOptionsGenerator);
selBackdropSize.value = pluginConfig.BackdropSize;
+ var selLogoSize = document.querySelector('#selectLogoSize');
+ selLogoSize.innerHTML = clientConfig.LogoSizes.map(sizeOptionsGenerator);
+ selLogoSize.value = pluginConfig.LogoSize;
+
var selProfileSize = document.querySelector('#selectProfileSize');
selProfileSize.innerHTML = clientConfig.ProfileSizes.map(sizeOptionsGenerator);
selProfileSize.value = pluginConfig.ProfileSize;
@@ -98,6 +109,7 @@
document.querySelector('#includeAdult').checked = config.IncludeAdult;
document.querySelector('#excludeTagsSeries').checked = config.ExcludeTagsSeries;
document.querySelector('#excludeTagsMovies').checked = config.ExcludeTagsMovies;
+ document.querySelector('#importSeasonName').checked = config.ImportSeasonName;
var maxCastMembers = document.querySelector('#maxCastMembers');
maxCastMembers.value = config.MaxCastMembers;
@@ -120,9 +132,11 @@
config.IncludeAdult = document.querySelector('#includeAdult').checked;
config.ExcludeTagsSeries = document.querySelector('#excludeTagsSeries').checked;
config.ExcludeTagsMovies = document.querySelector('#excludeTagsMovies').checked;
+ config.ImportSeasonName = document.querySelector('#importSeasonName').checked;
config.MaxCastMembers = document.querySelector('#maxCastMembers').value;
config.PosterSize = document.querySelector('#selectPosterSize').value;
config.BackdropSize = document.querySelector('#selectBackdropSize').value;
+ config.LogoSize = document.querySelector('#selectLogoSize').value;
config.ProfileSize = document.querySelector('#selectProfileSize').value;
config.StillSize = document.querySelector('#selectStillSize').value;
ApiClient.updatePluginConfiguration(PluginConfig.pluginId, config).then(Dashboard.processPluginConfigurationUpdateResult);
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieImageProvider.cs
index f71f7bd10..16f0089f8 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieImageProvider.cs
@@ -44,7 +44,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
return new List<ImageType>
{
ImageType.Primary,
- ImageType.Backdrop
+ ImageType.Backdrop,
+ ImageType.Logo
};
}
@@ -85,10 +86,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
var posters = movie.Images.Posters;
var backdrops = movie.Images.Backdrops;
- var remoteImages = new List<RemoteImageInfo>(posters.Count + backdrops.Count);
+ var logos = movie.Images.Logos;
+ var remoteImages = new List<RemoteImageInfo>(posters.Count + backdrops.Count + logos.Count);
_tmdbClientManager.ConvertPostersToRemoteImageInfo(posters, language, remoteImages);
_tmdbClientManager.ConvertBackdropsToRemoteImageInfo(backdrops, language, remoteImages);
+ _tmdbClientManager.ConvertLogosToRemoteImageInfo(logos, language, remoteImages);
return remoteImages;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs
index e4a56fde9..f14f31858 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs
@@ -312,7 +312,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
var trailers = new List<MediaUrl>();
for (var i = 0; i < movieResult.Videos.Results.Count; i++)
{
- var video = movieResult.Videos.Results[0];
+ var video = movieResult.Videos.Results[i];
if (!TmdbUtils.IsTrailerType(video))
{
continue;
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs
index 27c52a5a2..64ed3f408 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs
@@ -59,6 +59,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
Overview = seasonResult.Overview
};
+ if (Plugin.Instance.Configuration.ImportSeasonName)
+ {
+ result.Item.Name = seasonResult.Name;
+ }
+
if (!string.IsNullOrEmpty(seasonResult.ExternalIds?.TvdbId))
{
result.Item.SetProviderId(MetadataProvider.Tvdb, seasonResult.ExternalIds.TvdbId);
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs
index 5ef3736c4..130d6ce44 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs
@@ -42,7 +42,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
return new List<ImageType>
{
ImageType.Primary,
- ImageType.Backdrop
+ ImageType.Backdrop,
+ ImageType.Logo
};
}
@@ -69,10 +70,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
var posters = series.Images.Posters;
var backdrops = series.Images.Backdrops;
- var remoteImages = new List<RemoteImageInfo>(posters.Count + backdrops.Count);
+ var logos = series.Images.Logos;
+ var remoteImages = new List<RemoteImageInfo>(posters.Count + backdrops.Count + logos.Count);
_tmdbClientManager.ConvertPostersToRemoteImageInfo(posters, language, remoteImages);
_tmdbClientManager.ConvertBackdropsToRemoteImageInfo(backdrops, language, remoteImages);
+ _tmdbClientManager.ConvertLogosToRemoteImageInfo(logos, language, remoteImages);
return remoteImages;
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
index 28d6f4d0c..d78652834 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs
@@ -544,6 +544,17 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
}
/// <summary>
+ /// Converts logo <see cref="ImageData"/>s into <see cref="RemoteImageInfo"/>s.
+ /// </summary>
+ /// <param name="images">The input images.</param>
+ /// <param name="requestLanguage">The requested language.</param>
+ /// <param name="results">The collection to add the remote images into.</param>
+ public void ConvertLogosToRemoteImageInfo(List<ImageData> images, string requestLanguage, List<RemoteImageInfo> results)
+ {
+ ConvertToRemoteImageInfo(images, Plugin.Instance.Configuration.LogoSize, ImageType.Logo, requestLanguage, results);
+ }
+
+ /// <summary>
/// Converts profile <see cref="ImageData"/>s into <see cref="RemoteImageInfo"/>s.
/// </summary>
/// <param name="images">The input images.</param>
@@ -622,6 +633,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb
pluginConfig.BackdropSize = imageConfig.BackdropSizes[^1];
}
+ if (!imageConfig.LogoSizes.Contains(pluginConfig.LogoSize))
+ {
+ pluginConfig.LogoSize = imageConfig.LogoSizes[^1];
+ }
+
if (!imageConfig.ProfileSizes.Contains(pluginConfig.ProfileSize))
{
pluginConfig.ProfileSize = imageConfig.ProfileSizes[^1];
diff --git a/MediaBrowser.Providers/Studios/StudioMetadataService.cs b/MediaBrowser.Providers/Studios/StudioMetadataService.cs
index 091b33ce0..df938325f 100644
--- a/MediaBrowser.Providers/Studios/StudioMetadataService.cs
+++ b/MediaBrowser.Providers/Studios/StudioMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.Studios
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<Studio> source, MetadataResult<Studio> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
index 34019e582..d0e229b23 100644
--- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -248,8 +248,11 @@ namespace MediaBrowser.Providers.Subtitles
var fileOptions = AsyncFile.WriteOptions;
fileOptions.Mode = FileMode.CreateNew;
fileOptions.PreallocationSize = stream.Length;
- using var fs = new FileStream(savePath, fileOptions);
- await stream.CopyToAsync(fs).ConfigureAwait(false);
+ var fs = new FileStream(savePath, fileOptions);
+ await using (fs.ConfigureAwait(false))
+ {
+ await stream.CopyToAsync(fs).ConfigureAwait(false);
+ }
return;
}
diff --git a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
index 08cb6ced9..d8855ec93 100644
--- a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
+++ b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs
@@ -70,7 +70,7 @@ namespace MediaBrowser.Providers.TV
/// <inheritdoc />
protected override void MergeData(MetadataResult<Episode> source, MetadataResult<Episode> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
index 1f06cbdb2..54dcee41e 100644
--- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
@@ -87,12 +87,6 @@ namespace MediaBrowser.Providers.TV
return updateType;
}
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<Season> source, MetadataResult<Season> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
-
private ItemUpdateType SaveIsVirtualItem(Season item, IList<BaseItem> episodes)
{
var isVirtualItem = item.LocationType == LocationType.Virtual && (episodes.Count == 0 || episodes.All(i => i.LocationType == LocationType.Virtual));
diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
index 770dc3e00..f49492f33 100644
--- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
@@ -63,7 +63,7 @@ namespace MediaBrowser.Providers.TV
/// <inheritdoc />
protected override void MergeData(MetadataResult<Series> source, MetadataResult<Series> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
{
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
+ base.MergeData(source, target, lockedFields, replaceData, mergeMetadataSettings);
var sourceItem = source.Item;
var targetItem = target.Item;
diff --git a/MediaBrowser.Providers/Videos/VideoMetadataService.cs b/MediaBrowser.Providers/Videos/VideoMetadataService.cs
index 31c7eaac4..caa6d6e1f 100644
--- a/MediaBrowser.Providers/Videos/VideoMetadataService.cs
+++ b/MediaBrowser.Providers/Videos/VideoMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -26,11 +25,5 @@ namespace MediaBrowser.Providers.Videos
/// <inheritdoc />
// Make sure the type-specific services get picked first
public override int Order => 10;
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<Video> source, MetadataResult<Video> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.Providers/Years/YearMetadataService.cs b/MediaBrowser.Providers/Years/YearMetadataService.cs
index 6151d12e9..689e8661b 100644
--- a/MediaBrowser.Providers/Years/YearMetadataService.cs
+++ b/MediaBrowser.Providers/Years/YearMetadataService.cs
@@ -4,7 +4,6 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Providers.Manager;
using Microsoft.Extensions.Logging;
@@ -22,11 +21,5 @@ namespace MediaBrowser.Providers.Years
: base(serverConfigurationManager, logger, providerManager, fileSystem, libraryManager)
{
}
-
- /// <inheritdoc />
- protected override void MergeData(MetadataResult<Year> source, MetadataResult<Year> target, MetadataField[] lockedFields, bool replaceData, bool mergeMetadataSettings)
- {
- ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
- }
}
}
diff --git a/MediaBrowser.XbmcMetadata/EntryPoint.cs b/MediaBrowser.XbmcMetadata/EntryPoint.cs
index 935ff5f59..a6216ef30 100644
--- a/MediaBrowser.XbmcMetadata/EntryPoint.cs
+++ b/MediaBrowser.XbmcMetadata/EntryPoint.cs
@@ -47,7 +47,7 @@ namespace MediaBrowser.XbmcMetadata
{
if (!string.IsNullOrWhiteSpace(_config.GetNfoConfiguration().UserId))
{
- SaveMetadataForItem(e.Item, ItemUpdateType.MetadataDownload);
+ _ = SaveMetadataForItemAsync(e.Item, ItemUpdateType.MetadataDownload);
}
}
}
@@ -58,7 +58,7 @@ namespace MediaBrowser.XbmcMetadata
_userDataManager.UserDataSaved -= OnUserDataSaved;
}
- private void SaveMetadataForItem(BaseItem item, ItemUpdateType updateReason)
+ private async Task SaveMetadataForItemAsync(BaseItem item, ItemUpdateType updateReason)
{
if (!item.IsFileProtocol || !item.SupportsLocalMetadata)
{
@@ -67,7 +67,7 @@ namespace MediaBrowser.XbmcMetadata
try
{
- _providerManager.SaveMetadata(item, updateReason, new[] { BaseNfoSaver.SaverName });
+ await _providerManager.SaveMetadataAsync(item, updateReason, new[] { BaseNfoSaver.SaverName }).ConfigureAwait(false);
}
catch (Exception ex)
{
diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
index ad06688fb..4d0ba487b 100644
--- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
+++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj
@@ -22,6 +22,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
index 007101868..09ff84044 100644
--- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
+++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs
@@ -778,7 +778,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
case "thumb":
{
- FetchThumbNode(reader, itemResult);
+ FetchThumbNode(reader, itemResult, "thumb");
break;
}
@@ -796,7 +796,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
break;
}
- FetchThumbNode(subtree, itemResult);
+ FetchThumbNode(subtree, itemResult, "fanart");
break;
}
@@ -819,17 +819,22 @@ namespace MediaBrowser.XbmcMetadata.Parsers
}
}
- private void FetchThumbNode(XmlReader reader, MetadataResult<T> itemResult)
+ private void FetchThumbNode(XmlReader reader, MetadataResult<T> itemResult, string parentNode)
{
var artType = reader.GetAttribute("aspect");
var val = reader.ReadElementContentAsString();
// artType is null if the thumb node is a child of the fanart tag
// -> set image type to fanart
- if (string.IsNullOrWhiteSpace(artType))
+ if (string.IsNullOrWhiteSpace(artType) && parentNode.Equals("fanart", StringComparison.Ordinal))
{
artType = "fanart";
}
+ else if (string.IsNullOrWhiteSpace(artType))
+ {
+ // Sonarr writes thumb tags for posters without aspect property
+ artType = "poster";
+ }
// skip:
// - empty uri
diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
index d09981304..39bd87e96 100644
--- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
+++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs
@@ -8,6 +8,7 @@ using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
+using System.Threading.Tasks;
using System.Xml;
using Jellyfin.Extensions;
using MediaBrowser.Common.Extensions;
@@ -180,7 +181,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
}
/// <inheritdoc />
- public void Save(BaseItem item, CancellationToken cancellationToken)
+ public async Task SaveAsync(BaseItem item, CancellationToken cancellationToken)
{
var path = GetSavePath(item);
@@ -192,11 +193,11 @@ namespace MediaBrowser.XbmcMetadata.Savers
cancellationToken.ThrowIfCancellationRequested();
- SaveToFile(memoryStream, path);
+ await SaveToFileAsync(memoryStream, path).ConfigureAwait(false);
}
}
- private void SaveToFile(Stream stream, string path)
+ private async Task SaveToFileAsync(Stream stream, string path)
{
var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path));
Directory.CreateDirectory(directory);
@@ -209,12 +210,14 @@ namespace MediaBrowser.XbmcMetadata.Savers
Mode = FileMode.Create,
Access = FileAccess.Write,
Share = FileShare.None,
- PreallocationSize = stream.Length
+ PreallocationSize = stream.Length,
+ Options = FileOptions.Asynchronous
};
- using (var filestream = new FileStream(path, fileStreamOptions))
+ var filestream = new FileStream(path, fileStreamOptions);
+ await using (filestream.ConfigureAwait(false))
{
- stream.CopyTo(filestream);
+ await stream.CopyToAsync(filestream).ConfigureAwait(false);
}
if (ConfigurationManager.Configuration.SaveMetadataHidden)
diff --git a/RSSDP/DeviceAvailableEventArgs.cs b/RSSDP/DeviceAvailableEventArgs.cs
index 04b14c4dc..9d477ea9f 100644
--- a/RSSDP/DeviceAvailableEventArgs.cs
+++ b/RSSDP/DeviceAvailableEventArgs.cs
@@ -4,7 +4,7 @@ using System.Net;
namespace Rssdp
{
/// <summary>
- /// Event arguments for the <see cref="Infrastructure.SsdpDeviceLocatorBase.DeviceAvailable"/> event.
+ /// Event arguments for the <see cref="Infrastructure.SsdpDeviceLocator.DeviceAvailable"/> event.
/// </summary>
public sealed class DeviceAvailableEventArgs : EventArgs
{
diff --git a/RSSDP/DeviceUnavailableEventArgs.cs b/RSSDP/DeviceUnavailableEventArgs.cs
index 94248f39f..ca2515202 100644
--- a/RSSDP/DeviceUnavailableEventArgs.cs
+++ b/RSSDP/DeviceUnavailableEventArgs.cs
@@ -3,7 +3,7 @@ using System;
namespace Rssdp
{
/// <summary>
- /// Event arguments for the <see cref="Infrastructure.SsdpDeviceLocatorBase.DeviceUnavailable"/> event.
+ /// Event arguments for the <see cref="Infrastructure.SsdpDeviceLocator.DeviceUnavailable"/> event.
/// </summary>
public sealed class DeviceUnavailableEventArgs : EventArgs
{
diff --git a/RSSDP/ISsdpCommunicationsServer.cs b/RSSDP/ISsdpCommunicationsServer.cs
index aa35811ef..3cbc991d6 100644
--- a/RSSDP/ISsdpCommunicationsServer.cs
+++ b/RSSDP/ISsdpCommunicationsServer.cs
@@ -42,10 +42,10 @@ namespace Rssdp.Infrastructure
Task SendMulticastMessage(string message, int sendCount, IPAddress fromLocalIpAddress, CancellationToken cancellationToken);
/// <summary>
- /// Gets or sets a boolean value indicating whether or not this instance is shared amongst multiple <see cref="SsdpDeviceLocatorBase"/> and/or <see cref="ISsdpDevicePublisher"/> instances.
+ /// Gets or sets a boolean value indicating whether or not this instance is shared amongst multiple <see cref="SsdpDeviceLocator"/> and/or <see cref="ISsdpDevicePublisher"/> instances.
/// </summary>
/// <remarks>
- /// <para>If true, disposing an instance of a <see cref="SsdpDeviceLocatorBase"/>or a <see cref="ISsdpDevicePublisher"/> will not dispose this comms server instance. The calling code is responsible for managing the lifetime of the server.</para>
+ /// <para>If true, disposing an instance of a <see cref="SsdpDeviceLocator"/>or a <see cref="ISsdpDevicePublisher"/> will not dispose this comms server instance. The calling code is responsible for managing the lifetime of the server.</para>
/// </remarks>
bool IsShared { get; set; }
}
diff --git a/RSSDP/RequestReceivedEventArgs.cs b/RSSDP/RequestReceivedEventArgs.cs
index 025c4d2e0..5cf74bd75 100644
--- a/RSSDP/RequestReceivedEventArgs.cs
+++ b/RSSDP/RequestReceivedEventArgs.cs
@@ -34,7 +34,7 @@ namespace Rssdp.Infrastructure
}
/// <summary>
- /// The <see cref="UdpEndPoint"/> the request came from.
+ /// The <see cref="IPEndPoint"/> the request came from.
/// </summary>
public IPEndPoint ReceivedFrom
{
diff --git a/RSSDP/ResponseReceivedEventArgs.cs b/RSSDP/ResponseReceivedEventArgs.cs
index 708113da1..93262a460 100644
--- a/RSSDP/ResponseReceivedEventArgs.cs
+++ b/RSSDP/ResponseReceivedEventArgs.cs
@@ -33,7 +33,7 @@ namespace Rssdp.Infrastructure
}
/// <summary>
- /// The <see cref="UdpEndPoint"/> the response came from.
+ /// The <see cref="IPEndPoint"/> the response came from.
/// </summary>
public IPEndPoint ReceivedFrom
{
diff --git a/RSSDP/SsdpCommunicationsServer.cs b/RSSDP/SsdpCommunicationsServer.cs
index 58dabc628..a66b70ac1 100644
--- a/RSSDP/SsdpCommunicationsServer.cs
+++ b/RSSDP/SsdpCommunicationsServer.cs
@@ -295,10 +295,10 @@ namespace Rssdp.Infrastructure
}
/// <summary>
- /// Gets or sets a boolean value indicating whether or not this instance is shared amongst multiple <see cref="SsdpDeviceLocatorBase"/> and/or <see cref="ISsdpDevicePublisher"/> instances.
+ /// Gets or sets a boolean value indicating whether or not this instance is shared amongst multiple <see cref="SsdpDeviceLocator"/> and/or <see cref="ISsdpDevicePublisher"/> instances.
/// </summary>
/// <remarks>
- /// <para>If true, disposing an instance of a <see cref="SsdpDeviceLocatorBase"/>or a <see cref="ISsdpDevicePublisher"/> will not dispose this comms server instance. The calling code is responsible for managing the lifetime of the server.</para>
+ /// <para>If true, disposing an instance of a <see cref="SsdpDeviceLocator"/>or a <see cref="ISsdpDevicePublisher"/> will not dispose this comms server instance. The calling code is responsible for managing the lifetime of the server.</para>
/// </remarks>
public bool IsShared
{
diff --git a/RSSDP/SsdpDeviceLocator.cs b/RSSDP/SsdpDeviceLocator.cs
index 3a52b2a3e..681ef0a5c 100644
--- a/RSSDP/SsdpDeviceLocator.cs
+++ b/RSSDP/SsdpDeviceLocator.cs
@@ -42,7 +42,7 @@ namespace Rssdp.Infrastructure
/// Raised for when
/// <list type="bullet">
/// <item>An 'alive' notification is received that a device, regardless of whether or not that device is not already in the cache or has previously raised this event.</item>
- /// <item>For each item found during a device <see cref="SearchAsync()"/> (cached or not), allowing clients to respond to found devices before the entire search is complete.</item>
+ /// <item>For each item found during a device <see cref="SearchAsync(System.Threading.CancellationToken)"/> (cached or not), allowing clients to respond to found devices before the entire search is complete.</item>
/// <item>Only if the notification type matches the <see cref="NotificationFilter"/> property. By default the filter is null, meaning all notifications raise events (regardless of ant </item>
/// </list>
/// <para>This event may be raised from a background thread, if interacting with UI or other objects with specific thread affinity invoking to the relevant thread is required.</para>
diff --git a/jellyfin.ruleset b/jellyfin.ruleset
index dea1a748b..cc7c54b97 100644
--- a/jellyfin.ruleset
+++ b/jellyfin.ruleset
@@ -136,4 +136,9 @@
<!-- disable warning CA2234: Pass System.Uri objects instead of strings -->
<Rule Id="CA2234" Action="None" />
</Rules>
+
+ <Rules AnalyzerId="Microsoft.CodeAnalysis.BannedApiAnalyzers" RuleNamespace="Microsoft.Design">
+ <!-- error on RS0030: Do not used banned APIs -->
+ <Rule Id="RS0030" Action="Error" />
+ </Rules>
</RuleSet>
diff --git a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
index 90d2a0da6..37baff5ae 100644
--- a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
+++ b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj
@@ -29,6 +29,10 @@
<!-- Code Analyzers-->
<ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/src/Jellyfin.MediaEncoding.Hls/Cache/CacheDecorator.cs b/src/Jellyfin.MediaEncoding.Hls/Cache/CacheDecorator.cs
new file mode 100644
index 000000000..09816c960
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Hls/Cache/CacheDecorator.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Text.Json;
+using Jellyfin.Extensions.Json;
+using Jellyfin.MediaEncoding.Hls.Extractors;
+using Jellyfin.MediaEncoding.Keyframes;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
+using Microsoft.Extensions.Logging;
+
+namespace Jellyfin.MediaEncoding.Hls.Cache;
+
+/// <inheritdoc />
+public class CacheDecorator : IKeyframeExtractor
+{
+ private readonly IKeyframeExtractor _keyframeExtractor;
+ private readonly ILogger<CacheDecorator> _logger;
+ private readonly string _keyframeExtractorName;
+ private static readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
+ private readonly string _keyframeCachePath;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CacheDecorator"/> class.
+ /// </summary>
+ /// <param name="applicationPaths">An instance of the <see cref="IApplicationPaths"/> interface.</param>
+ /// <param name="keyframeExtractor">An instance of the <see cref="IKeyframeExtractor"/> interface.</param>
+ /// <param name="logger">An instance of the <see cref="ILogger{CacheDecorator}"/> interface.</param>
+ public CacheDecorator(IApplicationPaths applicationPaths, IKeyframeExtractor keyframeExtractor, ILogger<CacheDecorator> logger)
+ {
+ ArgumentNullException.ThrowIfNull(applicationPaths);
+ ArgumentNullException.ThrowIfNull(keyframeExtractor);
+
+ _keyframeExtractor = keyframeExtractor;
+ _logger = logger;
+ _keyframeExtractorName = keyframeExtractor.GetType().Name;
+ // TODO make the dir configurable
+ _keyframeCachePath = Path.Combine(applicationPaths.DataPath, "keyframes");
+ }
+
+ /// <inheritdoc />
+ public bool IsMetadataBased => _keyframeExtractor.IsMetadataBased;
+
+ /// <inheritdoc />
+ public bool TryExtractKeyframes(string filePath, [NotNullWhen(true)] out KeyframeData? keyframeData)
+ {
+ keyframeData = null;
+ var cachePath = GetCachePath(_keyframeCachePath, filePath);
+ if (TryReadFromCache(cachePath, out var cachedResult))
+ {
+ keyframeData = cachedResult;
+ return true;
+ }
+
+ if (!_keyframeExtractor.TryExtractKeyframes(filePath, out var result))
+ {
+ _logger.LogDebug("Failed to extract keyframes using {ExtractorName}", _keyframeExtractorName);
+ return false;
+ }
+
+ _logger.LogDebug("Successfully extracted keyframes using {ExtractorName}", _keyframeExtractorName);
+ keyframeData = result;
+ SaveToCache(cachePath, keyframeData);
+ return true;
+ }
+
+ private static void SaveToCache(string cachePath, KeyframeData keyframeData)
+ {
+ var json = JsonSerializer.Serialize(keyframeData, _jsonOptions);
+ Directory.CreateDirectory(Path.GetDirectoryName(cachePath) ?? throw new ArgumentException($"Provided path ({cachePath}) is not valid.", nameof(cachePath)));
+ File.WriteAllText(cachePath, json);
+ }
+
+ private static string GetCachePath(string keyframeCachePath, string filePath)
+ {
+ var lastWriteTimeUtc = File.GetLastWriteTimeUtc(filePath);
+ ReadOnlySpan<char> filename = (filePath + "_" + lastWriteTimeUtc.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5() + ".json";
+ var prefix = filename[..1];
+
+ return Path.Join(keyframeCachePath, prefix, filename);
+ }
+
+ private static bool TryReadFromCache(string cachePath, [NotNullWhen(true)] out KeyframeData? cachedResult)
+ {
+ if (File.Exists(cachePath))
+ {
+ var bytes = File.ReadAllBytes(cachePath);
+ cachedResult = JsonSerializer.Deserialize<KeyframeData>(bytes, _jsonOptions);
+ return cachedResult != null;
+ }
+
+ cachedResult = null;
+ return false;
+ }
+}
diff --git a/src/Jellyfin.MediaEncoding.Hls/Extensions/MediaEncodingHlsServiceCollectionExtensions.cs b/src/Jellyfin.MediaEncoding.Hls/Extensions/MediaEncodingHlsServiceCollectionExtensions.cs
new file mode 100644
index 000000000..8ed4edcea
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Hls/Extensions/MediaEncodingHlsServiceCollectionExtensions.cs
@@ -0,0 +1,36 @@
+using System;
+using Jellyfin.MediaEncoding.Hls.Cache;
+using Jellyfin.MediaEncoding.Hls.Extractors;
+using Jellyfin.MediaEncoding.Hls.Playlist;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Jellyfin.MediaEncoding.Hls.Extensions;
+
+/// <summary>
+/// Extensions for the <see cref="IServiceCollection"/> interface.
+/// </summary>
+public static class MediaEncodingHlsServiceCollectionExtensions
+{
+ /// <summary>
+ /// Adds the hls playlist generators to the <see cref="IServiceCollection"/>.
+ /// </summary>
+ /// <param name="serviceCollection">An instance of the <see cref="IServiceCollection"/> interface.</param>
+ /// <returns>The updated service collection.</returns>
+ public static IServiceCollection AddHlsPlaylistGenerator(this IServiceCollection serviceCollection)
+ {
+ serviceCollection.AddSingletonWithDecorator(typeof(FfProbeKeyframeExtractor));
+ serviceCollection.AddSingletonWithDecorator(typeof(MatroskaKeyframeExtractor));
+ serviceCollection.AddSingleton<IDynamicHlsPlaylistGenerator, DynamicHlsPlaylistGenerator>();
+ return serviceCollection;
+ }
+
+ private static void AddSingletonWithDecorator(this IServiceCollection serviceCollection, Type type)
+ {
+ serviceCollection.AddSingleton<IKeyframeExtractor>(serviceProvider =>
+ {
+ var extractor = ActivatorUtilities.CreateInstance(serviceProvider, type);
+ var decorator = ActivatorUtilities.CreateInstance<CacheDecorator>(serviceProvider, extractor);
+ return decorator;
+ });
+ }
+}
diff --git a/src/Jellyfin.MediaEncoding.Hls/Extractors/FfProbeKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Hls/Extractors/FfProbeKeyframeExtractor.cs
new file mode 100644
index 000000000..f86599a23
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Hls/Extractors/FfProbeKeyframeExtractor.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using Emby.Naming.Common;
+using Jellyfin.Extensions;
+using Jellyfin.MediaEncoding.Keyframes;
+using MediaBrowser.Controller.MediaEncoding;
+using Microsoft.Extensions.Logging;
+using Extractor = Jellyfin.MediaEncoding.Keyframes.FfProbe.FfProbeKeyframeExtractor;
+
+namespace Jellyfin.MediaEncoding.Hls.Extractors;
+
+/// <inheritdoc />
+public class FfProbeKeyframeExtractor : IKeyframeExtractor
+{
+ private readonly IMediaEncoder _mediaEncoder;
+ private readonly NamingOptions _namingOptions;
+ private readonly ILogger<FfProbeKeyframeExtractor> _logger;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="FfProbeKeyframeExtractor"/> class.
+ /// </summary>
+ /// <param name="mediaEncoder">An instance of the <see cref="IMediaEncoder"/> interface.</param>
+ /// <param name="namingOptions">An instance of <see cref="NamingOptions"/>.</param>
+ /// <param name="logger">An instance of the <see cref="ILogger{FfprobeKeyframeExtractor}"/> interface.</param>
+ public FfProbeKeyframeExtractor(IMediaEncoder mediaEncoder, NamingOptions namingOptions, ILogger<FfProbeKeyframeExtractor> logger)
+ {
+ _mediaEncoder = mediaEncoder;
+ _namingOptions = namingOptions;
+ _logger = logger;
+ }
+
+ /// <inheritdoc />
+ public bool IsMetadataBased => false;
+
+ /// <inheritdoc />
+ public bool TryExtractKeyframes(string filePath, [NotNullWhen(true)] out KeyframeData? keyframeData)
+ {
+ if (!_namingOptions.VideoFileExtensions.Contains(Path.GetExtension(filePath.AsSpan()), StringComparison.OrdinalIgnoreCase))
+ {
+ keyframeData = null;
+ return false;
+ }
+
+ try
+ {
+ keyframeData = Extractor.GetKeyframeData(_mediaEncoder.ProbePath, filePath);
+ return keyframeData.KeyframeTicks.Count > 0;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Extracting keyframes from {FilePath} using ffprobe failed", filePath);
+ }
+
+ keyframeData = null;
+ return false;
+ }
+}
diff --git a/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs
new file mode 100644
index 000000000..497210f41
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using Jellyfin.MediaEncoding.Keyframes;
+
+namespace Jellyfin.MediaEncoding.Hls.Extractors;
+
+/// <summary>
+/// Keyframe extractor.
+/// </summary>
+public interface IKeyframeExtractor
+{
+ /// <summary>
+ /// Gets a value indicating whether the extractor is based on container metadata.
+ /// </summary>
+ bool IsMetadataBased { get; }
+
+ /// <summary>
+ /// Attempt to extract keyframes.
+ /// </summary>
+ /// <param name="filePath">The path to the file.</param>
+ /// <param name="keyframeData">The keyframes.</param>
+ /// <returns>A value indicating whether the keyframe extraction was successful.</returns>
+ bool TryExtractKeyframes(string filePath, [NotNullWhen(true)] out KeyframeData? keyframeData);
+}
diff --git a/src/Jellyfin.MediaEncoding.Hls/Extractors/MatroskaKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Hls/Extractors/MatroskaKeyframeExtractor.cs
new file mode 100644
index 000000000..4bc537c0e
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Hls/Extractors/MatroskaKeyframeExtractor.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using Jellyfin.MediaEncoding.Keyframes;
+using Microsoft.Extensions.Logging;
+using Extractor = Jellyfin.MediaEncoding.Keyframes.Matroska.MatroskaKeyframeExtractor;
+
+namespace Jellyfin.MediaEncoding.Hls.Extractors;
+
+/// <inheritdoc />
+public class MatroskaKeyframeExtractor : IKeyframeExtractor
+{
+ private readonly ILogger<MatroskaKeyframeExtractor> _logger;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MatroskaKeyframeExtractor"/> class.
+ /// </summary>
+ /// <param name="logger">An instance of the <see cref="ILogger{MatroskaKeyframeExtractor}"/> interface.</param>
+ public MatroskaKeyframeExtractor(ILogger<MatroskaKeyframeExtractor> logger)
+ {
+ _logger = logger;
+ }
+
+ /// <inheritdoc />
+ public bool IsMetadataBased => true;
+
+ /// <inheritdoc />
+ public bool TryExtractKeyframes(string filePath, [NotNullWhen(true)] out KeyframeData? keyframeData)
+ {
+ if (!filePath.AsSpan().EndsWith(".mkv", StringComparison.OrdinalIgnoreCase))
+ {
+ keyframeData = null;
+ return false;
+ }
+
+ try
+ {
+ keyframeData = Extractor.GetKeyframeData(filePath);
+ return keyframeData.KeyframeTicks.Count > 0;
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Extracting keyframes from {FilePath} using matroska metadata failed", filePath);
+ }
+
+ keyframeData = null;
+ return false;
+ }
+}
diff --git a/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj b/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj
new file mode 100644
index 000000000..56f973a21
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Hls/Jellyfin.MediaEncoding.Hls.csproj
@@ -0,0 +1,35 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net6.0</TargetFramework>
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
+ </PropertyGroup>
+
+ <!-- Code Analyzers-->
+ <ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="../../MediaBrowser.Common/MediaBrowser.Common.csproj" />
+ <ProjectReference Include="../../MediaBrowser.Controller/MediaBrowser.Controller.csproj" />
+ <ProjectReference Include="../Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
+ <_Parameter1>Jellyfin.MediaEncoding.Hls.Tests</_Parameter1>
+ </AssemblyAttribute>
+ </ItemGroup>
+
+</Project>
diff --git a/src/Jellyfin.MediaEncoding.Hls/Playlist/CreateMainPlaylistRequest.cs b/src/Jellyfin.MediaEncoding.Hls/Playlist/CreateMainPlaylistRequest.cs
new file mode 100644
index 000000000..ac28ca26a
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Hls/Playlist/CreateMainPlaylistRequest.cs
@@ -0,0 +1,56 @@
+namespace Jellyfin.MediaEncoding.Hls.Playlist;
+
+/// <summary>
+/// Request class for the <see cref="IDynamicHlsPlaylistGenerator.CreateMainPlaylist(CreateMainPlaylistRequest)"/> method.
+/// </summary>
+public class CreateMainPlaylistRequest
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CreateMainPlaylistRequest"/> class.
+ /// </summary>
+ /// <param name="filePath">The absolute file path to the file.</param>
+ /// <param name="desiredSegmentLengthMs">The desired segment length in milliseconds.</param>
+ /// <param name="totalRuntimeTicks">The total duration of the file in ticks.</param>
+ /// <param name="segmentContainer">The desired segment container eg. "ts".</param>
+ /// <param name="endpointPrefix">The URI prefix for the relative URL in the playlist.</param>
+ /// <param name="queryString">The desired query string to append (must start with ?).</param>
+ public CreateMainPlaylistRequest(string filePath, int desiredSegmentLengthMs, long totalRuntimeTicks, string segmentContainer, string endpointPrefix, string queryString)
+ {
+ FilePath = filePath;
+ DesiredSegmentLengthMs = desiredSegmentLengthMs;
+ TotalRuntimeTicks = totalRuntimeTicks;
+ SegmentContainer = segmentContainer;
+ EndpointPrefix = endpointPrefix;
+ QueryString = queryString;
+ }
+
+ /// <summary>
+ /// Gets the file path.
+ /// </summary>
+ public string FilePath { get; }
+
+ /// <summary>
+ /// Gets the desired segment length in milliseconds.
+ /// </summary>
+ public int DesiredSegmentLengthMs { get; }
+
+ /// <summary>
+ /// Gets the total runtime in ticks.
+ /// </summary>
+ public long TotalRuntimeTicks { get; }
+
+ /// <summary>
+ /// Gets the segment container.
+ /// </summary>
+ public string SegmentContainer { get; }
+
+ /// <summary>
+ /// Gets the endpoint prefix for the URL.
+ /// </summary>
+ public string EndpointPrefix { get; }
+
+ /// <summary>
+ /// Gets the query string.
+ /// </summary>
+ public string QueryString { get; }
+}
diff --git a/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs b/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs
new file mode 100644
index 000000000..3382ba251
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Hls/Playlist/DynamicHlsPlaylistGenerator.cs
@@ -0,0 +1,207 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Jellyfin.MediaEncoding.Hls.Extractors;
+using Jellyfin.MediaEncoding.Keyframes;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.MediaEncoding;
+
+namespace Jellyfin.MediaEncoding.Hls.Playlist;
+
+/// <inheritdoc />
+public class DynamicHlsPlaylistGenerator : IDynamicHlsPlaylistGenerator
+{
+ private readonly IServerConfigurationManager _serverConfigurationManager;
+ private readonly IKeyframeExtractor[] _extractors;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DynamicHlsPlaylistGenerator"/> class.
+ /// </summary>
+ /// <param name="serverConfigurationManager">An instance of the see <see cref="IServerConfigurationManager"/> interface.</param>
+ /// <param name="extractors">An instance of <see cref="IEnumerable{IKeyframeExtractor}"/>.</param>
+ public DynamicHlsPlaylistGenerator(IServerConfigurationManager serverConfigurationManager, IEnumerable<IKeyframeExtractor> extractors)
+ {
+ _serverConfigurationManager = serverConfigurationManager;
+ _extractors = extractors.Where(e => e.IsMetadataBased).ToArray();
+ }
+
+ /// <inheritdoc />
+ public string CreateMainPlaylist(CreateMainPlaylistRequest request)
+ {
+ IReadOnlyList<double> segments;
+ if (TryExtractKeyframes(request.FilePath, out var keyframeData))
+ {
+ segments = ComputeSegments(keyframeData, request.DesiredSegmentLengthMs);
+ }
+ else
+ {
+ segments = ComputeEqualLengthSegments(request.DesiredSegmentLengthMs, request.TotalRuntimeTicks);
+ }
+
+ var segmentExtension = EncodingHelper.GetSegmentFileExtension(request.SegmentContainer);
+
+ // http://ffmpeg.org/ffmpeg-all.html#toc-hls-2
+ var isHlsInFmp4 = string.Equals(segmentExtension, ".mp4", StringComparison.OrdinalIgnoreCase);
+ var hlsVersion = isHlsInFmp4 ? "7" : "3";
+
+ var builder = new StringBuilder(128);
+
+ builder.AppendLine("#EXTM3U")
+ .AppendLine("#EXT-X-PLAYLIST-TYPE:VOD")
+ .Append("#EXT-X-VERSION:")
+ .Append(hlsVersion)
+ .AppendLine()
+ .Append("#EXT-X-TARGETDURATION:")
+ .Append(Math.Ceiling(segments.Count > 0 ? segments.Max() : request.DesiredSegmentLengthMs))
+ .AppendLine()
+ .AppendLine("#EXT-X-MEDIA-SEQUENCE:0");
+
+ var index = 0;
+
+ if (isHlsInFmp4)
+ {
+ // Init file that only includes fMP4 headers
+ builder.Append("#EXT-X-MAP:URI=\"")
+ .Append(request.EndpointPrefix)
+ .Append("-1")
+ .Append(segmentExtension)
+ .Append(request.QueryString)
+ .Append("&runtimeTicks=0")
+ .Append("&actualSegmentLengthTicks=0")
+ .Append('"')
+ .AppendLine();
+ }
+
+ long currentRuntimeInSeconds = 0;
+ foreach (var length in segments)
+ {
+ // Manually convert to ticks to avoid precision loss when converting double
+ var lengthTicks = Convert.ToInt64(length * TimeSpan.TicksPerSecond);
+ builder.Append("#EXTINF:")
+ .Append(length.ToString("0.000000", CultureInfo.InvariantCulture))
+ .AppendLine(", nodesc")
+ .Append(request.EndpointPrefix)
+ .Append(index++)
+ .Append(segmentExtension)
+ .Append(request.QueryString)
+ .Append("&runtimeTicks=")
+ .Append(currentRuntimeInSeconds)
+ .Append("&actualSegmentLengthTicks=")
+ .Append(lengthTicks)
+ .AppendLine();
+
+ currentRuntimeInSeconds += lengthTicks;
+ }
+
+ builder.AppendLine("#EXT-X-ENDLIST");
+
+ return builder.ToString();
+ }
+
+ private bool TryExtractKeyframes(string filePath, [NotNullWhen(true)] out KeyframeData? keyframeData)
+ {
+ keyframeData = null;
+ if (!IsExtractionAllowedForFile(filePath, _serverConfigurationManager.GetEncodingOptions().AllowOnDemandMetadataBasedKeyframeExtractionForExtensions))
+ {
+ return false;
+ }
+
+ var len = _extractors.Length;
+ for (var i = 0; i < len; i++)
+ {
+ var extractor = _extractors[i];
+ if (!extractor.TryExtractKeyframes(filePath, out var result))
+ {
+ continue;
+ }
+
+ keyframeData = result;
+ return true;
+ }
+
+ return false;
+ }
+
+ internal static bool IsExtractionAllowedForFile(ReadOnlySpan<char> filePath, string[] allowedExtensions)
+ {
+ var extension = Path.GetExtension(filePath);
+ if (extension.IsEmpty)
+ {
+ return false;
+ }
+
+ // Remove the leading dot
+ var extensionWithoutDot = extension[1..];
+ for (var i = 0; i < allowedExtensions.Length; i++)
+ {
+ var allowedExtension = allowedExtensions[i].AsSpan().TrimStart('.');
+ if (extensionWithoutDot.Equals(allowedExtension, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ internal static IReadOnlyList<double> ComputeSegments(KeyframeData keyframeData, int desiredSegmentLengthMs)
+ {
+ if (keyframeData.KeyframeTicks.Count > 0 && keyframeData.TotalDuration < keyframeData.KeyframeTicks[^1])
+ {
+ throw new ArgumentException("Invalid duration in keyframe data", nameof(keyframeData));
+ }
+
+ long lastKeyframe = 0;
+ var result = new List<double>();
+ // Scale the segment length to ticks to match the keyframes
+ var desiredSegmentLengthTicks = TimeSpan.FromMilliseconds(desiredSegmentLengthMs).Ticks;
+ var desiredCutTime = desiredSegmentLengthTicks;
+ for (var j = 0; j < keyframeData.KeyframeTicks.Count; j++)
+ {
+ var keyframe = keyframeData.KeyframeTicks[j];
+ if (keyframe >= desiredCutTime)
+ {
+ var currentSegmentLength = keyframe - lastKeyframe;
+ result.Add(TimeSpan.FromTicks(currentSegmentLength).TotalSeconds);
+ lastKeyframe = keyframe;
+ desiredCutTime += desiredSegmentLengthTicks;
+ }
+ }
+
+ result.Add(TimeSpan.FromTicks(keyframeData.TotalDuration - lastKeyframe).TotalSeconds);
+ return result;
+ }
+
+ internal static double[] ComputeEqualLengthSegments(int desiredSegmentLengthMs, long totalRuntimeTicks)
+ {
+ if (desiredSegmentLengthMs == 0 || totalRuntimeTicks == 0)
+ {
+ throw new InvalidOperationException($"Invalid segment length ({desiredSegmentLengthMs}) or runtime ticks ({totalRuntimeTicks})");
+ }
+
+ var desiredSegmentLength = TimeSpan.FromMilliseconds(desiredSegmentLengthMs);
+
+ var segmentLengthTicks = desiredSegmentLength.Ticks;
+ var wholeSegments = totalRuntimeTicks / segmentLengthTicks;
+ var remainingTicks = totalRuntimeTicks % segmentLengthTicks;
+
+ var segmentsLen = wholeSegments + (remainingTicks == 0 ? 0 : 1);
+ var segments = new double[segmentsLen];
+ for (int i = 0; i < wholeSegments; i++)
+ {
+ segments[i] = desiredSegmentLength.TotalSeconds;
+ }
+
+ if (remainingTicks != 0)
+ {
+ segments[^1] = TimeSpan.FromTicks(remainingTicks).TotalSeconds;
+ }
+
+ return segments;
+ }
+}
diff --git a/src/Jellyfin.MediaEncoding.Hls/Playlist/IDynamicHlsPlaylistGenerator.cs b/src/Jellyfin.MediaEncoding.Hls/Playlist/IDynamicHlsPlaylistGenerator.cs
new file mode 100644
index 000000000..2626cb2dd
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Hls/Playlist/IDynamicHlsPlaylistGenerator.cs
@@ -0,0 +1,14 @@
+namespace Jellyfin.MediaEncoding.Hls.Playlist;
+
+/// <summary>
+/// Generator for dynamic HLS playlists where the segment lengths aren't known in advance.
+/// </summary>
+public interface IDynamicHlsPlaylistGenerator
+{
+ /// <summary>
+ /// Creates the main playlist containing the main video or audio stream.
+ /// </summary>
+ /// <param name="request">An instance of the <see cref="CreateMainPlaylistRequest"/> class.</param>
+ /// <returns>The playlist as a formatted string.</returns>
+ string CreateMainPlaylist(CreateMainPlaylistRequest request);
+}
diff --git a/src/Jellyfin.MediaEncoding.Hls/ScheduledTasks/KeyframeExtractionScheduledTask.cs b/src/Jellyfin.MediaEncoding.Hls/ScheduledTasks/KeyframeExtractionScheduledTask.cs
new file mode 100644
index 000000000..03acc6911
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Hls/ScheduledTasks/KeyframeExtractionScheduledTask.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
+using Jellyfin.MediaEncoding.Hls.Extractors;
+using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Globalization;
+using MediaBrowser.Model.Tasks;
+
+namespace Jellyfin.MediaEncoding.Hls.ScheduledTasks;
+
+/// <inheritdoc />
+public class KeyframeExtractionScheduledTask : IScheduledTask
+{
+ private const int Pagesize = 1000;
+
+ private readonly ILocalizationManager _localizationManager;
+ private readonly ILibraryManager _libraryManager;
+ private readonly IKeyframeExtractor[] _keyframeExtractors;
+ private static readonly BaseItemKind[] _itemTypes = { BaseItemKind.Episode, BaseItemKind.Movie };
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="KeyframeExtractionScheduledTask"/> class.
+ /// </summary>
+ /// <param name="localizationManager">An instance of the <see cref="ILocalizationManager"/> interface.</param>
+ /// <param name="libraryManager">An instance of the <see cref="ILibraryManager"/> interface.</param>
+ /// <param name="keyframeExtractors">The keyframe extractors.</param>
+ public KeyframeExtractionScheduledTask(ILocalizationManager localizationManager, ILibraryManager libraryManager, IEnumerable<IKeyframeExtractor> keyframeExtractors)
+ {
+ _localizationManager = localizationManager;
+ _libraryManager = libraryManager;
+ _keyframeExtractors = keyframeExtractors.OrderByDescending(e => e.IsMetadataBased).ToArray();
+ }
+
+ /// <inheritdoc />
+ public string Name => "Keyframe Extractor";
+
+ /// <inheritdoc />
+ public string Key => "KeyframeExtraction";
+
+ /// <inheritdoc />
+ public string Description => "Extracts keyframes from video files to create more precise HLS playlists. This task may run for a long time.";
+
+ /// <inheritdoc />
+ public string Category => _localizationManager.GetLocalizedString("TasksLibraryCategory");
+
+ /// <inheritdoc />
+ public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
+ {
+ var query = new InternalItemsQuery
+ {
+ MediaTypes = new[] { MediaType.Video },
+ IsVirtualItem = false,
+ IncludeItemTypes = _itemTypes,
+ DtoOptions = new DtoOptions(true),
+ SourceTypes = new[] { SourceType.Library },
+ Recursive = true,
+ Limit = Pagesize
+ };
+
+ var numberOfVideos = _libraryManager.GetCount(query);
+
+ var startIndex = 0;
+ var numComplete = 0;
+
+ while (startIndex < numberOfVideos)
+ {
+ query.StartIndex = startIndex;
+
+ var videos = _libraryManager.GetItemList(query);
+ var currentPageCount = videos.Count;
+ // TODO parallelize with Parallel.ForEach?
+ for (var i = 0; i < currentPageCount; i++)
+ {
+ var video = videos[i];
+ // Only local files supported
+ if (video.IsFileProtocol && File.Exists(video.Path))
+ {
+ for (var j = 0; j < _keyframeExtractors.Length; j++)
+ {
+ var extractor = _keyframeExtractors[j];
+ // The cache decorator will make sure to save them in the data dir
+ if (extractor.TryExtractKeyframes(video.Path, out _))
+ {
+ break;
+ }
+ }
+ }
+
+ // Update progress
+ numComplete++;
+ double percent = (double)numComplete / numberOfVideos;
+ progress.Report(100 * percent);
+ }
+
+ startIndex += Pagesize;
+ }
+
+ progress.Report(100);
+ return Task.CompletedTask;
+ }
+
+ /// <inheritdoc />
+ public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() => Enumerable.Empty<TaskTriggerInfo>();
+}
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs
new file mode 100644
index 000000000..320604e10
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Keyframes/FfProbe/FfProbeKeyframeExtractor.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+
+namespace Jellyfin.MediaEncoding.Keyframes.FfProbe;
+
+/// <summary>
+/// FfProbe based keyframe extractor.
+/// </summary>
+public static class FfProbeKeyframeExtractor
+{
+ private const string DefaultArguments = "-v error -skip_frame nokey -show_entries format=duration -show_entries stream=duration -show_entries packet=pts_time,flags -select_streams v -of csv \"{0}\"";
+
+ /// <summary>
+ /// Extracts the keyframes using the ffprobe executable at the specified path.
+ /// </summary>
+ /// <param name="ffProbePath">The path to the ffprobe executable.</param>
+ /// <param name="filePath">The file path.</param>
+ /// <returns>An instance of <see cref="KeyframeData"/>.</returns>
+ public static KeyframeData GetKeyframeData(string ffProbePath, string filePath)
+ {
+ using var process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ FileName = ffProbePath,
+ Arguments = string.Format(CultureInfo.InvariantCulture, DefaultArguments, filePath),
+
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+
+ WindowStyle = ProcessWindowStyle.Hidden,
+ ErrorDialog = false,
+ },
+ EnableRaisingEvents = true
+ };
+
+ process.Start();
+
+ return ParseStream(process.StandardOutput);
+ }
+
+ internal static KeyframeData ParseStream(StreamReader reader)
+ {
+ var keyframes = new List<long>();
+ double streamDuration = 0;
+ double formatDuration = 0;
+
+ while (!reader.EndOfStream)
+ {
+ var line = reader.ReadLine().AsSpan();
+ if (line.IsEmpty)
+ {
+ continue;
+ }
+
+ var firstComma = line.IndexOf(',');
+ var lineType = line[..firstComma];
+ var rest = line[(firstComma + 1)..];
+ if (lineType.Equals("packet", StringComparison.OrdinalIgnoreCase))
+ {
+ if (rest.EndsWith(",K_"))
+ {
+ // Trim the flags from the packet line. Example line: packet,7169.079000,K_
+ var keyframe = double.Parse(rest[..^3], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
+ // Have to manually convert to ticks to avoid rounding errors as TimeSpan is only precise down to 1 ms when converting double.
+ keyframes.Add(Convert.ToInt64(keyframe * TimeSpan.TicksPerSecond));
+ }
+ }
+ else if (lineType.Equals("stream", StringComparison.OrdinalIgnoreCase))
+ {
+ if (double.TryParse(rest, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var streamDurationResult))
+ {
+ streamDuration = streamDurationResult;
+ }
+ }
+ else if (lineType.Equals("format", StringComparison.OrdinalIgnoreCase))
+ {
+ if (double.TryParse(rest, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var formatDurationResult))
+ {
+ formatDuration = formatDurationResult;
+ }
+ }
+ }
+
+ // Prefer the stream duration as it should be more accurate
+ var duration = streamDuration > 0 ? streamDuration : formatDuration;
+
+ return new KeyframeData(TimeSpan.FromSeconds(duration).Ticks, keyframes);
+ }
+}
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/FfTool/FfToolKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Keyframes/FfTool/FfToolKeyframeExtractor.cs
new file mode 100644
index 000000000..aaaca6fe1
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Keyframes/FfTool/FfToolKeyframeExtractor.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Jellyfin.MediaEncoding.Keyframes.FfTool;
+
+/// <summary>
+/// FfTool based keyframe extractor.
+/// </summary>
+public static class FfToolKeyframeExtractor
+{
+ /// <summary>
+ /// Extracts the keyframes using the fftool executable at the specified path.
+ /// </summary>
+ /// <param name="ffToolPath">The path to the fftool executable.</param>
+ /// <param name="filePath">The file path.</param>
+ /// <returns>An instance of <see cref="KeyframeData"/>.</returns>
+ public static KeyframeData GetKeyframeData(string ffToolPath, string filePath) => throw new NotImplementedException();
+}
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj b/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj
new file mode 100644
index 000000000..5ec09c768
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj
@@ -0,0 +1,33 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net6.0</TargetFramework>
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="NEbml" Version="0.11.0" />
+ </ItemGroup>
+
+ <!-- Code Analyzers-->
+ <ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="5.0.0" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
+ <_Parameter1>Jellyfin.MediaEncoding.Keyframes.Tests</_Parameter1>
+ </AssemblyAttribute>
+ </ItemGroup>
+
+</Project>
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/KeyframeData.cs b/src/Jellyfin.MediaEncoding.Keyframes/KeyframeData.cs
new file mode 100644
index 000000000..06f9180e7
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Keyframes/KeyframeData.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+
+namespace Jellyfin.MediaEncoding.Keyframes;
+
+/// <summary>
+/// Keyframe information for a specific file.
+/// </summary>
+public class KeyframeData
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="KeyframeData"/> class.
+ /// </summary>
+ /// <param name="totalDuration">The total duration of the video stream in ticks.</param>
+ /// <param name="keyframeTicks">The video keyframes in ticks.</param>
+ public KeyframeData(long totalDuration, IReadOnlyList<long> keyframeTicks)
+ {
+ TotalDuration = totalDuration;
+ KeyframeTicks = keyframeTicks;
+ }
+
+ /// <summary>
+ /// Gets the total duration of the stream in ticks.
+ /// </summary>
+ public long TotalDuration { get; }
+
+ /// <summary>
+ /// Gets the keyframes in ticks.
+ /// </summary>
+ public IReadOnlyList<long> KeyframeTicks { get; }
+}
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Matroska/Extensions/EbmlReaderExtensions.cs b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/Extensions/EbmlReaderExtensions.cs
new file mode 100644
index 000000000..fd170864b
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/Extensions/EbmlReaderExtensions.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Buffers.Binary;
+using Jellyfin.MediaEncoding.Keyframes.Matroska.Models;
+using NEbml.Core;
+
+namespace Jellyfin.MediaEncoding.Keyframes.Matroska.Extensions;
+
+/// <summary>
+/// Extension methods for the <see cref="EbmlReader"/> class.
+/// </summary>
+internal static class EbmlReaderExtensions
+{
+ /// <summary>
+ /// Traverses the current container to find the element with <paramref name="identifier"/> identifier.
+ /// </summary>
+ /// <param name="reader">An instance of <see cref="EbmlReader"/>.</param>
+ /// <param name="identifier">The element identifier.</param>
+ /// <returns>A value indicating whether the element was found.</returns>
+ internal static bool FindElement(this EbmlReader reader, ulong identifier)
+ {
+ while (reader.ReadNext())
+ {
+ if (reader.ElementId.EncodedValue == identifier)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Reads the current position in the file as an unsigned integer converted from binary.
+ /// </summary>
+ /// <param name="reader">An instance of <see cref="EbmlReader"/>.</param>
+ /// <returns>The unsigned integer.</returns>
+ internal static uint ReadUIntFromBinary(this EbmlReader reader)
+ {
+ var buffer = new byte[4];
+ reader.ReadBinary(buffer, 0, 4);
+ return BinaryPrimitives.ReadUInt32BigEndian(buffer);
+ }
+
+ /// <summary>
+ /// Reads from the start of the file to retrieve the SeekHead segment.
+ /// </summary>
+ /// <param name="reader">An instance of <see cref="EbmlReader"/>.</param>
+ /// <returns>Instance of <see cref="SeekHead"/>.</returns>
+ internal static SeekHead ReadSeekHead(this EbmlReader reader)
+ {
+ reader = reader ?? throw new ArgumentNullException(nameof(reader));
+
+ if (reader.ElementPosition != 0)
+ {
+ throw new InvalidOperationException("File position must be at 0");
+ }
+
+ // Skip the header
+ if (!reader.FindElement(MatroskaConstants.SegmentContainer))
+ {
+ throw new InvalidOperationException("Expected a segment container");
+ }
+
+ reader.EnterContainer();
+
+ long? tracksPosition = null;
+ long? cuesPosition = null;
+ long? infoPosition = null;
+ // The first element should be a SeekHead otherwise we'll have to search manually
+ if (!reader.FindElement(MatroskaConstants.SeekHead))
+ {
+ throw new InvalidOperationException("Expected a SeekHead");
+ }
+
+ reader.EnterContainer();
+ while (reader.FindElement(MatroskaConstants.Seek))
+ {
+ reader.EnterContainer();
+ reader.ReadNext();
+ var type = (ulong)reader.ReadUIntFromBinary();
+ switch (type)
+ {
+ case MatroskaConstants.Tracks:
+ reader.ReadNext();
+ tracksPosition = (long)reader.ReadUInt();
+ break;
+ case MatroskaConstants.Cues:
+ reader.ReadNext();
+ cuesPosition = (long)reader.ReadUInt();
+ break;
+ case MatroskaConstants.Info:
+ reader.ReadNext();
+ infoPosition = (long)reader.ReadUInt();
+ break;
+ }
+
+ reader.LeaveContainer();
+
+ if (tracksPosition.HasValue && cuesPosition.HasValue && infoPosition.HasValue)
+ {
+ break;
+ }
+ }
+
+ reader.LeaveContainer();
+
+ if (!tracksPosition.HasValue || !cuesPosition.HasValue || !infoPosition.HasValue)
+ {
+ throw new InvalidOperationException("SeekHead is missing or does not contain Info, Tracks and Cues positions. SeekHead referencing another SeekHead is not supported");
+ }
+
+ return new SeekHead(infoPosition.Value, tracksPosition.Value, cuesPosition.Value);
+ }
+
+ /// <summary>
+ /// Reads from SegmentContainer to retrieve the Info segment.
+ /// </summary>
+ /// <param name="reader">An instance of <see cref="EbmlReader"/>.</param>
+ /// <param name="position">The position of the info segment relative to the Segment container.</param>
+ /// <returns>Instance of <see cref="Info"/>.</returns>
+ internal static Info ReadInfo(this EbmlReader reader, long position)
+ {
+ reader.ReadAt(position);
+
+ double? duration = null;
+ reader.EnterContainer();
+ // Mandatory element
+ reader.FindElement(MatroskaConstants.TimestampScale);
+ var timestampScale = reader.ReadUInt();
+
+ if (reader.FindElement(MatroskaConstants.Duration))
+ {
+ duration = reader.ReadFloat();
+ }
+
+ reader.LeaveContainer();
+
+ return new Info((long)timestampScale, duration);
+ }
+
+ /// <summary>
+ /// Enters the Tracks segment and reads all tracks to find the specified type.
+ /// </summary>
+ /// <param name="reader">Instance of <see cref="EbmlReader"/>.</param>
+ /// <param name="tracksPosition">The relative position of the tracks segment.</param>
+ /// <param name="type">The track type identifier.</param>
+ /// <returns>The first track number with the specified type.</returns>
+ /// <exception cref="InvalidOperationException">Stream type is not found.</exception>
+ internal static ulong FindFirstTrackNumberByType(this EbmlReader reader, long tracksPosition, ulong type)
+ {
+ reader.ReadAt(tracksPosition);
+
+ reader.EnterContainer();
+ while (reader.FindElement(MatroskaConstants.TrackEntry))
+ {
+ reader.EnterContainer();
+ // Mandatory element
+ reader.FindElement(MatroskaConstants.TrackNumber);
+ var trackNumber = reader.ReadUInt();
+
+ // Mandatory element
+ reader.FindElement(MatroskaConstants.TrackType);
+ var trackType = reader.ReadUInt();
+
+ reader.LeaveContainer();
+ if (trackType == MatroskaConstants.TrackTypeVideo)
+ {
+ reader.LeaveContainer();
+ return trackNumber;
+ }
+ }
+
+ reader.LeaveContainer();
+
+ throw new InvalidOperationException($"No stream with type {type} found");
+ }
+}
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaConstants.cs b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaConstants.cs
new file mode 100644
index 000000000..0d5c2f34f
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaConstants.cs
@@ -0,0 +1,30 @@
+namespace Jellyfin.MediaEncoding.Keyframes.Matroska;
+
+/// <summary>
+/// Constants for the Matroska identifiers.
+/// </summary>
+public static class MatroskaConstants
+{
+ internal const ulong SegmentContainer = 0x18538067;
+
+ internal const ulong SeekHead = 0x114D9B74;
+ internal const ulong Seek = 0x4DBB;
+
+ internal const ulong Info = 0x1549A966;
+ internal const ulong TimestampScale = 0x2AD7B1;
+ internal const ulong Duration = 0x4489;
+
+ internal const ulong Tracks = 0x1654AE6B;
+ internal const ulong TrackEntry = 0xAE;
+ internal const ulong TrackNumber = 0xD7;
+ internal const ulong TrackType = 0x83;
+
+ internal const ulong TrackTypeVideo = 0x1;
+ internal const ulong TrackTypeSubtitle = 0x11;
+
+ internal const ulong Cues = 0x1C53BB6B;
+ internal const ulong CueTime = 0xB3;
+ internal const ulong CuePoint = 0xBB;
+ internal const ulong CueTrackPositions = 0xB7;
+ internal const ulong CuePointTrackNumber = 0xF7;
+}
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs
new file mode 100644
index 000000000..501b2bb17
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/MatroskaKeyframeExtractor.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Jellyfin.MediaEncoding.Keyframes.Matroska.Extensions;
+using Jellyfin.MediaEncoding.Keyframes.Matroska.Models;
+using NEbml.Core;
+
+namespace Jellyfin.MediaEncoding.Keyframes.Matroska;
+
+/// <summary>
+/// The keyframe extractor for the matroska container.
+/// </summary>
+public static class MatroskaKeyframeExtractor
+{
+ /// <summary>
+ /// Extracts the keyframes in ticks (scaled using the container timestamp scale) from the matroska container.
+ /// </summary>
+ /// <param name="filePath">The file path.</param>
+ /// <returns>An instance of <see cref="KeyframeData"/>.</returns>
+ public static KeyframeData GetKeyframeData(string filePath)
+ {
+ using var stream = File.OpenRead(filePath);
+ using var reader = new EbmlReader(stream);
+
+ var seekHead = reader.ReadSeekHead();
+ // External lib does not support seeking backwards (yet)
+ Info info;
+ ulong videoTrackNumber;
+ if (seekHead.InfoPosition < seekHead.TracksPosition)
+ {
+ info = reader.ReadInfo(seekHead.InfoPosition);
+ videoTrackNumber = reader.FindFirstTrackNumberByType(seekHead.TracksPosition, MatroskaConstants.TrackTypeVideo);
+ }
+ else
+ {
+ videoTrackNumber = reader.FindFirstTrackNumberByType(seekHead.TracksPosition, MatroskaConstants.TrackTypeVideo);
+ info = reader.ReadInfo(seekHead.InfoPosition);
+ }
+
+ var keyframes = new List<long>();
+ reader.ReadAt(seekHead.CuesPosition);
+ reader.EnterContainer();
+
+ while (reader.FindElement(MatroskaConstants.CuePoint))
+ {
+ reader.EnterContainer();
+ ulong? trackNumber = null;
+ // Mandatory element
+ reader.FindElement(MatroskaConstants.CueTime);
+ var cueTime = reader.ReadUInt();
+
+ // Mandatory element
+ reader.FindElement(MatroskaConstants.CueTrackPositions);
+ reader.EnterContainer();
+ if (reader.FindElement(MatroskaConstants.CuePointTrackNumber))
+ {
+ trackNumber = reader.ReadUInt();
+ }
+
+ reader.LeaveContainer();
+
+ if (trackNumber == videoTrackNumber)
+ {
+ keyframes.Add(ScaleToTicks(cueTime, info.TimestampScale));
+ }
+
+ reader.LeaveContainer();
+ }
+
+ reader.LeaveContainer();
+
+ var result = new KeyframeData(ScaleToTicks(info.Duration ?? 0, info.TimestampScale), keyframes);
+ return result;
+ }
+
+ private static long ScaleToTicks(ulong unscaledValue, long timestampScale)
+ {
+ // TimestampScale is in nanoseconds, scale it to get the value in ticks, 1 tick == 100 ns
+ return (long)unscaledValue * timestampScale / 100;
+ }
+
+ private static long ScaleToTicks(double unscaledValue, long timestampScale)
+ {
+ // TimestampScale is in nanoseconds, scale it to get the value in ticks, 1 tick == 100 ns
+ return Convert.ToInt64(unscaledValue * timestampScale / 100);
+ }
+}
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Matroska/Models/Info.cs b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/Models/Info.cs
new file mode 100644
index 000000000..415d6da00
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/Models/Info.cs
@@ -0,0 +1,28 @@
+namespace Jellyfin.MediaEncoding.Keyframes.Matroska.Models;
+
+/// <summary>
+/// The matroska Info segment.
+/// </summary>
+internal class Info
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Info"/> class.
+ /// </summary>
+ /// <param name="timestampScale">The timestamp scale in nanoseconds.</param>
+ /// <param name="duration">The duration of the entire file.</param>
+ public Info(long timestampScale, double? duration)
+ {
+ TimestampScale = timestampScale;
+ Duration = duration;
+ }
+
+ /// <summary>
+ /// Gets the timestamp scale in nanoseconds.
+ /// </summary>
+ public long TimestampScale { get; }
+
+ /// <summary>
+ /// Gets the total duration of the file.
+ /// </summary>
+ public double? Duration { get; }
+}
diff --git a/src/Jellyfin.MediaEncoding.Keyframes/Matroska/Models/SeekHead.cs b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/Models/SeekHead.cs
new file mode 100644
index 000000000..95e4fd882
--- /dev/null
+++ b/src/Jellyfin.MediaEncoding.Keyframes/Matroska/Models/SeekHead.cs
@@ -0,0 +1,35 @@
+namespace Jellyfin.MediaEncoding.Keyframes.Matroska.Models;
+
+/// <summary>
+/// The matroska SeekHead segment. All positions are relative to the Segment container.
+/// </summary>
+internal class SeekHead
+{
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SeekHead"/> class.
+ /// </summary>
+ /// <param name="infoPosition">The relative file position of the info segment.</param>
+ /// <param name="tracksPosition">The relative file position of the tracks segment.</param>
+ /// <param name="cuesPosition">The relative file position of the cues segment.</param>
+ public SeekHead(long infoPosition, long tracksPosition, long cuesPosition)
+ {
+ InfoPosition = infoPosition;
+ TracksPosition = tracksPosition;
+ CuesPosition = cuesPosition;
+ }
+
+ /// <summary>
+ /// Gets relative file position of the info segment.
+ /// </summary>
+ public long InfoPosition { get; }
+
+ /// <summary>
+ /// Gets the relative file position of the tracks segment.
+ /// </summary>
+ public long TracksPosition { get; }
+
+ /// <summary>
+ /// Gets the relative file position of the cues segment.
+ /// </summary>
+ public long CuesPosition { get; }
+}
diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
index 6e0474dbf..bf95c458d 100644
--- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
+++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj
@@ -20,12 +20,16 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="Moq" Version="4.16.1" />
</ItemGroup>
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj
index aaa6b5d90..7b20823ba 100644
--- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj
+++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj
@@ -15,12 +15,16 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
</ItemGroup>
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj
index 981c7e9c9..374a17e2f 100644
--- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj
+++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj
@@ -16,11 +16,15 @@
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj
index 6200a148b..d178837b2 100644
--- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj
+++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj
@@ -11,11 +11,15 @@
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj
index 2a3918469..725947577 100644
--- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj
+++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj
@@ -13,7 +13,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
- <PackageReference Include="coverlet.collector" Version="3.1.0">
+ <PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
@@ -22,6 +22,10 @@
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj b/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj
new file mode 100644
index 000000000..539a80dad
--- /dev/null
+++ b/tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj
@@ -0,0 +1,37 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net6.0</TargetFramework>
+ <IsPackable>false</IsPackable>
+ <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="xunit" Version="2.4.1" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ <PrivateAssets>all</PrivateAssets>
+ </PackageReference>
+ <PackageReference Include="coverlet.collector" Version="3.1.2">
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ <PrivateAssets>all</PrivateAssets>
+ </PackageReference>
+ </ItemGroup>
+
+ <!-- Code Analyzers -->
+ <ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\src\Jellyfin.MediaEncoding.Hls\Jellyfin.MediaEncoding.Hls.csproj" />
+ <ProjectReference Include="..\..\src\Jellyfin.MediaEncoding.Keyframes\Jellyfin.MediaEncoding.Keyframes.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/tests/Jellyfin.MediaEncoding.Hls.Tests/Playlist/DynamicHlsPlaylistGeneratorTests.cs b/tests/Jellyfin.MediaEncoding.Hls.Tests/Playlist/DynamicHlsPlaylistGeneratorTests.cs
new file mode 100644
index 000000000..79648c4f6
--- /dev/null
+++ b/tests/Jellyfin.MediaEncoding.Hls.Tests/Playlist/DynamicHlsPlaylistGeneratorTests.cs
@@ -0,0 +1,101 @@
+using System;
+using Jellyfin.MediaEncoding.Hls.Playlist;
+using Jellyfin.MediaEncoding.Keyframes;
+using Xunit;
+
+namespace Jellyfin.MediaEncoding.Hls.Tests.Playlist
+{
+ public class DynamicHlsPlaylistGeneratorTests
+ {
+ [Theory]
+ [MemberData(nameof(ComputeSegments_Valid_Success_Data))]
+ public void ComputeSegments_Valid_Success(KeyframeData keyframeData, int desiredSegmentLengthMs, double[] segments)
+ {
+ Assert.Equal(segments, DynamicHlsPlaylistGenerator.ComputeSegments(keyframeData, desiredSegmentLengthMs));
+ }
+
+ [Fact]
+ public void ComputeSegments_InvalidDuration_ThrowsArgumentException()
+ {
+ var keyframeData = new KeyframeData(0, new[] { MsToTicks(10000) });
+ Assert.Throws<ArgumentException>(() => DynamicHlsPlaylistGenerator.ComputeSegments(keyframeData, 6000));
+ }
+
+ [Theory]
+ [MemberData(nameof(ComputeEqualLengthSegments_Valid_Success_Data))]
+ public void ComputeEqualLengthSegments_Valid_Success(int desiredSegmentLengthMs, long totalRuntimeTicks, double[] segments)
+ {
+ Assert.Equal(segments, DynamicHlsPlaylistGenerator.ComputeEqualLengthSegments(desiredSegmentLengthMs, totalRuntimeTicks));
+ }
+
+ [Theory]
+ [InlineData(0, 1000000)]
+ [InlineData(1000, 0)]
+ public void ComputeEqualLengthSegments_Invalid_ThrowsInvalidOperationException(int desiredSegmentLengthMs, long totalRuntimeTicks)
+ {
+ Assert.Throws<InvalidOperationException>(() => DynamicHlsPlaylistGenerator.ComputeEqualLengthSegments(desiredSegmentLengthMs, totalRuntimeTicks));
+ }
+
+ [Theory]
+ [InlineData("testfile.mkv", new string[0], false)]
+ [InlineData("testfile.flv", new[] { ".mp4", ".mkv", ".ts" }, false)]
+ [InlineData("testfile.flv", new[] { ".mp4", ".mkv", ".ts", ".flv" }, true)]
+ [InlineData("/some/arbitrarily/long/path/testfile.mkv", new[] { "mkv" }, true)]
+ public void IsExtractionAllowedForFile_Valid_Success(string filePath, string[] allowedExtensions, bool isAllowed)
+ {
+ Assert.Equal(isAllowed, DynamicHlsPlaylistGenerator.IsExtractionAllowedForFile(filePath, allowedExtensions));
+ }
+
+ [Theory]
+ [InlineData("testfile", new[] { ".mp4" })]
+ public void IsExtractionAllowedForFile_Invalid_ReturnsFalse(string filePath, string[] allowedExtensions)
+ {
+ Assert.False(DynamicHlsPlaylistGenerator.IsExtractionAllowedForFile(filePath, allowedExtensions));
+ }
+
+ private static TheoryData<int, long, double[]> ComputeEqualLengthSegments_Valid_Success_Data()
+ {
+ var data = new TheoryData<int, long, double[]>
+ {
+ { 6000, MsToTicks(13000), new[] { 6.0, 6.0, 1.0 } },
+ { 3000, MsToTicks(15000), new[] { 3.0, 3.0, 3.0, 3.0, 3.0 } },
+ { 6000, MsToTicks(25000), new[] { 6.0, 6.0, 6.0, 6.0, 1.0 } },
+ { 6000, MsToTicks(20123), new[] { 6.0, 6.0, 6.0, 2.123 } },
+ { 6000, MsToTicks(1234), new[] { 1.234 } }
+ };
+
+ return data;
+ }
+
+ private static TheoryData<KeyframeData, int, double[]> ComputeSegments_Valid_Success_Data()
+ {
+ var data = new TheoryData<KeyframeData, int, double[]>
+ {
+ {
+ new KeyframeData(MsToTicks(35000), new[] { 0, MsToTicks(10427), MsToTicks(20854), MsToTicks(31240) }),
+ 6000,
+ new[] { 10.427, 10.427, 10.386, 3.760 }
+ },
+ {
+ new KeyframeData(MsToTicks(10000), new[] { 0, MsToTicks(1000), MsToTicks(2000), MsToTicks(3000), MsToTicks(4000), MsToTicks(5000) }),
+ 2000,
+ new[] { 2.0, 2.0, 6.0 }
+ },
+ {
+ new KeyframeData(MsToTicks(10000), new[] { 0L }),
+ 6000,
+ new[] { 10.0 }
+ },
+ {
+ new KeyframeData(MsToTicks(10000), Array.Empty<long>()),
+ 6000,
+ new[] { 10.0 }
+ }
+ };
+
+ return data;
+ }
+
+ private static long MsToTicks(int value) => TimeSpan.FromMilliseconds(value).Ticks;
+ }
+}
diff --git a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/FfProbeKeyframeExtractorTests.cs b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/FfProbeKeyframeExtractorTests.cs
new file mode 100644
index 000000000..e5debf8c0
--- /dev/null
+++ b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/FfProbeKeyframeExtractorTests.cs
@@ -0,0 +1,28 @@
+using System.IO;
+using System.Text.Json;
+using Xunit;
+
+namespace Jellyfin.MediaEncoding.Keyframes.FfProbe
+{
+ public class FfProbeKeyframeExtractorTests
+ {
+ [Theory]
+ [InlineData("keyframes.txt", "keyframes_result.json")]
+ [InlineData("keyframes_streamduration.txt", "keyframes_streamduration_result.json")]
+ public void ParseStream_Valid_Success(string testDataFileName, string resultFileName)
+ {
+ var testDataPath = Path.Combine("FfProbe/Test Data", testDataFileName);
+ var resultPath = Path.Combine("FfProbe/Test Data", resultFileName);
+ using var resultFileStream = File.OpenRead(resultPath);
+ var expectedResult = JsonSerializer.Deserialize<KeyframeData>(resultFileStream)!;
+
+ using var fileStream = File.OpenRead(testDataPath);
+ using var streamReader = new StreamReader(fileStream);
+
+ var result = FfProbeKeyframeExtractor.ParseStream(streamReader);
+
+ Assert.Equal(expectedResult.TotalDuration, result.TotalDuration);
+ Assert.Equal(expectedResult.KeyframeTicks, result.KeyframeTicks);
+ }
+ }
+}
diff --git a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes.txt b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes.txt
new file mode 100644
index 000000000..a6d1b420c
--- /dev/null
+++ b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes.txt
@@ -0,0 +1,16937 @@
+packet,0.000000,K_
+packet,0.375000,__
+packet,0.167000,__
+packet,0.042000,__
+packet,0.083000,__
+packet,0.125000,__
+packet,0.209000,__
+packet,0.250000,__
+packet,0.292000,__
+packet,0.334000,__
+packet,0.751000,__
+packet,0.542000,__
+packet,0.417000,__
+packet,0.459000,__
+packet,0.501000,__
+packet,0.584000,__
+packet,0.626000,__
+packet,0.667000,__
+packet,0.709000,__
+packet,0.959000,__
+packet,0.834000,__
+packet,0.792000,__
+packet,0.876000,__
+packet,0.918000,__
+packet,1.001000,__
+packet,1.168000,__
+packet,1.084000,__
+packet,1.043000,__
+packet,1.126000,__
+packet,1.335000,__
+packet,1.251000,__
+packet,1.210000,__
+packet,1.293000,__
+packet,1.460000,__
+packet,1.376000,__
+packet,1.418000,__
+packet,1.668000,__
+packet,1.543000,__
+packet,1.502000,__
+packet,1.585000,__
+packet,1.627000,__
+packet,1.793000,__
+packet,1.710000,__
+packet,1.752000,__
+packet,1.960000,__
+packet,1.877000,__
+packet,1.835000,__
+packet,1.919000,__
+packet,2.127000,__
+packet,2.044000,__
+packet,2.002000,__
+packet,2.085000,__
+packet,2.211000,__
+packet,2.169000,__
+packet,2.377000,__
+packet,2.294000,__
+packet,2.252000,__
+packet,2.336000,__
+packet,2.461000,__
+packet,2.419000,__
+packet,2.503000,__
+packet,2.544000,__
+packet,2.628000,__
+packet,2.586000,__
+packet,2.669000,__
+packet,2.711000,__
+packet,2.794000,__
+packet,2.753000,__
+packet,2.836000,__
+packet,2.878000,__
+packet,2.920000,__
+packet,2.961000,__
+packet,3.003000,__
+packet,3.045000,__
+packet,3.086000,__
+packet,3.128000,__
+packet,3.170000,__
+packet,3.212000,__
+packet,3.337000,__
+packet,3.253000,__
+packet,3.295000,__
+packet,3.420000,__
+packet,3.378000,__
+packet,3.462000,__
+packet,3.504000,__
+packet,3.545000,__
+packet,3.587000,__
+packet,3.629000,__
+packet,3.670000,__
+packet,3.712000,__
+packet,3.754000,__
+packet,3.837000,__
+packet,3.795000,__
+packet,3.879000,__
+packet,3.921000,__
+packet,3.962000,__
+packet,4.004000,__
+packet,4.046000,__
+packet,4.087000,__
+packet,4.129000,__
+packet,4.171000,__
+packet,4.213000,__
+packet,4.254000,__
+packet,4.338000,__
+packet,4.296000,__
+packet,4.421000,__
+packet,4.379000,__
+packet,4.505000,__
+packet,4.463000,__
+packet,4.588000,__
+packet,4.546000,__
+packet,4.630000,__
+packet,4.671000,__
+packet,4.713000,__
+packet,4.838000,__
+packet,4.755000,__
+packet,4.796000,__
+packet,4.880000,__
+packet,4.922000,__
+packet,4.963000,__
+packet,5.005000,__
+packet,5.047000,__
+packet,5.088000,__
+packet,5.130000,__
+packet,5.172000,__
+packet,5.214000,__
+packet,5.297000,__
+packet,5.255000,__
+packet,5.339000,__
+packet,5.380000,__
+packet,5.422000,__
+packet,5.464000,__
+packet,5.506000,__
+packet,5.547000,__
+packet,5.589000,__
+packet,5.631000,__
+packet,5.756000,__
+packet,5.672000,__
+packet,5.714000,__
+packet,5.923000,__
+packet,5.839000,__
+packet,5.797000,__
+packet,5.881000,__
+packet,6.089000,__
+packet,6.006000,__
+packet,5.964000,__
+packet,6.048000,__
+packet,6.256000,__
+packet,6.173000,__
+packet,6.131000,__
+packet,6.215000,__
+packet,6.381000,__
+packet,6.298000,__
+packet,6.340000,__
+packet,6.465000,__
+packet,6.423000,__
+packet,6.590000,__
+packet,6.507000,__
+packet,6.548000,__
+packet,6.632000,__
+packet,6.715000,__
+packet,6.673000,__
+packet,6.757000,__
+packet,6.882000,__
+packet,6.798000,__
+packet,6.840000,__
+packet,6.924000,__
+packet,6.965000,__
+packet,7.007000,__
+packet,7.049000,__
+packet,7.090000,__
+packet,7.132000,__
+packet,7.174000,__
+packet,7.216000,__
+packet,7.257000,__
+packet,7.299000,__
+packet,7.341000,__
+packet,7.382000,__
+packet,7.424000,__
+packet,7.466000,__
+packet,7.508000,__
+packet,7.549000,__
+packet,7.591000,__
+packet,7.633000,__
+packet,7.674000,__
+packet,7.716000,__
+packet,7.758000,__
+packet,7.799000,__
+packet,7.841000,__
+packet,7.966000,__
+packet,7.883000,__
+packet,7.925000,__
+packet,8.050000,__
+packet,8.008000,__
+packet,8.091000,__
+packet,8.133000,__
+packet,8.217000,__
+packet,8.175000,__
+packet,8.258000,__
+packet,8.300000,__
+packet,8.342000,__
+packet,8.383000,__
+packet,8.425000,__
+packet,8.467000,__
+packet,8.509000,__
+packet,8.550000,__
+packet,8.592000,__
+packet,8.634000,__
+packet,8.717000,__
+packet,8.675000,__
+packet,8.759000,__
+packet,8.800000,__
+packet,8.842000,__
+packet,8.884000,__
+packet,8.926000,__
+packet,8.967000,__
+packet,9.009000,__
+packet,9.051000,__
+packet,9.092000,__
+packet,9.134000,__
+packet,9.176000,__
+packet,9.218000,__
+packet,9.259000,__
+packet,9.301000,__
+packet,9.343000,__
+packet,9.384000,__
+packet,9.426000,__
+packet,9.468000,__
+packet,9.510000,__
+packet,9.551000,__
+packet,9.593000,__
+packet,9.635000,__
+packet,9.718000,__
+packet,9.676000,__
+packet,9.801000,__
+packet,9.760000,__
+packet,9.927000,__
+packet,9.843000,__
+packet,9.885000,__
+packet,10.010000,__
+packet,9.968000,__
+packet,10.052000,__
+packet,10.093000,__
+packet,10.177000,__
+packet,10.135000,__
+packet,10.260000,__
+packet,10.219000,__
+packet,10.302000,__
+packet,10.344000,__
+packet,10.385000,K_
+packet,10.427000,__
+packet,10.469000,__
+packet,10.511000,__
+packet,10.552000,__
+packet,10.594000,__
+packet,10.636000,__
+packet,10.677000,__
+packet,10.719000,__
+packet,10.761000,__
+packet,10.802000,__
+packet,10.844000,__
+packet,10.886000,__
+packet,10.928000,__
+packet,10.969000,__
+packet,11.011000,__
+packet,11.053000,__
+packet,11.094000,__
+packet,11.220000,__
+packet,11.136000,__
+packet,11.178000,__
+packet,11.345000,__
+packet,11.261000,__
+packet,11.303000,__
+packet,11.553000,__
+packet,11.428000,__
+packet,11.386000,__
+packet,11.470000,__
+packet,11.512000,__
+packet,11.637000,__
+packet,11.595000,__
+packet,11.762000,__
+packet,11.678000,__
+packet,11.720000,__
+packet,11.845000,__
+packet,11.803000,__
+packet,11.887000,__
+packet,11.929000,__
+packet,11.970000,__
+packet,12.012000,__
+packet,12.054000,__
+packet,12.095000,__
+packet,12.137000,__
+packet,12.179000,__
+packet,12.262000,__
+packet,12.221000,__
+packet,12.304000,__
+packet,12.346000,__
+packet,12.387000,__
+packet,12.429000,__
+packet,12.471000,__
+packet,12.513000,__
+packet,12.554000,__
+packet,12.596000,__
+packet,12.846000,__
+packet,12.721000,__
+packet,12.638000,__
+packet,12.679000,__
+packet,12.763000,__
+packet,12.804000,__
+packet,12.971000,__
+packet,12.888000,__
+packet,12.930000,__
+packet,13.180000,__
+packet,13.055000,__
+packet,13.013000,__
+packet,13.096000,__
+packet,13.138000,__
+packet,13.347000,__
+packet,13.263000,__
+packet,13.222000,__
+packet,13.305000,__
+packet,13.388000,K_
+packet,13.472000,__
+packet,13.430000,__
+packet,13.722000,__
+packet,13.597000,__
+packet,13.514000,__
+packet,13.555000,__
+packet,13.639000,__
+packet,13.680000,__
+packet,13.847000,__
+packet,13.764000,__
+packet,13.805000,__
+packet,13.889000,__
+packet,13.972000,__
+packet,13.931000,__
+packet,14.139000,__
+packet,14.056000,__
+packet,14.014000,__
+packet,14.097000,__
+packet,14.389000,__
+packet,14.264000,__
+packet,14.181000,__
+packet,14.223000,__
+packet,14.306000,__
+packet,14.348000,__
+packet,14.473000,__
+packet,14.431000,__
+packet,14.515000,K_
+packet,14.681000,__
+packet,14.598000,__
+packet,14.556000,__
+packet,14.640000,__
+packet,14.765000,__
+packet,14.723000,__
+packet,14.806000,__
+packet,14.848000,__
+packet,14.890000,__
+packet,14.932000,__
+packet,14.973000,__
+packet,15.015000,__
+packet,15.057000,__
+packet,15.098000,__
+packet,15.140000,__
+packet,15.224000,__
+packet,15.182000,__
+packet,15.265000,__
+packet,15.432000,__
+packet,15.349000,__
+packet,15.307000,__
+packet,15.390000,__
+packet,15.557000,__
+packet,15.474000,__
+packet,15.516000,__
+packet,15.599000,__
+packet,15.641000,__
+packet,15.724000,__
+packet,15.682000,__
+packet,15.766000,__
+packet,15.891000,__
+packet,15.807000,__
+packet,15.849000,__
+packet,15.974000,__
+packet,15.933000,__
+packet,16.016000,__
+packet,16.058000,__
+packet,16.099000,__
+packet,16.225000,__
+packet,16.141000,__
+packet,16.183000,__
+packet,16.266000,__
+packet,16.308000,__
+packet,16.350000,__
+packet,16.391000,__
+packet,16.433000,__
+packet,16.475000,__
+packet,16.517000,__
+packet,16.558000,K_
+packet,16.683000,__
+packet,16.600000,__
+packet,16.642000,__
+packet,16.808000,__
+packet,16.725000,__
+packet,16.767000,__
+packet,16.934000,__
+packet,16.850000,__
+packet,16.892000,__
+packet,17.017000,__
+packet,16.975000,__
+packet,17.100000,__
+packet,17.059000,__
+packet,17.267000,__
+packet,17.184000,__
+packet,17.142000,__
+packet,17.226000,__
+packet,17.434000,__
+packet,17.351000,__
+packet,17.309000,__
+packet,17.392000,__
+packet,17.518000,__
+packet,17.476000,__
+packet,17.684000,__
+packet,17.601000,__
+packet,17.559000,__
+packet,17.643000,__
+packet,17.851000,__
+packet,17.768000,__
+packet,17.726000,__
+packet,17.809000,__
+packet,18.018000,__
+packet,17.935000,__
+packet,17.893000,__
+packet,17.976000,__
+packet,18.101000,__
+packet,18.060000,__
+packet,18.185000,__
+packet,18.143000,__
+packet,18.352000,__
+packet,18.268000,__
+packet,18.227000,__
+packet,18.310000,__
+packet,18.519000,__
+packet,18.435000,__
+packet,18.393000,__
+packet,18.477000,__
+packet,18.602000,__
+packet,18.560000,__
+packet,18.644000,K_
+packet,18.769000,__
+packet,18.685000,__
+packet,18.727000,__
+packet,19.019000,__
+packet,18.894000,__
+packet,18.810000,__
+packet,18.852000,__
+packet,18.936000,__
+packet,18.977000,__
+packet,19.228000,__
+packet,19.102000,__
+packet,19.061000,__
+packet,19.144000,__
+packet,19.186000,__
+packet,19.603000,__
+packet,19.394000,__
+packet,19.269000,__
+packet,19.311000,__
+packet,19.353000,__
+packet,19.436000,__
+packet,19.478000,__
+packet,19.520000,__
+packet,19.561000,__
+packet,19.645000,K_
+packet,19.770000,__
+packet,19.686000,__
+packet,19.728000,__
+packet,19.937000,__
+packet,19.853000,__
+packet,19.811000,__
+packet,19.895000,__
+packet,20.187000,__
+packet,20.062000,__
+packet,19.978000,__
+packet,20.020000,__
+packet,20.103000,__
+packet,20.145000,__
+packet,20.354000,__
+packet,20.270000,__
+packet,20.229000,__
+packet,20.312000,__
+packet,20.646000,__
+packet,20.479000,__
+packet,20.395000,__
+packet,20.437000,__
+packet,20.521000,__
+packet,20.562000,__
+packet,20.604000,__
+packet,20.938000,__
+packet,20.771000,__
+packet,20.687000,__
+packet,20.729000,__
+packet,20.812000,__
+packet,20.854000,__
+packet,20.896000,__
+packet,20.979000,K_
+packet,21.146000,__
+packet,21.063000,__
+packet,21.021000,__
+packet,21.104000,__
+packet,21.271000,__
+packet,21.188000,__
+packet,21.230000,__
+packet,21.438000,__
+packet,21.355000,__
+packet,21.313000,__
+packet,21.396000,__
+packet,21.563000,__
+packet,21.480000,__
+packet,21.522000,__
+packet,21.688000,__
+packet,21.605000,__
+packet,21.647000,__
+packet,21.855000,__
+packet,21.772000,__
+packet,21.730000,__
+packet,21.813000,__
+packet,21.980000,__
+packet,21.897000,__
+packet,21.939000,__
+packet,22.189000,__
+packet,22.064000,__
+packet,22.022000,__
+packet,22.105000,__
+packet,22.147000,__
+packet,22.356000,__
+packet,22.272000,__
+packet,22.231000,__
+packet,22.314000,__
+packet,22.523000,__
+packet,22.439000,__
+packet,22.397000,__
+packet,22.481000,__
+packet,22.731000,__
+packet,22.606000,__
+packet,22.564000,__
+packet,22.648000,__
+packet,22.689000,__
+packet,22.981000,__
+packet,22.856000,__
+packet,22.773000,__
+packet,22.814000,__
+packet,22.898000,__
+packet,22.940000,__
+packet,23.232000,__
+packet,23.106000,__
+packet,23.023000,__
+packet,23.065000,__
+packet,23.148000,__
+packet,23.190000,__
+packet,23.315000,__
+packet,23.273000,__
+packet,23.398000,__
+packet,23.357000,__
+packet,23.565000,__
+packet,23.482000,__
+packet,23.440000,__
+packet,23.524000,__
+packet,23.607000,__
+packet,23.690000,__
+packet,23.649000,__
+packet,23.774000,__
+packet,23.732000,__
+packet,23.941000,__
+packet,23.857000,__
+packet,23.815000,__
+packet,23.899000,__
+packet,23.982000,__
+packet,24.024000,__
+packet,24.066000,__
+packet,24.107000,__
+packet,24.233000,__
+packet,24.149000,__
+packet,24.191000,__
+packet,24.358000,__
+packet,24.274000,__
+packet,24.316000,__
+packet,24.525000,__
+packet,24.441000,__
+packet,24.399000,__
+packet,24.483000,__
+packet,24.650000,__
+packet,24.566000,__
+packet,24.608000,__
+packet,24.775000,__
+packet,24.691000,__
+packet,24.733000,__
+packet,24.983000,__
+packet,24.858000,__
+packet,24.816000,__
+packet,24.900000,__
+packet,24.942000,__
+packet,25.359000,__
+packet,25.150000,__
+packet,25.025000,__
+packet,25.067000,__
+packet,25.108000,__
+packet,25.192000,__
+packet,25.234000,__
+packet,25.275000,__
+packet,25.317000,__
+packet,25.651000,__
+packet,25.484000,__
+packet,25.400000,__
+packet,25.442000,__
+packet,25.526000,__
+packet,25.567000,__
+packet,25.609000,__
+packet,25.734000,__
+packet,25.692000,__
+packet,25.776000,__
+packet,25.943000,__
+packet,25.859000,__
+packet,25.817000,__
+packet,25.901000,__
+packet,26.068000,__
+packet,25.984000,__
+packet,26.026000,__
+packet,26.443000,__
+packet,26.235000,__
+packet,26.109000,__
+packet,26.151000,__
+packet,26.193000,__
+packet,26.276000,__
+packet,26.318000,__
+packet,26.360000,__
+packet,26.401000,__
+packet,26.693000,__
+packet,26.568000,__
+packet,26.485000,__
+packet,26.527000,__
+packet,26.610000,__
+packet,26.652000,__
+packet,26.944000,__
+packet,26.818000,__
+packet,26.735000,__
+packet,26.777000,__
+packet,26.860000,__
+packet,26.902000,__
+packet,27.319000,__
+packet,27.110000,__
+packet,26.985000,__
+packet,27.027000,__
+packet,27.069000,__
+packet,27.152000,__
+packet,27.194000,__
+packet,27.236000,__
+packet,27.277000,__
+packet,27.694000,__
+packet,27.486000,__
+packet,27.361000,__
+packet,27.402000,__
+packet,27.444000,__
+packet,27.528000,__
+packet,27.569000,__
+packet,27.611000,__
+packet,27.653000,__
+packet,27.736000,__
+packet,28.111000,__
+packet,27.903000,__
+packet,27.778000,__
+packet,27.819000,__
+packet,27.861000,__
+packet,27.945000,__
+packet,27.986000,__
+packet,28.028000,__
+packet,28.070000,__
+packet,28.445000,__
+packet,28.278000,__
+packet,28.153000,__
+packet,28.195000,__
+packet,28.237000,__
+packet,28.320000,__
+packet,28.362000,__
+packet,28.403000,__
+packet,28.695000,__
+packet,28.570000,__
+packet,28.487000,__
+packet,28.529000,__
+packet,28.612000,__
+packet,28.654000,__
+packet,28.987000,__
+packet,28.820000,__
+packet,28.737000,__
+packet,28.779000,__
+packet,28.862000,__
+packet,28.904000,__
+packet,28.946000,__
+packet,29.363000,__
+packet,29.154000,__
+packet,29.029000,__
+packet,29.071000,__
+packet,29.112000,__
+packet,29.196000,__
+packet,29.238000,__
+packet,29.279000,__
+packet,29.321000,__
+packet,29.738000,__
+packet,29.530000,__
+packet,29.404000,__
+packet,29.446000,__
+packet,29.488000,__
+packet,29.571000,__
+packet,29.613000,__
+packet,29.655000,__
+packet,29.696000,__
+packet,29.863000,__
+packet,29.780000,__
+packet,29.821000,__
+packet,30.113000,__
+packet,29.988000,__
+packet,29.905000,__
+packet,29.947000,__
+packet,30.030000,__
+packet,30.072000,__
+packet,30.280000,__
+packet,30.197000,__
+packet,30.155000,__
+packet,30.239000,__
+packet,30.572000,__
+packet,30.405000,__
+packet,30.322000,__
+packet,30.364000,__
+packet,30.447000,__
+packet,30.489000,__
+packet,30.531000,__
+packet,30.656000,__
+packet,30.614000,__
+packet,30.989000,__
+packet,30.822000,__
+packet,30.697000,__
+packet,30.739000,__
+packet,30.781000,__
+packet,30.864000,__
+packet,30.906000,__
+packet,30.948000,__
+packet,31.073000,__
+packet,31.031000,__
+packet,31.365000,__
+packet,31.198000,__
+packet,31.114000,__
+packet,31.156000,__
+packet,31.240000,__
+packet,31.281000,__
+packet,31.323000,__
+packet,31.406000,K_
+packet,31.573000,__
+packet,31.490000,__
+packet,31.448000,__
+packet,31.532000,__
+packet,31.698000,__
+packet,31.615000,__
+packet,31.657000,__
+packet,32.074000,__
+packet,31.865000,__
+packet,31.740000,__
+packet,31.782000,__
+packet,31.823000,__
+packet,31.907000,__
+packet,31.949000,__
+packet,31.990000,__
+packet,32.032000,__
+packet,32.449000,__
+packet,32.241000,__
+packet,32.115000,__
+packet,32.157000,__
+packet,32.199000,__
+packet,32.282000,__
+packet,32.324000,__
+packet,32.366000,__
+packet,32.407000,__
+packet,32.658000,__
+packet,32.533000,__
+packet,32.491000,__
+packet,32.574000,__
+packet,32.616000,__
+packet,32.699000,K_
+packet,32.908000,__
+packet,32.783000,__
+packet,32.741000,__
+packet,32.824000,__
+packet,32.866000,__
+packet,33.116000,__
+packet,32.991000,__
+packet,32.950000,__
+packet,33.033000,__
+packet,33.075000,__
+packet,33.367000,__
+packet,33.242000,__
+packet,33.158000,__
+packet,33.200000,__
+packet,33.283000,__
+packet,33.325000,__
+packet,33.617000,__
+packet,33.492000,__
+packet,33.408000,__
+packet,33.450000,__
+packet,33.534000,__
+packet,33.575000,__
+packet,33.825000,__
+packet,33.700000,__
+packet,33.659000,__
+packet,33.742000,__
+packet,33.784000,__
+packet,34.117000,__
+packet,33.951000,__
+packet,33.867000,__
+packet,33.909000,__
+packet,33.992000,__
+packet,34.034000,__
+packet,34.076000,__
+packet,34.368000,__
+packet,34.243000,__
+packet,34.159000,__
+packet,34.201000,__
+packet,34.284000,__
+packet,34.326000,__
+packet,34.576000,__
+packet,34.451000,__
+packet,34.409000,__
+packet,34.493000,__
+packet,34.535000,__
+packet,34.701000,__
+packet,34.618000,__
+packet,34.660000,__
+packet,34.952000,__
+packet,34.826000,__
+packet,34.743000,__
+packet,34.785000,__
+packet,34.868000,__
+packet,34.910000,__
+packet,35.118000,__
+packet,35.035000,__
+packet,34.993000,__
+packet,35.077000,__
+packet,35.410000,__
+packet,35.244000,__
+packet,35.160000,__
+packet,35.202000,__
+packet,35.285000,__
+packet,35.327000,__
+packet,35.369000,__
+packet,35.494000,__
+packet,35.452000,__
+packet,35.744000,__
+packet,35.619000,__
+packet,35.536000,__
+packet,35.577000,__
+packet,35.661000,__
+packet,35.702000,__
+packet,35.911000,__
+packet,35.827000,__
+packet,35.786000,__
+packet,35.869000,__
+packet,36.078000,__
+packet,35.994000,__
+packet,35.953000,__
+packet,36.036000,__
+packet,36.245000,__
+packet,36.161000,__
+packet,36.119000,__
+packet,36.203000,__
+packet,36.370000,__
+packet,36.286000,__
+packet,36.328000,__
+packet,36.537000,__
+packet,36.453000,__
+packet,36.411000,__
+packet,36.495000,__
+packet,36.620000,__
+packet,36.578000,__
+packet,36.662000,__
+packet,36.787000,__
+packet,36.703000,__
+packet,36.745000,__
+packet,36.995000,__
+packet,36.870000,__
+packet,36.828000,__
+packet,36.912000,__
+packet,36.954000,__
+packet,37.162000,__
+packet,37.079000,__
+packet,37.037000,__
+packet,37.120000,__
+packet,37.329000,__
+packet,37.246000,__
+packet,37.204000,__
+packet,37.287000,__
+packet,37.454000,__
+packet,37.371000,__
+packet,37.412000,__
+packet,37.579000,__
+packet,37.496000,__
+packet,37.538000,__
+packet,37.704000,__
+packet,37.621000,__
+packet,37.663000,__
+packet,37.955000,__
+packet,37.829000,__
+packet,37.746000,__
+packet,37.788000,__
+packet,37.871000,__
+packet,37.913000,__
+packet,38.163000,__
+packet,38.038000,__
+packet,37.996000,__
+packet,38.080000,__
+packet,38.121000,__
+packet,38.330000,__
+packet,38.247000,__
+packet,38.205000,__
+packet,38.288000,__
+packet,38.455000,__
+packet,38.372000,__
+packet,38.413000,__
+packet,38.539000,__
+packet,38.497000,__
+packet,38.705000,__
+packet,38.622000,__
+packet,38.580000,__
+packet,38.664000,__
+packet,38.914000,__
+packet,38.789000,__
+packet,38.747000,__
+packet,38.830000,__
+packet,38.872000,__
+packet,39.081000,__
+packet,38.997000,__
+packet,38.956000,__
+packet,39.039000,__
+packet,39.414000,__
+packet,39.248000,__
+packet,39.122000,__
+packet,39.164000,__
+packet,39.206000,__
+packet,39.289000,__
+packet,39.331000,__
+packet,39.373000,__
+packet,39.540000,__
+packet,39.456000,__
+packet,39.498000,__
+packet,39.581000,__
+packet,39.623000,K_
+packet,39.831000,__
+packet,39.706000,__
+packet,39.665000,__
+packet,39.748000,__
+packet,39.790000,__
+packet,39.998000,__
+packet,39.915000,__
+packet,39.873000,__
+packet,39.957000,__
+packet,40.165000,__
+packet,40.082000,__
+packet,40.040000,__
+packet,40.123000,__
+packet,40.290000,__
+packet,40.207000,__
+packet,40.249000,__
+packet,40.499000,__
+packet,40.374000,__
+packet,40.332000,__
+packet,40.415000,__
+packet,40.457000,__
+packet,40.666000,__
+packet,40.582000,__
+packet,40.541000,__
+packet,40.624000,__
+packet,40.707000,K_
+packet,40.832000,__
+packet,40.749000,__
+packet,40.791000,__
+packet,40.999000,__
+packet,40.916000,__
+packet,40.874000,__
+packet,40.958000,__
+packet,41.166000,__
+packet,41.083000,__
+packet,41.041000,__
+packet,41.124000,__
+packet,41.333000,__
+packet,41.250000,__
+packet,41.208000,__
+packet,41.291000,__
+packet,41.500000,__
+packet,41.416000,__
+packet,41.375000,__
+packet,41.458000,__
+packet,41.542000,__
+packet,41.583000,__
+packet,41.792000,__
+packet,41.667000,__
+packet,41.625000,__
+packet,41.708000,__
+packet,41.750000,__
+packet,41.917000,__
+packet,41.833000,__
+packet,41.875000,__
+packet,42.125000,__
+packet,42.000000,__
+packet,41.959000,__
+packet,42.042000,__
+packet,42.084000,__
+packet,42.251000,__
+packet,42.167000,__
+packet,42.209000,__
+packet,42.459000,__
+packet,42.334000,__
+packet,42.292000,__
+packet,42.376000,__
+packet,42.417000,__
+packet,42.626000,__
+packet,42.543000,__
+packet,42.501000,__
+packet,42.584000,__
+packet,42.751000,__
+packet,42.668000,__
+packet,42.709000,__
+packet,42.918000,__
+packet,42.834000,__
+packet,42.793000,__
+packet,42.876000,__
+packet,43.126000,__
+packet,43.001000,__
+packet,42.960000,__
+packet,43.043000,__
+packet,43.085000,__
+packet,43.210000,__
+packet,43.168000,__
+packet,43.252000,K_
+packet,43.418000,__
+packet,43.335000,__
+packet,43.293000,__
+packet,43.377000,__
+packet,43.544000,__
+packet,43.460000,__
+packet,43.502000,__
+packet,43.710000,__
+packet,43.627000,__
+packet,43.585000,__
+packet,43.669000,__
+packet,43.835000,__
+packet,43.752000,__
+packet,43.794000,__
+packet,44.002000,__
+packet,43.919000,__
+packet,43.877000,__
+packet,43.961000,__
+packet,44.169000,__
+packet,44.086000,__
+packet,44.044000,__
+packet,44.127000,__
+packet,44.336000,__
+packet,44.253000,__
+packet,44.211000,__
+packet,44.294000,__
+packet,44.503000,__
+packet,44.419000,__
+packet,44.378000,__
+packet,44.461000,__
+packet,44.670000,__
+packet,44.586000,__
+packet,44.545000,__
+packet,44.628000,__
+packet,44.878000,__
+packet,44.753000,__
+packet,44.711000,__
+packet,44.795000,__
+packet,44.836000,__
+packet,44.962000,__
+packet,44.920000,__
+packet,45.128000,__
+packet,45.045000,__
+packet,45.003000,__
+packet,45.087000,__
+packet,45.212000,__
+packet,45.170000,__
+packet,45.295000,__
+packet,45.254000,__
+packet,45.379000,__
+packet,45.337000,__
+packet,45.546000,__
+packet,45.462000,__
+packet,45.420000,__
+packet,45.504000,__
+packet,45.671000,__
+packet,45.587000,__
+packet,45.629000,__
+packet,45.837000,__
+packet,45.754000,__
+packet,45.712000,__
+packet,45.796000,__
+packet,46.004000,__
+packet,45.921000,__
+packet,45.879000,__
+packet,45.963000,__
+packet,46.088000,__
+packet,46.046000,__
+packet,46.171000,__
+packet,46.129000,__
+packet,46.296000,__
+packet,46.213000,__
+packet,46.255000,__
+packet,46.380000,__
+packet,46.338000,__
+packet,46.421000,__
+packet,46.505000,__
+packet,46.463000,__
+packet,46.672000,__
+packet,46.588000,__
+packet,46.547000,__
+packet,46.630000,__
+packet,46.880000,__
+packet,46.755000,__
+packet,46.713000,__
+packet,46.797000,__
+packet,46.838000,__
+packet,47.005000,__
+packet,46.922000,__
+packet,46.964000,__
+packet,47.089000,__
+packet,47.047000,__
+packet,47.297000,__
+packet,47.172000,__
+packet,47.130000,__
+packet,47.214000,__
+packet,47.256000,__
+packet,47.464000,__
+packet,47.381000,__
+packet,47.339000,__
+packet,47.422000,__
+packet,47.589000,__
+packet,47.506000,__
+packet,47.548000,__
+packet,47.631000,K_
+packet,47.798000,__
+packet,47.714000,__
+packet,47.673000,__
+packet,47.756000,__
+packet,48.006000,__
+packet,47.881000,__
+packet,47.839000,__
+packet,47.923000,__
+packet,47.965000,__
+packet,48.131000,__
+packet,48.048000,__
+packet,48.090000,__
+packet,48.340000,__
+packet,48.215000,__
+packet,48.173000,__
+packet,48.257000,__
+packet,48.298000,__
+packet,48.507000,__
+packet,48.423000,__
+packet,48.382000,__
+packet,48.465000,__
+packet,48.632000,__
+packet,48.549000,__
+packet,48.590000,__
+packet,48.715000,__
+packet,48.674000,__
+packet,48.882000,__
+packet,48.799000,__
+packet,48.757000,__
+packet,48.840000,__
+packet,49.049000,__
+packet,48.966000,__
+packet,48.924000,__
+packet,49.007000,__
+packet,49.216000,__
+packet,49.132000,__
+packet,49.091000,__
+packet,49.174000,__
+packet,49.424000,__
+packet,49.299000,__
+packet,49.258000,__
+packet,49.341000,__
+packet,49.383000,__
+packet,49.591000,__
+packet,49.508000,__
+packet,49.466000,__
+packet,49.550000,__
+packet,49.675000,__
+packet,49.633000,__
+packet,49.841000,__
+packet,49.758000,__
+packet,49.716000,__
+packet,49.800000,__
+packet,50.008000,__
+packet,49.925000,__
+packet,49.883000,__
+packet,49.967000,__
+packet,50.133000,__
+packet,50.050000,__
+packet,50.092000,__
+packet,50.217000,__
+packet,50.175000,__
+packet,50.425000,__
+packet,50.300000,__
+packet,50.259000,__
+packet,50.342000,__
+packet,50.384000,__
+packet,50.592000,__
+packet,50.509000,__
+packet,50.467000,__
+packet,50.551000,__
+packet,50.717000,__
+packet,50.634000,__
+packet,50.676000,__
+packet,50.884000,__
+packet,50.801000,__
+packet,50.759000,__
+packet,50.842000,__
+packet,51.051000,__
+packet,50.968000,__
+packet,50.926000,__
+packet,51.009000,__
+packet,51.218000,__
+packet,51.134000,__
+packet,51.093000,__
+packet,51.176000,__
+packet,51.426000,__
+packet,51.301000,__
+packet,51.260000,__
+packet,51.343000,__
+packet,51.385000,__
+packet,51.593000,__
+packet,51.510000,__
+packet,51.468000,__
+packet,51.552000,__
+packet,51.760000,__
+packet,51.677000,__
+packet,51.635000,__
+packet,51.718000,__
+packet,51.885000,__
+packet,51.802000,__
+packet,51.843000,__
+packet,52.094000,__
+packet,51.969000,__
+packet,51.927000,__
+packet,52.010000,__
+packet,52.052000,__
+packet,52.261000,__
+packet,52.177000,__
+packet,52.135000,__
+packet,52.219000,__
+packet,52.302000,K_
+packet,52.469000,__
+packet,52.386000,__
+packet,52.344000,__
+packet,52.427000,__
+packet,52.594000,__
+packet,52.511000,__
+packet,52.553000,__
+packet,52.761000,__
+packet,52.678000,__
+packet,52.636000,__
+packet,52.719000,__
+packet,52.844000,__
+packet,52.803000,__
+packet,52.928000,__
+packet,52.886000,__
+packet,53.095000,__
+packet,53.011000,__
+packet,52.970000,__
+packet,53.053000,__
+packet,53.262000,__
+packet,53.178000,__
+packet,53.136000,__
+packet,53.220000,__
+packet,53.470000,__
+packet,53.345000,__
+packet,53.303000,__
+packet,53.387000,__
+packet,53.428000,__
+packet,53.512000,__
+packet,53.554000,K_
+packet,53.637000,__
+packet,53.595000,__
+packet,53.887000,__
+packet,53.762000,__
+packet,53.679000,__
+packet,53.720000,__
+packet,53.804000,__
+packet,53.845000,__
+packet,54.096000,__
+packet,53.971000,__
+packet,53.929000,__
+packet,54.012000,__
+packet,54.054000,__
+packet,54.346000,__
+packet,54.221000,__
+packet,54.137000,__
+packet,54.179000,__
+packet,54.263000,__
+packet,54.304000,__
+packet,54.513000,__
+packet,54.429000,__
+packet,54.388000,__
+packet,54.471000,__
+packet,54.763000,__
+packet,54.638000,__
+packet,54.555000,__
+packet,54.596000,__
+packet,54.680000,__
+packet,54.721000,__
+packet,54.930000,__
+packet,54.846000,__
+packet,54.805000,__
+packet,54.888000,__
+packet,55.013000,__
+packet,54.972000,__
+packet,55.055000,K_
+packet,55.180000,__
+packet,55.097000,__
+packet,55.138000,__
+packet,55.305000,__
+packet,55.222000,__
+packet,55.264000,__
+packet,55.430000,__
+packet,55.347000,__
+packet,55.389000,__
+packet,55.556000,__
+packet,55.472000,__
+packet,55.514000,__
+packet,55.722000,__
+packet,55.639000,__
+packet,55.597000,__
+packet,55.681000,__
+packet,56.098000,__
+packet,55.889000,__
+packet,55.764000,__
+packet,55.806000,__
+packet,55.847000,__
+packet,55.931000,__
+packet,55.973000,__
+packet,56.014000,__
+packet,56.056000,__
+packet,56.265000,__
+packet,56.181000,__
+packet,56.139000,__
+packet,56.223000,__
+packet,56.473000,__
+packet,56.348000,__
+packet,56.306000,__
+packet,56.390000,__
+packet,56.431000,__
+packet,56.640000,__
+packet,56.557000,__
+packet,56.515000,__
+packet,56.598000,__
+packet,56.682000,__
+packet,56.807000,__
+packet,56.723000,__
+packet,56.765000,__
+packet,56.848000,__
+packet,56.890000,__
+packet,56.932000,__
+packet,57.057000,__
+packet,56.974000,__
+packet,57.015000,__
+packet,57.099000,__
+packet,57.224000,__
+packet,57.140000,__
+packet,57.182000,__
+packet,57.266000,__
+packet,57.307000,__
+packet,57.474000,__
+packet,57.391000,__
+packet,57.349000,__
+packet,57.432000,__
+packet,57.516000,__
+packet,57.641000,__
+packet,57.558000,__
+packet,57.599000,__
+packet,57.683000,__
+packet,57.724000,__
+packet,57.933000,__
+packet,57.808000,__
+packet,57.766000,__
+packet,57.849000,__
+packet,57.891000,__
+packet,58.058000,__
+packet,57.975000,__
+packet,58.016000,__
+packet,58.267000,__
+packet,58.141000,__
+packet,58.100000,__
+packet,58.183000,__
+packet,58.225000,__
+packet,58.392000,__
+packet,58.308000,__
+packet,58.350000,__
+packet,58.559000,__
+packet,58.475000,__
+packet,58.433000,__
+packet,58.517000,__
+packet,58.725000,__
+packet,58.642000,__
+packet,58.600000,__
+packet,58.684000,__
+packet,58.809000,__
+packet,58.767000,__
+packet,59.017000,__
+packet,58.892000,__
+packet,58.850000,__
+packet,58.934000,__
+packet,58.976000,__
+packet,59.184000,__
+packet,59.101000,__
+packet,59.059000,__
+packet,59.142000,__
+packet,59.518000,__
+packet,59.351000,__
+packet,59.226000,__
+packet,59.268000,__
+packet,59.309000,__
+packet,59.393000,__
+packet,59.434000,__
+packet,59.476000,__
+packet,59.601000,__
+packet,59.560000,__
+packet,59.768000,__
+packet,59.685000,__
+packet,59.643000,__
+packet,59.726000,__
+packet,59.935000,__
+packet,59.851000,__
+packet,59.810000,__
+packet,59.893000,__
+packet,60.269000,__
+packet,60.102000,__
+packet,59.977000,__
+packet,60.018000,__
+packet,60.060000,__
+packet,60.143000,__
+packet,60.185000,__
+packet,60.227000,__
+packet,60.477000,__
+packet,60.352000,__
+packet,60.310000,__
+packet,60.394000,__
+packet,60.435000,__
+packet,60.644000,__
+packet,60.561000,__
+packet,60.519000,__
+packet,60.602000,__
+packet,60.811000,__
+packet,60.727000,__
+packet,60.686000,__
+packet,60.769000,__
+packet,61.019000,__
+packet,60.894000,__
+packet,60.852000,__
+packet,60.936000,__
+packet,60.978000,__
+packet,61.228000,__
+packet,61.103000,__
+packet,61.061000,__
+packet,61.144000,__
+packet,61.186000,__
+packet,61.603000,__
+packet,61.395000,__
+packet,61.270000,__
+packet,61.311000,__
+packet,61.353000,__
+packet,61.436000,__
+packet,61.478000,__
+packet,61.520000,__
+packet,61.562000,__
+packet,61.979000,__
+packet,61.770000,__
+packet,61.645000,__
+packet,61.687000,__
+packet,61.728000,__
+packet,61.812000,__
+packet,61.853000,__
+packet,61.895000,__
+packet,61.937000,__
+packet,62.271000,__
+packet,62.104000,__
+packet,62.020000,__
+packet,62.062000,__
+packet,62.145000,__
+packet,62.187000,__
+packet,62.229000,__
+packet,62.396000,__
+packet,62.312000,__
+packet,62.354000,__
+packet,62.604000,__
+packet,62.479000,__
+packet,62.437000,__
+packet,62.521000,__
+packet,62.563000,__
+packet,62.896000,__
+packet,62.729000,__
+packet,62.646000,__
+packet,62.688000,__
+packet,62.771000,__
+packet,62.813000,__
+packet,62.854000,__
+packet,63.063000,__
+packet,62.980000,__
+packet,62.938000,__
+packet,63.021000,__
+packet,63.105000,K_
+packet,63.355000,__
+packet,63.230000,__
+packet,63.146000,__
+packet,63.188000,__
+packet,63.272000,__
+packet,63.313000,__
+packet,63.605000,__
+packet,63.480000,__
+packet,63.397000,__
+packet,63.438000,__
+packet,63.522000,__
+packet,63.564000,__
+packet,63.855000,__
+packet,63.730000,__
+packet,63.647000,__
+packet,63.689000,__
+packet,63.772000,__
+packet,63.814000,__
+packet,64.106000,__
+packet,63.981000,__
+packet,63.897000,__
+packet,63.939000,__
+packet,64.022000,__
+packet,64.064000,__
+packet,64.231000,__
+packet,64.147000,__
+packet,64.189000,__
+packet,64.606000,__
+packet,64.398000,__
+packet,64.273000,__
+packet,64.314000,__
+packet,64.356000,__
+packet,64.439000,__
+packet,64.481000,__
+packet,64.523000,__
+packet,64.565000,__
+packet,64.648000,K_
+packet,64.773000,__
+packet,64.690000,__
+packet,64.731000,__
+packet,64.898000,__
+packet,64.815000,__
+packet,64.856000,__
+packet,65.107000,__
+packet,64.982000,__
+packet,64.940000,__
+packet,65.023000,__
+packet,65.065000,__
+packet,65.274000,__
+packet,65.190000,__
+packet,65.148000,__
+packet,65.232000,__
+packet,65.649000,__
+packet,65.440000,__
+packet,65.315000,__
+packet,65.357000,__
+packet,65.399000,__
+packet,65.482000,__
+packet,65.524000,__
+packet,65.566000,__
+packet,65.607000,__
+packet,65.816000,__
+packet,65.732000,__
+packet,65.691000,__
+packet,65.774000,__
+packet,66.024000,__
+packet,65.899000,__
+packet,65.857000,__
+packet,65.941000,__
+packet,65.983000,__
+packet,66.191000,__
+packet,66.108000,__
+packet,66.066000,__
+packet,66.149000,__
+packet,66.233000,__
+packet,66.400000,__
+packet,66.316000,__
+packet,66.275000,__
+packet,66.358000,__
+packet,66.525000,__
+packet,66.441000,__
+packet,66.483000,__
+packet,66.567000,K_
+packet,66.733000,__
+packet,66.650000,__
+packet,66.608000,__
+packet,66.692000,__
+packet,66.984000,__
+packet,66.858000,__
+packet,66.775000,__
+packet,66.817000,__
+packet,66.900000,__
+packet,66.942000,__
+packet,67.359000,__
+packet,67.150000,__
+packet,67.025000,__
+packet,67.067000,__
+packet,67.109000,__
+packet,67.192000,__
+packet,67.234000,__
+packet,67.276000,__
+packet,67.317000,__
+packet,67.734000,__
+packet,67.526000,__
+packet,67.401000,__
+packet,67.442000,__
+packet,67.484000,__
+packet,67.568000,__
+packet,67.609000,__
+packet,67.651000,__
+packet,67.693000,__
+packet,67.859000,__
+packet,67.776000,__
+packet,67.818000,__
+packet,68.151000,__
+packet,67.985000,__
+packet,67.901000,__
+packet,67.943000,__
+packet,68.026000,__
+packet,68.068000,__
+packet,68.110000,__
+packet,68.402000,__
+packet,68.277000,__
+packet,68.193000,__
+packet,68.235000,__
+packet,68.318000,__
+packet,68.360000,__
+packet,68.610000,__
+packet,68.485000,__
+packet,68.443000,__
+packet,68.527000,__
+packet,68.569000,__
+packet,68.652000,K_
+packet,68.819000,__
+packet,68.735000,__
+packet,68.694000,__
+packet,68.777000,__
+packet,68.986000,__
+packet,68.902000,__
+packet,68.860000,__
+packet,68.944000,__
+packet,69.361000,__
+packet,69.152000,__
+packet,69.027000,__
+packet,69.069000,__
+packet,69.111000,__
+packet,69.194000,__
+packet,69.236000,__
+packet,69.278000,__
+packet,69.319000,__
+packet,69.444000,__
+packet,69.403000,__
+packet,69.820000,__
+packet,69.611000,__
+packet,69.486000,__
+packet,69.528000,__
+packet,69.570000,__
+packet,69.653000,__
+packet,69.695000,__
+packet,69.736000,__
+packet,69.778000,__
+packet,70.028000,__
+packet,69.903000,__
+packet,69.861000,__
+packet,69.945000,__
+packet,69.987000,__
+packet,70.195000,__
+packet,70.112000,__
+packet,70.070000,__
+packet,70.153000,__
+packet,70.529000,__
+packet,70.362000,__
+packet,70.237000,__
+packet,70.279000,__
+packet,70.320000,__
+packet,70.404000,__
+packet,70.445000,__
+packet,70.487000,__
+packet,70.862000,__
+packet,70.696000,__
+packet,70.571000,__
+packet,70.612000,__
+packet,70.654000,__
+packet,70.737000,__
+packet,70.779000,__
+packet,70.821000,__
+packet,71.029000,__
+packet,70.946000,__
+packet,70.904000,__
+packet,70.988000,__
+packet,71.280000,__
+packet,71.154000,__
+packet,71.071000,__
+packet,71.113000,__
+packet,71.196000,__
+packet,71.238000,__
+packet,71.488000,__
+packet,71.363000,__
+packet,71.321000,__
+packet,71.405000,__
+packet,71.446000,__
+packet,71.863000,__
+packet,71.655000,__
+packet,71.530000,__
+packet,71.572000,__
+packet,71.613000,__
+packet,71.697000,__
+packet,71.738000,__
+packet,71.780000,__
+packet,71.822000,__
+packet,72.114000,__
+packet,71.989000,__
+packet,71.905000,__
+packet,71.947000,__
+packet,72.030000,__
+packet,72.072000,__
+packet,72.281000,__
+packet,72.197000,__
+packet,72.155000,__
+packet,72.239000,__
+packet,72.406000,__
+packet,72.322000,__
+packet,72.364000,__
+packet,72.614000,__
+packet,72.489000,__
+packet,72.447000,__
+packet,72.531000,__
+packet,72.573000,__
+packet,72.739000,__
+packet,72.656000,__
+packet,72.698000,__
+packet,73.031000,__
+packet,72.864000,__
+packet,72.781000,__
+packet,72.823000,__
+packet,72.906000,__
+packet,72.948000,__
+packet,72.990000,__
+packet,73.198000,__
+packet,73.115000,__
+packet,73.073000,__
+packet,73.156000,__
+packet,73.240000,K_
+packet,73.407000,__
+packet,73.323000,__
+packet,73.282000,__
+packet,73.365000,__
+packet,73.532000,__
+packet,73.448000,__
+packet,73.490000,__
+packet,73.699000,__
+packet,73.615000,__
+packet,73.574000,__
+packet,73.657000,__
+packet,73.865000,__
+packet,73.782000,__
+packet,73.740000,__
+packet,73.824000,__
+packet,74.032000,__
+packet,73.949000,__
+packet,73.907000,__
+packet,73.991000,__
+packet,74.199000,__
+packet,74.116000,__
+packet,74.074000,__
+packet,74.157000,__
+packet,74.283000,__
+packet,74.241000,__
+packet,74.408000,__
+packet,74.324000,__
+packet,74.366000,__
+packet,74.533000,__
+packet,74.449000,__
+packet,74.491000,__
+packet,74.700000,__
+packet,74.616000,__
+packet,74.575000,__
+packet,74.658000,__
+packet,74.866000,__
+packet,74.783000,__
+packet,74.741000,__
+packet,74.825000,__
+packet,75.033000,__
+packet,74.950000,__
+packet,74.908000,__
+packet,74.992000,__
+packet,75.200000,__
+packet,75.117000,__
+packet,75.075000,__
+packet,75.158000,__
+packet,75.409000,__
+packet,75.284000,__
+packet,75.242000,__
+packet,75.325000,__
+packet,75.367000,__
+packet,75.784000,__
+packet,75.576000,__
+packet,75.450000,__
+packet,75.492000,__
+packet,75.534000,__
+packet,75.617000,__
+packet,75.659000,__
+packet,75.701000,__
+packet,75.742000,__
+packet,75.826000,__
+packet,76.201000,__
+packet,75.993000,__
+packet,75.867000,__
+packet,75.909000,__
+packet,75.951000,__
+packet,76.034000,__
+packet,76.076000,__
+packet,76.118000,__
+packet,76.159000,__
+packet,76.368000,__
+packet,76.285000,__
+packet,76.243000,__
+packet,76.326000,__
+packet,76.451000,__
+packet,76.410000,__
+packet,76.618000,__
+packet,76.535000,__
+packet,76.493000,__
+packet,76.577000,__
+packet,76.827000,__
+packet,76.702000,__
+packet,76.660000,__
+packet,76.743000,__
+packet,76.785000,__
+packet,76.952000,__
+packet,76.868000,__
+packet,76.910000,__
+packet,77.160000,__
+packet,77.035000,__
+packet,76.994000,__
+packet,77.077000,__
+packet,77.119000,__
+packet,77.202000,K_
+packet,77.369000,__
+packet,77.286000,__
+packet,77.244000,__
+packet,77.327000,__
+packet,77.536000,__
+packet,77.452000,__
+packet,77.411000,__
+packet,77.494000,__
+packet,77.661000,__
+packet,77.578000,__
+packet,77.619000,__
+packet,77.828000,__
+packet,77.744000,__
+packet,77.703000,__
+packet,77.786000,__
+packet,77.953000,__
+packet,77.869000,__
+packet,77.911000,__
+packet,78.036000,__
+packet,77.995000,__
+packet,78.245000,__
+packet,78.120000,__
+packet,78.078000,__
+packet,78.161000,__
+packet,78.203000,__
+packet,78.328000,__
+packet,78.287000,__
+packet,78.495000,__
+packet,78.412000,__
+packet,78.370000,__
+packet,78.453000,__
+packet,78.620000,__
+packet,78.537000,__
+packet,78.579000,__
+packet,78.787000,__
+packet,78.704000,__
+packet,78.662000,__
+packet,78.745000,__
+packet,79.037000,__
+packet,78.912000,__
+packet,78.829000,__
+packet,78.870000,__
+packet,78.954000,__
+packet,78.996000,__
+packet,79.288000,__
+packet,79.162000,__
+packet,79.079000,__
+packet,79.121000,__
+packet,79.204000,__
+packet,79.246000,__
+packet,79.538000,__
+packet,79.413000,__
+packet,79.329000,__
+packet,79.371000,__
+packet,79.454000,__
+packet,79.496000,__
+packet,79.580000,__
+packet,79.621000,K_
+packet,79.663000,__
+packet,79.997000,__
+packet,79.830000,__
+packet,79.705000,__
+packet,79.746000,__
+packet,79.788000,__
+packet,79.871000,__
+packet,79.913000,__
+packet,79.955000,__
+packet,80.038000,__
+packet,80.247000,__
+packet,80.122000,__
+packet,80.080000,__
+packet,80.163000,__
+packet,80.205000,__
+packet,80.372000,__
+packet,80.289000,__
+packet,80.330000,__
+packet,80.539000,__
+packet,80.455000,__
+packet,80.414000,__
+packet,80.497000,__
+packet,80.706000,__
+packet,80.622000,__
+packet,80.581000,__
+packet,80.664000,__
+packet,80.872000,__
+packet,80.789000,__
+packet,80.747000,__
+packet,80.831000,__
+packet,81.039000,__
+packet,80.956000,__
+packet,80.914000,__
+packet,80.998000,__
+packet,81.248000,__
+packet,81.123000,__
+packet,81.081000,__
+packet,81.164000,__
+packet,81.206000,__
+packet,81.290000,__
+packet,81.456000,__
+packet,81.373000,__
+packet,81.331000,__
+packet,81.415000,__
+packet,81.623000,__
+packet,81.540000,__
+packet,81.498000,__
+packet,81.582000,__
+packet,81.999000,__
+packet,81.790000,__
+packet,81.665000,__
+packet,81.707000,__
+packet,81.748000,__
+packet,81.832000,__
+packet,81.873000,__
+packet,81.915000,__
+packet,81.957000,__
+packet,82.040000,__
+packet,82.249000,__
+packet,82.124000,__
+packet,82.082000,__
+packet,82.165000,__
+packet,82.207000,__
+packet,82.291000,__
+packet,82.541000,__
+packet,82.416000,__
+packet,82.332000,__
+packet,82.374000,__
+packet,82.457000,__
+packet,82.499000,__
+packet,82.916000,__
+packet,82.708000,__
+packet,82.583000,__
+packet,82.624000,__
+packet,82.666000,__
+packet,82.749000,__
+packet,82.791000,__
+packet,82.833000,__
+packet,82.874000,__
+packet,83.166000,__
+packet,83.041000,__
+packet,82.958000,__
+packet,83.000000,__
+packet,83.083000,__
+packet,83.125000,__
+packet,83.458000,__
+packet,83.292000,__
+packet,83.208000,__
+packet,83.250000,__
+packet,83.333000,__
+packet,83.375000,__
+packet,83.417000,__
+packet,83.584000,__
+packet,83.500000,__
+packet,83.542000,__
+packet,83.667000,__
+packet,83.625000,__
+packet,83.792000,__
+packet,83.709000,__
+packet,83.750000,__
+packet,83.959000,__
+packet,83.875000,__
+packet,83.834000,__
+packet,83.917000,__
+packet,84.167000,__
+packet,84.042000,__
+packet,84.001000,__
+packet,84.084000,__
+packet,84.126000,__
+packet,84.293000,__
+packet,84.209000,__
+packet,84.251000,__
+packet,84.459000,__
+packet,84.376000,__
+packet,84.334000,__
+packet,84.418000,__
+packet,84.751000,__
+packet,84.585000,__
+packet,84.501000,__
+packet,84.543000,__
+packet,84.626000,__
+packet,84.668000,__
+packet,84.710000,__
+packet,84.918000,__
+packet,84.835000,__
+packet,84.793000,__
+packet,84.876000,__
+packet,85.168000,__
+packet,85.043000,__
+packet,84.960000,__
+packet,85.002000,__
+packet,85.085000,__
+packet,85.127000,__
+packet,85.502000,__
+packet,85.335000,__
+packet,85.210000,__
+packet,85.252000,__
+packet,85.294000,__
+packet,85.377000,__
+packet,85.419000,__
+packet,85.460000,__
+packet,85.586000,__
+packet,85.544000,__
+packet,85.627000,__
+packet,85.669000,K_
+packet,85.752000,__
+packet,85.711000,__
+packet,85.919000,__
+packet,85.836000,__
+packet,85.794000,__
+packet,85.877000,__
+packet,86.044000,__
+packet,85.961000,__
+packet,86.003000,__
+packet,86.253000,__
+packet,86.128000,__
+packet,86.086000,__
+packet,86.169000,__
+packet,86.211000,__
+packet,86.461000,__
+packet,86.336000,__
+packet,86.295000,__
+packet,86.378000,__
+packet,86.420000,__
+packet,86.628000,__
+packet,86.545000,__
+packet,86.503000,__
+packet,86.587000,__
+packet,86.795000,__
+packet,86.712000,__
+packet,86.670000,__
+packet,86.753000,__
+packet,86.962000,__
+packet,86.878000,__
+packet,86.837000,__
+packet,86.920000,__
+packet,87.129000,__
+packet,87.045000,__
+packet,87.004000,__
+packet,87.087000,__
+packet,87.296000,__
+packet,87.212000,__
+packet,87.170000,__
+packet,87.254000,__
+packet,87.462000,__
+packet,87.379000,__
+packet,87.337000,__
+packet,87.421000,__
+packet,87.838000,__
+packet,87.629000,__
+packet,87.504000,__
+packet,87.546000,__
+packet,87.588000,__
+packet,87.671000,__
+packet,87.713000,__
+packet,87.754000,__
+packet,87.796000,__
+packet,87.921000,__
+packet,87.879000,__
+packet,88.046000,__
+packet,87.963000,__
+packet,88.005000,__
+packet,88.255000,__
+packet,88.130000,__
+packet,88.088000,__
+packet,88.171000,__
+packet,88.213000,__
+packet,88.297000,__
+packet,88.463000,__
+packet,88.380000,__
+packet,88.338000,__
+packet,88.422000,__
+packet,88.630000,__
+packet,88.547000,__
+packet,88.505000,__
+packet,88.589000,__
+packet,88.755000,__
+packet,88.672000,__
+packet,88.714000,__
+packet,88.797000,K_
+packet,88.880000,__
+packet,88.839000,__
+packet,88.922000,__
+packet,88.964000,__
+packet,89.131000,__
+packet,89.047000,__
+packet,89.006000,__
+packet,89.089000,__
+packet,89.506000,__
+packet,89.298000,__
+packet,89.172000,__
+packet,89.214000,__
+packet,89.256000,__
+packet,89.339000,__
+packet,89.381000,__
+packet,89.423000,__
+packet,89.464000,__
+packet,89.756000,__
+packet,89.631000,__
+packet,89.548000,__
+packet,89.590000,__
+packet,89.673000,__
+packet,89.715000,__
+packet,89.881000,__
+packet,89.798000,__
+packet,89.840000,__
+packet,90.090000,__
+packet,89.965000,__
+packet,89.923000,__
+packet,90.007000,__
+packet,90.048000,__
+packet,90.340000,__
+packet,90.215000,__
+packet,90.132000,__
+packet,90.173000,__
+packet,90.257000,__
+packet,90.299000,__
+packet,90.382000,K_
+packet,90.591000,__
+packet,90.465000,__
+packet,90.424000,__
+packet,90.507000,__
+packet,90.549000,__
+packet,90.841000,__
+packet,90.716000,__
+packet,90.632000,__
+packet,90.674000,__
+packet,90.757000,__
+packet,90.799000,__
+packet,90.882000,__
+packet,91.049000,__
+packet,90.966000,__
+packet,90.924000,__
+packet,91.008000,__
+packet,91.258000,__
+packet,91.133000,__
+packet,91.091000,__
+packet,91.174000,__
+packet,91.216000,__
+packet,91.550000,__
+packet,91.383000,__
+packet,91.300000,__
+packet,91.341000,__
+packet,91.425000,__
+packet,91.466000,__
+packet,91.508000,__
+packet,91.758000,__
+packet,91.633000,__
+packet,91.592000,__
+packet,91.675000,__
+packet,91.717000,__
+packet,92.009000,__
+packet,91.883000,__
+packet,91.800000,__
+packet,91.842000,__
+packet,91.925000,__
+packet,91.967000,__
+packet,92.259000,__
+packet,92.134000,__
+packet,92.050000,__
+packet,92.092000,__
+packet,92.175000,__
+packet,92.217000,__
+packet,92.634000,__
+packet,92.426000,__
+packet,92.301000,__
+packet,92.342000,__
+packet,92.384000,__
+packet,92.467000,__
+packet,92.509000,__
+packet,92.551000,__
+packet,92.593000,__
+packet,92.926000,__
+packet,92.759000,__
+packet,92.676000,__
+packet,92.718000,__
+packet,92.801000,__
+packet,92.843000,__
+packet,92.884000,__
+packet,93.176000,__
+packet,93.051000,__
+packet,92.968000,__
+packet,93.010000,__
+packet,93.093000,__
+packet,93.135000,__
+packet,93.385000,__
+packet,93.260000,__
+packet,93.218000,__
+packet,93.302000,__
+packet,93.343000,__
+packet,93.427000,K_
+packet,93.468000,__
+packet,93.552000,__
+packet,93.510000,__
+packet,93.719000,__
+packet,93.635000,__
+packet,93.594000,__
+packet,93.677000,__
+packet,93.969000,__
+packet,93.844000,__
+packet,93.760000,__
+packet,93.802000,__
+packet,93.885000,__
+packet,93.927000,__
+packet,94.094000,__
+packet,94.011000,__
+packet,94.052000,__
+packet,94.136000,__
+packet,94.303000,__
+packet,94.219000,__
+packet,94.177000,__
+packet,94.261000,__
+packet,94.511000,__
+packet,94.386000,__
+packet,94.344000,__
+packet,94.428000,__
+packet,94.469000,__
+packet,94.636000,__
+packet,94.553000,__
+packet,94.595000,__
+packet,94.803000,__
+packet,94.720000,__
+packet,94.678000,__
+packet,94.761000,__
+packet,94.886000,__
+packet,94.845000,__
+packet,95.012000,__
+packet,94.928000,__
+packet,94.970000,__
+packet,95.053000,__
+packet,95.220000,__
+packet,95.137000,__
+packet,95.095000,__
+packet,95.178000,__
+packet,95.387000,__
+packet,95.304000,__
+packet,95.262000,__
+packet,95.345000,__
+packet,95.679000,__
+packet,95.512000,__
+packet,95.429000,__
+packet,95.470000,__
+packet,95.554000,__
+packet,95.596000,__
+packet,95.637000,__
+packet,95.762000,__
+packet,95.721000,__
+packet,96.138000,__
+packet,95.929000,__
+packet,95.804000,__
+packet,95.846000,__
+packet,95.887000,__
+packet,95.971000,__
+packet,96.013000,__
+packet,96.054000,__
+packet,96.096000,__
+packet,96.430000,__
+packet,96.263000,__
+packet,96.179000,__
+packet,96.221000,__
+packet,96.305000,__
+packet,96.346000,__
+packet,96.388000,__
+packet,96.722000,__
+packet,96.555000,__
+packet,96.471000,__
+packet,96.513000,__
+packet,96.597000,__
+packet,96.638000,__
+packet,96.680000,__
+packet,96.930000,__
+packet,96.805000,__
+packet,96.763000,__
+packet,96.847000,__
+packet,96.888000,__
+packet,97.014000,__
+packet,96.972000,__
+packet,97.055000,__
+packet,97.264000,__
+packet,97.139000,__
+packet,97.097000,__
+packet,97.180000,__
+packet,97.222000,__
+packet,97.306000,__
+packet,97.431000,__
+packet,97.347000,__
+packet,97.389000,__
+packet,97.556000,__
+packet,97.472000,__
+packet,97.514000,__
+packet,97.806000,__
+packet,97.681000,__
+packet,97.598000,__
+packet,97.639000,__
+packet,97.723000,__
+packet,97.764000,__
+packet,97.931000,__
+packet,97.848000,__
+packet,97.889000,__
+packet,98.056000,__
+packet,97.973000,__
+packet,98.015000,__
+packet,98.181000,__
+packet,98.098000,__
+packet,98.140000,__
+packet,98.265000,__
+packet,98.223000,__
+packet,98.307000,K_
+packet,98.390000,__
+packet,98.348000,__
+packet,98.515000,__
+packet,98.432000,__
+packet,98.473000,__
+packet,98.599000,__
+packet,98.557000,__
+packet,98.765000,__
+packet,98.682000,__
+packet,98.640000,__
+packet,98.724000,__
+packet,98.974000,__
+packet,98.849000,__
+packet,98.807000,__
+packet,98.890000,__
+packet,98.932000,__
+packet,99.016000,__
+packet,99.182000,__
+packet,99.099000,__
+packet,99.057000,__
+packet,99.141000,__
+packet,99.391000,__
+packet,99.266000,__
+packet,99.224000,__
+packet,99.308000,__
+packet,99.349000,__
+packet,99.641000,__
+packet,99.516000,__
+packet,99.433000,__
+packet,99.474000,__
+packet,99.558000,__
+packet,99.600000,__
+packet,99.891000,__
+packet,99.766000,__
+packet,99.683000,__
+packet,99.725000,__
+packet,99.808000,__
+packet,99.850000,__
+packet,100.058000,__
+packet,99.975000,__
+packet,99.933000,__
+packet,100.017000,__
+packet,100.142000,__
+packet,100.100000,__
+packet,100.309000,__
+packet,100.225000,__
+packet,100.183000,__
+packet,100.267000,__
+packet,100.434000,__
+packet,100.350000,__
+packet,100.392000,__
+packet,100.642000,__
+packet,100.517000,__
+packet,100.475000,__
+packet,100.559000,__
+packet,100.601000,__
+packet,100.809000,__
+packet,100.726000,__
+packet,100.684000,__
+packet,100.767000,__
+packet,100.976000,__
+packet,100.892000,__
+packet,100.851000,__
+packet,100.934000,__
+packet,101.143000,__
+packet,101.059000,__
+packet,101.018000,__
+packet,101.101000,__
+packet,101.351000,__
+packet,101.226000,__
+packet,101.184000,__
+packet,101.268000,__
+packet,101.310000,__
+packet,101.518000,__
+packet,101.435000,__
+packet,101.393000,__
+packet,101.476000,__
+packet,101.685000,__
+packet,101.602000,__
+packet,101.560000,__
+packet,101.643000,__
+packet,101.935000,__
+packet,101.810000,__
+packet,101.727000,__
+packet,101.768000,__
+packet,101.852000,__
+packet,101.893000,__
+packet,102.102000,__
+packet,102.019000,__
+packet,101.977000,__
+packet,102.060000,__
+packet,102.269000,__
+packet,102.185000,__
+packet,102.144000,__
+packet,102.227000,__
+packet,102.519000,__
+packet,102.394000,__
+packet,102.311000,__
+packet,102.352000,__
+packet,102.436000,__
+packet,102.477000,__
+packet,102.686000,__
+packet,102.603000,__
+packet,102.561000,__
+packet,102.644000,__
+packet,102.853000,__
+packet,102.769000,__
+packet,102.728000,__
+packet,102.811000,__
+packet,103.061000,__
+packet,102.936000,__
+packet,102.894000,__
+packet,102.978000,__
+packet,103.020000,__
+packet,103.270000,__
+packet,103.145000,__
+packet,103.103000,__
+packet,103.186000,__
+packet,103.228000,__
+packet,103.353000,__
+packet,103.312000,__
+packet,103.562000,__
+packet,103.437000,__
+packet,103.395000,__
+packet,103.478000,__
+packet,103.520000,__
+packet,103.687000,__
+packet,103.604000,__
+packet,103.645000,__
+packet,103.979000,__
+packet,103.812000,__
+packet,103.729000,__
+packet,103.770000,__
+packet,103.854000,__
+packet,103.895000,__
+packet,103.937000,__
+packet,104.229000,__
+packet,104.104000,__
+packet,104.021000,__
+packet,104.062000,__
+packet,104.146000,__
+packet,104.187000,__
+packet,104.396000,__
+packet,104.313000,__
+packet,104.271000,__
+packet,104.354000,__
+packet,104.563000,__
+packet,104.479000,__
+packet,104.438000,__
+packet,104.521000,__
+packet,104.730000,__
+packet,104.646000,__
+packet,104.605000,__
+packet,104.688000,__
+packet,104.896000,__
+packet,104.813000,__
+packet,104.771000,__
+packet,104.855000,__
+packet,104.938000,__
+packet,105.063000,__
+packet,104.980000,__
+packet,105.022000,__
+packet,105.188000,__
+packet,105.105000,__
+packet,105.147000,__
+packet,105.397000,__
+packet,105.272000,__
+packet,105.230000,__
+packet,105.314000,__
+packet,105.355000,__
+packet,105.522000,__
+packet,105.439000,__
+packet,105.480000,__
+packet,105.564000,__
+packet,105.606000,K_
+packet,105.814000,__
+packet,105.689000,__
+packet,105.647000,__
+packet,105.731000,__
+packet,105.772000,__
+packet,105.981000,__
+packet,105.897000,__
+packet,105.856000,__
+packet,105.939000,__
+packet,106.148000,__
+packet,106.064000,__
+packet,106.023000,__
+packet,106.106000,__
+packet,106.273000,__
+packet,106.189000,__
+packet,106.231000,__
+packet,106.440000,__
+packet,106.356000,__
+packet,106.315000,__
+packet,106.398000,__
+packet,106.607000,__
+packet,106.523000,__
+packet,106.481000,__
+packet,106.565000,__
+packet,106.690000,__
+packet,106.648000,__
+packet,106.857000,__
+packet,106.773000,__
+packet,106.732000,__
+packet,106.815000,__
+packet,107.065000,__
+packet,106.940000,__
+packet,106.898000,__
+packet,106.982000,__
+packet,107.024000,__
+packet,107.232000,__
+packet,107.149000,__
+packet,107.107000,__
+packet,107.190000,__
+packet,107.357000,__
+packet,107.274000,__
+packet,107.316000,__
+packet,107.649000,__
+packet,107.482000,__
+packet,107.399000,__
+packet,107.441000,__
+packet,107.524000,__
+packet,107.566000,__
+packet,107.608000,__
+packet,107.816000,__
+packet,107.733000,__
+packet,107.691000,__
+packet,107.774000,__
+packet,108.025000,__
+packet,107.899000,__
+packet,107.858000,__
+packet,107.941000,__
+packet,107.983000,__
+packet,108.317000,__
+packet,108.150000,__
+packet,108.066000,__
+packet,108.108000,__
+packet,108.191000,__
+packet,108.233000,__
+packet,108.275000,__
+packet,108.567000,__
+packet,108.442000,__
+packet,108.358000,__
+packet,108.400000,__
+packet,108.483000,__
+packet,108.525000,__
+packet,108.734000,__
+packet,108.650000,__
+packet,108.609000,__
+packet,108.692000,__
+packet,108.775000,K_
+packet,108.859000,__
+packet,108.817000,__
+packet,109.192000,__
+packet,109.026000,__
+packet,108.900000,__
+packet,108.942000,__
+packet,108.984000,__
+packet,109.067000,__
+packet,109.109000,__
+packet,109.151000,__
+packet,109.443000,__
+packet,109.318000,__
+packet,109.234000,__
+packet,109.276000,__
+packet,109.359000,__
+packet,109.401000,__
+packet,109.568000,__
+packet,109.484000,__
+packet,109.526000,__
+packet,109.818000,__
+packet,109.693000,__
+packet,109.610000,__
+packet,109.651000,__
+packet,109.735000,__
+packet,109.776000,__
+packet,110.027000,__
+packet,109.901000,__
+packet,109.860000,__
+packet,109.943000,__
+packet,109.985000,__
+packet,110.402000,__
+packet,110.193000,__
+packet,110.068000,__
+packet,110.110000,__
+packet,110.152000,__
+packet,110.235000,__
+packet,110.277000,__
+packet,110.319000,__
+packet,110.360000,__
+packet,110.777000,__
+packet,110.569000,__
+packet,110.444000,__
+packet,110.485000,__
+packet,110.527000,__
+packet,110.611000,__
+packet,110.652000,__
+packet,110.694000,__
+packet,110.736000,__
+packet,110.944000,__
+packet,110.861000,__
+packet,110.819000,__
+packet,110.902000,__
+packet,111.069000,__
+packet,110.986000,__
+packet,111.028000,__
+packet,111.236000,__
+packet,111.153000,__
+packet,111.111000,__
+packet,111.194000,__
+packet,111.445000,__
+packet,111.320000,__
+packet,111.278000,__
+packet,111.361000,__
+packet,111.403000,__
+packet,111.612000,__
+packet,111.528000,__
+packet,111.486000,__
+packet,111.570000,__
+packet,111.778000,__
+packet,111.695000,__
+packet,111.653000,__
+packet,111.737000,__
+packet,112.029000,__
+packet,111.903000,__
+packet,111.820000,__
+packet,111.862000,__
+packet,111.945000,__
+packet,111.987000,__
+packet,112.195000,__
+packet,112.112000,__
+packet,112.070000,__
+packet,112.154000,__
+packet,112.571000,__
+packet,112.362000,__
+packet,112.237000,__
+packet,112.279000,__
+packet,112.321000,__
+packet,112.404000,__
+packet,112.446000,__
+packet,112.487000,__
+packet,112.529000,__
+packet,112.821000,__
+packet,112.696000,__
+packet,112.613000,__
+packet,112.654000,__
+packet,112.738000,__
+packet,112.779000,__
+packet,113.196000,__
+packet,112.988000,__
+packet,112.863000,__
+packet,112.904000,__
+packet,112.946000,__
+packet,113.030000,__
+packet,113.071000,__
+packet,113.113000,__
+packet,113.155000,__
+packet,113.363000,__
+packet,113.280000,__
+packet,113.238000,__
+packet,113.322000,__
+packet,113.447000,__
+packet,113.405000,__
+packet,113.614000,__
+packet,113.530000,__
+packet,113.488000,__
+packet,113.572000,__
+packet,113.739000,__
+packet,113.655000,__
+packet,113.697000,__
+packet,113.905000,__
+packet,113.822000,__
+packet,113.780000,__
+packet,113.864000,__
+packet,114.072000,__
+packet,113.989000,__
+packet,113.947000,__
+packet,114.031000,__
+packet,114.281000,__
+packet,114.156000,__
+packet,114.114000,__
+packet,114.197000,__
+packet,114.239000,__
+packet,114.656000,__
+packet,114.448000,__
+packet,114.323000,__
+packet,114.364000,__
+packet,114.406000,__
+packet,114.489000,__
+packet,114.531000,__
+packet,114.573000,__
+packet,114.615000,__
+packet,114.990000,__
+packet,114.823000,__
+packet,114.698000,__
+packet,114.740000,__
+packet,114.781000,__
+packet,114.865000,__
+packet,114.906000,__
+packet,114.948000,__
+packet,115.157000,__
+packet,115.073000,__
+packet,115.032000,__
+packet,115.115000,__
+packet,115.324000,__
+packet,115.240000,__
+packet,115.198000,__
+packet,115.282000,__
+packet,115.365000,__
+packet,115.407000,__
+packet,115.532000,__
+packet,115.449000,__
+packet,115.490000,__
+packet,115.657000,__
+packet,115.574000,__
+packet,115.616000,__
+packet,115.824000,__
+packet,115.741000,__
+packet,115.699000,__
+packet,115.782000,__
+packet,116.033000,__
+packet,115.907000,__
+packet,115.866000,__
+packet,115.949000,__
+packet,115.991000,__
+packet,116.158000,__
+packet,116.074000,__
+packet,116.116000,__
+packet,116.533000,__
+packet,116.325000,__
+packet,116.199000,__
+packet,116.241000,__
+packet,116.283000,__
+packet,116.366000,__
+packet,116.408000,__
+packet,116.450000,__
+packet,116.491000,__
+packet,116.575000,__
+packet,116.742000,__
+packet,116.658000,__
+packet,116.617000,__
+packet,116.700000,__
+packet,116.908000,__
+packet,116.825000,__
+packet,116.783000,__
+packet,116.867000,__
+packet,117.075000,__
+packet,116.992000,__
+packet,116.950000,__
+packet,117.034000,__
+packet,117.326000,__
+packet,117.200000,__
+packet,117.117000,__
+packet,117.159000,__
+packet,117.242000,__
+packet,117.284000,__
+packet,117.492000,__
+packet,117.409000,__
+packet,117.367000,__
+packet,117.451000,__
+packet,117.701000,__
+packet,117.576000,__
+packet,117.534000,__
+packet,117.618000,__
+packet,117.659000,__
+packet,118.035000,__
+packet,117.868000,__
+packet,117.743000,__
+packet,117.784000,__
+packet,117.826000,__
+packet,117.909000,__
+packet,117.951000,__
+packet,117.993000,__
+packet,118.327000,__
+packet,118.160000,__
+packet,118.076000,__
+packet,118.118000,__
+packet,118.201000,__
+packet,118.243000,__
+packet,118.285000,__
+packet,118.535000,__
+packet,118.410000,__
+packet,118.368000,__
+packet,118.452000,__
+packet,118.493000,__
+packet,118.744000,__
+packet,118.619000,__
+packet,118.577000,__
+packet,118.660000,__
+packet,118.702000,__
+packet,118.785000,K_
+packet,118.910000,__
+packet,118.827000,__
+packet,118.869000,__
+packet,119.077000,__
+packet,118.994000,__
+packet,118.952000,__
+packet,119.036000,__
+packet,119.244000,__
+packet,119.161000,__
+packet,119.119000,__
+packet,119.202000,__
+packet,119.620000,__
+packet,119.411000,__
+packet,119.286000,__
+packet,119.328000,__
+packet,119.369000,__
+packet,119.453000,__
+packet,119.494000,__
+packet,119.536000,__
+packet,119.578000,__
+packet,119.786000,__
+packet,119.703000,__
+packet,119.661000,__
+packet,119.745000,__
+packet,120.037000,__
+packet,119.911000,__
+packet,119.828000,__
+packet,119.870000,__
+packet,119.953000,__
+packet,119.995000,__
+packet,120.287000,__
+packet,120.162000,__
+packet,120.078000,__
+packet,120.120000,__
+packet,120.203000,__
+packet,120.245000,__
+packet,120.621000,__
+packet,120.454000,__
+packet,120.329000,__
+packet,120.370000,__
+packet,120.412000,__
+packet,120.495000,__
+packet,120.537000,__
+packet,120.579000,__
+packet,120.746000,__
+packet,120.662000,__
+packet,120.704000,__
+packet,120.912000,__
+packet,120.829000,__
+packet,120.787000,__
+packet,120.871000,__
+packet,121.121000,__
+packet,120.996000,__
+packet,120.954000,__
+packet,121.038000,__
+packet,121.079000,__
+packet,121.330000,__
+packet,121.204000,__
+packet,121.163000,__
+packet,121.246000,__
+packet,121.288000,__
+packet,121.580000,__
+packet,121.455000,__
+packet,121.371000,__
+packet,121.413000,__
+packet,121.496000,__
+packet,121.538000,__
+packet,121.622000,__
+packet,121.788000,__
+packet,121.705000,__
+packet,121.663000,__
+packet,121.747000,__
+packet,122.080000,__
+packet,121.913000,__
+packet,121.830000,__
+packet,121.872000,__
+packet,121.955000,__
+packet,121.997000,__
+packet,122.039000,__
+packet,122.164000,__
+packet,122.122000,__
+packet,122.205000,K_
+packet,122.331000,__
+packet,122.247000,__
+packet,122.289000,__
+packet,122.664000,__
+packet,122.497000,__
+packet,122.372000,__
+packet,122.414000,__
+packet,122.456000,__
+packet,122.539000,__
+packet,122.581000,__
+packet,122.623000,__
+packet,122.998000,__
+packet,122.831000,__
+packet,122.706000,__
+packet,122.748000,__
+packet,122.789000,__
+packet,122.873000,__
+packet,122.914000,__
+packet,122.956000,__
+packet,123.165000,__
+packet,123.081000,__
+packet,123.040000,__
+packet,123.123000,__
+packet,123.290000,__
+packet,123.206000,__
+packet,123.248000,__
+packet,123.624000,__
+packet,123.457000,__
+packet,123.332000,__
+packet,123.373000,__
+packet,123.415000,__
+packet,123.498000,__
+packet,123.540000,__
+packet,123.582000,__
+packet,123.999000,__
+packet,123.790000,__
+packet,123.665000,__
+packet,123.707000,__
+packet,123.749000,__
+packet,123.832000,__
+packet,123.874000,__
+packet,123.915000,__
+packet,123.957000,__
+packet,124.249000,__
+packet,124.124000,__
+packet,124.041000,__
+packet,124.082000,__
+packet,124.166000,__
+packet,124.207000,__
+packet,124.541000,__
+packet,124.374000,__
+packet,124.291000,__
+packet,124.333000,__
+packet,124.416000,__
+packet,124.458000,__
+packet,124.499000,__
+packet,124.708000,__
+packet,124.625000,__
+packet,124.583000,__
+packet,124.666000,__
+packet,124.875000,__
+packet,124.791000,__
+packet,124.750000,__
+packet,124.833000,__
+packet,125.083000,__
+packet,124.958000,__
+packet,124.916000,__
+packet,125.000000,__
+packet,125.042000,__
+packet,125.125000,K_
+packet,125.417000,__
+packet,125.250000,__
+packet,125.167000,__
+packet,125.208000,__
+packet,125.292000,__
+packet,125.334000,__
+packet,125.375000,__
+packet,125.751000,__
+packet,125.584000,__
+packet,125.459000,__
+packet,125.500000,__
+packet,125.542000,__
+packet,125.626000,__
+packet,125.667000,__
+packet,125.709000,__
+packet,126.126000,__
+packet,125.917000,__
+packet,125.792000,__
+packet,125.834000,__
+packet,125.876000,__
+packet,125.959000,__
+packet,126.001000,__
+packet,126.043000,__
+packet,126.084000,__
+packet,126.251000,__
+packet,126.168000,__
+packet,126.209000,__
+packet,126.501000,__
+packet,126.376000,__
+packet,126.293000,__
+packet,126.335000,__
+packet,126.418000,__
+packet,126.460000,__
+packet,126.543000,K_
+packet,126.585000,__
+packet,126.627000,__
+packet,126.835000,__
+packet,126.710000,__
+packet,126.668000,__
+packet,126.752000,__
+packet,126.793000,__
+packet,126.960000,__
+packet,126.877000,__
+packet,126.918000,__
+packet,127.127000,__
+packet,127.044000,__
+packet,127.002000,__
+packet,127.085000,__
+packet,127.169000,__
+packet,127.336000,__
+packet,127.252000,__
+packet,127.210000,__
+packet,127.294000,__
+packet,127.461000,__
+packet,127.377000,__
+packet,127.419000,__
+packet,127.628000,__
+packet,127.544000,__
+packet,127.502000,__
+packet,127.586000,__
+packet,127.753000,__
+packet,127.669000,__
+packet,127.711000,__
+packet,127.878000,__
+packet,127.794000,__
+packet,127.836000,__
+packet,128.045000,__
+packet,127.961000,__
+packet,127.919000,__
+packet,128.003000,__
+packet,128.253000,__
+packet,128.128000,__
+packet,128.086000,__
+packet,128.170000,__
+packet,128.211000,__
+packet,128.295000,__
+packet,128.503000,__
+packet,128.378000,__
+packet,128.337000,__
+packet,128.420000,__
+packet,128.462000,__
+packet,128.545000,__
+packet,128.670000,__
+packet,128.587000,__
+packet,128.629000,__
+packet,128.795000,__
+packet,128.712000,__
+packet,128.754000,__
+packet,129.004000,__
+packet,128.879000,__
+packet,128.837000,__
+packet,128.920000,__
+packet,128.962000,__
+packet,129.171000,__
+packet,129.087000,__
+packet,129.046000,__
+packet,129.129000,__
+packet,129.212000,__
+packet,129.296000,__
+packet,129.254000,__
+packet,129.379000,__
+packet,129.338000,__
+packet,129.504000,__
+packet,129.421000,__
+packet,129.463000,__
+packet,129.671000,__
+packet,129.588000,__
+packet,129.546000,__
+packet,129.630000,__
+packet,129.838000,__
+packet,129.755000,__
+packet,129.713000,__
+packet,129.796000,__
+packet,129.921000,__
+packet,129.880000,__
+packet,129.963000,__
+packet,130.172000,__
+packet,130.047000,__
+packet,130.005000,__
+packet,130.088000,__
+packet,130.130000,__
+packet,130.255000,__
+packet,130.213000,__
+packet,130.422000,__
+packet,130.339000,__
+packet,130.297000,__
+packet,130.380000,__
+packet,130.505000,__
+packet,130.464000,__
+packet,130.547000,K_
+packet,130.714000,__
+packet,130.631000,__
+packet,130.589000,__
+packet,130.672000,__
+packet,131.048000,__
+packet,130.881000,__
+packet,130.756000,__
+packet,130.797000,__
+packet,130.839000,__
+packet,130.922000,__
+packet,130.964000,__
+packet,131.006000,__
+packet,131.089000,__
+packet,131.173000,__
+packet,131.131000,__
+packet,131.298000,__
+packet,131.214000,__
+packet,131.256000,__
+packet,131.340000,__
+packet,131.381000,__
+packet,131.548000,__
+packet,131.465000,__
+packet,131.423000,__
+packet,131.506000,__
+packet,131.923000,__
+packet,131.715000,__
+packet,131.590000,__
+packet,131.632000,__
+packet,131.673000,__
+packet,131.757000,__
+packet,131.798000,__
+packet,131.840000,__
+packet,131.882000,__
+packet,132.132000,__
+packet,132.007000,__
+packet,131.965000,__
+packet,132.049000,__
+packet,132.090000,__
+packet,132.341000,__
+packet,132.215000,__
+packet,132.174000,__
+packet,132.257000,__
+packet,132.299000,__
+packet,132.382000,__
+packet,132.549000,__
+packet,132.466000,__
+packet,132.424000,__
+packet,132.507000,__
+packet,132.716000,__
+packet,132.633000,__
+packet,132.591000,__
+packet,132.674000,__
+packet,132.883000,__
+packet,132.799000,__
+packet,132.758000,__
+packet,132.841000,__
+packet,133.216000,__
+packet,133.050000,__
+packet,132.924000,__
+packet,132.966000,__
+packet,133.008000,__
+packet,133.091000,__
+packet,133.133000,__
+packet,133.175000,__
+packet,133.342000,__
+packet,133.258000,__
+packet,133.300000,__
+packet,133.383000,K_
+packet,133.759000,__
+packet,133.550000,__
+packet,133.425000,__
+packet,133.467000,__
+packet,133.508000,__
+packet,133.592000,__
+packet,133.634000,__
+packet,133.675000,__
+packet,133.717000,__
+packet,134.092000,__
+packet,133.925000,__
+packet,133.800000,__
+packet,133.842000,__
+packet,133.884000,__
+packet,133.967000,__
+packet,134.009000,__
+packet,134.051000,__
+packet,134.468000,__
+packet,134.259000,__
+packet,134.134000,__
+packet,134.176000,__
+packet,134.217000,__
+packet,134.301000,__
+packet,134.343000,__
+packet,134.384000,__
+packet,134.426000,__
+packet,134.509000,__
+packet,134.551000,K_
+packet,134.718000,__
+packet,134.635000,__
+packet,134.593000,__
+packet,134.676000,__
+packet,134.885000,__
+packet,134.801000,__
+packet,134.760000,__
+packet,134.843000,__
+packet,135.052000,__
+packet,134.968000,__
+packet,134.926000,__
+packet,135.010000,__
+packet,135.218000,__
+packet,135.135000,__
+packet,135.093000,__
+packet,135.177000,__
+packet,135.385000,__
+packet,135.302000,__
+packet,135.260000,__
+packet,135.344000,__
+packet,135.469000,__
+packet,135.427000,__
+packet,135.636000,__
+packet,135.552000,__
+packet,135.510000,__
+packet,135.594000,__
+packet,135.677000,K_
+packet,136.053000,__
+packet,135.844000,__
+packet,135.719000,__
+packet,135.761000,__
+packet,135.802000,__
+packet,135.886000,__
+packet,135.927000,__
+packet,135.969000,__
+packet,136.011000,__
+packet,136.303000,__
+packet,136.178000,__
+packet,136.094000,__
+packet,136.136000,__
+packet,136.219000,__
+packet,136.261000,__
+packet,136.678000,__
+packet,136.470000,__
+packet,136.345000,__
+packet,136.386000,__
+packet,136.428000,__
+packet,136.511000,__
+packet,136.553000,__
+packet,136.595000,__
+packet,136.637000,__
+packet,136.803000,__
+packet,136.720000,__
+packet,136.762000,__
+packet,136.845000,K_
+packet,136.928000,__
+packet,136.887000,__
+packet,137.012000,__
+packet,136.970000,__
+packet,137.137000,__
+packet,137.054000,__
+packet,137.095000,__
+packet,137.387000,__
+packet,137.262000,__
+packet,137.179000,__
+packet,137.220000,__
+packet,137.304000,__
+packet,137.346000,__
+packet,137.596000,__
+packet,137.471000,__
+packet,137.429000,__
+packet,137.512000,__
+packet,137.554000,__
+packet,137.721000,__
+packet,137.638000,__
+packet,137.679000,__
+packet,138.013000,__
+packet,137.846000,__
+packet,137.763000,__
+packet,137.804000,__
+packet,137.888000,__
+packet,137.929000,__
+packet,137.971000,__
+packet,138.138000,__
+packet,138.055000,__
+packet,138.096000,__
+packet,138.430000,__
+packet,138.263000,__
+packet,138.180000,__
+packet,138.221000,__
+packet,138.305000,__
+packet,138.347000,__
+packet,138.388000,__
+packet,138.680000,__
+packet,138.555000,__
+packet,138.472000,__
+packet,138.513000,__
+packet,138.597000,__
+packet,138.639000,__
+packet,138.972000,__
+packet,138.805000,__
+packet,138.722000,__
+packet,138.764000,__
+packet,138.847000,__
+packet,138.889000,__
+packet,138.930000,__
+packet,139.056000,__
+packet,139.014000,__
+packet,139.431000,__
+packet,139.222000,__
+packet,139.097000,__
+packet,139.139000,__
+packet,139.181000,__
+packet,139.264000,__
+packet,139.306000,__
+packet,139.348000,__
+packet,139.389000,__
+packet,139.723000,__
+packet,139.556000,__
+packet,139.473000,__
+packet,139.514000,__
+packet,139.598000,__
+packet,139.640000,__
+packet,139.681000,__
+packet,139.806000,__
+packet,139.765000,__
+packet,139.973000,__
+packet,139.890000,__
+packet,139.848000,__
+packet,139.931000,__
+packet,140.223000,__
+packet,140.098000,__
+packet,140.015000,__
+packet,140.057000,__
+packet,140.140000,__
+packet,140.182000,__
+packet,140.307000,__
+packet,140.265000,__
+packet,140.474000,__
+packet,140.390000,__
+packet,140.349000,__
+packet,140.432000,__
+packet,140.849000,__
+packet,140.641000,__
+packet,140.515000,__
+packet,140.557000,__
+packet,140.599000,__
+packet,140.682000,__
+packet,140.724000,__
+packet,140.766000,__
+packet,140.807000,__
+packet,141.224000,__
+packet,141.016000,__
+packet,140.891000,__
+packet,140.932000,__
+packet,140.974000,__
+packet,141.058000,__
+packet,141.099000,__
+packet,141.141000,__
+packet,141.183000,__
+packet,141.600000,__
+packet,141.391000,__
+packet,141.266000,__
+packet,141.308000,__
+packet,141.350000,__
+packet,141.433000,__
+packet,141.475000,__
+packet,141.516000,__
+packet,141.558000,__
+packet,141.975000,__
+packet,141.767000,__
+packet,141.642000,__
+packet,141.683000,__
+packet,141.725000,__
+packet,141.808000,__
+packet,141.850000,__
+packet,141.892000,__
+packet,141.933000,__
+packet,142.351000,__
+packet,142.142000,__
+packet,142.017000,__
+packet,142.059000,__
+packet,142.100000,__
+packet,142.184000,__
+packet,142.225000,__
+packet,142.267000,__
+packet,142.309000,__
+packet,142.643000,__
+packet,142.476000,__
+packet,142.392000,__
+packet,142.434000,__
+packet,142.517000,__
+packet,142.559000,__
+packet,142.601000,__
+packet,142.684000,__
+packet,142.726000,K_
+packet,142.893000,__
+packet,142.809000,__
+packet,142.768000,__
+packet,142.851000,__
+packet,143.060000,__
+packet,142.976000,__
+packet,142.934000,__
+packet,143.018000,__
+packet,143.435000,__
+packet,143.226000,__
+packet,143.101000,__
+packet,143.143000,__
+packet,143.185000,__
+packet,143.268000,__
+packet,143.310000,__
+packet,143.352000,__
+packet,143.393000,__
+packet,143.477000,__
+packet,143.560000,__
+packet,143.518000,__
+packet,143.727000,__
+packet,143.644000,__
+packet,143.602000,__
+packet,143.685000,__
+packet,143.935000,__
+packet,143.810000,__
+packet,143.769000,__
+packet,143.852000,__
+packet,143.894000,__
+packet,144.102000,__
+packet,144.019000,__
+packet,143.977000,__
+packet,144.061000,__
+packet,144.144000,__
+packet,144.353000,__
+packet,144.227000,__
+packet,144.186000,__
+packet,144.269000,__
+packet,144.311000,__
+packet,144.478000,__
+packet,144.394000,__
+packet,144.436000,__
+packet,144.561000,__
+packet,144.519000,__
+packet,144.770000,__
+packet,144.645000,__
+packet,144.603000,__
+packet,144.686000,__
+packet,144.728000,__
+packet,144.936000,__
+packet,144.853000,__
+packet,144.811000,__
+packet,144.895000,__
+packet,145.020000,__
+packet,144.978000,__
+packet,145.187000,__
+packet,145.103000,__
+packet,145.062000,__
+packet,145.145000,__
+packet,145.562000,__
+packet,145.354000,__
+packet,145.228000,__
+packet,145.270000,__
+packet,145.312000,__
+packet,145.395000,__
+packet,145.437000,__
+packet,145.479000,__
+packet,145.520000,__
+packet,145.729000,__
+packet,145.646000,__
+packet,145.604000,__
+packet,145.687000,__
+packet,145.937000,__
+packet,145.812000,__
+packet,145.771000,__
+packet,145.854000,__
+packet,145.896000,__
+packet,146.021000,__
+packet,145.979000,__
+packet,146.063000,K_
+packet,146.313000,__
+packet,146.188000,__
+packet,146.104000,__
+packet,146.146000,__
+packet,146.229000,__
+packet,146.271000,__
+packet,146.438000,__
+packet,146.355000,__
+packet,146.396000,__
+packet,146.521000,__
+packet,146.480000,__
+packet,146.688000,__
+packet,146.605000,__
+packet,146.563000,__
+packet,146.647000,__
+packet,146.855000,__
+packet,146.772000,__
+packet,146.730000,__
+packet,146.813000,__
+packet,147.064000,__
+packet,146.938000,__
+packet,146.897000,__
+packet,146.980000,__
+packet,147.022000,__
+packet,147.189000,__
+packet,147.105000,__
+packet,147.147000,__
+packet,147.314000,__
+packet,147.230000,__
+packet,147.272000,__
+packet,147.481000,__
+packet,147.397000,__
+packet,147.356000,__
+packet,147.439000,__
+packet,147.522000,__
+packet,147.731000,__
+packet,147.606000,__
+packet,147.564000,__
+packet,147.648000,__
+packet,147.689000,__
+packet,147.898000,__
+packet,147.814000,__
+packet,147.773000,__
+packet,147.856000,__
+packet,148.065000,__
+packet,147.981000,__
+packet,147.939000,__
+packet,148.023000,__
+packet,148.106000,__
+packet,148.315000,__
+packet,148.190000,__
+packet,148.148000,__
+packet,148.231000,__
+packet,148.273000,__
+packet,148.482000,__
+packet,148.398000,__
+packet,148.357000,__
+packet,148.440000,__
+packet,148.649000,__
+packet,148.565000,__
+packet,148.523000,__
+packet,148.607000,__
+packet,148.815000,__
+packet,148.732000,__
+packet,148.690000,__
+packet,148.774000,__
+packet,148.982000,__
+packet,148.899000,__
+packet,148.857000,__
+packet,148.940000,__
+packet,149.107000,__
+packet,149.024000,__
+packet,149.066000,__
+packet,149.358000,__
+packet,149.232000,__
+packet,149.149000,__
+packet,149.191000,__
+packet,149.274000,__
+packet,149.316000,__
+packet,149.608000,__
+packet,149.483000,__
+packet,149.399000,__
+packet,149.441000,__
+packet,149.524000,__
+packet,149.566000,__
+packet,149.733000,__
+packet,149.650000,__
+packet,149.691000,__
+packet,149.941000,__
+packet,149.816000,__
+packet,149.775000,__
+packet,149.858000,__
+packet,149.900000,__
+packet,150.025000,__
+packet,149.983000,__
+packet,150.067000,K_
+packet,150.108000,__
+packet,150.275000,__
+packet,150.192000,__
+packet,150.150000,__
+packet,150.233000,__
+packet,150.400000,__
+packet,150.317000,__
+packet,150.359000,__
+packet,150.484000,__
+packet,150.442000,__
+packet,150.609000,__
+packet,150.525000,__
+packet,150.567000,__
+packet,150.984000,__
+packet,150.776000,__
+packet,150.651000,__
+packet,150.692000,__
+packet,150.734000,__
+packet,150.817000,__
+packet,150.859000,__
+packet,150.901000,__
+packet,150.942000,__
+packet,151.109000,__
+packet,151.026000,__
+packet,151.068000,__
+packet,151.485000,__
+packet,151.276000,__
+packet,151.151000,__
+packet,151.193000,__
+packet,151.234000,__
+packet,151.318000,__
+packet,151.360000,__
+packet,151.401000,__
+packet,151.443000,__
+packet,151.693000,__
+packet,151.568000,__
+packet,151.526000,__
+packet,151.610000,__
+packet,151.652000,__
+packet,151.860000,__
+packet,151.777000,__
+packet,151.735000,__
+packet,151.818000,__
+packet,152.235000,__
+packet,152.027000,__
+packet,151.902000,__
+packet,151.943000,__
+packet,151.985000,__
+packet,152.069000,__
+packet,152.110000,__
+packet,152.152000,__
+packet,152.194000,__
+packet,152.361000,__
+packet,152.277000,__
+packet,152.319000,__
+packet,152.486000,__
+packet,152.402000,__
+packet,152.444000,__
+packet,152.694000,__
+packet,152.569000,__
+packet,152.527000,__
+packet,152.611000,__
+packet,152.653000,__
+packet,152.944000,__
+packet,152.819000,__
+packet,152.736000,__
+packet,152.778000,__
+packet,152.861000,__
+packet,152.903000,__
+packet,153.111000,__
+packet,153.028000,__
+packet,152.986000,__
+packet,153.070000,__
+packet,153.487000,__
+packet,153.278000,__
+packet,153.153000,__
+packet,153.195000,__
+packet,153.236000,__
+packet,153.320000,__
+packet,153.362000,__
+packet,153.403000,__
+packet,153.445000,__
+packet,153.654000,__
+packet,153.570000,__
+packet,153.528000,__
+packet,153.612000,__
+packet,153.862000,__
+packet,153.737000,__
+packet,153.695000,__
+packet,153.779000,__
+packet,153.820000,__
+packet,154.029000,__
+packet,153.945000,__
+packet,153.904000,__
+packet,153.987000,__
+packet,154.071000,K_
+packet,154.237000,__
+packet,154.154000,__
+packet,154.112000,__
+packet,154.196000,__
+packet,154.404000,__
+packet,154.321000,__
+packet,154.279000,__
+packet,154.363000,__
+packet,154.571000,__
+packet,154.488000,__
+packet,154.446000,__
+packet,154.529000,__
+packet,154.946000,__
+packet,154.738000,__
+packet,154.613000,__
+packet,154.655000,__
+packet,154.696000,__
+packet,154.780000,__
+packet,154.821000,__
+packet,154.863000,__
+packet,154.905000,__
+packet,154.988000,__
+packet,155.113000,__
+packet,155.030000,__
+packet,155.072000,__
+packet,155.238000,__
+packet,155.155000,__
+packet,155.197000,__
+packet,155.364000,__
+packet,155.280000,__
+packet,155.322000,__
+packet,155.489000,__
+packet,155.405000,__
+packet,155.447000,__
+packet,155.614000,__
+packet,155.530000,__
+packet,155.572000,__
+packet,155.781000,__
+packet,155.697000,__
+packet,155.656000,__
+packet,155.739000,__
+packet,156.114000,__
+packet,155.947000,__
+packet,155.822000,__
+packet,155.864000,__
+packet,155.906000,__
+packet,155.989000,__
+packet,156.031000,__
+packet,156.073000,__
+packet,156.281000,__
+packet,156.198000,__
+packet,156.156000,__
+packet,156.239000,__
+packet,156.448000,__
+packet,156.365000,__
+packet,156.323000,__
+packet,156.406000,__
+packet,156.615000,__
+packet,156.531000,__
+packet,156.490000,__
+packet,156.573000,__
+packet,156.740000,__
+packet,156.657000,__
+packet,156.698000,__
+packet,156.907000,__
+packet,156.823000,__
+packet,156.782000,__
+packet,156.865000,__
+packet,157.115000,__
+packet,156.990000,__
+packet,156.948000,__
+packet,157.032000,__
+packet,157.074000,__
+packet,157.366000,__
+packet,157.240000,__
+packet,157.157000,__
+packet,157.199000,__
+packet,157.282000,__
+packet,157.324000,__
+packet,157.532000,__
+packet,157.449000,__
+packet,157.407000,__
+packet,157.491000,__
+packet,157.866000,__
+packet,157.699000,__
+packet,157.574000,__
+packet,157.616000,__
+packet,157.658000,__
+packet,157.741000,__
+packet,157.783000,__
+packet,157.824000,__
+packet,158.075000,__
+packet,157.949000,__
+packet,157.908000,__
+packet,157.991000,__
+packet,158.033000,__
+packet,158.367000,__
+packet,158.200000,__
+packet,158.116000,__
+packet,158.158000,__
+packet,158.241000,__
+packet,158.283000,__
+packet,158.325000,__
+packet,158.408000,__
+packet,158.450000,K_
+packet,158.492000,__
+packet,158.533000,__
+packet,158.575000,__
+packet,158.784000,__
+packet,158.659000,__
+packet,158.617000,__
+packet,158.700000,__
+packet,158.742000,__
+packet,158.909000,__
+packet,158.825000,__
+packet,158.867000,__
+packet,159.034000,__
+packet,158.950000,__
+packet,158.992000,__
+packet,159.117000,__
+packet,159.076000,__
+packet,159.368000,__
+packet,159.242000,__
+packet,159.159000,__
+packet,159.201000,__
+packet,159.284000,__
+packet,159.326000,__
+packet,159.743000,__
+packet,159.534000,__
+packet,159.409000,__
+packet,159.451000,__
+packet,159.493000,__
+packet,159.576000,__
+packet,159.618000,__
+packet,159.660000,__
+packet,159.701000,__
+packet,159.785000,__
+packet,159.993000,__
+packet,159.868000,__
+packet,159.826000,__
+packet,159.910000,__
+packet,159.951000,__
+packet,160.118000,__
+packet,160.035000,__
+packet,160.077000,__
+packet,160.410000,__
+packet,160.243000,__
+packet,160.160000,__
+packet,160.202000,__
+packet,160.285000,__
+packet,160.327000,__
+packet,160.369000,__
+packet,160.619000,__
+packet,160.494000,__
+packet,160.452000,__
+packet,160.535000,__
+packet,160.577000,__
+packet,160.661000,__
+packet,160.702000,K_
+packet,160.869000,__
+packet,160.786000,__
+packet,160.744000,__
+packet,160.827000,__
+packet,161.119000,__
+packet,160.994000,__
+packet,160.911000,__
+packet,160.952000,__
+packet,161.036000,__
+packet,161.078000,__
+packet,161.328000,__
+packet,161.203000,__
+packet,161.161000,__
+packet,161.244000,__
+packet,161.286000,__
+packet,161.578000,__
+packet,161.453000,__
+packet,161.370000,__
+packet,161.411000,__
+packet,161.495000,__
+packet,161.536000,__
+packet,161.828000,__
+packet,161.703000,__
+packet,161.620000,__
+packet,161.662000,__
+packet,161.745000,__
+packet,161.787000,__
+packet,162.079000,__
+packet,161.953000,__
+packet,161.870000,__
+packet,161.912000,__
+packet,161.995000,__
+packet,162.037000,__
+packet,162.162000,__
+packet,162.120000,__
+packet,162.245000,__
+packet,162.204000,__
+packet,162.287000,__
+packet,162.412000,__
+packet,162.329000,__
+packet,162.371000,__
+packet,162.579000,__
+packet,162.496000,__
+packet,162.454000,__
+packet,162.537000,__
+packet,162.746000,__
+packet,162.663000,__
+packet,162.621000,__
+packet,162.704000,__
+packet,162.788000,K_
+packet,162.829000,__
+packet,163.205000,__
+packet,162.996000,__
+packet,162.871000,__
+packet,162.913000,__
+packet,162.954000,__
+packet,163.038000,__
+packet,163.080000,__
+packet,163.121000,__
+packet,163.163000,__
+packet,163.455000,__
+packet,163.330000,__
+packet,163.246000,__
+packet,163.288000,__
+packet,163.372000,__
+packet,163.413000,__
+packet,163.622000,__
+packet,163.538000,__
+packet,163.497000,__
+packet,163.580000,__
+packet,163.872000,__
+packet,163.747000,__
+packet,163.664000,__
+packet,163.705000,__
+packet,163.789000,__
+packet,163.830000,__
+packet,163.914000,__
+packet,163.955000,K_
+packet,164.164000,__
+packet,164.039000,__
+packet,163.997000,__
+packet,164.081000,__
+packet,164.122000,__
+packet,164.206000,__
+packet,164.373000,__
+packet,164.289000,__
+packet,164.247000,__
+packet,164.331000,__
+packet,164.581000,__
+packet,164.456000,__
+packet,164.414000,__
+packet,164.498000,__
+packet,164.539000,__
+packet,164.748000,__
+packet,164.665000,__
+packet,164.623000,__
+packet,164.706000,__
+packet,164.915000,__
+packet,164.831000,__
+packet,164.790000,__
+packet,164.873000,__
+packet,165.040000,__
+packet,164.956000,__
+packet,164.998000,__
+packet,165.248000,__
+packet,165.123000,__
+packet,165.082000,__
+packet,165.165000,__
+packet,165.207000,__
+packet,165.415000,__
+packet,165.332000,__
+packet,165.290000,__
+packet,165.374000,__
+packet,165.457000,__
+packet,165.666000,__
+packet,165.540000,__
+packet,165.499000,__
+packet,165.582000,__
+packet,165.624000,__
+packet,165.749000,__
+packet,165.707000,__
+packet,165.916000,__
+packet,165.832000,__
+packet,165.791000,__
+packet,165.874000,__
+packet,165.957000,__
+packet,166.124000,__
+packet,166.041000,__
+packet,165.999000,__
+packet,166.083000,__
+packet,166.375000,__
+packet,166.249000,__
+packet,166.166000,__
+packet,166.208000,__
+packet,166.291000,__
+packet,166.333000,__
+packet,166.416000,__
+packet,166.458000,__
+packet,166.625000,__
+packet,166.541000,__
+packet,166.500000,__
+packet,166.583000,__
+packet,166.792000,__
+packet,166.708000,__
+packet,166.667000,__
+packet,166.750000,__
+packet,166.958000,__
+packet,166.875000,__
+packet,166.833000,__
+packet,166.917000,__
+packet,167.125000,__
+packet,167.042000,__
+packet,167.000000,__
+packet,167.084000,__
+packet,167.167000,__
+packet,167.209000,K_
+packet,167.250000,__
+packet,167.376000,__
+packet,167.292000,__
+packet,167.334000,__
+packet,167.417000,__
+packet,167.501000,__
+packet,167.459000,__
+packet,167.584000,__
+packet,167.542000,__
+packet,167.751000,__
+packet,167.668000,__
+packet,167.626000,__
+packet,167.709000,__
+packet,167.959000,__
+packet,167.834000,__
+packet,167.793000,__
+packet,167.876000,__
+packet,167.918000,__
+packet,168.085000,__
+packet,168.001000,__
+packet,168.043000,__
+packet,168.460000,__
+packet,168.251000,__
+packet,168.126000,__
+packet,168.168000,__
+packet,168.210000,__
+packet,168.293000,__
+packet,168.335000,__
+packet,168.377000,__
+packet,168.418000,__
+packet,168.502000,K_
+packet,168.627000,__
+packet,168.543000,__
+packet,168.585000,__
+packet,168.835000,__
+packet,168.710000,__
+packet,168.669000,__
+packet,168.752000,__
+packet,168.794000,__
+packet,169.127000,__
+packet,168.960000,__
+packet,168.877000,__
+packet,168.919000,__
+packet,169.002000,__
+packet,169.044000,__
+packet,169.086000,__
+packet,169.294000,__
+packet,169.211000,__
+packet,169.169000,__
+packet,169.252000,__
+packet,169.419000,__
+packet,169.336000,__
+packet,169.378000,__
+packet,169.544000,__
+packet,169.461000,__
+packet,169.503000,__
+packet,169.586000,__
+packet,169.878000,__
+packet,169.711000,__
+packet,169.628000,__
+packet,169.670000,__
+packet,169.753000,__
+packet,169.795000,__
+packet,169.836000,__
+packet,170.128000,__
+packet,170.003000,__
+packet,169.920000,__
+packet,169.961000,__
+packet,170.045000,__
+packet,170.087000,__
+packet,170.379000,__
+packet,170.253000,__
+packet,170.170000,__
+packet,170.212000,__
+packet,170.295000,__
+packet,170.337000,__
+packet,170.545000,__
+packet,170.462000,__
+packet,170.420000,__
+packet,170.504000,__
+packet,170.671000,__
+packet,170.587000,__
+packet,170.629000,__
+packet,170.837000,__
+packet,170.754000,__
+packet,170.712000,__
+packet,170.796000,__
+packet,171.046000,__
+packet,170.921000,__
+packet,170.879000,__
+packet,170.962000,__
+packet,171.004000,__
+packet,171.380000,__
+packet,171.213000,__
+packet,171.088000,__
+packet,171.129000,__
+packet,171.171000,__
+packet,171.254000,__
+packet,171.296000,__
+packet,171.338000,__
+packet,171.463000,__
+packet,171.421000,__
+packet,171.505000,__
+packet,171.588000,__
+packet,171.546000,__
+packet,171.672000,__
+packet,171.630000,__
+packet,171.797000,__
+packet,171.713000,__
+packet,171.755000,__
+packet,171.880000,__
+packet,171.838000,__
+packet,172.005000,__
+packet,171.922000,__
+packet,171.963000,__
+packet,172.130000,__
+packet,172.047000,__
+packet,172.089000,__
+packet,172.297000,__
+packet,172.214000,__
+packet,172.172000,__
+packet,172.255000,__
+packet,172.464000,__
+packet,172.381000,__
+packet,172.339000,__
+packet,172.422000,__
+packet,172.756000,__
+packet,172.589000,__
+packet,172.506000,__
+packet,172.547000,__
+packet,172.631000,__
+packet,172.673000,__
+packet,172.714000,__
+packet,172.923000,__
+packet,172.839000,__
+packet,172.798000,__
+packet,172.881000,__
+packet,172.964000,__
+packet,173.006000,__
+packet,173.131000,__
+packet,173.048000,__
+packet,173.090000,__
+packet,173.215000,__
+packet,173.173000,__
+packet,173.256000,__
+packet,173.298000,__
+packet,173.382000,__
+packet,173.340000,__
+packet,173.465000,__
+packet,173.423000,__
+packet,173.507000,__
+packet,173.715000,__
+packet,173.590000,__
+packet,173.548000,__
+packet,173.632000,__
+packet,173.674000,__
+packet,173.882000,__
+packet,173.799000,__
+packet,173.757000,__
+packet,173.840000,__
+packet,174.132000,__
+packet,174.007000,__
+packet,173.924000,__
+packet,173.965000,__
+packet,174.049000,__
+packet,174.091000,__
+packet,174.341000,__
+packet,174.216000,__
+packet,174.174000,__
+packet,174.257000,__
+packet,174.299000,__
+packet,174.508000,__
+packet,174.424000,__
+packet,174.383000,__
+packet,174.466000,__
+packet,174.633000,__
+packet,174.549000,__
+packet,174.591000,__
+packet,174.883000,__
+packet,174.758000,__
+packet,174.675000,__
+packet,174.716000,__
+packet,174.800000,__
+packet,174.841000,__
+packet,175.092000,__
+packet,174.966000,__
+packet,174.925000,__
+packet,175.008000,__
+packet,175.050000,__
+packet,175.384000,__
+packet,175.217000,__
+packet,175.133000,__
+packet,175.175000,__
+packet,175.258000,__
+packet,175.300000,__
+packet,175.342000,__
+packet,175.592000,__
+packet,175.467000,__
+packet,175.425000,__
+packet,175.509000,__
+packet,175.550000,__
+packet,175.717000,__
+packet,175.634000,__
+packet,175.676000,__
+packet,175.884000,__
+packet,175.801000,__
+packet,175.759000,__
+packet,175.842000,__
+packet,176.093000,__
+packet,175.967000,__
+packet,175.926000,__
+packet,176.009000,__
+packet,176.051000,__
+packet,176.259000,__
+packet,176.176000,__
+packet,176.134000,__
+packet,176.218000,__
+packet,176.510000,__
+packet,176.385000,__
+packet,176.301000,__
+packet,176.343000,__
+packet,176.426000,__
+packet,176.468000,__
+packet,176.635000,__
+packet,176.551000,__
+packet,176.593000,__
+packet,176.718000,__
+packet,176.677000,__
+packet,177.010000,__
+packet,176.843000,__
+packet,176.760000,__
+packet,176.802000,__
+packet,176.885000,__
+packet,176.927000,__
+packet,176.968000,__
+packet,177.260000,__
+packet,177.135000,__
+packet,177.052000,__
+packet,177.094000,__
+packet,177.177000,__
+packet,177.219000,__
+packet,177.427000,__
+packet,177.344000,__
+packet,177.302000,__
+packet,177.386000,__
+packet,177.803000,__
+packet,177.594000,__
+packet,177.469000,__
+packet,177.511000,__
+packet,177.552000,__
+packet,177.636000,__
+packet,177.678000,__
+packet,177.719000,__
+packet,177.761000,__
+packet,177.844000,__
+packet,178.095000,__
+packet,177.969000,__
+packet,177.886000,__
+packet,177.928000,__
+packet,178.011000,__
+packet,178.053000,__
+packet,178.261000,__
+packet,178.178000,__
+packet,178.136000,__
+packet,178.220000,__
+packet,178.428000,__
+packet,178.345000,__
+packet,178.303000,__
+packet,178.387000,__
+packet,178.762000,__
+packet,178.595000,__
+packet,178.470000,__
+packet,178.512000,__
+packet,178.553000,__
+packet,178.637000,__
+packet,178.679000,__
+packet,178.720000,__
+packet,178.887000,__
+packet,178.804000,__
+packet,178.845000,__
+packet,178.929000,K_
+packet,179.012000,__
+packet,178.970000,__
+packet,179.221000,__
+packet,179.096000,__
+packet,179.054000,__
+packet,179.137000,__
+packet,179.179000,__
+packet,179.388000,__
+packet,179.304000,__
+packet,179.262000,__
+packet,179.346000,__
+packet,179.638000,__
+packet,179.513000,__
+packet,179.429000,__
+packet,179.471000,__
+packet,179.554000,__
+packet,179.596000,__
+packet,179.888000,__
+packet,179.763000,__
+packet,179.680000,__
+packet,179.721000,__
+packet,179.805000,__
+packet,179.846000,__
+packet,180.097000,__
+packet,179.971000,__
+packet,179.930000,__
+packet,180.013000,__
+packet,180.055000,__
+packet,180.138000,__
+packet,180.263000,__
+packet,180.180000,__
+packet,180.222000,__
+packet,180.389000,__
+packet,180.305000,__
+packet,180.347000,__
+packet,180.555000,__
+packet,180.472000,__
+packet,180.430000,__
+packet,180.514000,__
+packet,180.847000,__
+packet,180.681000,__
+packet,180.597000,__
+packet,180.639000,__
+packet,180.722000,__
+packet,180.764000,__
+packet,180.806000,__
+packet,181.014000,__
+packet,180.931000,__
+packet,180.889000,__
+packet,180.972000,__
+packet,181.139000,__
+packet,181.056000,__
+packet,181.098000,__
+packet,181.348000,__
+packet,181.223000,__
+packet,181.181000,__
+packet,181.264000,__
+packet,181.306000,__
+packet,181.473000,__
+packet,181.390000,__
+packet,181.431000,__
+packet,181.640000,__
+packet,181.556000,__
+packet,181.515000,__
+packet,181.598000,__
+packet,181.765000,__
+packet,181.682000,__
+packet,181.723000,__
+packet,182.057000,__
+packet,181.890000,__
+packet,181.807000,__
+packet,181.848000,__
+packet,181.932000,__
+packet,181.973000,__
+packet,182.015000,__
+packet,182.224000,__
+packet,182.140000,__
+packet,182.099000,__
+packet,182.182000,__
+packet,182.391000,__
+packet,182.307000,__
+packet,182.265000,__
+packet,182.349000,__
+packet,182.474000,__
+packet,182.432000,__
+packet,182.641000,__
+packet,182.557000,__
+packet,182.516000,__
+packet,182.599000,__
+packet,183.016000,__
+packet,182.808000,__
+packet,182.683000,__
+packet,182.724000,__
+packet,182.766000,__
+packet,182.849000,__
+packet,182.891000,__
+packet,182.933000,__
+packet,182.974000,__
+packet,183.266000,__
+packet,183.141000,__
+packet,183.058000,__
+packet,183.100000,__
+packet,183.183000,__
+packet,183.225000,__
+packet,183.475000,__
+packet,183.350000,__
+packet,183.308000,__
+packet,183.392000,__
+packet,183.433000,__
+packet,183.725000,__
+packet,183.600000,__
+packet,183.517000,__
+packet,183.558000,__
+packet,183.642000,__
+packet,183.684000,__
+packet,183.850000,__
+packet,183.767000,__
+packet,183.809000,__
+packet,184.142000,__
+packet,183.975000,__
+packet,183.892000,__
+packet,183.934000,__
+packet,184.017000,__
+packet,184.059000,__
+packet,184.101000,__
+packet,184.351000,__
+packet,184.226000,__
+packet,184.184000,__
+packet,184.267000,__
+packet,184.309000,__
+packet,184.476000,__
+packet,184.393000,__
+packet,184.434000,__
+packet,184.559000,__
+packet,184.518000,__
+packet,184.810000,__
+packet,184.685000,__
+packet,184.601000,__
+packet,184.643000,__
+packet,184.726000,__
+packet,184.768000,__
+packet,184.976000,__
+packet,184.893000,__
+packet,184.851000,__
+packet,184.935000,__
+packet,185.060000,__
+packet,185.018000,__
+packet,185.227000,__
+packet,185.143000,__
+packet,185.102000,__
+packet,185.185000,__
+packet,185.394000,__
+packet,185.310000,__
+packet,185.268000,__
+packet,185.352000,__
+packet,185.602000,__
+packet,185.477000,__
+packet,185.435000,__
+packet,185.519000,__
+packet,185.560000,__
+packet,185.644000,__
+packet,185.894000,__
+packet,185.769000,__
+packet,185.686000,__
+packet,185.727000,__
+packet,185.811000,__
+packet,185.852000,__
+packet,186.144000,__
+packet,186.019000,__
+packet,185.936000,__
+packet,185.977000,__
+packet,186.061000,__
+packet,186.103000,__
+packet,186.353000,__
+packet,186.228000,__
+packet,186.186000,__
+packet,186.269000,__
+packet,186.311000,__
+packet,186.436000,__
+packet,186.395000,__
+packet,186.603000,__
+packet,186.520000,__
+packet,186.478000,__
+packet,186.561000,__
+packet,186.645000,__
+packet,187.020000,__
+packet,186.812000,__
+packet,186.687000,__
+packet,186.728000,__
+packet,186.770000,__
+packet,186.853000,__
+packet,186.895000,__
+packet,186.937000,__
+packet,186.978000,__
+packet,187.062000,__
+packet,187.396000,__
+packet,187.229000,__
+packet,187.104000,__
+packet,187.145000,__
+packet,187.187000,__
+packet,187.270000,__
+packet,187.312000,__
+packet,187.354000,__
+packet,187.604000,__
+packet,187.479000,__
+packet,187.437000,__
+packet,187.521000,__
+packet,187.562000,__
+packet,187.646000,__
+packet,187.896000,__
+packet,187.771000,__
+packet,187.688000,__
+packet,187.729000,__
+packet,187.813000,__
+packet,187.854000,__
+packet,188.230000,__
+packet,188.063000,__
+packet,187.938000,__
+packet,187.979000,__
+packet,188.021000,__
+packet,188.105000,__
+packet,188.146000,__
+packet,188.188000,__
+packet,188.271000,__
+packet,188.313000,K_
+packet,188.480000,__
+packet,188.397000,__
+packet,188.355000,__
+packet,188.438000,__
+packet,188.730000,__
+packet,188.605000,__
+packet,188.522000,__
+packet,188.563000,__
+packet,188.647000,__
+packet,188.689000,__
+packet,188.897000,__
+packet,188.814000,__
+packet,188.772000,__
+packet,188.855000,__
+packet,189.106000,__
+packet,188.980000,__
+packet,188.939000,__
+packet,189.022000,__
+packet,189.064000,__
+packet,189.481000,__
+packet,189.272000,__
+packet,189.147000,__
+packet,189.189000,__
+packet,189.231000,__
+packet,189.314000,__
+packet,189.356000,__
+packet,189.398000,__
+packet,189.439000,__
+packet,189.856000,__
+packet,189.648000,__
+packet,189.523000,__
+packet,189.564000,__
+packet,189.606000,__
+packet,189.690000,__
+packet,189.731000,__
+packet,189.773000,__
+packet,189.815000,__
+packet,190.023000,__
+packet,189.940000,__
+packet,189.898000,__
+packet,189.981000,__
+packet,190.148000,__
+packet,190.065000,__
+packet,190.107000,__
+packet,190.357000,__
+packet,190.232000,__
+packet,190.190000,__
+packet,190.273000,__
+packet,190.315000,__
+packet,190.732000,__
+packet,190.524000,__
+packet,190.399000,__
+packet,190.440000,__
+packet,190.482000,__
+packet,190.565000,__
+packet,190.607000,__
+packet,190.649000,__
+packet,190.691000,__
+packet,190.941000,__
+packet,190.816000,__
+packet,190.774000,__
+packet,190.857000,__
+packet,190.899000,__
+packet,190.982000,K_
+packet,191.066000,__
+packet,191.024000,__
+packet,191.233000,__
+packet,191.149000,__
+packet,191.108000,__
+packet,191.191000,__
+packet,191.400000,__
+packet,191.316000,__
+packet,191.274000,__
+packet,191.358000,__
+packet,191.525000,__
+packet,191.441000,__
+packet,191.483000,__
+packet,191.692000,__
+packet,191.608000,__
+packet,191.566000,__
+packet,191.650000,__
+packet,191.858000,__
+packet,191.775000,__
+packet,191.733000,__
+packet,191.817000,__
+packet,191.900000,__
+packet,191.983000,__
+packet,191.942000,__
+packet,192.109000,__
+packet,192.025000,__
+packet,192.067000,__
+packet,192.150000,__
+packet,192.234000,__
+packet,192.192000,__
+packet,192.317000,__
+packet,192.275000,__
+packet,192.401000,__
+packet,192.359000,__
+packet,192.526000,__
+packet,192.442000,__
+packet,192.484000,__
+packet,192.609000,__
+packet,192.567000,__
+packet,192.651000,__
+packet,192.734000,__
+packet,192.693000,__
+packet,192.818000,__
+packet,192.776000,__
+packet,192.901000,__
+packet,192.859000,__
+packet,193.068000,__
+packet,192.984000,__
+packet,192.943000,__
+packet,193.026000,__
+packet,193.110000,__
+packet,193.151000,K_
+packet,193.318000,__
+packet,193.235000,__
+packet,193.193000,__
+packet,193.276000,__
+packet,193.443000,__
+packet,193.360000,__
+packet,193.402000,__
+packet,193.527000,__
+packet,193.485000,__
+packet,193.694000,__
+packet,193.610000,__
+packet,193.568000,__
+packet,193.652000,__
+packet,193.777000,__
+packet,193.735000,__
+packet,193.944000,__
+packet,193.860000,__
+packet,193.819000,__
+packet,193.902000,__
+packet,194.027000,__
+packet,193.985000,__
+packet,194.152000,__
+packet,194.069000,__
+packet,194.111000,__
+packet,194.361000,__
+packet,194.236000,__
+packet,194.194000,__
+packet,194.277000,__
+packet,194.319000,__
+packet,194.528000,__
+packet,194.444000,__
+packet,194.403000,__
+packet,194.486000,__
+packet,194.778000,__
+packet,194.653000,__
+packet,194.569000,__
+packet,194.611000,__
+packet,194.695000,__
+packet,194.736000,__
+packet,195.112000,__
+packet,194.945000,__
+packet,194.820000,__
+packet,194.861000,__
+packet,194.903000,__
+packet,194.986000,__
+packet,195.028000,__
+packet,195.070000,__
+packet,195.362000,__
+packet,195.237000,__
+packet,195.153000,__
+packet,195.195000,__
+packet,195.278000,__
+packet,195.320000,__
+packet,195.487000,__
+packet,195.404000,__
+packet,195.445000,__
+packet,195.654000,__
+packet,195.570000,__
+packet,195.529000,__
+packet,195.612000,__
+packet,195.862000,__
+packet,195.737000,__
+packet,195.696000,__
+packet,195.779000,__
+packet,195.821000,__
+packet,195.946000,__
+packet,195.904000,__
+packet,196.029000,__
+packet,195.987000,__
+packet,196.154000,__
+packet,196.071000,__
+packet,196.113000,__
+packet,196.363000,__
+packet,196.238000,__
+packet,196.196000,__
+packet,196.279000,__
+packet,196.321000,__
+packet,196.488000,__
+packet,196.405000,__
+packet,196.446000,__
+packet,196.655000,__
+packet,196.571000,__
+packet,196.530000,__
+packet,196.613000,__
+packet,196.822000,__
+packet,196.738000,__
+packet,196.697000,__
+packet,196.780000,__
+packet,196.988000,__
+packet,196.905000,__
+packet,196.863000,__
+packet,196.947000,__
+packet,197.155000,__
+packet,197.072000,__
+packet,197.030000,__
+packet,197.114000,__
+packet,197.239000,__
+packet,197.197000,__
+packet,197.364000,__
+packet,197.280000,__
+packet,197.322000,__
+packet,197.489000,__
+packet,197.406000,__
+packet,197.447000,__
+packet,197.614000,__
+packet,197.531000,__
+packet,197.572000,__
+packet,197.656000,__
+packet,197.906000,__
+packet,197.781000,__
+packet,197.698000,__
+packet,197.739000,__
+packet,197.823000,__
+packet,197.864000,__
+packet,198.115000,__
+packet,197.989000,__
+packet,197.948000,__
+packet,198.031000,__
+packet,198.073000,__
+packet,198.281000,__
+packet,198.198000,__
+packet,198.156000,__
+packet,198.240000,__
+packet,198.448000,__
+packet,198.365000,__
+packet,198.323000,__
+packet,198.407000,__
+packet,198.615000,__
+packet,198.532000,__
+packet,198.490000,__
+packet,198.573000,__
+packet,198.740000,__
+packet,198.657000,__
+packet,198.699000,__
+packet,198.949000,__
+packet,198.824000,__
+packet,198.782000,__
+packet,198.865000,__
+packet,198.907000,__
+packet,199.074000,__
+packet,198.990000,__
+packet,199.032000,__
+packet,199.157000,__
+packet,199.116000,__
+packet,199.408000,__
+packet,199.282000,__
+packet,199.199000,__
+packet,199.241000,__
+packet,199.324000,__
+packet,199.366000,__
+packet,199.616000,__
+packet,199.491000,__
+packet,199.449000,__
+packet,199.533000,__
+packet,199.574000,__
+packet,199.658000,K_
+packet,199.825000,__
+packet,199.741000,__
+packet,199.700000,__
+packet,199.783000,__
+packet,199.991000,__
+packet,199.908000,__
+packet,199.866000,__
+packet,199.950000,__
+packet,200.158000,__
+packet,200.075000,__
+packet,200.033000,__
+packet,200.117000,__
+packet,200.325000,__
+packet,200.242000,__
+packet,200.200000,__
+packet,200.283000,__
+packet,200.492000,__
+packet,200.409000,__
+packet,200.367000,__
+packet,200.450000,__
+packet,200.659000,__
+packet,200.575000,__
+packet,200.534000,__
+packet,200.617000,__
+packet,200.826000,__
+packet,200.742000,__
+packet,200.701000,__
+packet,200.784000,__
+packet,200.867000,__
+packet,201.118000,__
+packet,200.992000,__
+packet,200.909000,__
+packet,200.951000,__
+packet,201.034000,__
+packet,201.076000,__
+packet,201.493000,__
+packet,201.284000,__
+packet,201.159000,__
+packet,201.201000,__
+packet,201.243000,__
+packet,201.326000,__
+packet,201.368000,__
+packet,201.410000,__
+packet,201.451000,__
+packet,201.660000,__
+packet,201.576000,__
+packet,201.535000,__
+packet,201.618000,__
+packet,201.702000,K_
+packet,201.868000,__
+packet,201.785000,__
+packet,201.743000,__
+packet,201.827000,__
+packet,202.035000,__
+packet,201.952000,__
+packet,201.910000,__
+packet,201.993000,__
+packet,202.077000,__
+packet,202.285000,__
+packet,202.160000,__
+packet,202.119000,__
+packet,202.202000,__
+packet,202.244000,__
+packet,202.452000,__
+packet,202.369000,__
+packet,202.327000,__
+packet,202.411000,__
+packet,202.661000,__
+packet,202.536000,__
+packet,202.494000,__
+packet,202.577000,__
+packet,202.619000,__
+packet,202.911000,__
+packet,202.786000,__
+packet,202.703000,__
+packet,202.744000,__
+packet,202.828000,__
+packet,202.869000,__
+packet,203.078000,__
+packet,202.994000,__
+packet,202.953000,__
+packet,203.036000,__
+packet,203.245000,__
+packet,203.161000,__
+packet,203.120000,__
+packet,203.203000,__
+packet,203.412000,__
+packet,203.328000,__
+packet,203.286000,__
+packet,203.370000,__
+packet,203.495000,__
+packet,203.453000,__
+packet,203.537000,K_
+packet,203.704000,__
+packet,203.620000,__
+packet,203.578000,__
+packet,203.662000,__
+packet,203.870000,__
+packet,203.787000,__
+packet,203.745000,__
+packet,203.829000,__
+packet,203.954000,__
+packet,203.912000,__
+packet,204.121000,__
+packet,204.037000,__
+packet,203.995000,__
+packet,204.079000,__
+packet,204.287000,__
+packet,204.204000,__
+packet,204.162000,__
+packet,204.246000,__
+packet,204.413000,__
+packet,204.329000,__
+packet,204.371000,__
+packet,204.538000,__
+packet,204.454000,__
+packet,204.496000,__
+packet,204.621000,__
+packet,204.579000,__
+packet,204.788000,__
+packet,204.705000,__
+packet,204.663000,__
+packet,204.746000,__
+packet,204.996000,__
+packet,204.871000,__
+packet,204.830000,__
+packet,204.913000,__
+packet,204.955000,__
+packet,205.080000,__
+packet,205.038000,__
+packet,205.122000,K_
+packet,205.372000,__
+packet,205.247000,__
+packet,205.163000,__
+packet,205.205000,__
+packet,205.288000,__
+packet,205.330000,__
+packet,205.664000,__
+packet,205.497000,__
+packet,205.414000,__
+packet,205.455000,__
+packet,205.539000,__
+packet,205.580000,__
+packet,205.622000,__
+packet,205.831000,__
+packet,205.747000,__
+packet,205.706000,__
+packet,205.789000,__
+packet,206.164000,__
+packet,205.997000,__
+packet,205.872000,__
+packet,205.914000,__
+packet,205.956000,__
+packet,206.039000,__
+packet,206.081000,__
+packet,206.123000,__
+packet,206.373000,__
+packet,206.248000,__
+packet,206.206000,__
+packet,206.289000,__
+packet,206.331000,__
+packet,206.498000,__
+packet,206.415000,__
+packet,206.456000,__
+packet,206.540000,K_
+packet,206.665000,__
+packet,206.581000,__
+packet,206.623000,__
+packet,206.873000,__
+packet,206.748000,__
+packet,206.707000,__
+packet,206.790000,__
+packet,206.832000,__
+packet,207.040000,__
+packet,206.957000,__
+packet,206.915000,__
+packet,206.998000,__
+packet,207.165000,__
+packet,207.082000,__
+packet,207.124000,__
+packet,207.332000,__
+packet,207.249000,__
+packet,207.207000,__
+packet,207.290000,__
+packet,207.541000,__
+packet,207.416000,__
+packet,207.374000,__
+packet,207.457000,__
+packet,207.499000,__
+packet,207.708000,__
+packet,207.624000,__
+packet,207.582000,__
+packet,207.666000,__
+packet,207.833000,__
+packet,207.749000,__
+packet,207.791000,__
+packet,208.041000,__
+packet,207.916000,__
+packet,207.874000,__
+packet,207.958000,__
+packet,207.999000,__
+packet,208.166000,__
+packet,208.083000,__
+packet,208.125000,__
+packet,208.375000,__
+packet,208.250000,__
+packet,208.208000,__
+packet,208.291000,__
+packet,208.333000,__
+packet,208.417000,__
+packet,208.458000,__
+packet,208.500000,K_
+packet,208.625000,__
+packet,208.542000,__
+packet,208.583000,__
+packet,208.792000,__
+packet,208.709000,__
+packet,208.667000,__
+packet,208.750000,__
+packet,208.917000,__
+packet,208.834000,__
+packet,208.875000,__
+packet,209.084000,__
+packet,209.000000,__
+packet,208.959000,__
+packet,209.042000,__
+packet,209.292000,__
+packet,209.167000,__
+packet,209.126000,__
+packet,209.209000,__
+packet,209.251000,__
+packet,209.334000,__
+packet,209.459000,__
+packet,209.376000,__
+packet,209.418000,__
+packet,209.584000,__
+packet,209.501000,__
+packet,209.543000,__
+packet,209.793000,__
+packet,209.668000,__
+packet,209.626000,__
+packet,209.710000,__
+packet,209.751000,__
+packet,209.918000,__
+packet,209.835000,__
+packet,209.876000,__
+packet,210.085000,__
+packet,210.001000,__
+packet,209.960000,__
+packet,210.043000,__
+packet,210.252000,__
+packet,210.168000,__
+packet,210.127000,__
+packet,210.210000,__
+packet,210.419000,__
+packet,210.335000,__
+packet,210.293000,__
+packet,210.377000,__
+packet,210.627000,__
+packet,210.502000,__
+packet,210.460000,__
+packet,210.544000,__
+packet,210.585000,__
+packet,210.836000,__
+packet,210.711000,__
+packet,210.669000,__
+packet,210.752000,__
+packet,210.794000,__
+packet,210.877000,__
+packet,210.919000,K_
+packet,211.044000,__
+packet,210.961000,__
+packet,211.002000,__
+packet,211.128000,__
+packet,211.086000,__
+packet,211.169000,__
+packet,211.294000,__
+packet,211.211000,__
+packet,211.253000,__
+packet,211.420000,__
+packet,211.336000,__
+packet,211.378000,__
+packet,211.670000,__
+packet,211.545000,__
+packet,211.461000,__
+packet,211.503000,__
+packet,211.586000,__
+packet,211.628000,__
+packet,212.003000,__
+packet,211.837000,__
+packet,211.712000,__
+packet,211.753000,__
+packet,211.795000,__
+packet,211.878000,__
+packet,211.920000,__
+packet,211.962000,__
+packet,212.045000,__
+packet,212.087000,K_
+packet,212.212000,__
+packet,212.129000,__
+packet,212.170000,__
+packet,212.379000,__
+packet,212.295000,__
+packet,212.254000,__
+packet,212.337000,__
+packet,212.462000,__
+packet,212.421000,__
+packet,212.838000,__
+packet,212.629000,__
+packet,212.504000,__
+packet,212.546000,__
+packet,212.587000,__
+packet,212.671000,__
+packet,212.713000,__
+packet,212.754000,__
+packet,212.796000,__
+packet,212.963000,__
+packet,212.879000,__
+packet,212.921000,__
+packet,213.171000,__
+packet,213.046000,__
+packet,213.004000,__
+packet,213.088000,__
+packet,213.130000,__
+packet,213.547000,__
+packet,213.338000,__
+packet,213.213000,__
+packet,213.255000,__
+packet,213.296000,__
+packet,213.380000,__
+packet,213.422000,__
+packet,213.463000,__
+packet,213.505000,__
+packet,213.630000,__
+packet,213.588000,__
+packet,213.797000,__
+packet,213.714000,__
+packet,213.672000,__
+packet,213.755000,__
+packet,214.172000,__
+packet,213.964000,__
+packet,213.839000,__
+packet,213.880000,__
+packet,213.922000,__
+packet,214.005000,__
+packet,214.047000,__
+packet,214.089000,__
+packet,214.131000,__
+packet,214.381000,__
+packet,214.256000,__
+packet,214.214000,__
+packet,214.297000,__
+packet,214.339000,__
+packet,214.548000,__
+packet,214.464000,__
+packet,214.423000,__
+packet,214.506000,__
+packet,214.798000,__
+packet,214.673000,__
+packet,214.589000,__
+packet,214.631000,__
+packet,214.715000,__
+packet,214.756000,__
+packet,214.965000,__
+packet,214.881000,__
+packet,214.840000,__
+packet,214.923000,__
+packet,215.132000,__
+packet,215.048000,__
+packet,215.006000,__
+packet,215.090000,__
+packet,215.298000,__
+packet,215.215000,__
+packet,215.173000,__
+packet,215.257000,__
+packet,215.507000,__
+packet,215.382000,__
+packet,215.340000,__
+packet,215.424000,__
+packet,215.465000,__
+packet,215.674000,__
+packet,215.590000,__
+packet,215.549000,__
+packet,215.632000,__
+packet,215.882000,__
+packet,215.757000,__
+packet,215.716000,__
+packet,215.799000,__
+packet,215.841000,__
+packet,216.258000,__
+packet,216.049000,__
+packet,215.924000,__
+packet,215.966000,__
+packet,216.007000,__
+packet,216.091000,__
+packet,216.133000,__
+packet,216.174000,__
+packet,216.216000,__
+packet,216.550000,__
+packet,216.383000,__
+packet,216.299000,__
+packet,216.341000,__
+packet,216.425000,__
+packet,216.466000,__
+packet,216.508000,__
+packet,216.800000,__
+packet,216.675000,__
+packet,216.591000,__
+packet,216.633000,__
+packet,216.717000,__
+packet,216.758000,__
+packet,216.842000,K_
+packet,216.883000,__
+packet,217.050000,__
+packet,216.967000,__
+packet,216.925000,__
+packet,217.008000,__
+packet,217.259000,__
+packet,217.134000,__
+packet,217.092000,__
+packet,217.175000,__
+packet,217.217000,__
+packet,217.509000,__
+packet,217.384000,__
+packet,217.300000,__
+packet,217.342000,__
+packet,217.426000,__
+packet,217.467000,__
+packet,217.634000,__
+packet,217.551000,__
+packet,217.592000,__
+packet,217.843000,__
+packet,217.718000,__
+packet,217.676000,__
+packet,217.759000,__
+packet,217.801000,__
+packet,217.968000,__
+packet,217.884000,__
+packet,217.926000,__
+packet,218.176000,__
+packet,218.051000,__
+packet,218.009000,__
+packet,218.093000,__
+packet,218.135000,__
+packet,218.343000,__
+packet,218.260000,__
+packet,218.218000,__
+packet,218.301000,__
+packet,218.552000,__
+packet,218.427000,__
+packet,218.385000,__
+packet,218.468000,__
+packet,218.510000,__
+packet,218.885000,__
+packet,218.719000,__
+packet,218.593000,__
+packet,218.635000,__
+packet,218.677000,__
+packet,218.760000,__
+packet,218.802000,__
+packet,218.844000,__
+packet,219.177000,__
+packet,219.010000,__
+packet,218.927000,__
+packet,218.969000,__
+packet,219.052000,__
+packet,219.094000,__
+packet,219.136000,__
+packet,219.428000,__
+packet,219.302000,__
+packet,219.219000,__
+packet,219.261000,__
+packet,219.344000,__
+packet,219.386000,__
+packet,219.553000,__
+packet,219.469000,__
+packet,219.511000,__
+packet,219.845000,__
+packet,219.678000,__
+packet,219.594000,__
+packet,219.636000,__
+packet,219.720000,__
+packet,219.761000,__
+packet,219.803000,__
+packet,220.178000,__
+packet,220.011000,__
+packet,219.886000,__
+packet,219.928000,__
+packet,219.970000,__
+packet,220.053000,__
+packet,220.095000,__
+packet,220.137000,__
+packet,220.429000,__
+packet,220.303000,__
+packet,220.220000,__
+packet,220.262000,__
+packet,220.345000,__
+packet,220.387000,__
+packet,220.679000,__
+packet,220.554000,__
+packet,220.470000,__
+packet,220.512000,__
+packet,220.595000,__
+packet,220.637000,__
+packet,220.929000,__
+packet,220.804000,__
+packet,220.721000,__
+packet,220.762000,__
+packet,220.846000,__
+packet,220.887000,__
+packet,221.263000,__
+packet,221.096000,__
+packet,220.971000,__
+packet,221.012000,__
+packet,221.054000,__
+packet,221.138000,__
+packet,221.179000,__
+packet,221.221000,__
+packet,221.388000,__
+packet,221.304000,__
+packet,221.346000,__
+packet,221.555000,__
+packet,221.471000,__
+packet,221.430000,__
+packet,221.513000,__
+packet,221.638000,__
+packet,221.596000,__
+packet,221.722000,__
+packet,221.680000,__
+packet,221.805000,__
+packet,221.763000,__
+packet,221.930000,__
+packet,221.847000,__
+packet,221.888000,__
+packet,222.055000,__
+packet,221.972000,__
+packet,222.013000,__
+packet,222.139000,__
+packet,222.097000,__
+packet,222.389000,__
+packet,222.264000,__
+packet,222.180000,__
+packet,222.222000,__
+packet,222.305000,__
+packet,222.347000,__
+packet,222.431000,__
+packet,222.597000,__
+packet,222.514000,__
+packet,222.472000,__
+packet,222.556000,__
+packet,222.639000,__
+packet,222.681000,__
+packet,222.764000,__
+packet,222.723000,__
+packet,222.931000,__
+packet,222.848000,__
+packet,222.806000,__
+packet,222.889000,__
+packet,223.181000,__
+packet,223.056000,__
+packet,222.973000,__
+packet,223.014000,__
+packet,223.098000,__
+packet,223.140000,__
+packet,223.390000,__
+packet,223.265000,__
+packet,223.223000,__
+packet,223.306000,__
+packet,223.348000,__
+packet,223.765000,__
+packet,223.557000,__
+packet,223.432000,__
+packet,223.473000,__
+packet,223.515000,__
+packet,223.598000,__
+packet,223.640000,__
+packet,223.682000,__
+packet,223.724000,__
+packet,224.141000,__
+packet,223.932000,__
+packet,223.807000,__
+packet,223.849000,__
+packet,223.890000,__
+packet,223.974000,__
+packet,224.015000,__
+packet,224.057000,__
+packet,224.099000,__
+packet,224.433000,__
+packet,224.266000,__
+packet,224.182000,__
+packet,224.224000,__
+packet,224.307000,__
+packet,224.349000,__
+packet,224.391000,__
+packet,224.683000,__
+packet,224.558000,__
+packet,224.474000,__
+packet,224.516000,__
+packet,224.599000,__
+packet,224.641000,__
+packet,224.975000,__
+packet,224.808000,__
+packet,224.725000,__
+packet,224.766000,__
+packet,224.850000,__
+packet,224.891000,__
+packet,224.933000,__
+packet,225.183000,__
+packet,225.058000,__
+packet,225.016000,__
+packet,225.100000,__
+packet,225.142000,__
+packet,225.350000,__
+packet,225.267000,__
+packet,225.225000,__
+packet,225.308000,__
+packet,225.392000,K_
+packet,225.559000,__
+packet,225.475000,__
+packet,225.434000,__
+packet,225.517000,__
+packet,225.934000,__
+packet,225.726000,__
+packet,225.600000,__
+packet,225.642000,__
+packet,225.684000,__
+packet,225.767000,__
+packet,225.809000,__
+packet,225.851000,__
+packet,225.892000,__
+packet,226.143000,__
+packet,226.017000,__
+packet,225.976000,__
+packet,226.059000,__
+packet,226.101000,__
+packet,226.268000,__
+packet,226.184000,__
+packet,226.226000,__
+packet,226.351000,__
+packet,226.309000,__
+packet,226.435000,__
+packet,226.393000,__
+packet,226.685000,__
+packet,226.560000,__
+packet,226.476000,__
+packet,226.518000,__
+packet,226.601000,__
+packet,226.643000,__
+packet,226.810000,__
+packet,226.727000,__
+packet,226.768000,__
+packet,227.144000,__
+packet,226.977000,__
+packet,226.852000,__
+packet,226.893000,__
+packet,226.935000,__
+packet,227.018000,__
+packet,227.060000,__
+packet,227.102000,__
+packet,227.519000,__
+packet,227.310000,__
+packet,227.185000,__
+packet,227.227000,__
+packet,227.269000,__
+packet,227.352000,__
+packet,227.394000,__
+packet,227.436000,__
+packet,227.477000,__
+packet,227.769000,__
+packet,227.644000,__
+packet,227.561000,__
+packet,227.602000,__
+packet,227.686000,__
+packet,227.728000,__
+packet,227.936000,__
+packet,227.853000,__
+packet,227.811000,__
+packet,227.894000,__
+packet,228.186000,__
+packet,228.061000,__
+packet,227.978000,__
+packet,228.019000,__
+packet,228.103000,__
+packet,228.145000,__
+packet,228.311000,__
+packet,228.228000,__
+packet,228.270000,__
+packet,228.478000,__
+packet,228.395000,__
+packet,228.353000,__
+packet,228.437000,__
+packet,228.812000,__
+packet,228.645000,__
+packet,228.520000,__
+packet,228.562000,__
+packet,228.603000,__
+packet,228.687000,__
+packet,228.729000,__
+packet,228.770000,__
+packet,229.062000,__
+packet,228.937000,__
+packet,228.854000,__
+packet,228.895000,__
+packet,228.979000,__
+packet,229.020000,__
+packet,229.312000,__
+packet,229.187000,__
+packet,229.104000,__
+packet,229.146000,__
+packet,229.229000,__
+packet,229.271000,__
+packet,229.479000,__
+packet,229.396000,__
+packet,229.354000,__
+packet,229.438000,__
+packet,229.521000,K_
+packet,229.646000,__
+packet,229.563000,__
+packet,229.604000,__
+packet,229.855000,__
+packet,229.730000,__
+packet,229.688000,__
+packet,229.771000,__
+packet,229.813000,__
+packet,230.063000,__
+packet,229.938000,__
+packet,229.896000,__
+packet,229.980000,__
+packet,230.021000,__
+packet,230.147000,__
+packet,230.105000,__
+packet,230.313000,__
+packet,230.230000,__
+packet,230.188000,__
+packet,230.272000,__
+packet,230.480000,__
+packet,230.397000,__
+packet,230.355000,__
+packet,230.439000,__
+packet,230.647000,__
+packet,230.564000,__
+packet,230.522000,__
+packet,230.605000,__
+packet,230.897000,__
+packet,230.772000,__
+packet,230.689000,__
+packet,230.731000,__
+packet,230.814000,__
+packet,230.856000,__
+packet,231.064000,__
+packet,230.981000,__
+packet,230.939000,__
+packet,231.022000,__
+packet,231.231000,__
+packet,231.148000,__
+packet,231.106000,__
+packet,231.189000,__
+packet,231.523000,__
+packet,231.356000,__
+packet,231.273000,__
+packet,231.314000,__
+packet,231.398000,__
+packet,231.440000,__
+packet,231.481000,__
+packet,231.690000,__
+packet,231.606000,__
+packet,231.565000,__
+packet,231.648000,__
+packet,231.898000,__
+packet,231.773000,__
+packet,231.732000,__
+packet,231.815000,__
+packet,231.857000,__
+packet,232.065000,__
+packet,231.982000,__
+packet,231.940000,__
+packet,232.023000,__
+packet,232.190000,__
+packet,232.107000,__
+packet,232.149000,__
+packet,232.399000,__
+packet,232.274000,__
+packet,232.232000,__
+packet,232.315000,__
+packet,232.357000,__
+packet,232.524000,__
+packet,232.441000,__
+packet,232.482000,__
+packet,232.691000,__
+packet,232.607000,__
+packet,232.566000,__
+packet,232.649000,__
+packet,232.899000,__
+packet,232.774000,__
+packet,232.733000,__
+packet,232.816000,__
+packet,232.858000,__
+packet,233.191000,__
+packet,233.024000,__
+packet,232.941000,__
+packet,232.983000,__
+packet,233.066000,__
+packet,233.108000,__
+packet,233.150000,__
+packet,233.275000,__
+packet,233.233000,__
+packet,233.316000,__
+packet,233.483000,__
+packet,233.400000,__
+packet,233.358000,__
+packet,233.442000,__
+packet,233.859000,__
+packet,233.650000,__
+packet,233.525000,__
+packet,233.567000,__
+packet,233.608000,__
+packet,233.692000,__
+packet,233.734000,__
+packet,233.775000,__
+packet,233.817000,__
+packet,234.025000,__
+packet,233.942000,__
+packet,233.900000,__
+packet,233.984000,__
+packet,234.192000,__
+packet,234.109000,__
+packet,234.067000,__
+packet,234.151000,__
+packet,234.401000,__
+packet,234.276000,__
+packet,234.234000,__
+packet,234.317000,__
+packet,234.359000,__
+packet,234.568000,__
+packet,234.484000,__
+packet,234.443000,__
+packet,234.526000,__
+packet,234.943000,__
+packet,234.735000,__
+packet,234.609000,__
+packet,234.651000,__
+packet,234.693000,__
+packet,234.776000,__
+packet,234.818000,__
+packet,234.860000,__
+packet,234.901000,__
+packet,235.193000,__
+packet,235.068000,__
+packet,234.985000,__
+packet,235.026000,__
+packet,235.110000,__
+packet,235.152000,__
+packet,235.360000,__
+packet,235.277000,__
+packet,235.235000,__
+packet,235.318000,__
+packet,235.652000,__
+packet,235.485000,__
+packet,235.402000,__
+packet,235.444000,__
+packet,235.527000,__
+packet,235.569000,__
+packet,235.610000,__
+packet,235.986000,__
+packet,235.819000,__
+packet,235.694000,__
+packet,235.736000,__
+packet,235.777000,__
+packet,235.861000,__
+packet,235.902000,__
+packet,235.944000,__
+packet,236.236000,__
+packet,236.111000,__
+packet,236.027000,__
+packet,236.069000,__
+packet,236.153000,__
+packet,236.194000,__
+packet,236.403000,__
+packet,236.319000,__
+packet,236.278000,__
+packet,236.361000,__
+packet,236.528000,__
+packet,236.445000,__
+packet,236.486000,__
+packet,236.737000,__
+packet,236.611000,__
+packet,236.570000,__
+packet,236.653000,__
+packet,236.695000,__
+packet,236.987000,__
+packet,236.862000,__
+packet,236.778000,__
+packet,236.820000,__
+packet,236.903000,__
+packet,236.945000,__
+packet,237.279000,__
+packet,237.112000,__
+packet,237.028000,__
+packet,237.070000,__
+packet,237.154000,__
+packet,237.195000,__
+packet,237.237000,__
+packet,237.404000,__
+packet,237.320000,__
+packet,237.362000,__
+packet,237.446000,K_
+packet,237.696000,__
+packet,237.571000,__
+packet,237.487000,__
+packet,237.529000,__
+packet,237.612000,__
+packet,237.654000,__
+packet,237.863000,__
+packet,237.779000,__
+packet,237.738000,__
+packet,237.821000,__
+packet,238.071000,__
+packet,237.946000,__
+packet,237.904000,__
+packet,237.988000,__
+packet,238.029000,__
+packet,238.238000,__
+packet,238.155000,__
+packet,238.113000,__
+packet,238.196000,__
+packet,238.363000,__
+packet,238.280000,__
+packet,238.321000,__
+packet,238.530000,__
+packet,238.447000,__
+packet,238.405000,__
+packet,238.488000,__
+packet,238.739000,__
+packet,238.613000,__
+packet,238.572000,__
+packet,238.655000,__
+packet,238.697000,__
+packet,238.864000,__
+packet,238.780000,__
+packet,238.822000,__
+packet,239.030000,__
+packet,238.947000,__
+packet,238.905000,__
+packet,238.989000,__
+packet,239.239000,__
+packet,239.114000,__
+packet,239.072000,__
+packet,239.156000,__
+packet,239.197000,__
+packet,239.489000,__
+packet,239.364000,__
+packet,239.281000,__
+packet,239.322000,__
+packet,239.406000,__
+packet,239.448000,__
+packet,239.740000,__
+packet,239.614000,__
+packet,239.531000,__
+packet,239.573000,__
+packet,239.656000,__
+packet,239.698000,__
+packet,239.990000,__
+packet,239.865000,__
+packet,239.781000,__
+packet,239.823000,__
+packet,239.906000,__
+packet,239.948000,__
+packet,240.240000,__
+packet,240.115000,__
+packet,240.031000,__
+packet,240.073000,__
+packet,240.157000,__
+packet,240.198000,__
+packet,240.490000,__
+packet,240.365000,__
+packet,240.282000,__
+packet,240.323000,__
+packet,240.407000,__
+packet,240.449000,__
+packet,240.741000,__
+packet,240.615000,__
+packet,240.532000,__
+packet,240.574000,__
+packet,240.657000,__
+packet,240.699000,__
+packet,240.907000,__
+packet,240.824000,__
+packet,240.782000,__
+packet,240.866000,__
+packet,241.074000,__
+packet,240.991000,__
+packet,240.949000,__
+packet,241.032000,__
+packet,241.199000,__
+packet,241.116000,__
+packet,241.158000,__
+packet,241.366000,__
+packet,241.283000,__
+packet,241.241000,__
+packet,241.324000,__
+packet,241.616000,__
+packet,241.491000,__
+packet,241.408000,__
+packet,241.450000,__
+packet,241.533000,__
+packet,241.575000,__
+packet,241.783000,__
+packet,241.700000,__
+packet,241.658000,__
+packet,241.742000,__
+packet,241.992000,__
+packet,241.867000,__
+packet,241.825000,__
+packet,241.908000,__
+packet,241.950000,__
+packet,242.200000,__
+packet,242.075000,__
+packet,242.033000,__
+packet,242.117000,__
+packet,242.159000,__
+packet,242.367000,__
+packet,242.284000,__
+packet,242.242000,__
+packet,242.325000,__
+packet,242.617000,__
+packet,242.492000,__
+packet,242.409000,__
+packet,242.451000,__
+packet,242.534000,__
+packet,242.576000,__
+packet,242.868000,__
+packet,242.743000,__
+packet,242.659000,__
+packet,242.701000,__
+packet,242.784000,__
+packet,242.826000,__
+packet,243.118000,__
+packet,242.993000,__
+packet,242.909000,__
+packet,242.951000,__
+packet,243.034000,__
+packet,243.076000,__
+packet,243.243000,__
+packet,243.160000,__
+packet,243.201000,__
+packet,243.493000,__
+packet,243.368000,__
+packet,243.285000,__
+packet,243.326000,__
+packet,243.410000,__
+packet,243.452000,__
+packet,243.744000,__
+packet,243.618000,__
+packet,243.535000,__
+packet,243.577000,__
+packet,243.660000,__
+packet,243.702000,__
+packet,243.869000,__
+packet,243.785000,__
+packet,243.827000,__
+packet,244.119000,__
+packet,243.994000,__
+packet,243.910000,__
+packet,243.952000,__
+packet,244.035000,__
+packet,244.077000,__
+packet,244.286000,__
+packet,244.202000,__
+packet,244.161000,__
+packet,244.244000,__
+packet,244.494000,__
+packet,244.369000,__
+packet,244.327000,__
+packet,244.411000,__
+packet,244.453000,__
+packet,244.745000,__
+packet,244.619000,__
+packet,244.536000,__
+packet,244.578000,__
+packet,244.661000,__
+packet,244.703000,__
+packet,244.995000,__
+packet,244.870000,__
+packet,244.786000,__
+packet,244.828000,__
+packet,244.911000,__
+packet,244.953000,__
+packet,245.162000,__
+packet,245.078000,__
+packet,245.036000,__
+packet,245.120000,__
+packet,245.245000,__
+packet,245.203000,__
+packet,245.370000,__
+packet,245.287000,__
+packet,245.328000,__
+packet,245.537000,__
+packet,245.454000,__
+packet,245.412000,__
+packet,245.495000,__
+packet,245.746000,__
+packet,245.620000,__
+packet,245.579000,__
+packet,245.662000,__
+packet,245.704000,__
+packet,245.912000,__
+packet,245.829000,__
+packet,245.787000,__
+packet,245.871000,__
+packet,246.079000,__
+packet,245.996000,__
+packet,245.954000,__
+packet,246.037000,__
+packet,246.204000,__
+packet,246.121000,__
+packet,246.163000,__
+packet,246.371000,__
+packet,246.288000,__
+packet,246.246000,__
+packet,246.329000,__
+packet,246.538000,__
+packet,246.455000,__
+packet,246.413000,__
+packet,246.496000,__
+packet,246.747000,__
+packet,246.621000,__
+packet,246.580000,__
+packet,246.663000,__
+packet,246.705000,__
+packet,246.872000,__
+packet,246.788000,__
+packet,246.830000,__
+packet,246.997000,__
+packet,246.913000,__
+packet,246.955000,__
+packet,247.122000,__
+packet,247.038000,__
+packet,247.080000,__
+packet,247.289000,__
+packet,247.205000,__
+packet,247.164000,__
+packet,247.247000,__
+packet,247.497000,__
+packet,247.372000,__
+packet,247.330000,__
+packet,247.414000,__
+packet,247.456000,__
+packet,247.622000,__
+packet,247.539000,__
+packet,247.581000,__
+packet,247.831000,__
+packet,247.706000,__
+packet,247.664000,__
+packet,247.748000,__
+packet,247.789000,__
+packet,247.873000,K_
+packet,248.081000,__
+packet,247.956000,__
+packet,247.914000,__
+packet,247.998000,__
+packet,248.039000,__
+packet,248.206000,__
+packet,248.123000,__
+packet,248.165000,__
+packet,248.373000,__
+packet,248.290000,__
+packet,248.248000,__
+packet,248.331000,__
+packet,248.540000,__
+packet,248.457000,__
+packet,248.415000,__
+packet,248.498000,__
+packet,248.749000,__
+packet,248.623000,__
+packet,248.582000,__
+packet,248.665000,__
+packet,248.707000,__
+packet,248.874000,__
+packet,248.790000,__
+packet,248.832000,__
+packet,249.040000,__
+packet,248.957000,__
+packet,248.915000,__
+packet,248.999000,__
+packet,249.249000,__
+packet,249.124000,__
+packet,249.082000,__
+packet,249.166000,__
+packet,249.207000,__
+packet,249.374000,__
+packet,249.291000,__
+packet,249.332000,__
+packet,249.541000,__
+packet,249.458000,__
+packet,249.416000,__
+packet,249.499000,__
+packet,249.750000,__
+packet,249.624000,__
+packet,249.583000,__
+packet,249.666000,__
+packet,249.708000,__
+packet,249.875000,__
+packet,249.791000,__
+packet,249.833000,__
+packet,250.041000,__
+packet,249.958000,__
+packet,249.916000,__
+packet,250.000000,__
+packet,250.208000,__
+packet,250.125000,__
+packet,250.083000,__
+packet,250.167000,__
+packet,250.375000,__
+packet,250.292000,__
+packet,250.250000,__
+packet,250.333000,__
+packet,250.542000,__
+packet,250.459000,__
+packet,250.417000,__
+packet,250.500000,__
+packet,250.751000,__
+packet,250.625000,__
+packet,250.584000,__
+packet,250.667000,__
+packet,250.709000,__
+packet,250.876000,__
+packet,250.792000,__
+packet,250.834000,__
+packet,251.042000,__
+packet,250.959000,__
+packet,250.917000,__
+packet,251.001000,__
+packet,251.251000,__
+packet,251.126000,__
+packet,251.084000,__
+packet,251.168000,__
+packet,251.209000,__
+packet,251.376000,__
+packet,251.293000,__
+packet,251.334000,__
+packet,251.543000,__
+packet,251.460000,__
+packet,251.418000,__
+packet,251.501000,__
+packet,251.710000,__
+packet,251.626000,__
+packet,251.585000,__
+packet,251.668000,__
+packet,251.793000,__
+packet,251.752000,__
+packet,251.960000,__
+packet,251.877000,__
+packet,251.835000,__
+packet,251.918000,__
+packet,252.127000,__
+packet,252.043000,__
+packet,252.002000,__
+packet,252.085000,__
+packet,252.294000,__
+packet,252.210000,__
+packet,252.169000,__
+packet,252.252000,__
+packet,252.419000,__
+packet,252.335000,__
+packet,252.377000,__
+packet,252.586000,__
+packet,252.502000,__
+packet,252.461000,__
+packet,252.544000,__
+packet,252.711000,__
+packet,252.627000,__
+packet,252.669000,__
+packet,252.878000,__
+packet,252.794000,__
+packet,252.753000,__
+packet,252.836000,__
+packet,253.044000,__
+packet,252.961000,__
+packet,252.919000,__
+packet,253.003000,__
+packet,253.211000,__
+packet,253.128000,__
+packet,253.086000,__
+packet,253.170000,__
+packet,253.378000,__
+packet,253.295000,__
+packet,253.253000,__
+packet,253.336000,__
+packet,253.545000,__
+packet,253.462000,__
+packet,253.420000,__
+packet,253.503000,__
+packet,253.754000,__
+packet,253.628000,__
+packet,253.587000,__
+packet,253.670000,__
+packet,253.712000,__
+packet,253.920000,__
+packet,253.837000,__
+packet,253.795000,__
+packet,253.879000,__
+packet,254.087000,__
+packet,254.004000,__
+packet,253.962000,__
+packet,254.045000,__
+packet,254.254000,__
+packet,254.171000,__
+packet,254.129000,__
+packet,254.212000,__
+packet,254.421000,__
+packet,254.337000,__
+packet,254.296000,__
+packet,254.379000,__
+packet,254.588000,__
+packet,254.504000,__
+packet,254.463000,__
+packet,254.546000,__
+packet,254.755000,__
+packet,254.671000,__
+packet,254.629000,__
+packet,254.713000,__
+packet,254.921000,__
+packet,254.838000,__
+packet,254.796000,__
+packet,254.880000,__
+packet,255.088000,__
+packet,255.005000,__
+packet,254.963000,__
+packet,255.046000,__
+packet,255.255000,__
+packet,255.172000,__
+packet,255.130000,__
+packet,255.213000,__
+packet,255.422000,__
+packet,255.338000,__
+packet,255.297000,__
+packet,255.380000,__
+packet,255.589000,__
+packet,255.505000,__
+packet,255.464000,__
+packet,255.547000,__
+packet,255.756000,__
+packet,255.672000,__
+packet,255.630000,__
+packet,255.714000,__
+packet,255.922000,__
+packet,255.839000,__
+packet,255.797000,__
+packet,255.881000,__
+packet,256.089000,__
+packet,256.006000,__
+packet,255.964000,__
+packet,256.047000,__
+packet,256.256000,__
+packet,256.173000,__
+packet,256.131000,__
+packet,256.214000,__
+packet,256.423000,__
+packet,256.339000,__
+packet,256.298000,__
+packet,256.381000,__
+packet,256.590000,__
+packet,256.506000,__
+packet,256.465000,__
+packet,256.548000,__
+packet,256.757000,__
+packet,256.673000,__
+packet,256.631000,__
+packet,256.715000,__
+packet,256.882000,__
+packet,256.798000,__
+packet,256.840000,__
+packet,257.048000,__
+packet,256.965000,__
+packet,256.923000,__
+packet,257.007000,__
+packet,257.215000,__
+packet,257.132000,__
+packet,257.090000,__
+packet,257.174000,__
+packet,257.382000,__
+packet,257.299000,__
+packet,257.257000,__
+packet,257.340000,__
+packet,257.549000,__
+packet,257.466000,__
+packet,257.424000,__
+packet,257.507000,__
+packet,257.758000,__
+packet,257.632000,__
+packet,257.591000,__
+packet,257.674000,__
+packet,257.716000,__
+packet,257.924000,__
+packet,257.841000,__
+packet,257.799000,__
+packet,257.883000,__
+packet,258.091000,__
+packet,258.008000,__
+packet,257.966000,__
+packet,258.049000,__
+packet,258.175000,__
+packet,258.133000,__
+packet,258.216000,K_
+packet,258.383000,__
+packet,258.300000,__
+packet,258.258000,__
+packet,258.341000,__
+packet,258.550000,__
+packet,258.467000,__
+packet,258.425000,__
+packet,258.508000,__
+packet,258.717000,__
+packet,258.633000,__
+packet,258.592000,__
+packet,258.675000,__
+packet,258.884000,__
+packet,258.800000,__
+packet,258.759000,__
+packet,258.842000,__
+packet,259.050000,__
+packet,258.967000,__
+packet,258.925000,__
+packet,259.009000,__
+packet,259.217000,__
+packet,259.134000,__
+packet,259.092000,__
+packet,259.176000,__
+packet,259.384000,__
+packet,259.301000,__
+packet,259.259000,__
+packet,259.342000,__
+packet,259.551000,__
+packet,259.468000,__
+packet,259.426000,__
+packet,259.509000,__
+packet,259.718000,__
+packet,259.634000,__
+packet,259.593000,__
+packet,259.676000,__
+packet,259.885000,__
+packet,259.801000,__
+packet,259.760000,__
+packet,259.843000,__
+packet,260.051000,__
+packet,259.968000,__
+packet,259.926000,__
+packet,260.010000,__
+packet,260.218000,__
+packet,260.135000,__
+packet,260.093000,__
+packet,260.177000,__
+packet,260.385000,__
+packet,260.302000,__
+packet,260.260000,__
+packet,260.343000,__
+packet,260.552000,__
+packet,260.469000,__
+packet,260.427000,__
+packet,260.510000,__
+packet,260.677000,__
+packet,260.594000,__
+packet,260.635000,__
+packet,260.719000,K_
+packet,260.761000,__
+packet,261.011000,__
+packet,260.886000,__
+packet,260.802000,__
+packet,260.844000,__
+packet,260.927000,__
+packet,260.969000,__
+packet,261.178000,__
+packet,261.094000,__
+packet,261.052000,__
+packet,261.136000,__
+packet,261.303000,__
+packet,261.219000,__
+packet,261.261000,__
+packet,261.636000,__
+packet,261.470000,__
+packet,261.344000,__
+packet,261.386000,__
+packet,261.428000,__
+packet,261.511000,__
+packet,261.553000,__
+packet,261.595000,__
+packet,261.845000,__
+packet,261.720000,__
+packet,261.678000,__
+packet,261.762000,__
+packet,261.803000,__
+packet,262.179000,__
+packet,262.012000,__
+packet,261.887000,__
+packet,261.928000,__
+packet,261.970000,__
+packet,262.053000,__
+packet,262.095000,__
+packet,262.137000,__
+packet,262.429000,__
+packet,262.304000,__
+packet,262.220000,__
+packet,262.262000,__
+packet,262.345000,__
+packet,262.387000,__
+packet,262.554000,__
+packet,262.471000,__
+packet,262.512000,__
+packet,262.846000,__
+packet,262.679000,__
+packet,262.596000,__
+packet,262.637000,__
+packet,262.721000,__
+packet,262.763000,__
+packet,262.804000,__
+packet,263.054000,__
+packet,262.929000,__
+packet,262.888000,__
+packet,262.971000,__
+packet,263.013000,__
+packet,263.305000,__
+packet,263.180000,__
+packet,263.096000,__
+packet,263.138000,__
+packet,263.221000,__
+packet,263.263000,__
+packet,263.638000,__
+packet,263.472000,__
+packet,263.346000,__
+packet,263.388000,__
+packet,263.430000,__
+packet,263.513000,__
+packet,263.555000,__
+packet,263.597000,__
+packet,263.972000,__
+packet,263.805000,__
+packet,263.680000,__
+packet,263.722000,__
+packet,263.764000,__
+packet,263.847000,__
+packet,263.889000,__
+packet,263.930000,__
+packet,264.181000,__
+packet,264.055000,__
+packet,264.014000,__
+packet,264.097000,__
+packet,264.139000,__
+packet,264.556000,__
+packet,264.347000,__
+packet,264.222000,__
+packet,264.264000,__
+packet,264.306000,__
+packet,264.389000,__
+packet,264.431000,__
+packet,264.473000,__
+packet,264.514000,__
+packet,264.765000,__
+packet,264.639000,__
+packet,264.598000,__
+packet,264.681000,__
+packet,264.723000,__
+packet,265.140000,__
+packet,264.931000,__
+packet,264.806000,__
+packet,264.848000,__
+packet,264.890000,__
+packet,264.973000,__
+packet,265.015000,__
+packet,265.056000,__
+packet,265.098000,__
+packet,265.474000,__
+packet,265.307000,__
+packet,265.182000,__
+packet,265.223000,__
+packet,265.265000,__
+packet,265.348000,__
+packet,265.390000,__
+packet,265.432000,__
+packet,265.557000,__
+packet,265.515000,__
+packet,265.932000,__
+packet,265.724000,__
+packet,265.599000,__
+packet,265.640000,__
+packet,265.682000,__
+packet,265.766000,__
+packet,265.807000,__
+packet,265.849000,__
+packet,265.891000,__
+packet,266.183000,__
+packet,266.057000,__
+packet,265.974000,__
+packet,266.016000,__
+packet,266.099000,__
+packet,266.141000,__
+packet,266.558000,__
+packet,266.349000,__
+packet,266.224000,__
+packet,266.266000,__
+packet,266.308000,__
+packet,266.391000,__
+packet,266.433000,__
+packet,266.475000,__
+packet,266.516000,__
+packet,266.725000,__
+packet,266.641000,__
+packet,266.600000,__
+packet,266.683000,__
+packet,266.933000,__
+packet,266.808000,__
+packet,266.767000,__
+packet,266.850000,__
+packet,266.892000,__
+packet,267.058000,__
+packet,266.975000,__
+packet,267.017000,__
+packet,267.225000,__
+packet,267.142000,__
+packet,267.100000,__
+packet,267.184000,__
+packet,267.434000,__
+packet,267.309000,__
+packet,267.267000,__
+packet,267.350000,__
+packet,267.392000,__
+packet,267.559000,__
+packet,267.476000,__
+packet,267.517000,__
+packet,267.851000,__
+packet,267.684000,__
+packet,267.601000,__
+packet,267.642000,__
+packet,267.726000,__
+packet,267.768000,__
+packet,267.809000,__
+packet,267.934000,__
+packet,267.893000,__
+packet,268.101000,__
+packet,268.018000,__
+packet,267.976000,__
+packet,268.059000,__
+packet,268.185000,__
+packet,268.143000,__
+packet,268.435000,__
+packet,268.310000,__
+packet,268.226000,__
+packet,268.268000,__
+packet,268.351000,__
+packet,268.393000,__
+packet,268.602000,__
+packet,268.518000,__
+packet,268.477000,__
+packet,268.560000,__
+packet,268.852000,__
+packet,268.727000,__
+packet,268.643000,__
+packet,268.685000,__
+packet,268.769000,__
+packet,268.810000,__
+packet,269.102000,__
+packet,268.977000,__
+packet,268.894000,__
+packet,268.935000,__
+packet,269.019000,__
+packet,269.060000,__
+packet,269.186000,__
+packet,269.144000,__
+packet,269.478000,__
+packet,269.311000,__
+packet,269.227000,__
+packet,269.269000,__
+packet,269.352000,__
+packet,269.394000,__
+packet,269.436000,__
+packet,269.686000,__
+packet,269.561000,__
+packet,269.519000,__
+packet,269.603000,__
+packet,269.644000,__
+packet,269.728000,K_
+packet,269.853000,__
+packet,269.770000,__
+packet,269.811000,__
+packet,270.020000,__
+packet,269.936000,__
+packet,269.895000,__
+packet,269.978000,__
+packet,270.228000,__
+packet,270.103000,__
+packet,270.061000,__
+packet,270.145000,__
+packet,270.187000,__
+packet,270.520000,__
+packet,270.353000,__
+packet,270.270000,__
+packet,270.312000,__
+packet,270.395000,__
+packet,270.437000,__
+packet,270.479000,__
+packet,270.771000,__
+packet,270.645000,__
+packet,270.562000,__
+packet,270.604000,__
+packet,270.687000,__
+packet,270.729000,__
+packet,271.021000,__
+packet,270.896000,__
+packet,270.812000,__
+packet,270.854000,__
+packet,270.937000,__
+packet,270.979000,__
+packet,271.313000,__
+packet,271.146000,__
+packet,271.062000,__
+packet,271.104000,__
+packet,271.188000,__
+packet,271.229000,__
+packet,271.271000,__
+packet,271.521000,__
+packet,271.396000,__
+packet,271.354000,__
+packet,271.438000,__
+packet,271.480000,__
+packet,271.772000,__
+packet,271.646000,__
+packet,271.563000,__
+packet,271.605000,__
+packet,271.688000,__
+packet,271.730000,__
+packet,272.022000,__
+packet,271.897000,__
+packet,271.813000,__
+packet,271.855000,__
+packet,271.938000,__
+packet,271.980000,__
+packet,272.272000,__
+packet,272.147000,__
+packet,272.063000,__
+packet,272.105000,__
+packet,272.189000,__
+packet,272.230000,__
+packet,272.439000,__
+packet,272.355000,__
+packet,272.314000,__
+packet,272.397000,__
+packet,272.647000,__
+packet,272.522000,__
+packet,272.481000,__
+packet,272.564000,__
+packet,272.606000,__
+packet,272.898000,__
+packet,272.773000,__
+packet,272.689000,__
+packet,272.731000,__
+packet,272.814000,__
+packet,272.856000,__
+packet,273.148000,__
+packet,273.023000,__
+packet,272.939000,__
+packet,272.981000,__
+packet,273.064000,__
+packet,273.106000,__
+packet,273.523000,__
+packet,273.315000,__
+packet,273.190000,__
+packet,273.231000,__
+packet,273.273000,__
+packet,273.356000,__
+packet,273.398000,__
+packet,273.440000,__
+packet,273.482000,__
+packet,273.774000,__
+packet,273.648000,__
+packet,273.565000,__
+packet,273.607000,__
+packet,273.690000,__
+packet,273.732000,__
+packet,274.024000,__
+packet,273.899000,__
+packet,273.815000,__
+packet,273.857000,__
+packet,273.940000,__
+packet,273.982000,__
+packet,274.274000,__
+packet,274.149000,__
+packet,274.065000,__
+packet,274.107000,__
+packet,274.191000,__
+packet,274.232000,__
+packet,274.524000,__
+packet,274.399000,__
+packet,274.316000,__
+packet,274.357000,__
+packet,274.441000,__
+packet,274.483000,__
+packet,274.775000,__
+packet,274.649000,__
+packet,274.566000,__
+packet,274.608000,__
+packet,274.691000,__
+packet,274.733000,__
+packet,275.025000,__
+packet,274.900000,__
+packet,274.816000,__
+packet,274.858000,__
+packet,274.941000,__
+packet,274.983000,__
+packet,275.275000,__
+packet,275.150000,__
+packet,275.066000,__
+packet,275.108000,__
+packet,275.192000,__
+packet,275.233000,__
+packet,275.525000,__
+packet,275.400000,__
+packet,275.317000,__
+packet,275.358000,__
+packet,275.442000,__
+packet,275.484000,__
+packet,275.776000,__
+packet,275.650000,__
+packet,275.567000,__
+packet,275.609000,__
+packet,275.692000,__
+packet,275.734000,__
+packet,276.026000,__
+packet,275.901000,__
+packet,275.817000,__
+packet,275.859000,__
+packet,275.942000,__
+packet,275.984000,__
+packet,276.276000,__
+packet,276.151000,__
+packet,276.067000,__
+packet,276.109000,__
+packet,276.193000,__
+packet,276.234000,__
+packet,276.526000,__
+packet,276.401000,__
+packet,276.318000,__
+packet,276.359000,__
+packet,276.443000,__
+packet,276.485000,__
+packet,276.777000,__
+packet,276.651000,__
+packet,276.568000,__
+packet,276.610000,__
+packet,276.693000,__
+packet,276.735000,__
+packet,277.027000,__
+packet,276.902000,__
+packet,276.818000,__
+packet,276.860000,__
+packet,276.943000,__
+packet,276.985000,__
+packet,277.277000,__
+packet,277.152000,__
+packet,277.068000,__
+packet,277.110000,__
+packet,277.194000,__
+packet,277.235000,__
+packet,277.527000,__
+packet,277.402000,__
+packet,277.319000,__
+packet,277.360000,__
+packet,277.444000,__
+packet,277.486000,__
+packet,277.778000,__
+packet,277.652000,__
+packet,277.569000,__
+packet,277.611000,__
+packet,277.694000,__
+packet,277.736000,__
+packet,278.028000,__
+packet,277.903000,__
+packet,277.819000,__
+packet,277.861000,__
+packet,277.944000,__
+packet,277.986000,__
+packet,278.278000,__
+packet,278.153000,__
+packet,278.069000,__
+packet,278.111000,__
+packet,278.195000,__
+packet,278.236000,__
+packet,278.320000,__
+packet,278.361000,K_
+packet,278.737000,__
+packet,278.528000,__
+packet,278.403000,__
+packet,278.445000,__
+packet,278.487000,__
+packet,278.570000,__
+packet,278.612000,__
+packet,278.653000,__
+packet,278.695000,__
+packet,279.112000,__
+packet,278.904000,__
+packet,278.779000,__
+packet,278.820000,__
+packet,278.862000,__
+packet,278.945000,__
+packet,278.987000,__
+packet,279.029000,__
+packet,279.070000,__
+packet,279.321000,__
+packet,279.196000,__
+packet,279.154000,__
+packet,279.237000,__
+packet,279.279000,__
+packet,279.446000,__
+packet,279.362000,__
+packet,279.404000,__
+packet,279.488000,__
+packet,279.529000,__
+packet,279.571000,__
+packet,279.738000,__
+packet,279.654000,__
+packet,279.613000,__
+packet,279.696000,__
+packet,279.821000,__
+packet,279.780000,__
+packet,279.863000,__
+packet,279.905000,__
+packet,279.946000,__
+packet,279.988000,__
+packet,280.071000,__
+packet,280.030000,__
+packet,280.238000,__
+packet,280.155000,__
+packet,280.113000,__
+packet,280.197000,__
+packet,280.405000,__
+packet,280.322000,__
+packet,280.280000,__
+packet,280.363000,__
+packet,280.572000,__
+packet,280.489000,__
+packet,280.447000,__
+packet,280.530000,__
+packet,280.739000,__
+packet,280.655000,__
+packet,280.614000,__
+packet,280.697000,__
+packet,280.906000,__
+packet,280.822000,__
+packet,280.781000,__
+packet,280.864000,__
+packet,280.989000,__
+packet,280.947000,__
+packet,281.156000,__
+packet,281.072000,__
+packet,281.031000,__
+packet,281.114000,__
+packet,281.531000,__
+packet,281.323000,__
+packet,281.198000,__
+packet,281.239000,__
+packet,281.281000,__
+packet,281.364000,__
+packet,281.406000,__
+packet,281.448000,__
+packet,281.490000,__
+packet,281.907000,__
+packet,281.698000,__
+packet,281.573000,__
+packet,281.615000,__
+packet,281.656000,__
+packet,281.740000,__
+packet,281.782000,__
+packet,281.823000,__
+packet,281.865000,__
+packet,282.282000,__
+packet,282.073000,__
+packet,281.948000,__
+packet,281.990000,__
+packet,282.032000,__
+packet,282.115000,__
+packet,282.157000,__
+packet,282.199000,__
+packet,282.240000,__
+packet,282.324000,__
+packet,282.491000,__
+packet,282.407000,__
+packet,282.365000,__
+packet,282.449000,__
+packet,282.532000,K_
+packet,282.699000,__
+packet,282.616000,__
+packet,282.574000,__
+packet,282.657000,__
+packet,282.908000,__
+packet,282.783000,__
+packet,282.741000,__
+packet,282.824000,__
+packet,282.866000,__
+packet,283.074000,__
+packet,282.991000,__
+packet,282.949000,__
+packet,283.033000,__
+packet,283.241000,__
+packet,283.158000,__
+packet,283.116000,__
+packet,283.200000,__
+packet,283.408000,__
+packet,283.325000,__
+packet,283.283000,__
+packet,283.366000,__
+packet,283.533000,__
+packet,283.450000,__
+packet,283.492000,__
+packet,283.700000,__
+packet,283.617000,__
+packet,283.575000,__
+packet,283.658000,__
+packet,283.992000,__
+packet,283.825000,__
+packet,283.742000,__
+packet,283.784000,__
+packet,283.867000,__
+packet,283.909000,__
+packet,283.950000,__
+packet,284.242000,__
+packet,284.117000,__
+packet,284.034000,__
+packet,284.075000,__
+packet,284.159000,__
+packet,284.201000,__
+packet,284.409000,__
+packet,284.326000,__
+packet,284.284000,__
+packet,284.367000,__
+packet,284.534000,__
+packet,284.451000,__
+packet,284.493000,__
+packet,284.701000,__
+packet,284.618000,__
+packet,284.576000,__
+packet,284.659000,__
+packet,284.910000,__
+packet,284.785000,__
+packet,284.743000,__
+packet,284.826000,__
+packet,284.868000,__
+packet,285.076000,__
+packet,284.993000,__
+packet,284.951000,__
+packet,285.035000,__
+packet,285.243000,__
+packet,285.160000,__
+packet,285.118000,__
+packet,285.202000,__
+packet,285.410000,__
+packet,285.327000,__
+packet,285.285000,__
+packet,285.368000,__
+packet,285.577000,__
+packet,285.494000,__
+packet,285.452000,__
+packet,285.535000,__
+packet,285.744000,__
+packet,285.660000,__
+packet,285.619000,__
+packet,285.702000,__
+packet,285.911000,__
+packet,285.827000,__
+packet,285.786000,__
+packet,285.869000,__
+packet,286.077000,__
+packet,285.994000,__
+packet,285.952000,__
+packet,286.036000,__
+packet,286.244000,__
+packet,286.161000,__
+packet,286.119000,__
+packet,286.203000,__
+packet,286.411000,__
+packet,286.328000,__
+packet,286.286000,__
+packet,286.369000,__
+packet,286.578000,__
+packet,286.495000,__
+packet,286.453000,__
+packet,286.536000,__
+packet,286.745000,__
+packet,286.661000,__
+packet,286.620000,__
+packet,286.703000,__
+packet,286.912000,__
+packet,286.828000,__
+packet,286.787000,__
+packet,286.870000,__
+packet,287.078000,__
+packet,286.995000,__
+packet,286.953000,__
+packet,287.037000,__
+packet,287.245000,__
+packet,287.162000,__
+packet,287.120000,__
+packet,287.204000,__
+packet,287.412000,__
+packet,287.329000,__
+packet,287.287000,__
+packet,287.370000,__
+packet,287.579000,__
+packet,287.496000,__
+packet,287.454000,__
+packet,287.537000,__
+packet,287.746000,__
+packet,287.662000,__
+packet,287.621000,__
+packet,287.704000,__
+packet,287.913000,__
+packet,287.829000,__
+packet,287.788000,__
+packet,287.871000,__
+packet,288.079000,__
+packet,287.996000,__
+packet,287.954000,__
+packet,288.038000,__
+packet,288.246000,__
+packet,288.163000,__
+packet,288.121000,__
+packet,288.205000,__
+packet,288.413000,__
+packet,288.330000,__
+packet,288.288000,__
+packet,288.371000,__
+packet,288.580000,__
+packet,288.497000,__
+packet,288.455000,__
+packet,288.538000,__
+packet,288.747000,__
+packet,288.663000,__
+packet,288.622000,__
+packet,288.705000,__
+packet,288.914000,__
+packet,288.830000,__
+packet,288.789000,__
+packet,288.872000,__
+packet,289.080000,__
+packet,288.997000,__
+packet,288.955000,__
+packet,289.039000,__
+packet,289.247000,__
+packet,289.164000,__
+packet,289.122000,__
+packet,289.206000,__
+packet,289.414000,__
+packet,289.331000,__
+packet,289.289000,__
+packet,289.372000,__
+packet,289.581000,__
+packet,289.498000,__
+packet,289.456000,__
+packet,289.539000,__
+packet,289.748000,__
+packet,289.664000,__
+packet,289.623000,__
+packet,289.706000,__
+packet,289.915000,__
+packet,289.831000,__
+packet,289.790000,__
+packet,289.873000,__
+packet,289.956000,K_
+packet,290.207000,__
+packet,290.081000,__
+packet,289.998000,__
+packet,290.040000,__
+packet,290.123000,__
+packet,290.165000,__
+packet,290.415000,__
+packet,290.290000,__
+packet,290.248000,__
+packet,290.332000,__
+packet,290.373000,__
+packet,290.540000,__
+packet,290.457000,__
+packet,290.499000,__
+packet,290.665000,__
+packet,290.582000,__
+packet,290.624000,__
+packet,290.874000,__
+packet,290.749000,__
+packet,290.707000,__
+packet,290.791000,__
+packet,290.832000,__
+packet,291.041000,__
+packet,290.957000,__
+packet,290.916000,__
+packet,290.999000,__
+packet,291.291000,__
+packet,291.166000,__
+packet,291.082000,__
+packet,291.124000,__
+packet,291.208000,__
+packet,291.249000,__
+packet,291.458000,__
+packet,291.374000,__
+packet,291.333000,__
+packet,291.416000,__
+packet,291.666000,__
+packet,291.541000,__
+packet,291.500000,__
+packet,291.583000,__
+packet,291.625000,__
+packet,291.917000,__
+packet,291.792000,__
+packet,291.708000,__
+packet,291.750000,__
+packet,291.833000,__
+packet,291.875000,__
+packet,292.042000,__
+packet,291.958000,__
+packet,292.000000,__
+packet,292.250000,__
+packet,292.125000,__
+packet,292.083000,__
+packet,292.167000,__
+packet,292.209000,__
+packet,292.417000,__
+packet,292.334000,__
+packet,292.292000,__
+packet,292.375000,__
+packet,292.542000,__
+packet,292.459000,__
+packet,292.501000,__
+packet,292.793000,__
+packet,292.667000,__
+packet,292.584000,__
+packet,292.626000,__
+packet,292.709000,__
+packet,292.751000,__
+packet,292.918000,__
+packet,292.834000,__
+packet,292.876000,__
+packet,292.959000,K_
+packet,293.084000,__
+packet,293.001000,__
+packet,293.043000,__
+packet,293.251000,__
+packet,293.168000,__
+packet,293.126000,__
+packet,293.210000,__
+packet,293.418000,__
+packet,293.335000,__
+packet,293.293000,__
+packet,293.376000,__
+packet,293.460000,__
+packet,293.502000,__
+packet,293.627000,__
+packet,293.543000,__
+packet,293.585000,__
+packet,293.835000,__
+packet,293.710000,__
+packet,293.668000,__
+packet,293.752000,__
+packet,293.794000,__
+packet,294.085000,__
+packet,293.960000,__
+packet,293.877000,__
+packet,293.919000,__
+packet,294.002000,__
+packet,294.044000,__
+packet,294.211000,__
+packet,294.127000,__
+packet,294.169000,__
+packet,294.377000,__
+packet,294.294000,__
+packet,294.252000,__
+packet,294.336000,__
+packet,294.628000,__
+packet,294.503000,__
+packet,294.419000,__
+packet,294.461000,__
+packet,294.544000,__
+packet,294.586000,__
+packet,294.753000,__
+packet,294.669000,__
+packet,294.711000,__
+packet,294.961000,__
+packet,294.836000,__
+packet,294.795000,__
+packet,294.878000,__
+packet,294.920000,__
+packet,295.086000,__
+packet,295.003000,__
+packet,295.045000,__
+packet,295.253000,__
+packet,295.170000,__
+packet,295.128000,__
+packet,295.212000,__
+packet,295.504000,__
+packet,295.378000,__
+packet,295.295000,__
+packet,295.337000,__
+packet,295.420000,__
+packet,295.462000,__
+packet,295.712000,__
+packet,295.587000,__
+packet,295.545000,__
+packet,295.629000,__
+packet,295.670000,__
+packet,295.879000,__
+packet,295.796000,__
+packet,295.754000,__
+packet,295.837000,__
+packet,295.962000,__
+packet,295.921000,__
+packet,296.213000,__
+packet,296.087000,__
+packet,296.004000,__
+packet,296.046000,__
+packet,296.129000,__
+packet,296.171000,__
+packet,296.338000,__
+packet,296.254000,__
+packet,296.296000,__
+packet,296.505000,__
+packet,296.421000,__
+packet,296.379000,__
+packet,296.463000,__
+packet,296.755000,__
+packet,296.630000,__
+packet,296.546000,__
+packet,296.588000,__
+packet,296.671000,__
+packet,296.713000,__
+packet,296.963000,__
+packet,296.838000,__
+packet,296.797000,__
+packet,296.880000,__
+packet,296.922000,__
+packet,297.130000,__
+packet,297.047000,__
+packet,297.005000,__
+packet,297.088000,__
+packet,297.255000,__
+packet,297.172000,__
+packet,297.214000,__
+packet,297.464000,__
+packet,297.339000,__
+packet,297.297000,__
+packet,297.380000,__
+packet,297.422000,__
+packet,297.506000,__
+packet,297.714000,__
+packet,297.589000,__
+packet,297.547000,__
+packet,297.631000,__
+packet,297.672000,__
+packet,297.881000,__
+packet,297.798000,__
+packet,297.756000,__
+packet,297.839000,__
+packet,297.923000,K_
+packet,298.089000,__
+packet,298.006000,__
+packet,297.964000,__
+packet,298.048000,__
+packet,298.215000,__
+packet,298.131000,__
+packet,298.173000,__
+packet,298.256000,__
+packet,298.423000,__
+packet,298.340000,__
+packet,298.298000,__
+packet,298.381000,__
+packet,298.632000,__
+packet,298.507000,__
+packet,298.465000,__
+packet,298.548000,__
+packet,298.590000,__
+packet,298.840000,__
+packet,298.715000,__
+packet,298.673000,__
+packet,298.757000,__
+packet,298.799000,__
+packet,298.882000,__
+packet,299.049000,__
+packet,298.965000,__
+packet,298.924000,__
+packet,299.007000,__
+packet,299.174000,__
+packet,299.090000,__
+packet,299.132000,__
+packet,299.341000,__
+packet,299.257000,__
+packet,299.216000,__
+packet,299.299000,__
+packet,299.382000,__
+packet,299.633000,__
+packet,299.508000,__
+packet,299.424000,__
+packet,299.466000,__
+packet,299.549000,__
+packet,299.591000,__
+packet,299.800000,__
+packet,299.716000,__
+packet,299.674000,__
+packet,299.758000,__
+packet,299.841000,__
+packet,300.008000,__
+packet,299.925000,__
+packet,299.883000,__
+packet,299.966000,__
+packet,300.175000,__
+packet,300.091000,__
+packet,300.050000,__
+packet,300.133000,__
+packet,300.258000,__
+packet,300.217000,__
+packet,300.467000,__
+packet,300.342000,__
+packet,300.300000,__
+packet,300.383000,__
+packet,300.425000,__
+packet,300.592000,__
+packet,300.509000,__
+packet,300.550000,__
+packet,300.759000,__
+packet,300.675000,__
+packet,300.634000,__
+packet,300.717000,__
+packet,300.884000,__
+packet,300.801000,__
+packet,300.842000,__
+packet,301.092000,__
+packet,300.967000,__
+packet,300.926000,__
+packet,301.009000,__
+packet,301.051000,__
+packet,301.259000,__
+packet,301.176000,__
+packet,301.134000,__
+packet,301.218000,__
+packet,301.468000,__
+packet,301.343000,__
+packet,301.301000,__
+packet,301.384000,__
+packet,301.426000,__
+packet,301.718000,__
+packet,301.593000,__
+packet,301.510000,__
+packet,301.551000,__
+packet,301.635000,__
+packet,301.676000,__
+packet,301.760000,K_
+packet,301.927000,__
+packet,301.843000,__
+packet,301.802000,__
+packet,301.885000,__
+packet,302.177000,__
+packet,302.052000,__
+packet,301.968000,__
+packet,302.010000,__
+packet,302.093000,__
+packet,302.135000,__
+packet,302.427000,__
+packet,302.302000,__
+packet,302.219000,__
+packet,302.260000,__
+packet,302.344000,__
+packet,302.385000,__
+packet,302.677000,__
+packet,302.552000,__
+packet,302.469000,__
+packet,302.511000,__
+packet,302.594000,__
+packet,302.636000,__
+packet,303.011000,__
+packet,302.844000,__
+packet,302.719000,__
+packet,302.761000,__
+packet,302.803000,__
+packet,302.886000,__
+packet,302.928000,__
+packet,302.969000,__
+packet,303.386000,__
+packet,303.178000,__
+packet,303.053000,__
+packet,303.094000,__
+packet,303.136000,__
+packet,303.220000,__
+packet,303.261000,__
+packet,303.303000,__
+packet,303.345000,__
+packet,303.595000,__
+packet,303.470000,__
+packet,303.428000,__
+packet,303.512000,__
+packet,303.553000,__
+packet,303.845000,__
+packet,303.720000,__
+packet,303.637000,__
+packet,303.678000,__
+packet,303.762000,__
+packet,303.804000,__
+packet,304.137000,__
+packet,303.970000,__
+packet,303.887000,__
+packet,303.929000,__
+packet,304.012000,__
+packet,304.054000,__
+packet,304.095000,__
+packet,304.179000,__
+packet,304.554000,__
+packet,304.346000,__
+packet,304.221000,__
+packet,304.262000,__
+packet,304.304000,__
+packet,304.387000,__
+packet,304.429000,__
+packet,304.471000,__
+packet,304.513000,__
+packet,304.846000,__
+packet,304.679000,__
+packet,304.596000,__
+packet,304.638000,__
+packet,304.721000,__
+packet,304.763000,__
+packet,304.805000,__
+packet,304.888000,K_
+packet,305.013000,__
+packet,304.930000,__
+packet,304.971000,__
+packet,305.180000,__
+packet,305.096000,__
+packet,305.055000,__
+packet,305.138000,__
+packet,305.388000,__
+packet,305.263000,__
+packet,305.222000,__
+packet,305.305000,__
+packet,305.347000,__
+packet,305.764000,__
+packet,305.555000,__
+packet,305.430000,__
+packet,305.472000,__
+packet,305.514000,__
+packet,305.597000,__
+packet,305.639000,__
+packet,305.680000,__
+packet,305.722000,__
+packet,305.889000,__
+packet,305.806000,__
+packet,305.847000,__
+packet,306.014000,__
+packet,305.931000,__
+packet,305.972000,__
+packet,306.181000,__
+packet,306.097000,__
+packet,306.056000,__
+packet,306.139000,__
+packet,306.389000,__
+packet,306.264000,__
+packet,306.223000,__
+packet,306.306000,__
+packet,306.348000,__
+packet,306.556000,__
+packet,306.473000,__
+packet,306.431000,__
+packet,306.515000,__
+packet,306.765000,__
+packet,306.640000,__
+packet,306.598000,__
+packet,306.681000,__
+packet,306.723000,__
+packet,306.890000,__
+packet,306.807000,__
+packet,306.848000,__
+packet,307.140000,__
+packet,307.015000,__
+packet,306.932000,__
+packet,306.973000,__
+packet,307.057000,__
+packet,307.098000,__
+packet,307.265000,__
+packet,307.182000,__
+packet,307.224000,__
+packet,307.307000,__
+packet,307.349000,K_
+packet,307.390000,__
+packet,307.557000,__
+packet,307.474000,__
+packet,307.432000,__
+packet,307.516000,__
+packet,307.724000,__
+packet,307.641000,__
+packet,307.599000,__
+packet,307.682000,__
+packet,307.849000,__
+packet,307.766000,__
+packet,307.808000,__
+packet,308.016000,__
+packet,307.933000,__
+packet,307.891000,__
+packet,307.974000,__
+packet,308.225000,__
+packet,308.099000,__
+packet,308.058000,__
+packet,308.141000,__
+packet,308.183000,__
+packet,308.391000,__
+packet,308.308000,__
+packet,308.266000,__
+packet,308.350000,__
+packet,308.517000,__
+packet,308.433000,__
+packet,308.475000,__
+packet,308.767000,__
+packet,308.642000,__
+packet,308.558000,__
+packet,308.600000,__
+packet,308.683000,__
+packet,308.725000,__
+packet,309.142000,__
+packet,308.934000,__
+packet,308.809000,__
+packet,308.850000,__
+packet,308.892000,__
+packet,308.975000,__
+packet,309.017000,__
+packet,309.059000,__
+packet,309.100000,__
+packet,309.267000,__
+packet,309.184000,__
+packet,309.226000,__
+packet,309.476000,__
+packet,309.351000,__
+packet,309.309000,__
+packet,309.392000,__
+packet,309.434000,__
+packet,309.601000,__
+packet,309.518000,__
+packet,309.559000,__
+packet,309.768000,__
+packet,309.684000,__
+packet,309.643000,__
+packet,309.726000,__
+packet,309.976000,__
+packet,309.851000,__
+packet,309.810000,__
+packet,309.893000,__
+packet,309.935000,__
+packet,310.101000,__
+packet,310.018000,__
+packet,310.060000,__
+packet,310.268000,__
+packet,310.185000,__
+packet,310.143000,__
+packet,310.227000,__
+packet,310.477000,__
+packet,310.352000,__
+packet,310.310000,__
+packet,310.393000,__
+packet,310.435000,__
+packet,310.519000,__
+packet,310.727000,__
+packet,310.602000,__
+packet,310.560000,__
+packet,310.644000,__
+packet,310.685000,__
+packet,310.852000,__
+packet,310.769000,__
+packet,310.811000,__
+packet,310.977000,__
+packet,310.894000,__
+packet,310.936000,__
+packet,311.102000,__
+packet,311.019000,__
+packet,311.061000,__
+packet,311.269000,__
+packet,311.186000,__
+packet,311.144000,__
+packet,311.228000,__
+packet,311.478000,__
+packet,311.353000,__
+packet,311.311000,__
+packet,311.394000,__
+packet,311.436000,__
+packet,311.520000,__
+packet,311.645000,__
+packet,311.561000,__
+packet,311.603000,__
+packet,311.728000,__
+packet,311.686000,__
+packet,311.770000,K_
+packet,311.812000,__
+packet,311.978000,__
+packet,311.895000,__
+packet,311.853000,__
+packet,311.937000,__
+packet,312.062000,__
+packet,312.020000,__
+packet,312.187000,__
+packet,312.103000,__
+packet,312.145000,__
+packet,312.354000,__
+packet,312.270000,__
+packet,312.229000,__
+packet,312.312000,__
+packet,312.646000,__
+packet,312.479000,__
+packet,312.395000,__
+packet,312.437000,__
+packet,312.521000,__
+packet,312.562000,__
+packet,312.604000,__
+packet,312.979000,__
+packet,312.813000,__
+packet,312.687000,__
+packet,312.729000,__
+packet,312.771000,__
+packet,312.854000,__
+packet,312.896000,__
+packet,312.938000,__
+packet,313.063000,__
+packet,313.021000,__
+packet,313.230000,__
+packet,313.146000,__
+packet,313.104000,__
+packet,313.188000,__
+packet,313.313000,__
+packet,313.271000,__
+packet,313.480000,__
+packet,313.396000,__
+packet,313.355000,__
+packet,313.438000,__
+packet,313.605000,__
+packet,313.522000,__
+packet,313.563000,__
+packet,313.772000,__
+packet,313.688000,__
+packet,313.647000,__
+packet,313.730000,__
+packet,313.855000,__
+packet,313.814000,__
+packet,314.064000,__
+packet,313.939000,__
+packet,313.897000,__
+packet,313.980000,__
+packet,314.022000,__
+packet,314.105000,K_
+packet,314.272000,__
+packet,314.189000,__
+packet,314.147000,__
+packet,314.231000,__
+packet,314.439000,__
+packet,314.356000,__
+packet,314.314000,__
+packet,314.397000,__
+packet,314.689000,__
+packet,314.564000,__
+packet,314.481000,__
+packet,314.523000,__
+packet,314.606000,__
+packet,314.648000,__
+packet,315.023000,__
+packet,314.856000,__
+packet,314.731000,__
+packet,314.773000,__
+packet,314.815000,__
+packet,314.898000,__
+packet,314.940000,__
+packet,314.981000,__
+packet,315.190000,__
+packet,315.106000,__
+packet,315.065000,__
+packet,315.148000,__
+packet,315.398000,__
+packet,315.273000,__
+packet,315.232000,__
+packet,315.315000,__
+packet,315.357000,__
+packet,315.774000,__
+packet,315.565000,__
+packet,315.440000,__
+packet,315.482000,__
+packet,315.524000,__
+packet,315.607000,__
+packet,315.649000,__
+packet,315.690000,__
+packet,315.732000,__
+packet,315.816000,K_
+packet,315.982000,__
+packet,315.899000,__
+packet,315.857000,__
+packet,315.941000,__
+packet,316.191000,__
+packet,316.066000,__
+packet,316.024000,__
+packet,316.107000,__
+packet,316.149000,__
+packet,316.483000,__
+packet,316.316000,__
+packet,316.233000,__
+packet,316.274000,__
+packet,316.358000,__
+packet,316.399000,__
+packet,316.441000,__
+packet,316.650000,__
+packet,316.566000,__
+packet,316.525000,__
+packet,316.608000,__
+packet,317.025000,__
+packet,316.817000,__
+packet,316.691000,__
+packet,316.733000,__
+packet,316.775000,__
+packet,316.858000,__
+packet,316.900000,__
+packet,316.942000,__
+packet,316.983000,__
+packet,317.275000,__
+packet,317.150000,__
+packet,317.067000,__
+packet,317.108000,__
+packet,317.192000,__
+packet,317.234000,__
+packet,317.400000,__
+packet,317.317000,__
+packet,317.359000,__
+packet,317.567000,__
+packet,317.484000,__
+packet,317.442000,__
+packet,317.526000,__
+packet,317.651000,__
+packet,317.609000,__
+packet,317.734000,__
+packet,317.692000,__
+packet,317.818000,__
+packet,317.776000,__
+packet,317.859000,__
+packet,317.901000,__
+packet,317.943000,__
+packet,317.984000,__
+packet,318.068000,__
+packet,318.026000,__
+packet,318.193000,__
+packet,318.109000,__
+packet,318.151000,__
+packet,318.318000,__
+packet,318.235000,__
+packet,318.276000,__
+packet,318.485000,__
+packet,318.401000,__
+packet,318.360000,__
+packet,318.443000,__
+packet,318.652000,__
+packet,318.568000,__
+packet,318.527000,__
+packet,318.610000,__
+packet,318.819000,__
+packet,318.735000,__
+packet,318.693000,__
+packet,318.777000,__
+packet,319.027000,__
+packet,318.902000,__
+packet,318.860000,__
+packet,318.944000,__
+packet,318.985000,__
+packet,319.194000,__
+packet,319.110000,__
+packet,319.069000,__
+packet,319.152000,__
+packet,319.319000,__
+packet,319.236000,__
+packet,319.277000,__
+packet,319.486000,__
+packet,319.402000,__
+packet,319.361000,__
+packet,319.444000,__
+packet,319.528000,__
+packet,319.611000,__
+packet,319.569000,__
+packet,319.694000,__
+packet,319.653000,__
+packet,319.736000,__
+packet,319.903000,__
+packet,319.820000,__
+packet,319.778000,__
+packet,319.861000,__
+packet,320.028000,__
+packet,319.945000,__
+packet,319.986000,__
+packet,320.070000,K_
+packet,320.111000,__
+packet,320.195000,__
+packet,320.153000,__
+packet,320.237000,__
+packet,320.529000,__
+packet,320.362000,__
+packet,320.278000,__
+packet,320.320000,__
+packet,320.403000,__
+packet,320.445000,__
+packet,320.487000,__
+packet,320.779000,__
+packet,320.654000,__
+packet,320.570000,__
+packet,320.612000,__
+packet,320.695000,__
+packet,320.737000,__
+packet,321.029000,__
+packet,320.904000,__
+packet,320.821000,__
+packet,320.862000,__
+packet,320.946000,__
+packet,320.987000,__
+packet,321.279000,__
+packet,321.154000,__
+packet,321.071000,__
+packet,321.112000,__
+packet,321.196000,__
+packet,321.238000,__
+packet,321.530000,__
+packet,321.404000,__
+packet,321.321000,__
+packet,321.363000,__
+packet,321.446000,__
+packet,321.488000,__
+packet,321.780000,__
+packet,321.655000,__
+packet,321.571000,__
+packet,321.613000,__
+packet,321.696000,__
+packet,321.738000,__
+packet,321.863000,__
+packet,321.822000,__
+packet,322.113000,__
+packet,321.988000,__
+packet,321.905000,__
+packet,321.947000,__
+packet,322.030000,__
+packet,322.072000,__
+packet,322.364000,__
+packet,322.239000,__
+packet,322.155000,__
+packet,322.197000,__
+packet,322.280000,__
+packet,322.322000,__
+packet,322.614000,__
+packet,322.489000,__
+packet,322.405000,__
+packet,322.447000,__
+packet,322.531000,__
+packet,322.572000,__
+packet,322.864000,__
+packet,322.739000,__
+packet,322.656000,__
+packet,322.697000,__
+packet,322.781000,__
+packet,322.823000,__
+packet,323.114000,__
+packet,322.989000,__
+packet,322.906000,__
+packet,322.948000,__
+packet,323.031000,__
+packet,323.073000,__
+packet,323.198000,__
+packet,323.156000,__
+packet,323.448000,__
+packet,323.323000,__
+packet,323.240000,__
+packet,323.281000,__
+packet,323.365000,__
+packet,323.406000,__
+packet,323.698000,__
+packet,323.573000,__
+packet,323.490000,__
+packet,323.532000,__
+packet,323.615000,__
+packet,323.657000,__
+packet,323.949000,__
+packet,323.824000,__
+packet,323.740000,__
+packet,323.782000,__
+packet,323.865000,__
+packet,323.907000,__
+packet,324.199000,__
+packet,324.074000,__
+packet,323.990000,__
+packet,324.032000,__
+packet,324.115000,__
+packet,324.157000,__
+packet,324.449000,__
+packet,324.324000,__
+packet,324.241000,__
+packet,324.282000,__
+packet,324.366000,__
+packet,324.407000,__
+packet,324.699000,__
+packet,324.574000,__
+packet,324.491000,__
+packet,324.533000,__
+packet,324.616000,__
+packet,324.658000,__
+packet,324.783000,__
+packet,324.741000,__
+packet,324.866000,__
+packet,324.825000,__
+packet,325.116000,__
+packet,324.991000,__
+packet,324.908000,__
+packet,324.950000,__
+packet,325.033000,__
+packet,325.075000,__
+packet,325.367000,__
+packet,325.242000,__
+packet,325.158000,__
+packet,325.200000,__
+packet,325.283000,__
+packet,325.325000,__
+packet,325.617000,__
+packet,325.492000,__
+packet,325.408000,__
+packet,325.450000,__
+packet,325.534000,__
+packet,325.575000,__
+packet,325.867000,__
+packet,325.742000,__
+packet,325.659000,__
+packet,325.700000,__
+packet,325.784000,__
+packet,325.826000,__
+packet,326.117000,__
+packet,325.992000,__
+packet,325.909000,__
+packet,325.951000,__
+packet,326.034000,__
+packet,326.076000,__
+packet,326.409000,__
+packet,326.243000,__
+packet,326.159000,__
+packet,326.201000,__
+packet,326.284000,__
+packet,326.326000,__
+packet,326.368000,__
+packet,326.451000,__
+packet,326.576000,__
+packet,326.493000,__
+packet,326.535000,__
+packet,326.618000,__
+packet,326.743000,__
+packet,326.660000,__
+packet,326.701000,__
+packet,326.910000,__
+packet,326.827000,__
+packet,326.785000,__
+packet,326.868000,__
+packet,326.952000,__
+packet,327.077000,__
+packet,326.993000,__
+packet,327.035000,__
+packet,327.202000,__
+packet,327.118000,__
+packet,327.160000,__
+packet,327.285000,__
+packet,327.244000,__
+packet,327.619000,__
+packet,327.452000,__
+packet,327.327000,__
+packet,327.369000,__
+packet,327.410000,__
+packet,327.494000,__
+packet,327.536000,__
+packet,327.577000,__
+packet,327.911000,__
+packet,327.744000,__
+packet,327.661000,__
+packet,327.702000,__
+packet,327.786000,__
+packet,327.828000,__
+packet,327.869000,__
+packet,327.953000,K_
+packet,328.036000,__
+packet,327.994000,__
+packet,328.286000,__
+packet,328.161000,__
+packet,328.078000,__
+packet,328.119000,__
+packet,328.203000,__
+packet,328.245000,__
+packet,328.578000,__
+packet,328.411000,__
+packet,328.328000,__
+packet,328.370000,__
+packet,328.453000,__
+packet,328.495000,__
+packet,328.537000,__
+packet,328.703000,__
+packet,328.620000,__
+packet,328.662000,__
+packet,328.912000,__
+packet,328.787000,__
+packet,328.745000,__
+packet,328.829000,__
+packet,328.870000,__
+packet,328.954000,__
+packet,329.329000,__
+packet,329.120000,__
+packet,328.995000,__
+packet,329.037000,__
+packet,329.079000,__
+packet,329.162000,__
+packet,329.204000,__
+packet,329.246000,__
+packet,329.287000,__
+packet,329.412000,__
+packet,329.371000,__
+packet,329.579000,__
+packet,329.496000,__
+packet,329.454000,__
+packet,329.538000,__
+packet,329.704000,__
+packet,329.621000,__
+packet,329.663000,__
+packet,329.788000,__
+packet,329.746000,__
+packet,329.955000,__
+packet,329.871000,__
+packet,329.830000,__
+packet,329.913000,__
+packet,329.996000,K_
+packet,330.205000,__
+packet,330.080000,__
+packet,330.038000,__
+packet,330.121000,__
+packet,330.163000,__
+packet,330.539000,__
+packet,330.372000,__
+packet,330.247000,__
+packet,330.288000,__
+packet,330.330000,__
+packet,330.413000,__
+packet,330.455000,__
+packet,330.497000,__
+packet,330.622000,__
+packet,330.580000,__
+packet,330.789000,__
+packet,330.705000,__
+packet,330.664000,__
+packet,330.747000,__
+packet,330.997000,__
+packet,330.872000,__
+packet,330.831000,__
+packet,330.914000,__
+packet,330.956000,__
+packet,331.039000,__
+packet,331.206000,__
+packet,331.122000,__
+packet,331.081000,__
+packet,331.164000,__
+packet,331.248000,__
+packet,331.289000,K_
+packet,331.331000,__
+packet,331.498000,__
+packet,331.414000,__
+packet,331.373000,__
+packet,331.456000,__
+packet,331.665000,__
+packet,331.581000,__
+packet,331.540000,__
+packet,331.623000,__
+packet,331.790000,__
+packet,331.706000,__
+packet,331.748000,__
+packet,331.998000,__
+packet,331.873000,__
+packet,331.832000,__
+packet,331.915000,__
+packet,331.957000,__
+packet,332.123000,__
+packet,332.040000,__
+packet,332.082000,__
+packet,332.290000,__
+packet,332.207000,__
+packet,332.165000,__
+packet,332.249000,__
+packet,332.457000,__
+packet,332.374000,__
+packet,332.332000,__
+packet,332.415000,__
+packet,332.541000,__
+packet,332.499000,__
+packet,332.666000,__
+packet,332.582000,__
+packet,332.624000,__
+packet,332.833000,__
+packet,332.749000,__
+packet,332.707000,__
+packet,332.791000,__
+packet,332.958000,__
+packet,332.874000,__
+packet,332.916000,__
+packet,333.083000,__
+packet,332.999000,__
+packet,333.041000,__
+packet,333.250000,__
+packet,333.166000,__
+packet,333.124000,__
+packet,333.208000,__
+packet,333.291000,K_
+packet,333.542000,__
+packet,333.416000,__
+packet,333.333000,__
+packet,333.375000,__
+packet,333.458000,__
+packet,333.500000,__
+packet,333.875000,__
+packet,333.708000,__
+packet,333.583000,__
+packet,333.625000,__
+packet,333.667000,__
+packet,333.750000,__
+packet,333.792000,__
+packet,333.834000,__
+packet,334.084000,__
+packet,333.959000,__
+packet,333.917000,__
+packet,334.000000,__
+packet,334.042000,__
+packet,334.209000,__
+packet,334.125000,__
+packet,334.167000,__
+packet,334.417000,__
+packet,334.292000,__
+packet,334.251000,__
+packet,334.334000,__
+packet,334.376000,__
+packet,334.584000,__
+packet,334.501000,__
+packet,334.459000,__
+packet,334.543000,__
+packet,334.668000,__
+packet,334.626000,__
+packet,334.751000,__
+packet,334.709000,__
+packet,334.835000,__
+packet,334.793000,__
+packet,335.001000,__
+packet,334.918000,__
+packet,334.876000,__
+packet,334.960000,__
+packet,335.168000,__
+packet,335.085000,__
+packet,335.043000,__
+packet,335.126000,__
+packet,335.293000,__
+packet,335.210000,__
+packet,335.252000,__
+packet,335.460000,__
+packet,335.377000,__
+packet,335.335000,__
+packet,335.418000,__
+packet,335.627000,__
+packet,335.544000,__
+packet,335.502000,__
+packet,335.585000,__
+packet,335.919000,__
+packet,335.752000,__
+packet,335.669000,__
+packet,335.710000,__
+packet,335.794000,__
+packet,335.836000,__
+packet,335.877000,__
+packet,336.002000,__
+packet,335.961000,__
+packet,336.127000,__
+packet,336.044000,__
+packet,336.086000,__
+packet,336.253000,__
+packet,336.169000,__
+packet,336.211000,__
+packet,336.294000,__
+packet,336.419000,__
+packet,336.336000,__
+packet,336.378000,__
+packet,336.503000,__
+packet,336.461000,__
+packet,336.545000,__
+packet,336.670000,__
+packet,336.586000,__
+packet,336.628000,__
+packet,336.878000,__
+packet,336.753000,__
+packet,336.711000,__
+packet,336.795000,__
+packet,336.837000,__
+packet,336.920000,K_
+packet,337.128000,__
+packet,337.003000,__
+packet,336.962000,__
+packet,337.045000,__
+packet,337.087000,__
+packet,337.295000,__
+packet,337.212000,__
+packet,337.170000,__
+packet,337.254000,__
+packet,337.379000,__
+packet,337.337000,__
+packet,337.546000,__
+packet,337.462000,__
+packet,337.420000,__
+packet,337.504000,__
+packet,337.712000,__
+packet,337.629000,__
+packet,337.587000,__
+packet,337.671000,__
+packet,337.921000,__
+packet,337.796000,__
+packet,337.754000,__
+packet,337.838000,__
+packet,337.879000,__
+packet,337.963000,K_
+packet,338.129000,__
+packet,338.046000,__
+packet,338.004000,__
+packet,338.088000,__
+packet,338.296000,__
+packet,338.213000,__
+packet,338.171000,__
+packet,338.255000,__
+packet,338.463000,__
+packet,338.380000,__
+packet,338.338000,__
+packet,338.421000,__
+packet,338.630000,__
+packet,338.547000,__
+packet,338.505000,__
+packet,338.588000,__
+packet,338.880000,__
+packet,338.755000,__
+packet,338.672000,__
+packet,338.713000,__
+packet,338.797000,__
+packet,338.839000,__
+packet,339.047000,__
+packet,338.964000,__
+packet,338.922000,__
+packet,339.005000,__
+packet,339.214000,__
+packet,339.130000,__
+packet,339.089000,__
+packet,339.172000,__
+packet,339.297000,__
+packet,339.256000,__
+packet,339.464000,__
+packet,339.381000,__
+packet,339.339000,__
+packet,339.422000,__
+packet,339.506000,__
+packet,339.673000,__
+packet,339.589000,__
+packet,339.548000,__
+packet,339.631000,__
+packet,339.881000,__
+packet,339.756000,__
+packet,339.714000,__
+packet,339.798000,__
+packet,339.840000,__
+packet,340.048000,__
+packet,339.965000,__
+packet,339.923000,__
+packet,340.006000,__
+packet,340.215000,__
+packet,340.131000,__
+packet,340.090000,__
+packet,340.173000,__
+packet,340.382000,__
+packet,340.298000,__
+packet,340.257000,__
+packet,340.340000,__
+packet,340.715000,__
+packet,340.549000,__
+packet,340.423000,__
+packet,340.465000,__
+packet,340.507000,__
+packet,340.590000,__
+packet,340.632000,__
+packet,340.674000,__
+packet,341.091000,__
+packet,340.882000,__
+packet,340.757000,__
+packet,340.799000,__
+packet,340.841000,__
+packet,340.924000,__
+packet,340.966000,__
+packet,341.007000,__
+packet,341.049000,__
+packet,341.258000,__
+packet,341.174000,__
+packet,341.132000,__
+packet,341.216000,__
+packet,341.508000,__
+packet,341.383000,__
+packet,341.299000,__
+packet,341.341000,__
+packet,341.424000,__
+packet,341.466000,__
+packet,341.758000,__
+packet,341.633000,__
+packet,341.550000,__
+packet,341.591000,__
+packet,341.675000,__
+packet,341.716000,__
+packet,341.925000,__
+packet,341.842000,__
+packet,341.800000,__
+packet,341.883000,__
+packet,342.175000,__
+packet,342.050000,__
+packet,341.967000,__
+packet,342.008000,__
+packet,342.092000,__
+packet,342.133000,__
+packet,342.551000,__
+packet,342.342000,__
+packet,342.217000,__
+packet,342.259000,__
+packet,342.300000,__
+packet,342.384000,__
+packet,342.425000,__
+packet,342.467000,__
+packet,342.509000,__
+packet,342.926000,__
+packet,342.717000,__
+packet,342.592000,__
+packet,342.634000,__
+packet,342.676000,__
+packet,342.759000,__
+packet,342.801000,__
+packet,342.843000,__
+packet,342.884000,__
+packet,343.093000,__
+packet,343.009000,__
+packet,342.968000,__
+packet,343.051000,__
+packet,343.301000,__
+packet,343.176000,__
+packet,343.134000,__
+packet,343.218000,__
+packet,343.260000,__
+packet,343.510000,__
+packet,343.385000,__
+packet,343.343000,__
+packet,343.426000,__
+packet,343.468000,__
+packet,343.802000,__
+packet,343.635000,__
+packet,343.552000,__
+packet,343.593000,__
+packet,343.677000,__
+packet,343.718000,__
+packet,343.760000,__
+packet,343.844000,K_
+packet,344.010000,__
+packet,343.927000,__
+packet,343.885000,__
+packet,343.969000,__
+packet,344.177000,__
+packet,344.094000,__
+packet,344.052000,__
+packet,344.135000,__
+packet,344.261000,__
+packet,344.219000,__
+packet,344.553000,__
+packet,344.386000,__
+packet,344.302000,__
+packet,344.344000,__
+packet,344.427000,__
+packet,344.469000,__
+packet,344.511000,__
+packet,344.719000,__
+packet,344.636000,__
+packet,344.594000,__
+packet,344.678000,__
+packet,344.803000,__
+packet,344.761000,__
+packet,345.053000,__
+packet,344.928000,__
+packet,344.845000,__
+packet,344.886000,__
+packet,344.970000,__
+packet,345.011000,__
+packet,345.303000,__
+packet,345.178000,__
+packet,345.095000,__
+packet,345.136000,__
+packet,345.220000,__
+packet,345.262000,__
+packet,345.637000,__
+packet,345.470000,__
+packet,345.345000,__
+packet,345.387000,__
+packet,345.428000,__
+packet,345.512000,__
+packet,345.554000,__
+packet,345.595000,__
+packet,345.887000,__
+packet,345.762000,__
+packet,345.679000,__
+packet,345.720000,__
+packet,345.804000,__
+packet,345.846000,__
+packet,345.929000,K_
+packet,346.096000,__
+packet,346.012000,__
+packet,345.971000,__
+packet,346.054000,__
+packet,346.263000,__
+packet,346.179000,__
+packet,346.137000,__
+packet,346.221000,__
+packet,346.638000,__
+packet,346.429000,__
+packet,346.304000,__
+packet,346.346000,__
+packet,346.388000,__
+packet,346.471000,__
+packet,346.513000,__
+packet,346.555000,__
+packet,346.596000,__
+packet,346.930000,__
+packet,346.763000,__
+packet,346.680000,__
+packet,346.721000,__
+packet,346.805000,__
+packet,346.847000,__
+packet,346.888000,__
+packet,347.264000,__
+packet,347.097000,__
+packet,346.972000,__
+packet,347.013000,__
+packet,347.055000,__
+packet,347.138000,__
+packet,347.180000,__
+packet,347.222000,__
+packet,347.639000,__
+packet,347.430000,__
+packet,347.305000,__
+packet,347.347000,__
+packet,347.389000,__
+packet,347.472000,__
+packet,347.514000,__
+packet,347.556000,__
+packet,347.597000,__
+packet,347.931000,__
+packet,347.764000,__
+packet,347.681000,__
+packet,347.722000,__
+packet,347.806000,__
+packet,347.848000,__
+packet,347.889000,__
+packet,348.265000,__
+packet,348.098000,__
+packet,347.973000,__
+packet,348.014000,__
+packet,348.056000,__
+packet,348.139000,__
+packet,348.181000,__
+packet,348.223000,__
+packet,348.640000,__
+packet,348.431000,__
+packet,348.306000,__
+packet,348.348000,__
+packet,348.390000,__
+packet,348.473000,__
+packet,348.515000,__
+packet,348.557000,__
+packet,348.598000,__
+packet,348.932000,__
+packet,348.765000,__
+packet,348.682000,__
+packet,348.723000,__
+packet,348.807000,__
+packet,348.849000,__
+packet,348.890000,__
+packet,349.057000,__
+packet,348.974000,__
+packet,349.015000,__
+packet,349.099000,K_
+packet,349.266000,__
+packet,349.182000,__
+packet,349.140000,__
+packet,349.224000,__
+packet,349.558000,__
+packet,349.391000,__
+packet,349.307000,__
+packet,349.349000,__
+packet,349.432000,__
+packet,349.474000,__
+packet,349.516000,__
+packet,349.808000,__
+packet,349.683000,__
+packet,349.599000,__
+packet,349.641000,__
+packet,349.724000,__
+packet,349.766000,__
+packet,349.975000,__
+packet,349.891000,__
+packet,349.850000,__
+packet,349.933000,__
+packet,350.308000,__
+packet,350.141000,__
+packet,350.016000,__
+packet,350.058000,__
+packet,350.100000,__
+packet,350.183000,__
+packet,350.225000,__
+packet,350.267000,__
+packet,350.517000,__
+packet,350.392000,__
+packet,350.350000,__
+packet,350.433000,__
+packet,350.475000,__
+packet,350.851000,__
+packet,350.684000,__
+packet,350.559000,__
+packet,350.600000,__
+packet,350.642000,__
+packet,350.725000,__
+packet,350.767000,__
+packet,350.809000,__
+packet,350.934000,__
+packet,350.892000,__
+packet,351.309000,__
+packet,351.101000,__
+packet,350.976000,__
+packet,351.017000,__
+packet,351.059000,__
+packet,351.142000,__
+packet,351.184000,__
+packet,351.226000,__
+packet,351.268000,__
+packet,351.560000,__
+packet,351.434000,__
+packet,351.351000,__
+packet,351.393000,__
+packet,351.476000,__
+packet,351.518000,__
+packet,351.810000,__
+packet,351.685000,__
+packet,351.601000,__
+packet,351.643000,__
+packet,351.726000,__
+packet,351.768000,__
+packet,352.060000,__
+packet,351.935000,__
+packet,351.852000,__
+packet,351.893000,__
+packet,351.977000,__
+packet,352.018000,__
+packet,352.435000,__
+packet,352.227000,__
+packet,352.102000,__
+packet,352.143000,__
+packet,352.185000,__
+packet,352.269000,__
+packet,352.310000,__
+packet,352.352000,__
+packet,352.394000,__
+packet,352.686000,__
+packet,352.561000,__
+packet,352.477000,__
+packet,352.519000,__
+packet,352.602000,__
+packet,352.644000,__
+packet,353.061000,__
+packet,352.853000,__
+packet,352.727000,__
+packet,352.769000,__
+packet,352.811000,__
+packet,352.894000,__
+packet,352.936000,__
+packet,352.978000,__
+packet,353.019000,__
+packet,353.270000,__
+packet,353.144000,__
+packet,353.103000,__
+packet,353.186000,__
+packet,353.228000,__
+packet,353.311000,K_
+packet,353.562000,__
+packet,353.436000,__
+packet,353.353000,__
+packet,353.395000,__
+packet,353.478000,__
+packet,353.520000,__
+packet,353.937000,__
+packet,353.728000,__
+packet,353.603000,__
+packet,353.645000,__
+packet,353.687000,__
+packet,353.770000,__
+packet,353.812000,__
+packet,353.854000,__
+packet,353.895000,__
+packet,354.271000,__
+packet,354.104000,__
+packet,353.979000,__
+packet,354.020000,__
+packet,354.062000,__
+packet,354.145000,__
+packet,354.187000,__
+packet,354.229000,__
+packet,354.646000,__
+packet,354.437000,__
+packet,354.312000,__
+packet,354.354000,__
+packet,354.396000,__
+packet,354.479000,__
+packet,354.521000,__
+packet,354.563000,__
+packet,354.604000,__
+packet,354.938000,__
+packet,354.771000,__
+packet,354.688000,__
+packet,354.729000,__
+packet,354.813000,__
+packet,354.855000,__
+packet,354.896000,__
+packet,355.272000,__
+packet,355.105000,__
+packet,354.980000,__
+packet,355.021000,__
+packet,355.063000,__
+packet,355.146000,__
+packet,355.188000,__
+packet,355.230000,__
+packet,355.564000,__
+packet,355.397000,__
+packet,355.313000,__
+packet,355.355000,__
+packet,355.438000,__
+packet,355.480000,__
+packet,355.522000,__
+packet,355.814000,__
+packet,355.689000,__
+packet,355.605000,__
+packet,355.647000,__
+packet,355.730000,__
+packet,355.772000,__
+packet,356.147000,__
+packet,355.981000,__
+packet,355.856000,__
+packet,355.897000,__
+packet,355.939000,__
+packet,356.022000,__
+packet,356.064000,__
+packet,356.106000,__
+packet,356.231000,__
+packet,356.189000,__
+packet,356.273000,K_
+packet,356.398000,__
+packet,356.314000,__
+packet,356.356000,__
+packet,356.690000,__
+packet,356.523000,__
+packet,356.439000,__
+packet,356.481000,__
+packet,356.565000,__
+packet,356.606000,__
+packet,356.648000,__
+packet,356.940000,__
+packet,356.815000,__
+packet,356.731000,__
+packet,356.773000,__
+packet,356.857000,__
+packet,356.898000,__
+packet,356.982000,__
+packet,357.148000,__
+packet,357.065000,__
+packet,357.023000,__
+packet,357.107000,__
+packet,357.274000,__
+packet,357.190000,__
+packet,357.232000,__
+packet,357.649000,__
+packet,357.440000,__
+packet,357.315000,__
+packet,357.357000,__
+packet,357.399000,__
+packet,357.482000,__
+packet,357.524000,__
+packet,357.566000,__
+packet,357.607000,__
+packet,357.941000,__
+packet,357.774000,__
+packet,357.691000,__
+packet,357.732000,__
+packet,357.816000,__
+packet,357.858000,__
+packet,357.899000,__
+packet,358.275000,__
+packet,358.108000,__
+packet,357.983000,__
+packet,358.024000,__
+packet,358.066000,__
+packet,358.149000,__
+packet,358.191000,__
+packet,358.233000,__
+packet,358.650000,__
+packet,358.441000,__
+packet,358.316000,__
+packet,358.358000,__
+packet,358.400000,__
+packet,358.483000,__
+packet,358.525000,__
+packet,358.567000,__
+packet,358.608000,__
+packet,358.942000,__
+packet,358.775000,__
+packet,358.692000,__
+packet,358.733000,__
+packet,358.817000,__
+packet,358.859000,__
+packet,358.900000,__
+packet,359.276000,__
+packet,359.109000,__
+packet,358.984000,__
+packet,359.025000,__
+packet,359.067000,__
+packet,359.150000,__
+packet,359.192000,__
+packet,359.234000,__
+packet,359.651000,__
+packet,359.442000,__
+packet,359.317000,__
+packet,359.359000,__
+packet,359.401000,__
+packet,359.484000,__
+packet,359.526000,__
+packet,359.568000,__
+packet,359.609000,__
+packet,359.985000,__
+packet,359.818000,__
+packet,359.693000,__
+packet,359.734000,__
+packet,359.776000,__
+packet,359.860000,__
+packet,359.901000,__
+packet,359.943000,__
+packet,360.026000,K_
+packet,360.235000,__
+packet,360.110000,__
+packet,360.068000,__
+packet,360.151000,__
+packet,360.193000,__
+packet,360.610000,__
+packet,360.402000,__
+packet,360.277000,__
+packet,360.318000,__
+packet,360.360000,__
+packet,360.443000,__
+packet,360.485000,__
+packet,360.527000,__
+packet,360.569000,__
+packet,360.694000,__
+packet,360.652000,__
+packet,360.986000,__
+packet,360.819000,__
+packet,360.735000,__
+packet,360.777000,__
+packet,360.861000,__
+packet,360.902000,__
+packet,360.944000,__
+packet,361.236000,__
+packet,361.111000,__
+packet,361.027000,__
+packet,361.069000,__
+packet,361.152000,__
+packet,361.194000,__
+packet,361.444000,__
+packet,361.319000,__
+packet,361.278000,__
+packet,361.361000,__
+packet,361.403000,__
+packet,361.820000,__
+packet,361.611000,__
+packet,361.486000,__
+packet,361.528000,__
+packet,361.570000,__
+packet,361.653000,__
+packet,361.695000,__
+packet,361.736000,__
+packet,361.778000,__
+packet,362.070000,__
+packet,361.945000,__
+packet,361.862000,__
+packet,361.903000,__
+packet,361.987000,__
+packet,362.028000,__
+packet,362.362000,__
+packet,362.195000,__
+packet,362.112000,__
+packet,362.153000,__
+packet,362.237000,__
+packet,362.279000,__
+packet,362.320000,__
+packet,362.404000,K_
+packet,362.696000,__
+packet,362.529000,__
+packet,362.445000,__
+packet,362.487000,__
+packet,362.571000,__
+packet,362.612000,__
+packet,362.654000,__
+packet,362.946000,__
+packet,362.821000,__
+packet,362.737000,__
+packet,362.779000,__
+packet,362.863000,__
+packet,362.904000,__
+packet,363.280000,__
+packet,363.113000,__
+packet,362.988000,__
+packet,363.029000,__
+packet,363.071000,__
+packet,363.154000,__
+packet,363.196000,__
+packet,363.238000,__
+packet,363.655000,__
+packet,363.446000,__
+packet,363.321000,__
+packet,363.363000,__
+packet,363.405000,__
+packet,363.488000,__
+packet,363.530000,__
+packet,363.572000,__
+packet,363.613000,__
+packet,363.947000,__
+packet,363.780000,__
+packet,363.697000,__
+packet,363.738000,__
+packet,363.822000,__
+packet,363.864000,__
+packet,363.905000,__
+packet,364.281000,__
+packet,364.114000,__
+packet,363.989000,__
+packet,364.030000,__
+packet,364.072000,__
+packet,364.155000,__
+packet,364.197000,__
+packet,364.239000,__
+packet,364.656000,__
+packet,364.447000,__
+packet,364.322000,__
+packet,364.364000,__
+packet,364.406000,__
+packet,364.489000,__
+packet,364.531000,__
+packet,364.573000,__
+packet,364.614000,__
+packet,364.948000,__
+packet,364.781000,__
+packet,364.698000,__
+packet,364.739000,__
+packet,364.823000,__
+packet,364.865000,__
+packet,364.906000,__
+packet,365.282000,__
+packet,365.115000,__
+packet,364.990000,__
+packet,365.031000,__
+packet,365.073000,__
+packet,365.156000,__
+packet,365.198000,__
+packet,365.240000,__
+packet,365.657000,__
+packet,365.448000,__
+packet,365.323000,__
+packet,365.365000,__
+packet,365.407000,__
+packet,365.490000,__
+packet,365.532000,__
+packet,365.574000,__
+packet,365.615000,__
+packet,365.949000,__
+packet,365.782000,__
+packet,365.699000,__
+packet,365.740000,__
+packet,365.824000,__
+packet,365.866000,__
+packet,365.907000,__
+packet,366.283000,__
+packet,366.116000,__
+packet,365.991000,__
+packet,366.032000,__
+packet,366.074000,__
+packet,366.157000,__
+packet,366.199000,__
+packet,366.241000,__
+packet,366.658000,__
+packet,366.449000,__
+packet,366.324000,__
+packet,366.366000,__
+packet,366.408000,__
+packet,366.491000,__
+packet,366.533000,__
+packet,366.575000,__
+packet,366.616000,__
+packet,367.033000,__
+packet,366.825000,__
+packet,366.700000,__
+packet,366.741000,__
+packet,366.783000,__
+packet,366.867000,__
+packet,366.908000,__
+packet,366.950000,__
+packet,366.992000,__
+packet,367.158000,__
+packet,367.075000,__
+packet,367.117000,__
+packet,367.200000,K_
+packet,367.367000,__
+packet,367.284000,__
+packet,367.242000,__
+packet,367.325000,__
+packet,367.534000,__
+packet,367.450000,__
+packet,367.409000,__
+packet,367.492000,__
+packet,367.909000,__
+packet,367.701000,__
+packet,367.576000,__
+packet,367.617000,__
+packet,367.659000,__
+packet,367.742000,__
+packet,367.784000,__
+packet,367.826000,__
+packet,367.868000,__
+packet,368.285000,__
+packet,368.076000,__
+packet,367.951000,__
+packet,367.993000,__
+packet,368.034000,__
+packet,368.118000,__
+packet,368.159000,__
+packet,368.201000,__
+packet,368.243000,__
+packet,368.577000,__
+packet,368.410000,__
+packet,368.326000,__
+packet,368.368000,__
+packet,368.451000,__
+packet,368.493000,__
+packet,368.535000,__
+packet,368.785000,__
+packet,368.660000,__
+packet,368.618000,__
+packet,368.702000,__
+packet,368.743000,__
+packet,368.952000,__
+packet,368.869000,__
+packet,368.827000,__
+packet,368.910000,__
+packet,369.160000,__
+packet,369.035000,__
+packet,368.994000,__
+packet,369.077000,__
+packet,369.119000,__
+packet,369.327000,__
+packet,369.244000,__
+packet,369.202000,__
+packet,369.286000,__
+packet,369.578000,__
+packet,369.452000,__
+packet,369.369000,__
+packet,369.411000,__
+packet,369.494000,__
+packet,369.536000,__
+packet,369.786000,__
+packet,369.661000,__
+packet,369.619000,__
+packet,369.703000,__
+packet,369.744000,__
+packet,369.953000,__
+packet,369.870000,__
+packet,369.828000,__
+packet,369.911000,__
+packet,370.161000,__
+packet,370.036000,__
+packet,369.995000,__
+packet,370.078000,__
+packet,370.120000,__
+packet,370.287000,__
+packet,370.203000,__
+packet,370.245000,__
+packet,370.579000,__
+packet,370.412000,__
+packet,370.328000,__
+packet,370.370000,__
+packet,370.453000,__
+packet,370.495000,__
+packet,370.537000,__
+packet,370.829000,__
+packet,370.704000,__
+packet,370.620000,__
+packet,370.662000,__
+packet,370.745000,__
+packet,370.787000,__
+packet,371.079000,__
+packet,370.954000,__
+packet,370.871000,__
+packet,370.912000,__
+packet,370.996000,__
+packet,371.037000,__
+packet,371.329000,__
+packet,371.204000,__
+packet,371.121000,__
+packet,371.162000,__
+packet,371.246000,__
+packet,371.288000,__
+packet,371.580000,__
+packet,371.454000,__
+packet,371.371000,__
+packet,371.413000,__
+packet,371.496000,__
+packet,371.538000,__
+packet,371.830000,__
+packet,371.705000,__
+packet,371.621000,__
+packet,371.663000,__
+packet,371.746000,__
+packet,371.788000,__
+packet,371.997000,__
+packet,371.913000,__
+packet,371.872000,__
+packet,371.955000,__
+packet,372.163000,__
+packet,372.080000,__
+packet,372.038000,__
+packet,372.122000,__
+packet,372.205000,K_
+packet,372.330000,__
+packet,372.247000,__
+packet,372.289000,__
+packet,372.497000,__
+packet,372.414000,__
+packet,372.372000,__
+packet,372.455000,__
+packet,372.664000,__
+packet,372.581000,__
+packet,372.539000,__
+packet,372.622000,__
+packet,372.789000,__
+packet,372.706000,__
+packet,372.747000,__
+packet,372.956000,__
+packet,372.873000,__
+packet,372.831000,__
+packet,372.914000,__
+packet,373.123000,__
+packet,373.039000,__
+packet,372.998000,__
+packet,373.081000,__
+packet,373.331000,__
+packet,373.206000,__
+packet,373.164000,__
+packet,373.248000,__
+packet,373.290000,__
+packet,373.498000,__
+packet,373.415000,__
+packet,373.373000,__
+packet,373.456000,__
+packet,373.665000,__
+packet,373.582000,__
+packet,373.540000,__
+packet,373.623000,__
+packet,373.832000,__
+packet,373.748000,__
+packet,373.707000,__
+packet,373.790000,__
+packet,373.999000,__
+packet,373.915000,__
+packet,373.874000,__
+packet,373.957000,__
+packet,374.165000,__
+packet,374.082000,__
+packet,374.040000,__
+packet,374.124000,__
+packet,374.291000,__
+packet,374.207000,__
+packet,374.249000,__
+packet,374.666000,__
+packet,374.457000,__
+packet,374.332000,__
+packet,374.374000,__
+packet,374.416000,__
+packet,374.499000,__
+packet,374.541000,__
+packet,374.583000,__
+packet,374.624000,__
+packet,374.833000,__
+packet,374.749000,__
+packet,374.708000,__
+packet,374.791000,__
+packet,375.166000,__
+packet,375.000000,__
+packet,374.875000,__
+packet,374.916000,__
+packet,374.958000,__
+packet,375.041000,__
+packet,375.083000,__
+packet,375.125000,__
+packet,375.292000,__
+packet,375.208000,__
+packet,375.250000,__
+packet,375.333000,K_
+packet,375.500000,__
+packet,375.417000,__
+packet,375.375000,__
+packet,375.458000,__
+packet,375.709000,__
+packet,375.584000,__
+packet,375.542000,__
+packet,375.625000,__
+packet,375.667000,__
+packet,375.876000,__
+packet,375.792000,__
+packet,375.750000,__
+packet,375.834000,__
+packet,376.209000,__
+packet,376.042000,__
+packet,375.917000,__
+packet,375.959000,__
+packet,376.001000,__
+packet,376.084000,__
+packet,376.126000,__
+packet,376.167000,__
+packet,376.334000,__
+packet,376.251000,__
+packet,376.293000,__
+packet,376.501000,__
+packet,376.418000,__
+packet,376.376000,__
+packet,376.459000,__
+packet,376.668000,__
+packet,376.585000,__
+packet,376.543000,__
+packet,376.626000,__
+packet,377.043000,__
+packet,376.835000,__
+packet,376.710000,__
+packet,376.751000,__
+packet,376.793000,__
+packet,376.877000,__
+packet,376.918000,__
+packet,376.960000,__
+packet,377.002000,__
+packet,377.085000,__
+packet,377.127000,K_
+packet,377.252000,__
+packet,377.168000,__
+packet,377.210000,__
+packet,377.335000,__
+packet,377.294000,__
+packet,377.419000,__
+packet,377.377000,__
+packet,377.544000,__
+packet,377.460000,__
+packet,377.502000,__
+packet,377.711000,__
+packet,377.627000,__
+packet,377.586000,__
+packet,377.669000,__
+packet,377.919000,__
+packet,377.794000,__
+packet,377.752000,__
+packet,377.836000,__
+packet,377.878000,__
+packet,378.003000,__
+packet,377.961000,__
+packet,378.044000,__
+packet,378.211000,__
+packet,378.128000,__
+packet,378.086000,__
+packet,378.169000,__
+packet,378.420000,__
+packet,378.295000,__
+packet,378.253000,__
+packet,378.336000,__
+packet,378.378000,__
+packet,378.587000,__
+packet,378.503000,__
+packet,378.461000,__
+packet,378.545000,__
+packet,378.712000,__
+packet,378.628000,__
+packet,378.670000,__
+packet,378.879000,__
+packet,378.795000,__
+packet,378.753000,__
+packet,378.837000,__
+packet,379.045000,__
+packet,378.962000,__
+packet,378.920000,__
+packet,379.004000,__
+packet,379.129000,__
+packet,379.087000,__
+packet,379.296000,__
+packet,379.212000,__
+packet,379.170000,__
+packet,379.254000,__
+packet,379.421000,__
+packet,379.337000,__
+packet,379.379000,__
+packet,379.713000,__
+packet,379.546000,__
+packet,379.462000,__
+packet,379.504000,__
+packet,379.588000,__
+packet,379.629000,__
+packet,379.671000,__
+packet,379.838000,__
+packet,379.754000,__
+packet,379.796000,__
+packet,379.963000,__
+packet,379.880000,__
+packet,379.921000,__
+packet,380.130000,__
+packet,380.046000,__
+packet,380.005000,__
+packet,380.088000,__
+packet,380.297000,__
+packet,380.213000,__
+packet,380.171000,__
+packet,380.255000,__
+packet,380.547000,__
+packet,380.422000,__
+packet,380.338000,__
+packet,380.380000,__
+packet,380.463000,__
+packet,380.505000,__
+packet,380.714000,__
+packet,380.630000,__
+packet,380.589000,__
+packet,380.672000,__
+packet,380.755000,__
+packet,380.922000,__
+packet,380.839000,__
+packet,380.797000,__
+packet,380.881000,__
+packet,381.172000,__
+packet,381.047000,__
+packet,380.964000,__
+packet,381.006000,__
+packet,381.089000,__
+packet,381.131000,__
+packet,381.298000,__
+packet,381.214000,__
+packet,381.256000,__
+packet,381.464000,__
+packet,381.381000,__
+packet,381.339000,__
+packet,381.423000,__
+packet,381.631000,__
+packet,381.548000,__
+packet,381.506000,__
+packet,381.590000,__
+packet,381.756000,__
+packet,381.673000,__
+packet,381.715000,__
+packet,381.965000,__
+packet,381.840000,__
+packet,381.798000,__
+packet,381.882000,__
+packet,381.923000,__
+packet,382.007000,__
+packet,382.215000,__
+packet,382.090000,__
+packet,382.048000,__
+packet,382.132000,__
+packet,382.173000,__
+packet,382.340000,__
+packet,382.257000,__
+packet,382.299000,__
+packet,382.549000,__
+packet,382.424000,__
+packet,382.382000,__
+packet,382.465000,__
+packet,382.507000,__
+packet,382.674000,__
+packet,382.591000,__
+packet,382.632000,__
+packet,382.757000,__
+packet,382.716000,__
+packet,382.924000,__
+packet,382.841000,__
+packet,382.799000,__
+packet,382.883000,__
+packet,383.091000,__
+packet,383.008000,__
+packet,382.966000,__
+packet,383.049000,__
+packet,383.258000,__
+packet,383.174000,__
+packet,383.133000,__
+packet,383.216000,__
+packet,383.592000,__
+packet,383.425000,__
+packet,383.300000,__
+packet,383.341000,__
+packet,383.383000,__
+packet,383.466000,__
+packet,383.508000,__
+packet,383.550000,__
+packet,383.842000,__
+packet,383.717000,__
+packet,383.633000,__
+packet,383.675000,__
+packet,383.758000,__
+packet,383.800000,__
+packet,384.050000,__
+packet,383.925000,__
+packet,383.884000,__
+packet,383.967000,__
+packet,384.009000,__
+packet,384.301000,__
+packet,384.175000,__
+packet,384.092000,__
+packet,384.134000,__
+packet,384.217000,__
+packet,384.259000,__
+packet,384.551000,__
+packet,384.426000,__
+packet,384.342000,__
+packet,384.384000,__
+packet,384.467000,__
+packet,384.509000,__
+packet,384.676000,__
+packet,384.593000,__
+packet,384.634000,__
+packet,384.759000,__
+packet,384.718000,__
+packet,384.968000,__
+packet,384.843000,__
+packet,384.801000,__
+packet,384.885000,__
+packet,384.926000,__
+packet,385.093000,__
+packet,385.010000,__
+packet,385.051000,__
+packet,385.302000,__
+packet,385.176000,__
+packet,385.135000,__
+packet,385.218000,__
+packet,385.260000,__
+packet,385.427000,__
+packet,385.343000,__
+packet,385.385000,__
+packet,385.719000,__
+packet,385.552000,__
+packet,385.468000,__
+packet,385.510000,__
+packet,385.594000,__
+packet,385.635000,__
+packet,385.677000,__
+packet,385.969000,__
+packet,385.844000,__
+packet,385.760000,__
+packet,385.802000,__
+packet,385.886000,__
+packet,385.927000,__
+packet,386.219000,__
+packet,386.094000,__
+packet,386.011000,__
+packet,386.052000,__
+packet,386.136000,__
+packet,386.177000,__
+packet,386.344000,__
+packet,386.261000,__
+packet,386.303000,__
+packet,386.595000,__
+packet,386.469000,__
+packet,386.386000,__
+packet,386.428000,__
+packet,386.511000,__
+packet,386.553000,__
+packet,386.803000,__
+packet,386.678000,__
+packet,386.636000,__
+packet,386.720000,__
+packet,386.761000,__
+packet,386.970000,__
+packet,386.887000,__
+packet,386.845000,__
+packet,386.928000,__
+packet,387.304000,__
+packet,387.137000,__
+packet,387.012000,__
+packet,387.053000,__
+packet,387.095000,__
+packet,387.178000,__
+packet,387.220000,__
+packet,387.262000,__
+packet,387.345000,__
+packet,387.512000,__
+packet,387.429000,__
+packet,387.387000,__
+packet,387.470000,__
+packet,387.554000,K_
+packet,387.721000,__
+packet,387.637000,__
+packet,387.596000,__
+packet,387.679000,__
+packet,387.804000,__
+packet,387.762000,__
+packet,388.013000,__
+packet,387.888000,__
+packet,387.846000,__
+packet,387.929000,__
+packet,387.971000,__
+packet,388.305000,__
+packet,388.138000,__
+packet,388.054000,__
+packet,388.096000,__
+packet,388.179000,__
+packet,388.221000,__
+packet,388.263000,__
+packet,388.430000,__
+packet,388.346000,__
+packet,388.388000,__
+packet,388.597000,__
+packet,388.513000,__
+packet,388.471000,__
+packet,388.555000,__
+packet,388.722000,__
+packet,388.638000,__
+packet,388.680000,__
+packet,388.847000,__
+packet,388.763000,__
+packet,388.805000,__
+packet,389.055000,__
+packet,388.930000,__
+packet,388.889000,__
+packet,388.972000,__
+packet,389.014000,__
+packet,389.180000,__
+packet,389.097000,__
+packet,389.139000,__
+packet,389.306000,__
+packet,389.222000,__
+packet,389.264000,__
+packet,389.681000,__
+packet,389.472000,__
+packet,389.347000,__
+packet,389.389000,__
+packet,389.431000,__
+packet,389.514000,__
+packet,389.556000,__
+packet,389.598000,__
+packet,389.639000,__
+packet,389.848000,__
+packet,389.764000,__
+packet,389.723000,__
+packet,389.806000,__
+packet,390.015000,__
+packet,389.931000,__
+packet,389.890000,__
+packet,389.973000,__
+packet,390.348000,__
+packet,390.181000,__
+packet,390.056000,__
+packet,390.098000,__
+packet,390.140000,__
+packet,390.223000,__
+packet,390.265000,__
+packet,390.307000,__
+packet,390.557000,__
+packet,390.432000,__
+packet,390.390000,__
+packet,390.473000,__
+packet,390.515000,__
+packet,390.724000,__
+packet,390.640000,__
+packet,390.599000,__
+packet,390.682000,__
+packet,390.849000,__
+packet,390.765000,__
+packet,390.807000,__
+packet,391.224000,__
+packet,391.016000,__
+packet,390.891000,__
+packet,390.932000,__
+packet,390.974000,__
+packet,391.057000,__
+packet,391.099000,__
+packet,391.141000,__
+packet,391.182000,__
+packet,391.474000,__
+packet,391.349000,__
+packet,391.266000,__
+packet,391.308000,__
+packet,391.391000,__
+packet,391.433000,__
+packet,391.683000,__
+packet,391.558000,__
+packet,391.516000,__
+packet,391.600000,__
+packet,391.641000,__
+packet,391.850000,__
+packet,391.766000,__
+packet,391.725000,__
+packet,391.808000,__
+packet,392.017000,__
+packet,391.933000,__
+packet,391.892000,__
+packet,391.975000,__
+packet,392.142000,__
+packet,392.058000,__
+packet,392.100000,__
+packet,392.350000,__
+packet,392.225000,__
+packet,392.183000,__
+packet,392.267000,__
+packet,392.309000,__
+packet,392.559000,__
+packet,392.434000,__
+packet,392.392000,__
+packet,392.475000,__
+packet,392.517000,__
+packet,392.726000,__
+packet,392.642000,__
+packet,392.601000,__
+packet,392.684000,__
+packet,392.934000,__
+packet,392.809000,__
+packet,392.767000,__
+packet,392.851000,__
+packet,392.893000,__
+packet,393.101000,__
+packet,393.018000,__
+packet,392.976000,__
+packet,393.059000,__
+packet,393.310000,__
+packet,393.184000,__
+packet,393.143000,__
+packet,393.226000,__
+packet,393.268000,__
+packet,393.560000,__
+packet,393.435000,__
+packet,393.351000,__
+packet,393.393000,__
+packet,393.476000,__
+packet,393.518000,__
+packet,393.727000,__
+packet,393.643000,__
+packet,393.602000,__
+packet,393.685000,__
+packet,394.019000,__
+packet,393.852000,__
+packet,393.768000,__
+packet,393.810000,__
+packet,393.894000,__
+packet,393.935000,__
+packet,393.977000,__
+packet,394.060000,__
+packet,394.227000,__
+packet,394.144000,__
+packet,394.102000,__
+packet,394.185000,__
+packet,394.311000,__
+packet,394.269000,__
+packet,394.561000,__
+packet,394.436000,__
+packet,394.352000,__
+packet,394.394000,__
+packet,394.477000,__
+packet,394.519000,__
+packet,394.686000,__
+packet,394.603000,__
+packet,394.644000,__
+packet,394.728000,__
+packet,394.895000,__
+packet,394.811000,__
+packet,394.769000,__
+packet,394.853000,__
+packet,394.936000,__
+packet,395.103000,__
+packet,395.020000,__
+packet,394.978000,__
+packet,395.061000,__
+packet,395.270000,__
+packet,395.186000,__
+packet,395.145000,__
+packet,395.228000,__
+packet,395.645000,__
+packet,395.437000,__
+packet,395.312000,__
+packet,395.353000,__
+packet,395.395000,__
+packet,395.478000,__
+packet,395.520000,__
+packet,395.562000,__
+packet,395.604000,__
+packet,395.687000,__
+packet,395.729000,K_
+packet,395.896000,__
+packet,395.812000,__
+packet,395.770000,__
+packet,395.854000,__
+packet,395.937000,__
+packet,396.062000,__
+packet,395.979000,__
+packet,396.021000,__
+packet,396.146000,__
+packet,396.104000,__
+packet,396.187000,__
+packet,396.271000,__
+packet,396.229000,__
+packet,396.354000,__
+packet,396.313000,__
+packet,396.479000,__
+packet,396.396000,__
+packet,396.438000,__
+packet,396.521000,__
+packet,396.605000,__
+packet,396.563000,__
+packet,396.771000,__
+packet,396.688000,__
+packet,396.646000,__
+packet,396.730000,__
+packet,396.938000,__
+packet,396.855000,__
+packet,396.813000,__
+packet,396.897000,__
+packet,397.105000,__
+packet,397.022000,__
+packet,396.980000,__
+packet,397.063000,__
+packet,397.314000,__
+packet,397.188000,__
+packet,397.147000,__
+packet,397.230000,__
+packet,397.272000,__
+packet,397.564000,__
+packet,397.439000,__
+packet,397.355000,__
+packet,397.397000,__
+packet,397.480000,__
+packet,397.522000,__
+packet,397.606000,__
+packet,397.772000,__
+packet,397.689000,__
+packet,397.647000,__
+packet,397.731000,__
+packet,397.939000,__
+packet,397.856000,__
+packet,397.814000,__
+packet,397.898000,__
+packet,398.106000,__
+packet,398.023000,__
+packet,397.981000,__
+packet,398.064000,__
+packet,398.189000,__
+packet,398.148000,__
+packet,398.356000,__
+packet,398.273000,__
+packet,398.231000,__
+packet,398.315000,__
+packet,398.523000,__
+packet,398.440000,__
+packet,398.398000,__
+packet,398.481000,__
+packet,398.690000,__
+packet,398.607000,__
+packet,398.565000,__
+packet,398.648000,__
+packet,398.899000,__
+packet,398.773000,__
+packet,398.732000,__
+packet,398.815000,__
+packet,398.857000,__
+packet,399.065000,__
+packet,398.982000,__
+packet,398.940000,__
+packet,399.024000,__
+packet,399.232000,__
+packet,399.149000,__
+packet,399.107000,__
+packet,399.190000,__
+packet,399.274000,__
+packet,399.441000,__
+packet,399.357000,__
+packet,399.316000,__
+packet,399.399000,__
+packet,399.691000,__
+packet,399.566000,__
+packet,399.482000,__
+packet,399.524000,__
+packet,399.608000,__
+packet,399.649000,__
+packet,399.900000,__
+packet,399.774000,__
+packet,399.733000,__
+packet,399.816000,__
+packet,399.858000,__
+packet,400.025000,__
+packet,399.941000,__
+packet,399.983000,__
+packet,400.066000,__
+packet,400.233000,__
+packet,400.150000,__
+packet,400.108000,__
+packet,400.191000,__
+packet,400.400000,__
+packet,400.317000,__
+packet,400.275000,__
+packet,400.358000,__
+packet,400.567000,__
+packet,400.483000,__
+packet,400.442000,__
+packet,400.525000,__
+packet,400.650000,__
+packet,400.609000,__
+packet,401.026000,__
+packet,400.817000,__
+packet,400.692000,__
+packet,400.734000,__
+packet,400.775000,__
+packet,400.859000,__
+packet,400.901000,__
+packet,400.942000,__
+packet,400.984000,__
+packet,401.359000,__
+packet,401.192000,__
+packet,401.067000,__
+packet,401.109000,__
+packet,401.151000,__
+packet,401.234000,__
+packet,401.276000,__
+packet,401.318000,__
+packet,401.568000,__
+packet,401.443000,__
+packet,401.401000,__
+packet,401.484000,__
+packet,401.526000,__
+packet,401.610000,K_
+packet,401.776000,__
+packet,401.693000,__
+packet,401.651000,__
+packet,401.735000,__
+packet,401.902000,__
+packet,401.818000,__
+packet,401.860000,__
+packet,402.027000,__
+packet,401.943000,__
+packet,401.985000,__
+packet,402.193000,__
+packet,402.110000,__
+packet,402.068000,__
+packet,402.152000,__
+packet,402.277000,__
+packet,402.235000,__
+packet,402.485000,__
+packet,402.360000,__
+packet,402.319000,__
+packet,402.402000,__
+packet,402.444000,__
+packet,402.527000,__
+packet,402.611000,__
+packet,402.569000,__
+packet,402.777000,__
+packet,402.694000,__
+packet,402.652000,__
+packet,402.736000,__
+packet,402.986000,__
+packet,402.861000,__
+packet,402.819000,__
+packet,402.903000,__
+packet,402.944000,__
+packet,403.153000,__
+packet,403.069000,__
+packet,403.028000,__
+packet,403.111000,__
+packet,403.320000,__
+packet,403.236000,__
+packet,403.194000,__
+packet,403.278000,__
+packet,403.361000,__
+packet,403.528000,__
+packet,403.445000,__
+packet,403.403000,__
+packet,403.486000,__
+packet,403.570000,__
+packet,403.612000,__
+packet,403.778000,__
+packet,403.695000,__
+packet,403.653000,__
+packet,403.737000,__
+packet,403.987000,__
+packet,403.862000,__
+packet,403.820000,__
+packet,403.904000,__
+packet,403.945000,__
+packet,404.112000,__
+packet,404.029000,__
+packet,404.070000,__
+packet,404.279000,__
+packet,404.195000,__
+packet,404.154000,__
+packet,404.237000,__
+packet,404.487000,__
+packet,404.362000,__
+packet,404.321000,__
+packet,404.404000,__
+packet,404.446000,__
+packet,404.654000,__
+packet,404.571000,__
+packet,404.529000,__
+packet,404.613000,__
+packet,404.738000,__
+packet,404.696000,__
+packet,404.863000,__
+packet,404.779000,__
+packet,404.821000,__
+packet,405.071000,__
+packet,404.946000,__
+packet,404.905000,__
+packet,404.988000,__
+packet,405.030000,__
+packet,405.196000,__
+packet,405.113000,__
+packet,405.155000,__
+packet,405.363000,__
+packet,405.280000,__
+packet,405.238000,__
+packet,405.322000,__
+packet,405.447000,__
+packet,405.405000,__
+packet,405.614000,__
+packet,405.530000,__
+packet,405.488000,__
+packet,405.572000,__
+packet,405.822000,__
+packet,405.697000,__
+packet,405.655000,__
+packet,405.739000,__
+packet,405.780000,__
+packet,405.947000,__
+packet,405.864000,__
+packet,405.906000,__
+packet,406.114000,__
+packet,406.031000,__
+packet,405.989000,__
+packet,406.072000,__
+packet,406.323000,__
+packet,406.197000,__
+packet,406.156000,__
+packet,406.239000,__
+packet,406.281000,__
+packet,406.448000,__
+packet,406.364000,__
+packet,406.406000,__
+packet,406.615000,__
+packet,406.531000,__
+packet,406.489000,__
+packet,406.573000,__
+packet,406.823000,__
+packet,406.698000,__
+packet,406.656000,__
+packet,406.740000,__
+packet,406.781000,__
+packet,406.990000,__
+packet,406.907000,__
+packet,406.865000,__
+packet,406.948000,__
+packet,407.073000,__
+packet,407.032000,__
+packet,407.198000,__
+packet,407.115000,__
+packet,407.157000,__
+packet,407.365000,__
+packet,407.282000,__
+packet,407.240000,__
+packet,407.324000,__
+packet,407.574000,__
+packet,407.449000,__
+packet,407.407000,__
+packet,407.490000,__
+packet,407.532000,__
+packet,407.741000,__
+packet,407.657000,__
+packet,407.616000,__
+packet,407.699000,__
+packet,407.866000,__
+packet,407.782000,__
+packet,407.824000,__
+packet,408.074000,__
+packet,407.949000,__
+packet,407.908000,__
+packet,407.991000,__
+packet,408.033000,__
+packet,408.199000,__
+packet,408.116000,__
+packet,408.158000,__
+packet,408.366000,__
+packet,408.283000,__
+packet,408.241000,__
+packet,408.325000,__
+packet,408.575000,__
+packet,408.450000,__
+packet,408.408000,__
+packet,408.491000,__
+packet,408.533000,__
+packet,408.700000,__
+packet,408.617000,__
+packet,408.658000,__
+packet,408.992000,__
+packet,408.825000,__
+packet,408.742000,__
+packet,408.783000,__
+packet,408.867000,__
+packet,408.909000,__
+packet,408.950000,__
+packet,409.159000,__
+packet,409.075000,__
+packet,409.034000,__
+packet,409.117000,__
+packet,409.367000,__
+packet,409.242000,__
+packet,409.200000,__
+packet,409.284000,__
+packet,409.326000,__
+packet,409.534000,__
+packet,409.451000,__
+packet,409.409000,__
+packet,409.492000,__
+packet,409.618000,__
+packet,409.576000,__
+packet,409.826000,__
+packet,409.701000,__
+packet,409.659000,__
+packet,409.743000,__
+packet,409.784000,__
+packet,409.951000,__
+packet,409.868000,__
+packet,409.910000,__
+packet,409.993000,__
+packet,410.035000,K_
+packet,410.118000,__
+packet,410.076000,__
+packet,410.160000,__
+packet,410.201000,__
+packet,410.243000,__
+packet,410.327000,__
+packet,410.285000,__
+packet,410.368000,__
+packet,410.535000,__
+packet,410.452000,__
+packet,410.410000,__
+packet,410.493000,__
+packet,410.744000,__
+packet,410.619000,__
+packet,410.577000,__
+packet,410.660000,__
+packet,410.702000,__
+packet,410.785000,__
+packet,410.994000,__
+packet,410.869000,__
+packet,410.827000,__
+packet,410.911000,__
+packet,410.952000,__
+packet,411.119000,__
+packet,411.036000,__
+packet,411.077000,__
+packet,411.328000,__
+packet,411.202000,__
+packet,411.161000,__
+packet,411.244000,__
+packet,411.286000,__
+packet,411.411000,__
+packet,411.369000,__
+packet,411.453000,K_
+packet,411.620000,__
+packet,411.536000,__
+packet,411.494000,__
+packet,411.578000,__
+packet,411.828000,__
+packet,411.703000,__
+packet,411.661000,__
+packet,411.745000,__
+packet,411.786000,__
+packet,411.953000,__
+packet,411.870000,__
+packet,411.912000,__
+packet,412.120000,__
+packet,412.037000,__
+packet,411.995000,__
+packet,412.078000,__
+packet,412.245000,__
+packet,412.162000,__
+packet,412.203000,__
+packet,412.370000,__
+packet,412.287000,__
+packet,412.329000,__
+packet,412.412000,__
+packet,412.454000,K_
+packet,412.537000,__
+packet,412.495000,__
+packet,412.704000,__
+packet,412.621000,__
+packet,412.579000,__
+packet,412.662000,__
+packet,412.787000,__
+packet,412.746000,__
+packet,412.871000,__
+packet,412.829000,__
+packet,412.996000,__
+packet,412.913000,__
+packet,412.954000,__
+packet,413.121000,__
+packet,413.038000,__
+packet,413.079000,__
+packet,413.330000,__
+packet,413.204000,__
+packet,413.163000,__
+packet,413.246000,__
+packet,413.288000,__
+packet,413.496000,__
+packet,413.413000,__
+packet,413.371000,__
+packet,413.455000,__
+packet,413.663000,__
+packet,413.580000,__
+packet,413.538000,__
+packet,413.622000,__
+packet,413.830000,__
+packet,413.747000,__
+packet,413.705000,__
+packet,413.788000,__
+packet,413.872000,__
+packet,414.080000,__
+packet,413.955000,__
+packet,413.914000,__
+packet,413.997000,__
+packet,414.039000,__
+packet,414.205000,__
+packet,414.122000,__
+packet,414.164000,__
+packet,414.372000,__
+packet,414.289000,__
+packet,414.247000,__
+packet,414.331000,__
+packet,414.581000,__
+packet,414.456000,__
+packet,414.414000,__
+packet,414.497000,__
+packet,414.539000,__
+packet,414.664000,__
+packet,414.623000,__
+packet,414.998000,__
+packet,414.831000,__
+packet,414.706000,__
+packet,414.748000,__
+packet,414.789000,__
+packet,414.873000,__
+packet,414.915000,__
+packet,414.956000,__
+packet,415.123000,__
+packet,415.040000,__
+packet,415.081000,__
+packet,415.290000,__
+packet,415.206000,__
+packet,415.165000,__
+packet,415.248000,__
+packet,415.373000,__
+packet,415.332000,__
+packet,415.624000,__
+packet,415.498000,__
+packet,415.415000,__
+packet,415.457000,__
+packet,415.540000,__
+packet,415.582000,__
+packet,415.749000,__
+packet,415.665000,__
+packet,415.707000,__
+packet,415.790000,K_
+packet,415.999000,__
+packet,415.874000,__
+packet,415.832000,__
+packet,415.916000,__
+packet,415.957000,__
+packet,416.249000,__
+packet,416.124000,__
+packet,416.041000,__
+packet,416.082000,__
+packet,416.166000,__
+packet,416.207000,__
+packet,416.499000,__
+packet,416.374000,__
+packet,416.291000,__
+packet,416.333000,__
+packet,416.416000,__
+packet,416.458000,__
+packet,416.666000,__
+packet,416.583000,__
+packet,416.541000,__
+packet,416.625000,__
+packet,416.875000,__
+packet,416.750000,__
+packet,416.708000,__
+packet,416.791000,__
+packet,416.833000,__
+packet,417.125000,__
+packet,417.000000,__
+packet,416.917000,__
+packet,416.958000,__
+packet,417.042000,__
+packet,417.083000,__
+packet,417.250000,__
+packet,417.167000,__
+packet,417.208000,__
+packet,417.417000,__
+packet,417.334000,__
+packet,417.292000,__
+packet,417.375000,__
+packet,417.584000,__
+packet,417.500000,__
+packet,417.459000,__
+packet,417.542000,__
+packet,417.626000,__
+packet,417.792000,__
+packet,417.709000,__
+packet,417.667000,__
+packet,417.751000,__
+packet,417.918000,__
+packet,417.834000,__
+packet,417.876000,__
+packet,418.001000,__
+packet,417.959000,__
+packet,418.043000,K_
+packet,418.084000,__
+packet,418.293000,__
+packet,418.168000,__
+packet,418.126000,__
+packet,418.209000,__
+packet,418.251000,__
+packet,418.376000,__
+packet,418.335000,__
+packet,418.585000,__
+packet,418.460000,__
+packet,418.418000,__
+packet,418.501000,__
+packet,418.543000,__
+packet,418.627000,__
+packet,418.835000,__
+packet,418.710000,__
+packet,418.668000,__
+packet,418.752000,__
+packet,418.793000,__
+packet,419.127000,__
+packet,418.960000,__
+packet,418.877000,__
+packet,418.919000,__
+packet,419.002000,__
+packet,419.044000,__
+packet,419.085000,__
+packet,419.336000,__
+packet,419.210000,__
+packet,419.169000,__
+packet,419.252000,__
+packet,419.294000,__
+packet,419.502000,__
+packet,419.419000,__
+packet,419.377000,__
+packet,419.461000,__
+packet,419.628000,__
+packet,419.544000,__
+packet,419.586000,__
+packet,419.794000,__
+packet,419.711000,__
+packet,419.669000,__
+packet,419.753000,__
+packet,420.003000,__
+packet,419.878000,__
+packet,419.836000,__
+packet,419.920000,__
+packet,419.961000,__
+packet,420.045000,K_
+packet,420.170000,__
+packet,420.086000,__
+packet,420.128000,__
+packet,420.337000,__
+packet,420.253000,__
+packet,420.211000,__
+packet,420.295000,__
+packet,420.378000,__
+packet,420.545000,__
+packet,420.462000,__
+packet,420.420000,__
+packet,420.503000,__
+packet,420.879000,__
+packet,420.712000,__
+packet,420.587000,__
+packet,420.629000,__
+packet,420.670000,__
+packet,420.754000,__
+packet,420.795000,__
+packet,420.837000,__
+packet,421.087000,__
+packet,420.962000,__
+packet,420.921000,__
+packet,421.004000,__
+packet,421.046000,__
+packet,421.254000,__
+packet,421.171000,__
+packet,421.129000,__
+packet,421.212000,__
+packet,421.379000,__
+packet,421.296000,__
+packet,421.338000,__
+packet,421.588000,__
+packet,421.463000,__
+packet,421.421000,__
+packet,421.504000,__
+packet,421.546000,__
+packet,421.838000,__
+packet,421.713000,__
+packet,421.630000,__
+packet,421.671000,__
+packet,421.755000,__
+packet,421.796000,__
+packet,422.088000,__
+packet,421.963000,__
+packet,421.880000,__
+packet,421.922000,__
+packet,422.005000,__
+packet,422.047000,__
+packet,422.213000,__
+packet,422.130000,__
+packet,422.172000,__
+packet,422.255000,K_
+packet,422.422000,__
+packet,422.339000,__
+packet,422.297000,__
+packet,422.380000,__
+packet,422.464000,__
+packet,422.631000,__
+packet,422.547000,__
+packet,422.505000,__
+packet,422.589000,__
+packet,422.839000,__
+packet,422.714000,__
+packet,422.672000,__
+packet,422.756000,__
+packet,422.797000,__
+packet,422.964000,__
+packet,422.881000,__
+packet,422.923000,__
+packet,423.131000,__
+packet,423.048000,__
+packet,423.006000,__
+packet,423.089000,__
+packet,423.340000,__
+packet,423.214000,__
+packet,423.173000,__
+packet,423.256000,__
+packet,423.298000,__
+packet,423.632000,__
+packet,423.465000,__
+packet,423.381000,__
+packet,423.423000,__
+packet,423.506000,__
+packet,423.548000,__
+packet,423.590000,__
+packet,423.840000,__
+packet,423.715000,__
+packet,423.673000,__
+packet,423.757000,__
+packet,423.798000,__
+packet,423.882000,__
+packet,424.049000,__
+packet,423.965000,__
+packet,423.924000,__
+packet,424.007000,__
+packet,424.215000,__
+packet,424.132000,__
+packet,424.090000,__
+packet,424.174000,__
+packet,424.257000,__
+packet,424.382000,__
+packet,424.299000,__
+packet,424.341000,__
+packet,424.591000,__
+packet,424.466000,__
+packet,424.424000,__
+packet,424.507000,__
+packet,424.549000,__
+packet,424.716000,__
+packet,424.633000,__
+packet,424.674000,__
+packet,424.883000,__
+packet,424.799000,__
+packet,424.758000,__
+packet,424.841000,__
+packet,425.091000,__
+packet,424.966000,__
+packet,424.925000,__
+packet,425.008000,__
+packet,425.050000,__
+packet,425.175000,__
+packet,425.133000,__
+packet,425.216000,K_
+packet,425.383000,__
+packet,425.300000,__
+packet,425.258000,__
+packet,425.342000,__
+packet,425.634000,__
+packet,425.508000,__
+packet,425.425000,__
+packet,425.467000,__
+packet,425.550000,__
+packet,425.592000,__
+packet,425.717000,__
+packet,425.675000,__
+packet,426.009000,__
+packet,425.842000,__
+packet,425.759000,__
+packet,425.800000,__
+packet,425.884000,__
+packet,425.926000,__
+packet,425.967000,__
+packet,426.176000,__
+packet,426.092000,__
+packet,426.051000,__
+packet,426.134000,__
+packet,426.384000,__
+packet,426.259000,__
+packet,426.217000,__
+packet,426.301000,__
+packet,426.343000,__
+packet,426.593000,__
+packet,426.468000,__
+packet,426.426000,__
+packet,426.509000,__
+packet,426.551000,__
+packet,426.760000,__
+packet,426.676000,__
+packet,426.635000,__
+packet,426.718000,__
+packet,426.968000,__
+packet,426.843000,__
+packet,426.801000,__
+packet,426.885000,__
+packet,426.927000,__
+packet,427.135000,__
+packet,427.052000,__
+packet,427.010000,__
+packet,427.093000,__
+packet,427.385000,__
+packet,427.260000,__
+packet,427.177000,__
+packet,427.218000,__
+packet,427.302000,__
+packet,427.344000,__
+packet,427.510000,__
+packet,427.427000,__
+packet,427.469000,__
+packet,427.594000,__
+packet,427.552000,__
+packet,427.636000,__
+packet,427.677000,__
+packet,427.844000,__
+packet,427.761000,__
+packet,427.719000,__
+packet,427.802000,__
+packet,427.886000,__
+packet,428.136000,__
+packet,428.011000,__
+packet,427.928000,__
+packet,427.969000,__
+packet,428.053000,__
+packet,428.094000,__
+packet,428.303000,__
+packet,428.219000,__
+packet,428.178000,__
+packet,428.261000,__
+packet,428.386000,__
+packet,428.345000,__
+packet,428.553000,__
+packet,428.470000,__
+packet,428.428000,__
+packet,428.511000,__
+packet,428.720000,__
+packet,428.637000,__
+packet,428.595000,__
+packet,428.678000,__
+packet,429.012000,__
+packet,428.845000,__
+packet,428.762000,__
+packet,428.803000,__
+packet,428.887000,__
+packet,428.929000,__
+packet,428.970000,__
+packet,429.346000,__
+packet,429.179000,__
+packet,429.054000,__
+packet,429.095000,__
+packet,429.137000,__
+packet,429.220000,__
+packet,429.262000,__
+packet,429.304000,__
+packet,429.554000,__
+packet,429.429000,__
+packet,429.387000,__
+packet,429.471000,__
+packet,429.512000,__
+packet,429.596000,K_
+packet,429.679000,__
+packet,429.638000,__
+packet,429.721000,__
+packet,429.930000,__
+packet,429.804000,__
+packet,429.763000,__
+packet,429.846000,__
+packet,429.888000,__
+packet,430.096000,__
+packet,430.013000,__
+packet,429.971000,__
+packet,430.055000,__
+packet,430.221000,__
+packet,430.138000,__
+packet,430.180000,__
+packet,430.388000,__
+packet,430.305000,__
+packet,430.263000,__
+packet,430.347000,__
+packet,430.555000,__
+packet,430.472000,__
+packet,430.430000,__
+packet,430.513000,__
+packet,430.764000,__
+packet,430.639000,__
+packet,430.597000,__
+packet,430.680000,__
+packet,430.722000,__
+packet,430.889000,__
+packet,430.805000,__
+packet,430.847000,__
+packet,430.931000,__
+packet,430.972000,K_
+packet,431.139000,__
+packet,431.056000,__
+packet,431.014000,__
+packet,431.097000,__
+packet,431.306000,__
+packet,431.222000,__
+packet,431.181000,__
+packet,431.264000,__
+packet,431.598000,__
+packet,431.431000,__
+packet,431.348000,__
+packet,431.389000,__
+packet,431.473000,__
+packet,431.514000,__
+packet,431.556000,__
+packet,431.723000,__
+packet,431.640000,__
+packet,431.681000,__
+packet,431.806000,__
+packet,431.765000,__
+packet,431.973000,__
+packet,431.890000,__
+packet,431.848000,__
+packet,431.932000,__
+packet,432.140000,__
+packet,432.057000,__
+packet,432.015000,__
+packet,432.098000,__
+packet,432.390000,__
+packet,432.265000,__
+packet,432.182000,__
+packet,432.223000,__
+packet,432.307000,__
+packet,432.349000,__
+packet,432.599000,__
+packet,432.474000,__
+packet,432.432000,__
+packet,432.515000,__
+packet,432.557000,__
+packet,432.766000,__
+packet,432.682000,__
+packet,432.641000,__
+packet,432.724000,__
+packet,432.807000,K_
+packet,432.974000,__
+packet,432.891000,__
+packet,432.849000,__
+packet,432.933000,__
+packet,433.224000,__
+packet,433.099000,__
+packet,433.016000,__
+packet,433.058000,__
+packet,433.141000,__
+packet,433.183000,__
+packet,433.475000,__
+packet,433.350000,__
+packet,433.266000,__
+packet,433.308000,__
+packet,433.391000,__
+packet,433.433000,__
+packet,433.725000,__
+packet,433.600000,__
+packet,433.516000,__
+packet,433.558000,__
+packet,433.642000,__
+packet,433.683000,__
+packet,433.975000,__
+packet,433.850000,__
+packet,433.767000,__
+packet,433.808000,__
+packet,433.892000,__
+packet,433.934000,__
+packet,434.017000,__
+packet,434.059000,K_
+packet,434.142000,__
+packet,434.100000,__
+packet,434.517000,__
+packet,434.309000,__
+packet,434.184000,__
+packet,434.225000,__
+packet,434.267000,__
+packet,434.351000,__
+packet,434.392000,__
+packet,434.434000,__
+packet,434.476000,__
+packet,434.893000,__
+packet,434.684000,__
+packet,434.559000,__
+packet,434.601000,__
+packet,434.643000,__
+packet,434.726000,__
+packet,434.768000,__
+packet,434.809000,__
+packet,434.851000,__
+packet,435.143000,__
+packet,435.018000,__
+packet,434.935000,__
+packet,434.976000,__
+packet,435.060000,__
+packet,435.101000,__
+packet,435.393000,__
+packet,435.268000,__
+packet,435.185000,__
+packet,435.226000,__
+packet,435.310000,__
+packet,435.352000,__
+packet,435.518000,__
+packet,435.435000,__
+packet,435.477000,__
+packet,435.644000,__
+packet,435.560000,__
+packet,435.602000,__
+packet,435.769000,__
+packet,435.685000,__
+packet,435.727000,__
+packet,436.019000,__
+packet,435.894000,__
+packet,435.810000,__
+packet,435.852000,__
+packet,435.936000,__
+packet,435.977000,__
+packet,436.144000,__
+packet,436.061000,__
+packet,436.102000,__
+packet,436.394000,__
+packet,436.269000,__
+packet,436.186000,__
+packet,436.227000,__
+packet,436.311000,__
+packet,436.353000,__
+packet,436.519000,__
+packet,436.436000,__
+packet,436.478000,__
+packet,436.645000,__
+packet,436.561000,__
+packet,436.603000,__
+packet,436.853000,__
+packet,436.728000,__
+packet,436.686000,__
+packet,436.770000,__
+packet,436.811000,__
+packet,437.103000,__
+packet,436.978000,__
+packet,436.895000,__
+packet,436.937000,__
+packet,437.020000,__
+packet,437.062000,__
+packet,437.145000,K_
+packet,437.312000,__
+packet,437.228000,__
+packet,437.187000,__
+packet,437.270000,__
+packet,437.479000,__
+packet,437.395000,__
+packet,437.354000,__
+packet,437.437000,__
+packet,437.520000,__
+packet,437.604000,__
+packet,437.562000,__
+packet,437.771000,__
+packet,437.687000,__
+packet,437.646000,__
+packet,437.729000,__
+packet,438.146000,__
+packet,437.938000,__
+packet,437.812000,__
+packet,437.854000,__
+packet,437.896000,__
+packet,437.979000,__
+packet,438.021000,__
+packet,438.063000,__
+packet,438.104000,__
+packet,438.313000,__
+packet,438.229000,__
+packet,438.188000,__
+packet,438.271000,__
+packet,438.480000,__
+packet,438.396000,__
+packet,438.355000,__
+packet,438.438000,__
+packet,438.855000,__
+packet,438.647000,__
+packet,438.521000,__
+packet,438.563000,__
+packet,438.605000,__
+packet,438.688000,__
+packet,438.730000,__
+packet,438.772000,__
+packet,438.813000,__
+packet,438.939000,__
+packet,438.897000,__
+packet,439.314000,__
+packet,439.105000,__
+packet,438.980000,__
+packet,439.022000,__
+packet,439.064000,__
+packet,439.147000,__
+packet,439.189000,__
+packet,439.230000,__
+packet,439.272000,__
+packet,439.481000,__
+packet,439.397000,__
+packet,439.356000,__
+packet,439.439000,__
+packet,439.648000,__
+packet,439.564000,__
+packet,439.522000,__
+packet,439.606000,__
+packet,439.814000,__
+packet,439.731000,__
+packet,439.689000,__
+packet,439.773000,__
+packet,439.981000,__
+packet,439.898000,__
+packet,439.856000,__
+packet,439.940000,__
+packet,440.023000,K_
+packet,440.231000,__
+packet,440.106000,__
+packet,440.065000,__
+packet,440.148000,__
+packet,440.190000,__
+packet,440.398000,__
+packet,440.315000,__
+packet,440.273000,__
+packet,440.357000,__
+packet,440.649000,__
+packet,440.523000,__
+packet,440.440000,__
+packet,440.482000,__
+packet,440.565000,__
+packet,440.607000,__
+packet,440.774000,__
+packet,440.690000,__
+packet,440.732000,__
+packet,440.941000,__
+packet,440.857000,__
+packet,440.815000,__
+packet,440.899000,__
+packet,441.149000,__
+packet,441.024000,__
+packet,440.982000,__
+packet,441.066000,__
+packet,441.107000,__
+packet,441.274000,__
+packet,441.191000,__
+packet,441.232000,__
+packet,441.524000,__
+packet,441.399000,__
+packet,441.316000,__
+packet,441.358000,__
+packet,441.441000,__
+packet,441.483000,__
+packet,441.650000,__
+packet,441.566000,__
+packet,441.608000,__
+packet,441.858000,__
+packet,441.733000,__
+packet,441.691000,__
+packet,441.775000,__
+packet,441.816000,__
+packet,442.025000,__
+packet,441.942000,__
+packet,441.900000,__
+packet,441.983000,__
+packet,442.317000,__
+packet,442.150000,__
+packet,442.067000,__
+packet,442.108000,__
+packet,442.192000,__
+packet,442.233000,__
+packet,442.275000,__
+packet,442.651000,__
+packet,442.484000,__
+packet,442.359000,__
+packet,442.400000,__
+packet,442.442000,__
+packet,442.525000,__
+packet,442.567000,__
+packet,442.609000,__
+packet,442.692000,K_
+packet,442.901000,__
+packet,442.776000,__
+packet,442.734000,__
+packet,442.817000,__
+packet,442.859000,__
+packet,443.068000,__
+packet,442.984000,__
+packet,442.943000,__
+packet,443.026000,__
+packet,443.234000,__
+packet,443.151000,__
+packet,443.109000,__
+packet,443.193000,__
+packet,443.276000,__
+packet,443.318000,__
+packet,443.360000,__
+packet,443.401000,__
+packet,443.443000,__
+packet,443.485000,__
+packet,443.526000,__
+packet,443.652000,__
+packet,443.568000,__
+packet,443.610000,__
+packet,443.902000,__
+packet,443.777000,__
+packet,443.693000,__
+packet,443.735000,__
+packet,443.818000,__
+packet,443.860000,__
+packet,444.069000,__
+packet,443.985000,__
+packet,443.944000,__
+packet,444.027000,__
+packet,444.402000,__
+packet,444.235000,__
+packet,444.110000,__
+packet,444.152000,__
+packet,444.194000,__
+packet,444.277000,__
+packet,444.319000,__
+packet,444.361000,__
+packet,444.653000,__
+packet,444.527000,__
+packet,444.444000,__
+packet,444.486000,__
+packet,444.569000,__
+packet,444.611000,__
+packet,444.903000,__
+packet,444.778000,__
+packet,444.694000,__
+packet,444.736000,__
+packet,444.819000,__
+packet,444.861000,__
+packet,445.153000,__
+packet,445.028000,__
+packet,444.945000,__
+packet,444.986000,__
+packet,445.070000,__
+packet,445.111000,__
+packet,445.195000,__
+packet,445.403000,__
+packet,445.278000,__
+packet,445.236000,__
+packet,445.320000,__
+packet,445.362000,__
+packet,445.570000,__
+packet,445.487000,__
+packet,445.445000,__
+packet,445.528000,__
+packet,445.695000,__
+packet,445.612000,__
+packet,445.654000,__
+packet,445.779000,__
+packet,445.737000,__
+packet,445.820000,__
+packet,445.987000,__
+packet,445.904000,__
+packet,445.862000,__
+packet,445.946000,__
+packet,446.154000,__
+packet,446.071000,__
+packet,446.029000,__
+packet,446.112000,__
+packet,446.321000,__
+packet,446.237000,__
+packet,446.196000,__
+packet,446.279000,__
+packet,446.529000,__
+packet,446.404000,__
+packet,446.363000,__
+packet,446.446000,__
+packet,446.488000,__
+packet,446.696000,__
+packet,446.613000,__
+packet,446.571000,__
+packet,446.655000,__
+packet,446.780000,__
+packet,446.738000,__
+packet,446.988000,__
+packet,446.863000,__
+packet,446.821000,__
+packet,446.905000,__
+packet,446.947000,__
+packet,447.197000,__
+packet,447.072000,__
+packet,447.030000,__
+packet,447.113000,__
+packet,447.155000,__
+packet,447.364000,__
+packet,447.280000,__
+packet,447.238000,__
+packet,447.322000,__
+packet,447.530000,__
+packet,447.447000,__
+packet,447.405000,__
+packet,447.489000,__
+packet,447.697000,__
+packet,447.614000,__
+packet,447.572000,__
+packet,447.656000,__
+packet,447.864000,__
+packet,447.781000,__
+packet,447.739000,__
+packet,447.822000,__
+packet,448.031000,__
+packet,447.948000,__
+packet,447.906000,__
+packet,447.989000,__
+packet,448.198000,__
+packet,448.114000,__
+packet,448.073000,__
+packet,448.156000,__
+packet,448.490000,__
+packet,448.323000,__
+packet,448.239000,__
+packet,448.281000,__
+packet,448.365000,__
+packet,448.406000,__
+packet,448.448000,__
+packet,448.531000,__
+packet,448.782000,__
+packet,448.657000,__
+packet,448.573000,__
+packet,448.615000,__
+packet,448.698000,__
+packet,448.740000,__
+packet,448.907000,__
+packet,448.823000,__
+packet,448.865000,__
+packet,448.949000,K_
+packet,448.990000,__
+packet,449.324000,__
+packet,449.157000,__
+packet,449.032000,__
+packet,449.074000,__
+packet,449.115000,__
+packet,449.199000,__
+packet,449.240000,__
+packet,449.282000,__
+packet,449.658000,__
+packet,449.491000,__
+packet,449.366000,__
+packet,449.407000,__
+packet,449.449000,__
+packet,449.532000,__
+packet,449.574000,__
+packet,449.616000,__
+packet,449.991000,__
+packet,449.824000,__
+packet,449.699000,__
+packet,449.741000,__
+packet,449.783000,__
+packet,449.866000,__
+packet,449.908000,__
+packet,449.950000,__
+packet,450.325000,__
+packet,450.158000,__
+packet,450.033000,__
+packet,450.075000,__
+packet,450.116000,__
+packet,450.200000,__
+packet,450.241000,__
+packet,450.283000,__
+packet,450.659000,__
+packet,450.492000,__
+packet,450.367000,__
+packet,450.408000,__
+packet,450.450000,__
+packet,450.533000,__
+packet,450.575000,__
+packet,450.617000,__
+packet,450.992000,__
+packet,450.825000,__
+packet,450.700000,__
+packet,450.742000,__
+packet,450.784000,__
+packet,450.867000,__
+packet,450.909000,__
+packet,450.951000,__
+packet,451.159000,__
+packet,451.076000,__
+packet,451.034000,__
+packet,451.117000,__
+packet,451.201000,K_
+packet,451.284000,__
+packet,451.242000,__
+packet,451.534000,__
+packet,451.409000,__
+packet,451.326000,__
+packet,451.368000,__
+packet,451.451000,__
+packet,451.493000,__
+packet,451.743000,__
+packet,451.618000,__
+packet,451.576000,__
+packet,451.660000,__
+packet,451.701000,__
+packet,452.118000,__
+packet,451.910000,__
+packet,451.785000,__
+packet,451.826000,__
+packet,451.868000,__
+packet,451.952000,__
+packet,451.993000,__
+packet,452.035000,__
+packet,452.077000,__
+packet,452.285000,__
+packet,452.202000,__
+packet,452.160000,__
+packet,452.243000,__
+packet,452.494000,__
+packet,452.369000,__
+packet,452.327000,__
+packet,452.410000,__
+packet,452.452000,__
+packet,452.786000,__
+packet,452.619000,__
+packet,452.535000,__
+packet,452.577000,__
+packet,452.661000,__
+packet,452.702000,__
+packet,452.744000,__
+packet,453.078000,__
+packet,452.911000,__
+packet,452.827000,__
+packet,452.869000,__
+packet,452.953000,__
+packet,452.994000,__
+packet,453.036000,__
+packet,453.119000,K_
+packet,453.328000,__
+packet,453.203000,__
+packet,453.161000,__
+packet,453.244000,__
+packet,453.286000,__
+packet,453.495000,__
+packet,453.411000,__
+packet,453.370000,__
+packet,453.453000,__
+packet,453.620000,__
+packet,453.536000,__
+packet,453.578000,__
+packet,453.787000,__
+packet,453.703000,__
+packet,453.662000,__
+packet,453.745000,__
+packet,453.995000,__
+packet,453.870000,__
+packet,453.828000,__
+packet,453.912000,__
+packet,453.954000,__
+packet,454.329000,__
+packet,454.162000,__
+packet,454.037000,__
+packet,454.079000,__
+packet,454.120000,__
+packet,454.204000,__
+packet,454.245000,__
+packet,454.287000,__
+packet,454.496000,__
+packet,454.412000,__
+packet,454.371000,__
+packet,454.454000,__
+packet,454.663000,__
+packet,454.579000,__
+packet,454.537000,__
+packet,454.621000,__
+packet,454.788000,__
+packet,454.704000,__
+packet,454.746000,__
+packet,455.080000,__
+packet,454.913000,__
+packet,454.829000,__
+packet,454.871000,__
+packet,454.955000,__
+packet,454.996000,__
+packet,455.038000,__
+packet,455.413000,__
+packet,455.246000,__
+packet,455.121000,__
+packet,455.163000,__
+packet,455.205000,__
+packet,455.288000,__
+packet,455.330000,__
+packet,455.372000,__
+packet,455.664000,__
+packet,455.538000,__
+packet,455.455000,__
+packet,455.497000,__
+packet,455.580000,__
+packet,455.622000,__
+packet,455.747000,__
+packet,455.705000,__
+packet,455.914000,__
+packet,455.830000,__
+packet,455.789000,__
+packet,455.872000,__
+packet,455.997000,__
+packet,455.956000,__
+packet,456.164000,__
+packet,456.081000,__
+packet,456.039000,__
+packet,456.122000,__
+packet,456.289000,__
+packet,456.206000,__
+packet,456.247000,__
+packet,456.414000,__
+packet,456.331000,__
+packet,456.373000,__
+packet,456.581000,__
+packet,456.498000,__
+packet,456.456000,__
+packet,456.539000,__
+packet,456.790000,__
+packet,456.665000,__
+packet,456.623000,__
+packet,456.706000,__
+packet,456.748000,__
+packet,456.915000,__
+packet,456.831000,__
+packet,456.873000,__
+packet,456.957000,K_
+packet,457.165000,__
+packet,457.040000,__
+packet,456.998000,__
+packet,457.082000,__
+packet,457.123000,__
+packet,457.332000,__
+packet,457.248000,__
+packet,457.207000,__
+packet,457.290000,__
+packet,457.707000,__
+packet,457.499000,__
+packet,457.374000,__
+packet,457.415000,__
+packet,457.457000,__
+packet,457.540000,__
+packet,457.582000,__
+packet,457.624000,__
+packet,457.666000,__
+packet,457.874000,__
+packet,457.791000,__
+packet,457.749000,__
+packet,457.832000,__
+packet,458.166000,__
+packet,457.999000,__
+packet,457.916000,__
+packet,457.958000,__
+packet,458.041000,__
+packet,458.083000,__
+packet,458.124000,__
+packet,458.249000,__
+packet,458.208000,__
+packet,458.416000,__
+packet,458.333000,__
+packet,458.291000,__
+packet,458.375000,__
+packet,458.583000,__
+packet,458.500000,__
+packet,458.458000,__
+packet,458.541000,__
+packet,458.750000,__
+packet,458.667000,__
+packet,458.625000,__
+packet,458.708000,__
+packet,458.875000,__
+packet,458.792000,__
+packet,458.833000,__
+packet,459.125000,__
+packet,459.000000,__
+packet,458.917000,__
+packet,458.959000,__
+packet,459.042000,__
+packet,459.084000,__
+packet,459.334000,__
+packet,459.209000,__
+packet,459.167000,__
+packet,459.250000,__
+packet,459.292000,__
+packet,459.501000,__
+packet,459.417000,__
+packet,459.376000,__
+packet,459.459000,__
+packet,459.751000,__
+packet,459.626000,__
+packet,459.542000,__
+packet,459.584000,__
+packet,459.668000,__
+packet,459.709000,__
+packet,459.918000,__
+packet,459.834000,__
+packet,459.793000,__
+packet,459.876000,__
+packet,459.960000,K_
+packet,460.126000,__
+packet,460.043000,__
+packet,460.001000,__
+packet,460.085000,__
+packet,460.418000,__
+packet,460.251000,__
+packet,460.168000,__
+packet,460.210000,__
+packet,460.293000,__
+packet,460.335000,__
+packet,460.377000,__
+packet,460.627000,__
+packet,460.502000,__
+packet,460.460000,__
+packet,460.543000,__
+packet,460.585000,__
+packet,460.877000,__
+packet,460.752000,__
+packet,460.669000,__
+packet,460.710000,__
+packet,460.794000,__
+packet,460.835000,__
+packet,461.002000,__
+packet,460.919000,__
+packet,460.961000,__
+packet,461.252000,__
+packet,461.127000,__
+packet,461.044000,__
+packet,461.086000,__
+packet,461.169000,__
+packet,461.211000,__
+packet,461.294000,__
+packet,461.378000,__
+packet,461.336000,__
+packet,461.670000,__
+packet,461.503000,__
+packet,461.419000,__
+packet,461.461000,__
+packet,461.544000,__
+packet,461.586000,__
+packet,461.628000,__
+packet,461.878000,__
+packet,461.753000,__
+packet,461.711000,__
+packet,461.795000,__
+packet,461.836000,__
+packet,462.045000,__
+packet,461.962000,__
+packet,461.920000,__
+packet,462.003000,__
+packet,462.170000,__
+packet,462.087000,__
+packet,462.128000,__
+packet,462.295000,__
+packet,462.212000,__
+packet,462.253000,__
+packet,462.545000,__
+packet,462.420000,__
+packet,462.337000,__
+packet,462.379000,__
+packet,462.462000,__
+packet,462.504000,__
+packet,462.712000,__
+packet,462.629000,__
+packet,462.587000,__
+packet,462.671000,__
+packet,462.754000,__
+packet,462.796000,__
+packet,462.837000,__
+packet,462.879000,__
+packet,462.921000,__
+packet,463.004000,__
+packet,462.963000,__
+packet,463.129000,__
+packet,463.046000,__
+packet,463.088000,__
+packet,463.296000,__
+packet,463.213000,__
+packet,463.171000,__
+packet,463.254000,__
+packet,463.505000,__
+packet,463.380000,__
+packet,463.338000,__
+packet,463.421000,__
+packet,463.463000,__
+packet,463.546000,K_
+packet,463.588000,__
+packet,463.755000,__
+packet,463.672000,__
+packet,463.630000,__
+packet,463.713000,__
+packet,463.964000,__
+packet,463.838000,__
+packet,463.797000,__
+packet,463.880000,__
+packet,463.922000,__
+packet,464.130000,__
+packet,464.047000,__
+packet,464.005000,__
+packet,464.089000,__
+packet,464.255000,__
+packet,464.172000,__
+packet,464.214000,__
+packet,464.422000,__
+packet,464.339000,__
+packet,464.297000,__
+packet,464.381000,__
+packet,464.756000,__
+packet,464.589000,__
+packet,464.464000,__
+packet,464.506000,__
+packet,464.547000,__
+packet,464.631000,__
+packet,464.673000,__
+packet,464.714000,__
+packet,464.923000,__
+packet,464.839000,__
+packet,464.798000,__
+packet,464.881000,__
+packet,465.090000,__
+packet,465.006000,__
+packet,464.965000,__
+packet,465.048000,__
+packet,465.173000,__
+packet,465.131000,__
+packet,465.382000,__
+packet,465.256000,__
+packet,465.215000,__
+packet,465.298000,__
+packet,465.340000,__
+packet,465.548000,__
+packet,465.465000,__
+packet,465.423000,__
+packet,465.507000,__
+packet,465.715000,__
+packet,465.632000,__
+packet,465.590000,__
+packet,465.674000,__
+packet,465.882000,__
+packet,465.799000,__
+packet,465.757000,__
+packet,465.840000,__
+packet,465.966000,__
+packet,465.924000,__
+packet,466.007000,K_
+packet,466.174000,__
+packet,466.091000,__
+packet,466.049000,__
+packet,466.132000,__
+packet,466.299000,__
+packet,466.216000,__
+packet,466.257000,__
+packet,466.341000,__
+packet,466.424000,__
+packet,466.383000,__
+packet,466.508000,__
+packet,466.466000,__
+packet,466.675000,__
+packet,466.591000,__
+packet,466.549000,__
+packet,466.633000,__
+packet,466.758000,__
+packet,466.716000,__
+packet,466.925000,__
+packet,466.841000,__
+packet,466.800000,__
+packet,466.883000,__
+packet,467.092000,__
+packet,467.008000,__
+packet,466.967000,__
+packet,467.050000,__
+packet,467.300000,__
+packet,467.175000,__
+packet,467.133000,__
+packet,467.217000,__
+packet,467.258000,__
+packet,467.634000,__
+packet,467.467000,__
+packet,467.342000,__
+packet,467.384000,__
+packet,467.425000,__
+packet,467.509000,__
+packet,467.550000,__
+packet,467.592000,__
+packet,467.926000,__
+packet,467.759000,__
+packet,467.676000,__
+packet,467.717000,__
+packet,467.801000,__
+packet,467.842000,__
+packet,467.884000,__
+packet,468.051000,__
+packet,467.968000,__
+packet,468.009000,__
+packet,468.093000,K_
+packet,468.259000,__
+packet,468.176000,__
+packet,468.134000,__
+packet,468.218000,__
+packet,468.426000,__
+packet,468.343000,__
+packet,468.301000,__
+packet,468.385000,__
+packet,468.593000,__
+packet,468.510000,__
+packet,468.468000,__
+packet,468.551000,__
+packet,468.635000,__
+packet,468.802000,__
+packet,468.718000,__
+packet,468.677000,__
+packet,468.760000,__
+packet,468.969000,__
+packet,468.885000,__
+packet,468.843000,__
+packet,468.927000,__
+packet,469.135000,__
+packet,469.052000,__
+packet,469.010000,__
+packet,469.094000,__
+packet,469.302000,__
+packet,469.219000,__
+packet,469.177000,__
+packet,469.260000,__
+packet,469.344000,__
+packet,469.427000,__
+packet,469.386000,__
+packet,469.594000,__
+packet,469.511000,__
+packet,469.469000,__
+packet,469.552000,__
+packet,469.636000,__
+packet,469.678000,__
+packet,469.844000,__
+packet,469.761000,__
+packet,469.719000,__
+packet,469.803000,__
+packet,469.928000,__
+packet,469.886000,__
+packet,469.970000,__
+packet,470.136000,__
+packet,470.053000,__
+packet,470.011000,__
+packet,470.095000,__
+packet,470.303000,__
+packet,470.220000,__
+packet,470.178000,__
+packet,470.261000,__
+packet,470.428000,__
+packet,470.345000,__
+packet,470.387000,__
+packet,470.553000,__
+packet,470.470000,__
+packet,470.512000,__
+packet,470.720000,__
+packet,470.637000,__
+packet,470.595000,__
+packet,470.679000,__
+packet,470.887000,__
+packet,470.804000,__
+packet,470.762000,__
+packet,470.845000,__
+packet,471.012000,__
+packet,470.929000,__
+packet,470.971000,__
+packet,471.137000,__
+packet,471.054000,__
+packet,471.096000,__
+packet,471.262000,__
+packet,471.179000,__
+packet,471.221000,__
+packet,471.388000,__
+packet,471.304000,__
+packet,471.346000,__
+packet,471.513000,__
+packet,471.429000,__
+packet,471.471000,__
+packet,471.638000,__
+packet,471.554000,__
+packet,471.596000,__
+packet,471.721000,__
+packet,471.680000,__
+packet,471.846000,__
+packet,471.763000,__
+packet,471.805000,__
+packet,472.013000,__
+packet,471.930000,__
+packet,471.888000,__
+packet,471.972000,__
+packet,472.222000,__
+packet,472.097000,__
+packet,472.055000,__
+packet,472.138000,__
+packet,472.180000,__
+packet,472.389000,__
+packet,472.305000,__
+packet,472.263000,__
+packet,472.347000,__
+packet,472.555000,__
+packet,472.472000,__
+packet,472.430000,__
+packet,472.514000,__
+packet,472.889000,__
+packet,472.722000,__
+packet,472.597000,__
+packet,472.639000,__
+packet,472.681000,__
+packet,472.764000,__
+packet,472.806000,__
+packet,472.847000,__
+packet,472.931000,K_
+packet,473.014000,__
+packet,472.973000,__
+packet,473.098000,__
+packet,473.056000,__
+packet,473.139000,__
+packet,473.223000,__
+packet,473.181000,__
+packet,473.306000,__
+packet,473.264000,__
+packet,473.431000,__
+packet,473.348000,__
+packet,473.390000,__
+packet,473.598000,__
+packet,473.515000,__
+packet,473.473000,__
+packet,473.556000,__
+packet,473.640000,__
+packet,473.682000,__
+packet,473.723000,__
+packet,473.765000,__
+packet,473.807000,__
+packet,473.848000,__
+packet,473.890000,__
+packet,473.932000,__
+packet,473.974000,__
+packet,474.015000,__
+packet,474.057000,__
+packet,474.099000,__
+packet,474.182000,__
+packet,474.140000,__
+packet,474.349000,__
+packet,474.265000,__
+packet,474.224000,__
+packet,474.307000,__
+packet,474.516000,__
+packet,474.432000,__
+packet,474.391000,__
+packet,474.474000,__
+packet,474.683000,__
+packet,474.599000,__
+packet,474.557000,__
+packet,474.641000,__
+packet,474.766000,__
+packet,474.724000,__
+packet,474.849000,__
+packet,474.808000,__
+packet,474.891000,__
+packet,475.016000,__
+packet,474.933000,__
+packet,474.975000,__
+packet,475.141000,__
+packet,475.058000,__
+packet,475.100000,__
+packet,475.266000,__
+packet,475.183000,__
+packet,475.225000,__
+packet,475.308000,__
+packet,475.350000,__
+packet,475.392000,__
+packet,475.517000,__
+packet,475.433000,__
+packet,475.475000,__
+packet,475.600000,__
+packet,475.558000,__
+packet,475.642000,__
+packet,475.725000,__
+packet,475.684000,__
+packet,475.767000,K_
+packet,475.934000,__
+packet,475.850000,__
+packet,475.809000,__
+packet,475.892000,__
+packet,476.101000,__
+packet,476.017000,__
+packet,475.976000,__
+packet,476.059000,__
+packet,476.267000,__
+packet,476.184000,__
+packet,476.142000,__
+packet,476.226000,__
+packet,476.434000,__
+packet,476.351000,__
+packet,476.309000,__
+packet,476.393000,__
+packet,476.601000,__
+packet,476.518000,__
+packet,476.476000,__
+packet,476.559000,__
+packet,476.768000,__
+packet,476.685000,__
+packet,476.643000,__
+packet,476.726000,__
+packet,476.935000,__
+packet,476.851000,__
+packet,476.810000,__
+packet,476.893000,__
+packet,477.102000,__
+packet,477.018000,__
+packet,476.977000,__
+packet,477.060000,__
+packet,477.268000,__
+packet,477.185000,__
+packet,477.143000,__
+packet,477.227000,__
+packet,477.352000,__
+packet,477.310000,__
+packet,477.727000,__
+packet,477.519000,__
+packet,477.394000,__
+packet,477.435000,__
+packet,477.477000,__
+packet,477.560000,__
+packet,477.602000,__
+packet,477.644000,__
+packet,477.686000,__
+packet,477.769000,K_
+packet,477.936000,__
+packet,477.852000,__
+packet,477.811000,__
+packet,477.894000,__
+packet,478.228000,__
+packet,478.061000,__
+packet,477.978000,__
+packet,478.019000,__
+packet,478.103000,__
+packet,478.144000,__
+packet,478.186000,__
+packet,478.311000,__
+packet,478.269000,__
+packet,478.645000,__
+packet,478.478000,__
+packet,478.353000,__
+packet,478.395000,__
+packet,478.436000,__
+packet,478.520000,__
+packet,478.561000,__
+packet,478.603000,__
+packet,479.020000,__
+packet,478.812000,__
+packet,478.687000,__
+packet,478.728000,__
+packet,478.770000,__
+packet,478.853000,__
+packet,478.895000,__
+packet,478.937000,__
+packet,478.979000,__
+packet,479.187000,__
+packet,479.104000,__
+packet,479.062000,__
+packet,479.145000,__
+packet,479.396000,__
+packet,479.270000,__
+packet,479.229000,__
+packet,479.312000,__
+packet,479.354000,__
+packet,479.437000,__
+packet,479.646000,__
+packet,479.521000,__
+packet,479.479000,__
+packet,479.562000,__
+packet,479.604000,__
+packet,480.021000,__
+packet,479.813000,__
+packet,479.688000,__
+packet,479.729000,__
+packet,479.771000,__
+packet,479.854000,__
+packet,479.896000,__
+packet,479.938000,__
+packet,479.980000,__
+packet,480.355000,__
+packet,480.188000,__
+packet,480.063000,__
+packet,480.105000,__
+packet,480.146000,__
+packet,480.230000,__
+packet,480.271000,__
+packet,480.313000,__
+packet,480.689000,__
+packet,480.522000,__
+packet,480.397000,__
+packet,480.438000,__
+packet,480.480000,__
+packet,480.563000,__
+packet,480.605000,__
+packet,480.647000,__
+packet,480.814000,__
+packet,480.730000,__
+packet,480.772000,__
+packet,480.855000,K_
+packet,481.022000,__
+packet,480.939000,__
+packet,480.897000,__
+packet,480.981000,__
+packet,481.189000,__
+packet,481.106000,__
+packet,481.064000,__
+packet,481.147000,__
+packet,481.398000,__
+packet,481.272000,__
+packet,481.231000,__
+packet,481.314000,__
+packet,481.356000,__
+packet,481.481000,__
+packet,481.439000,__
+packet,481.523000,__
+packet,481.773000,__
+packet,481.648000,__
+packet,481.564000,__
+packet,481.606000,__
+packet,481.690000,__
+packet,481.731000,__
+packet,481.940000,__
+packet,481.856000,__
+packet,481.815000,__
+packet,481.898000,__
+packet,482.148000,__
+packet,482.023000,__
+packet,481.982000,__
+packet,482.065000,__
+packet,482.107000,__
+packet,482.399000,__
+packet,482.273000,__
+packet,482.190000,__
+packet,482.232000,__
+packet,482.315000,__
+packet,482.357000,__
+packet,482.440000,K_
+packet,482.816000,__
+packet,482.607000,__
+packet,482.482000,__
+packet,482.524000,__
+packet,482.565000,__
+packet,482.649000,__
+packet,482.691000,__
+packet,482.732000,__
+packet,482.774000,__
+packet,483.191000,__
+packet,482.983000,__
+packet,482.857000,__
+packet,482.899000,__
+packet,482.941000,__
+packet,483.024000,__
+packet,483.066000,__
+packet,483.108000,__
+packet,483.149000,__
+packet,483.358000,__
+packet,483.274000,__
+packet,483.233000,__
+packet,483.316000,__
+packet,483.441000,__
+packet,483.400000,__
+packet,483.483000,__
+packet,483.525000,__
+packet,483.692000,__
+packet,483.608000,__
+packet,483.566000,__
+packet,483.650000,__
+packet,483.817000,__
+packet,483.733000,__
+packet,483.775000,__
+packet,483.858000,__
+packet,483.942000,__
+packet,483.900000,__
+packet,484.109000,__
+packet,484.025000,__
+packet,483.984000,__
+packet,484.067000,__
+packet,484.275000,__
+packet,484.192000,__
+packet,484.150000,__
+packet,484.234000,__
+packet,484.442000,__
+packet,484.359000,__
+packet,484.317000,__
+packet,484.401000,__
+packet,484.567000,__
+packet,484.484000,__
+packet,484.526000,__
+packet,484.818000,__
+packet,484.693000,__
+packet,484.609000,__
+packet,484.651000,__
+packet,484.734000,__
+packet,484.776000,__
+packet,484.943000,__
+packet,484.859000,__
+packet,484.901000,__
+packet,485.068000,__
+packet,484.985000,__
+packet,485.026000,__
+packet,485.110000,K_
+packet,485.151000,__
+packet,485.318000,__
+packet,485.235000,__
+packet,485.193000,__
+packet,485.276000,__
+packet,485.360000,__
+packet,485.443000,__
+packet,485.402000,__
+packet,485.610000,__
+packet,485.527000,__
+packet,485.485000,__
+packet,485.568000,__
+packet,485.819000,__
+packet,485.694000,__
+packet,485.652000,__
+packet,485.735000,__
+packet,485.777000,__
+packet,486.069000,__
+packet,485.944000,__
+packet,485.860000,__
+packet,485.902000,__
+packet,485.986000,__
+packet,486.027000,__
+packet,486.111000,__
+packet,486.403000,__
+packet,486.236000,__
+packet,486.152000,__
+packet,486.194000,__
+packet,486.277000,__
+packet,486.319000,__
+packet,486.361000,__
+packet,486.444000,K_
+packet,486.653000,__
+packet,486.528000,__
+packet,486.486000,__
+packet,486.569000,__
+packet,486.611000,__
+packet,486.736000,__
+packet,486.695000,__
+packet,486.903000,__
+packet,486.820000,__
+packet,486.778000,__
+packet,486.861000,__
+packet,487.112000,__
+packet,486.987000,__
+packet,486.945000,__
+packet,487.028000,__
+packet,487.070000,__
+packet,487.445000,__
+packet,487.278000,__
+packet,487.153000,__
+packet,487.195000,__
+packet,487.237000,__
+packet,487.320000,__
+packet,487.362000,__
+packet,487.404000,__
+packet,487.696000,__
+packet,487.570000,__
+packet,487.487000,__
+packet,487.529000,__
+packet,487.612000,__
+packet,487.654000,__
+packet,487.904000,__
+packet,487.779000,__
+packet,487.737000,__
+packet,487.821000,__
+packet,487.862000,__
+packet,488.154000,__
+packet,488.029000,__
+packet,487.946000,__
+packet,487.988000,__
+packet,488.071000,__
+packet,488.113000,__
+packet,488.405000,__
+packet,488.279000,__
+packet,488.196000,__
+packet,488.238000,__
+packet,488.321000,__
+packet,488.363000,__
+packet,488.571000,__
+packet,488.488000,__
+packet,488.446000,__
+packet,488.530000,__
+packet,488.822000,__
+packet,488.697000,__
+packet,488.613000,__
+packet,488.655000,__
+packet,488.738000,__
+packet,488.780000,__
+packet,488.947000,__
+packet,488.863000,__
+packet,488.905000,__
+packet,489.280000,__
+packet,489.114000,__
+packet,488.989000,__
+packet,489.030000,__
+packet,489.072000,__
+packet,489.155000,__
+packet,489.197000,__
+packet,489.239000,__
+packet,489.531000,__
+packet,489.406000,__
+packet,489.322000,__
+packet,489.364000,__
+packet,489.447000,__
+packet,489.489000,__
+packet,489.823000,__
+packet,489.656000,__
+packet,489.572000,__
+packet,489.614000,__
+packet,489.698000,__
+packet,489.739000,__
+packet,489.781000,__
+packet,489.948000,__
+packet,489.864000,__
+packet,489.906000,__
+packet,490.073000,__
+packet,489.990000,__
+packet,490.031000,__
+packet,490.198000,__
+packet,490.115000,__
+packet,490.156000,__
+packet,490.448000,__
+packet,490.323000,__
+packet,490.240000,__
+packet,490.281000,__
+packet,490.365000,__
+packet,490.407000,__
+packet,490.490000,__
+packet,490.532000,K_
+packet,490.573000,__
+packet,490.824000,__
+packet,490.699000,__
+packet,490.615000,__
+packet,490.657000,__
+packet,490.740000,__
+packet,490.782000,__
+packet,491.032000,__
+packet,490.907000,__
+packet,490.865000,__
+packet,490.949000,__
+packet,490.991000,__
+packet,491.199000,__
+packet,491.116000,__
+packet,491.074000,__
+packet,491.157000,__
+packet,491.324000,__
+packet,491.241000,__
+packet,491.282000,__
+packet,491.658000,__
+packet,491.491000,__
+packet,491.366000,__
+packet,491.408000,__
+packet,491.449000,__
+packet,491.533000,__
+packet,491.574000,__
+packet,491.616000,__
+packet,491.700000,__
+packet,491.908000,__
+packet,491.783000,__
+packet,491.741000,__
+packet,491.825000,__
+packet,491.866000,__
+packet,492.033000,__
+packet,491.950000,__
+packet,491.992000,__
+packet,492.409000,__
+packet,492.200000,__
+packet,492.075000,__
+packet,492.117000,__
+packet,492.158000,__
+packet,492.242000,__
+packet,492.283000,__
+packet,492.325000,__
+packet,492.367000,__
+packet,492.659000,__
+packet,492.534000,__
+packet,492.450000,__
+packet,492.492000,__
+packet,492.575000,__
+packet,492.617000,__
+packet,492.909000,__
+packet,492.784000,__
+packet,492.701000,__
+packet,492.742000,__
+packet,492.826000,__
+packet,492.867000,__
+packet,493.159000,__
+packet,493.034000,__
+packet,492.951000,__
+packet,492.993000,__
+packet,493.076000,__
+packet,493.118000,__
+packet,493.368000,__
+packet,493.243000,__
+packet,493.201000,__
+packet,493.284000,__
+packet,493.326000,__
+packet,493.451000,__
+packet,493.410000,__
+packet,493.660000,__
+packet,493.535000,__
+packet,493.493000,__
+packet,493.576000,__
+packet,493.618000,__
+packet,493.910000,__
+packet,493.785000,__
+packet,493.702000,__
+packet,493.743000,__
+packet,493.827000,__
+packet,493.868000,__
+packet,494.119000,__
+packet,493.994000,__
+packet,493.952000,__
+packet,494.035000,__
+packet,494.077000,__
+packet,494.327000,__
+packet,494.202000,__
+packet,494.160000,__
+packet,494.244000,__
+packet,494.285000,__
+packet,494.452000,__
+packet,494.369000,__
+packet,494.411000,__
+packet,494.661000,__
+packet,494.536000,__
+packet,494.494000,__
+packet,494.577000,__
+packet,494.619000,__
+packet,494.786000,__
+packet,494.703000,__
+packet,494.744000,__
+packet,494.911000,__
+packet,494.828000,__
+packet,494.869000,__
+packet,495.161000,__
+packet,495.036000,__
+packet,494.953000,__
+packet,494.995000,__
+packet,495.078000,__
+packet,495.120000,__
+packet,495.328000,__
+packet,495.245000,__
+packet,495.203000,__
+packet,495.286000,__
+packet,495.495000,__
+packet,495.412000,__
+packet,495.370000,__
+packet,495.453000,__
+packet,495.537000,K_
+packet,495.578000,__
+packet,495.745000,__
+packet,495.662000,__
+packet,495.620000,__
+packet,495.704000,__
+packet,495.912000,__
+packet,495.829000,__
+packet,495.787000,__
+packet,495.870000,__
+packet,496.079000,__
+packet,495.996000,__
+packet,495.954000,__
+packet,496.037000,__
+packet,496.204000,__
+packet,496.121000,__
+packet,496.162000,__
+packet,496.287000,__
+packet,496.246000,__
+packet,496.454000,__
+packet,496.371000,__
+packet,496.329000,__
+packet,496.413000,__
+packet,496.663000,__
+packet,496.538000,__
+packet,496.496000,__
+packet,496.579000,__
+packet,496.621000,__
+packet,496.705000,__
+packet,496.913000,__
+packet,496.788000,__
+packet,496.746000,__
+packet,496.830000,__
+packet,496.871000,__
+packet,496.997000,__
+packet,496.955000,__
+packet,497.038000,K_
+packet,497.205000,__
+packet,497.122000,__
+packet,497.080000,__
+packet,497.163000,__
+packet,497.580000,__
+packet,497.372000,__
+packet,497.247000,__
+packet,497.288000,__
+packet,497.330000,__
+packet,497.414000,__
+packet,497.455000,__
+packet,497.497000,__
+packet,497.539000,__
+packet,497.747000,__
+packet,497.664000,__
+packet,497.622000,__
+packet,497.706000,__
+packet,497.914000,__
+packet,497.831000,__
+packet,497.789000,__
+packet,497.872000,__
+packet,498.039000,__
+packet,497.956000,__
+packet,497.998000,__
+packet,498.248000,__
+packet,498.123000,__
+packet,498.081000,__
+packet,498.164000,__
+packet,498.206000,__
+packet,498.289000,__
+packet,498.456000,__
+packet,498.373000,__
+packet,498.331000,__
+packet,498.415000,__
+packet,498.623000,__
+packet,498.540000,__
+packet,498.498000,__
+packet,498.581000,__
+packet,498.790000,__
+packet,498.707000,__
+packet,498.665000,__
+packet,498.748000,__
+packet,498.957000,__
+packet,498.873000,__
+packet,498.832000,__
+packet,498.915000,__
+packet,499.165000,__
+packet,499.040000,__
+packet,498.999000,__
+packet,499.082000,__
+packet,499.124000,__
+packet,499.332000,__
+packet,499.249000,__
+packet,499.207000,__
+packet,499.290000,__
+packet,499.457000,__
+packet,499.374000,__
+packet,499.416000,__
+packet,499.582000,__
+packet,499.499000,__
+packet,499.541000,__
+packet,499.749000,__
+packet,499.666000,__
+packet,499.624000,__
+packet,499.708000,__
+packet,499.874000,__
+packet,499.791000,__
+packet,499.833000,__
+packet,500.083000,__
+packet,499.958000,__
+packet,499.916000,__
+packet,500.000000,__
+packet,500.041000,__
+packet,500.250000,__
+packet,500.166000,__
+packet,500.125000,__
+packet,500.208000,__
+packet,500.375000,__
+packet,500.291000,__
+packet,500.333000,__
+packet,500.542000,__
+packet,500.458000,__
+packet,500.417000,__
+packet,500.500000,__
+packet,500.709000,__
+packet,500.625000,__
+packet,500.583000,__
+packet,500.667000,__
+packet,500.917000,__
+packet,500.792000,__
+packet,500.750000,__
+packet,500.834000,__
+packet,500.875000,__
+packet,501.042000,__
+packet,500.959000,__
+packet,501.001000,__
+packet,501.209000,__
+packet,501.126000,__
+packet,501.084000,__
+packet,501.167000,__
+packet,501.376000,__
+packet,501.292000,__
+packet,501.251000,__
+packet,501.334000,__
+packet,501.501000,__
+packet,501.418000,__
+packet,501.459000,__
+packet,501.626000,__
+packet,501.543000,__
+packet,501.584000,__
+packet,501.793000,__
+packet,501.710000,__
+packet,501.668000,__
+packet,501.751000,__
+packet,501.918000,__
+packet,501.835000,__
+packet,501.876000,__
+packet,502.168000,__
+packet,502.043000,__
+packet,501.960000,__
+packet,502.002000,__
+packet,502.085000,__
+packet,502.127000,__
+packet,502.460000,__
+packet,502.293000,__
+packet,502.210000,__
+packet,502.252000,__
+packet,502.335000,__
+packet,502.377000,__
+packet,502.419000,__
+packet,502.627000,__
+packet,502.544000,__
+packet,502.502000,__
+packet,502.585000,__
+packet,502.794000,__
+packet,502.711000,__
+packet,502.669000,__
+packet,502.752000,__
+packet,503.044000,__
+packet,502.919000,__
+packet,502.836000,__
+packet,502.877000,__
+packet,502.961000,__
+packet,503.003000,__
+packet,503.086000,__
+packet,503.211000,__
+packet,503.128000,__
+packet,503.169000,__
+packet,503.378000,__
+packet,503.294000,__
+packet,503.253000,__
+packet,503.336000,__
+packet,503.545000,__
+packet,503.461000,__
+packet,503.420000,__
+packet,503.503000,__
+packet,503.795000,__
+packet,503.670000,__
+packet,503.586000,__
+packet,503.628000,__
+packet,503.712000,__
+packet,503.753000,__
+packet,503.920000,__
+packet,503.837000,__
+packet,503.878000,__
+packet,504.087000,__
+packet,504.004000,__
+packet,503.962000,__
+packet,504.045000,__
+packet,504.212000,__
+packet,504.129000,__
+packet,504.170000,__
+packet,504.421000,__
+packet,504.295000,__
+packet,504.254000,__
+packet,504.337000,__
+packet,504.379000,__
+packet,504.713000,__
+packet,504.546000,__
+packet,504.462000,__
+packet,504.504000,__
+packet,504.587000,__
+packet,504.629000,__
+packet,504.671000,__
+packet,504.921000,__
+packet,504.796000,__
+packet,504.754000,__
+packet,504.838000,__
+packet,504.879000,__
+packet,505.088000,__
+packet,505.005000,__
+packet,504.963000,__
+packet,505.046000,__
+packet,505.296000,__
+packet,505.171000,__
+packet,505.130000,__
+packet,505.213000,__
+packet,505.255000,__
+packet,505.422000,__
+packet,505.338000,__
+packet,505.380000,__
+packet,505.588000,__
+packet,505.505000,__
+packet,505.463000,__
+packet,505.547000,__
+packet,505.839000,__
+packet,505.714000,__
+packet,505.630000,__
+packet,505.672000,__
+packet,505.755000,__
+packet,505.797000,__
+packet,505.964000,__
+packet,505.880000,__
+packet,505.922000,__
+packet,506.214000,__
+packet,506.089000,__
+packet,506.006000,__
+packet,506.047000,__
+packet,506.131000,__
+packet,506.172000,__
+packet,506.339000,__
+packet,506.256000,__
+packet,506.297000,__
+packet,506.381000,__
+packet,506.423000,__
+packet,506.464000,__
+packet,506.506000,__
+packet,506.548000,__
+packet,506.589000,__
+packet,506.631000,__
+packet,506.673000,__
+packet,506.715000,__
+packet,506.756000,__
+packet,506.798000,__
+packet,506.840000,__
+packet,506.881000,__
+packet,506.923000,__
+packet,506.965000,__
+packet,507.048000,__
+packet,507.007000,__
+packet,507.090000,__
+packet,507.132000,__
+packet,507.215000,__
+packet,507.173000,__
+packet,507.257000,__
+packet,507.424000,__
+packet,507.340000,__
+packet,507.298000,__
+packet,507.382000,__
+packet,507.465000,K_
+packet,507.632000,__
+packet,507.549000,__
+packet,507.507000,__
+packet,507.590000,__
+packet,507.799000,__
+packet,507.716000,__
+packet,507.674000,__
+packet,507.757000,__
+packet,507.966000,__
+packet,507.882000,__
+packet,507.841000,__
+packet,507.924000,__
+packet,508.049000,__
+packet,508.008000,__
+packet,508.091000,__
+packet,508.174000,__
+packet,508.133000,__
+packet,508.383000,__
+packet,508.258000,__
+packet,508.216000,__
+packet,508.299000,__
+packet,508.341000,__
+packet,508.550000,__
+packet,508.466000,__
+packet,508.425000,__
+packet,508.508000,__
+packet,508.591000,__
+packet,508.717000,__
+packet,508.633000,__
+packet,508.675000,__
+packet,508.883000,__
+packet,508.800000,__
+packet,508.758000,__
+packet,508.842000,__
+packet,508.925000,__
+packet,509.134000,__
+packet,509.009000,__
+packet,508.967000,__
+packet,509.050000,__
+packet,509.092000,__
+packet,509.300000,__
+packet,509.217000,__
+packet,509.175000,__
+packet,509.259000,__
+packet,509.467000,__
+packet,509.384000,__
+packet,509.342000,__
+packet,509.426000,__
+packet,509.509000,K_
+packet,509.676000,__
+packet,509.592000,__
+packet,509.551000,__
+packet,509.634000,__
+packet,509.884000,__
+packet,509.759000,__
+packet,509.718000,__
+packet,509.801000,__
+packet,509.843000,__
+packet,510.010000,__
+packet,509.926000,__
+packet,509.968000,__
+packet,510.176000,__
+packet,510.093000,__
+packet,510.051000,__
+packet,510.135000,__
+packet,510.343000,__
+packet,510.260000,__
+packet,510.218000,__
+packet,510.301000,__
+packet,510.593000,__
+packet,510.468000,__
+packet,510.385000,__
+packet,510.427000,__
+packet,510.510000,__
+packet,510.552000,__
+packet,510.844000,__
+packet,510.719000,__
+packet,510.635000,__
+packet,510.677000,__
+packet,510.760000,__
+packet,510.802000,__
+packet,510.885000,__
+packet,510.927000,K_
+packet,510.969000,__
+packet,511.219000,__
+packet,511.094000,__
+packet,511.011000,__
+packet,511.052000,__
+packet,511.136000,__
+packet,511.177000,__
+packet,511.386000,__
+packet,511.302000,__
+packet,511.261000,__
+packet,511.344000,__
+packet,511.720000,__
+packet,511.553000,__
+packet,511.428000,__
+packet,511.469000,__
+packet,511.511000,__
+packet,511.594000,__
+packet,511.636000,__
+packet,511.678000,__
+packet,511.845000,__
+packet,511.761000,__
+packet,511.803000,__
+packet,512.012000,__
+packet,511.928000,__
+packet,511.886000,__
+packet,511.970000,__
+packet,512.178000,__
+packet,512.095000,__
+packet,512.053000,__
+packet,512.137000,__
+packet,512.220000,__
+packet,512.595000,__
+packet,512.387000,__
+packet,512.262000,__
+packet,512.303000,__
+packet,512.345000,__
+packet,512.429000,__
+packet,512.470000,__
+packet,512.512000,__
+packet,512.554000,__
+packet,512.762000,__
+packet,512.679000,__
+packet,512.637000,__
+packet,512.721000,__
+packet,512.929000,__
+packet,512.846000,__
+packet,512.804000,__
+packet,512.887000,__
+packet,512.971000,__
+packet,513.138000,__
+packet,513.054000,__
+packet,513.013000,__
+packet,513.096000,__
+packet,513.263000,__
+packet,513.179000,__
+packet,513.221000,__
+packet,513.471000,__
+packet,513.346000,__
+packet,513.304000,__
+packet,513.388000,__
+packet,513.430000,__
+packet,513.680000,__
+packet,513.555000,__
+packet,513.513000,__
+packet,513.596000,__
+packet,513.638000,__
+packet,513.972000,__
+packet,513.805000,__
+packet,513.722000,__
+packet,513.763000,__
+packet,513.847000,__
+packet,513.888000,__
+packet,513.930000,__
+packet,514.222000,__
+packet,514.097000,__
+packet,514.014000,__
+packet,514.055000,__
+packet,514.139000,__
+packet,514.180000,__
+packet,514.431000,__
+packet,514.305000,__
+packet,514.264000,__
+packet,514.347000,__
+packet,514.389000,__
+packet,514.556000,__
+packet,514.472000,__
+packet,514.514000,__
+packet,514.806000,__
+packet,514.681000,__
+packet,514.597000,__
+packet,514.639000,__
+packet,514.723000,__
+packet,514.764000,__
+packet,514.931000,__
+packet,514.848000,__
+packet,514.889000,__
+packet,515.098000,__
+packet,515.015000,__
+packet,514.973000,__
+packet,515.056000,__
+packet,515.306000,__
+packet,515.181000,__
+packet,515.140000,__
+packet,515.223000,__
+packet,515.265000,__
+packet,515.432000,__
+packet,515.348000,__
+packet,515.390000,__
+packet,515.807000,__
+packet,515.598000,__
+packet,515.473000,__
+packet,515.515000,__
+packet,515.557000,__
+packet,515.640000,__
+packet,515.682000,__
+packet,515.724000,__
+packet,515.765000,__
+packet,516.057000,__
+packet,515.932000,__
+packet,515.849000,__
+packet,515.890000,__
+packet,515.974000,__
+packet,516.016000,__
+packet,516.099000,__
+packet,516.266000,__
+packet,516.182000,__
+packet,516.141000,__
+packet,516.224000,__
+packet,516.349000,__
+packet,516.307000,__
+packet,516.558000,__
+packet,516.433000,__
+packet,516.391000,__
+packet,516.474000,__
+packet,516.516000,__
+packet,516.683000,__
+packet,516.599000,__
+packet,516.641000,__
+packet,516.808000,__
+packet,516.725000,__
+packet,516.766000,__
+packet,516.933000,__
+packet,516.850000,__
+packet,516.891000,__
+packet,517.100000,__
+packet,517.017000,__
+packet,516.975000,__
+packet,517.058000,__
+packet,517.308000,__
+packet,517.183000,__
+packet,517.142000,__
+packet,517.225000,__
+packet,517.267000,__
+packet,517.475000,__
+packet,517.392000,__
+packet,517.350000,__
+packet,517.434000,__
+packet,517.684000,__
+packet,517.559000,__
+packet,517.517000,__
+packet,517.600000,__
+packet,517.642000,__
+packet,517.892000,__
+packet,517.767000,__
+packet,517.726000,__
+packet,517.809000,__
+packet,517.851000,__
+packet,518.226000,__
+packet,518.059000,__
+packet,517.934000,__
+packet,517.976000,__
+packet,518.018000,__
+packet,518.101000,__
+packet,518.143000,__
+packet,518.184000,__
+packet,518.309000,__
+packet,518.268000,__
+packet,518.435000,__
+packet,518.351000,__
+packet,518.393000,__
+packet,518.560000,__
+packet,518.476000,__
+packet,518.518000,__
+packet,518.601000,K_
+packet,518.727000,__
+packet,518.643000,__
+packet,518.685000,__
+packet,518.810000,__
+packet,518.768000,__
+packet,518.977000,__
+packet,518.893000,__
+packet,518.852000,__
+packet,518.935000,__
+packet,519.310000,__
+packet,519.144000,__
+packet,519.019000,__
+packet,519.060000,__
+packet,519.102000,__
+packet,519.185000,__
+packet,519.227000,__
+packet,519.269000,__
+packet,519.352000,__
+packet,519.436000,__
+packet,519.394000,__
+packet,519.561000,__
+packet,519.477000,__
+packet,519.519000,__
+packet,519.602000,__
+packet,519.769000,__
+packet,519.686000,__
+packet,519.644000,__
+packet,519.728000,__
+packet,519.936000,__
+packet,519.853000,__
+packet,519.811000,__
+packet,519.894000,__
+packet,520.103000,__
+packet,520.020000,__
+packet,519.978000,__
+packet,520.061000,__
+packet,520.311000,__
+packet,520.186000,__
+packet,520.145000,__
+packet,520.228000,__
+packet,520.270000,__
+packet,520.395000,__
+packet,520.353000,__
+packet,520.437000,K_
+packet,520.603000,__
+packet,520.520000,__
+packet,520.478000,__
+packet,520.562000,__
+packet,520.895000,__
+packet,520.729000,__
+packet,520.645000,__
+packet,520.687000,__
+packet,520.770000,__
+packet,520.812000,__
+packet,520.854000,__
+packet,521.271000,__
+packet,521.062000,__
+packet,520.937000,__
+packet,520.979000,__
+packet,521.021000,__
+packet,521.104000,__
+packet,521.146000,__
+packet,521.187000,__
+packet,521.229000,__
+packet,521.479000,__
+packet,521.354000,__
+packet,521.312000,__
+packet,521.396000,__
+packet,521.438000,__
+packet,521.688000,__
+packet,521.563000,__
+packet,521.521000,__
+packet,521.604000,__
+packet,521.646000,__
+packet,521.855000,__
+packet,521.771000,__
+packet,521.730000,__
+packet,521.813000,__
+packet,521.938000,__
+packet,521.896000,__
+packet,522.105000,__
+packet,522.022000,__
+packet,521.980000,__
+packet,522.063000,__
+packet,522.355000,__
+packet,522.230000,__
+packet,522.147000,__
+packet,522.188000,__
+packet,522.272000,__
+packet,522.313000,__
+packet,522.564000,__
+packet,522.439000,__
+packet,522.397000,__
+packet,522.480000,__
+packet,522.522000,__
+packet,522.605000,__
+packet,522.731000,__
+packet,522.647000,__
+packet,522.689000,__
+packet,522.772000,K_
+packet,522.856000,__
+packet,522.814000,__
+packet,522.981000,__
+packet,522.897000,__
+packet,522.939000,__
+packet,523.314000,__
+packet,523.148000,__
+packet,523.023000,__
+packet,523.064000,__
+packet,523.106000,__
+packet,523.189000,__
+packet,523.231000,__
+packet,523.273000,__
+packet,523.440000,__
+packet,523.356000,__
+packet,523.398000,__
+packet,523.565000,__
+packet,523.481000,__
+packet,523.523000,__
+packet,523.648000,__
+packet,523.606000,__
+packet,523.857000,__
+packet,523.732000,__
+packet,523.690000,__
+packet,523.773000,__
+packet,523.815000,__
+packet,524.024000,__
+packet,523.940000,__
+packet,523.898000,__
+packet,523.982000,__
+packet,524.232000,__
+packet,524.107000,__
+packet,524.065000,__
+packet,524.149000,__
+packet,524.190000,__
+packet,524.274000,K_
+packet,524.315000,__
+packet,524.357000,__
+packet,524.441000,__
+packet,524.399000,__
+packet,524.607000,__
+packet,524.524000,__
+packet,524.482000,__
+packet,524.566000,__
+packet,524.816000,__
+packet,524.691000,__
+packet,524.649000,__
+packet,524.733000,__
+packet,524.774000,__
+packet,524.941000,__
+packet,524.858000,__
+packet,524.899000,__
+packet,524.983000,__
+packet,525.025000,__
+packet,525.233000,__
+packet,525.108000,__
+packet,525.066000,__
+packet,525.150000,__
+packet,525.191000,__
+packet,525.358000,__
+packet,525.275000,__
+packet,525.316000,__
+packet,525.525000,__
+packet,525.442000,__
+packet,525.400000,__
+packet,525.483000,__
+packet,525.650000,__
+packet,525.567000,__
+packet,525.608000,__
+packet,525.817000,__
+packet,525.734000,__
+packet,525.692000,__
+packet,525.775000,__
+packet,526.151000,__
+packet,525.984000,__
+packet,525.859000,__
+packet,525.900000,__
+packet,525.942000,__
+packet,526.026000,__
+packet,526.067000,__
+packet,526.109000,__
+packet,526.192000,__
+packet,526.234000,__
+packet,526.276000,__
+packet,526.443000,__
+packet,526.359000,__
+packet,526.317000,__
+packet,526.401000,__
+packet,526.651000,__
+packet,526.526000,__
+packet,526.484000,__
+packet,526.568000,__
+packet,526.609000,__
+packet,526.693000,K_
+packet,526.860000,__
+packet,526.776000,__
+packet,526.735000,__
+packet,526.818000,__
+packet,527.152000,__
+packet,526.985000,__
+packet,526.901000,__
+packet,526.943000,__
+packet,527.027000,__
+packet,527.068000,__
+packet,527.110000,__
+packet,527.318000,__
+packet,527.235000,__
+packet,527.193000,__
+packet,527.277000,__
+packet,527.569000,__
+packet,527.444000,__
+packet,527.360000,__
+packet,527.402000,__
+packet,527.485000,__
+packet,527.527000,__
+packet,527.694000,__
+packet,527.610000,__
+packet,527.652000,__
+packet,527.861000,__
+packet,527.777000,__
+packet,527.736000,__
+packet,527.819000,__
+packet,528.236000,__
+packet,528.028000,__
+packet,527.902000,__
+packet,527.944000,__
+packet,527.986000,__
+packet,528.069000,__
+packet,528.111000,__
+packet,528.153000,__
+packet,528.194000,__
+packet,528.570000,__
+packet,528.403000,__
+packet,528.278000,__
+packet,528.319000,__
+packet,528.361000,__
+packet,528.445000,__
+packet,528.486000,__
+packet,528.528000,__
+packet,528.737000,__
+packet,528.653000,__
+packet,528.611000,__
+packet,528.695000,__
+packet,528.862000,__
+packet,528.778000,__
+packet,528.820000,__
+packet,529.070000,__
+packet,528.945000,__
+packet,528.903000,__
+packet,528.987000,__
+packet,529.029000,__
+packet,529.362000,__
+packet,529.195000,__
+packet,529.112000,__
+packet,529.154000,__
+packet,529.237000,__
+packet,529.279000,__
+packet,529.320000,__
+packet,529.446000,__
+packet,529.404000,__
+packet,529.821000,__
+packet,529.612000,__
+packet,529.487000,__
+packet,529.529000,__
+packet,529.571000,__
+packet,529.654000,__
+packet,529.696000,__
+packet,529.738000,__
+packet,529.779000,__
+packet,530.155000,__
+packet,529.988000,__
+packet,529.863000,__
+packet,529.904000,__
+packet,529.946000,__
+packet,530.030000,__
+packet,530.071000,__
+packet,530.113000,__
+packet,530.488000,__
+packet,530.321000,__
+packet,530.196000,__
+packet,530.238000,__
+packet,530.280000,__
+packet,530.363000,__
+packet,530.405000,__
+packet,530.447000,__
+packet,530.739000,__
+packet,530.613000,__
+packet,530.530000,__
+packet,530.572000,__
+packet,530.655000,__
+packet,530.697000,__
+packet,531.114000,__
+packet,530.905000,__
+packet,530.780000,__
+packet,530.822000,__
+packet,530.864000,__
+packet,530.947000,__
+packet,530.989000,__
+packet,531.031000,__
+packet,531.072000,__
+packet,531.322000,__
+packet,531.197000,__
+packet,531.156000,__
+packet,531.239000,__
+packet,531.281000,__
+packet,531.573000,__
+packet,531.448000,__
+packet,531.364000,__
+packet,531.406000,__
+packet,531.489000,__
+packet,531.531000,__
+packet,531.698000,__
+packet,531.614000,__
+packet,531.656000,__
+packet,531.906000,__
+packet,531.781000,__
+packet,531.740000,__
+packet,531.823000,__
+packet,531.865000,__
+packet,532.073000,__
+packet,531.990000,__
+packet,531.948000,__
+packet,532.032000,__
+packet,532.240000,__
+packet,532.157000,__
+packet,532.115000,__
+packet,532.198000,__
+packet,532.323000,__
+packet,532.282000,__
+packet,532.490000,__
+packet,532.407000,__
+packet,532.365000,__
+packet,532.449000,__
+packet,532.657000,__
+packet,532.574000,__
+packet,532.532000,__
+packet,532.615000,__
+packet,532.824000,__
+packet,532.741000,__
+packet,532.699000,__
+packet,532.782000,__
+packet,532.991000,__
+packet,532.907000,__
+packet,532.866000,__
+packet,532.949000,__
+packet,533.074000,__
+packet,533.033000,__
+packet,533.199000,__
+packet,533.116000,__
+packet,533.158000,__
+packet,533.491000,__
+packet,533.324000,__
+packet,533.241000,__
+packet,533.283000,__
+packet,533.366000,__
+packet,533.408000,__
+packet,533.450000,__
+packet,533.658000,__
+packet,533.575000,__
+packet,533.533000,__
+packet,533.616000,__
+packet,533.825000,__
+packet,533.742000,__
+packet,533.700000,__
+packet,533.783000,__
+packet,534.159000,__
+packet,533.992000,__
+packet,533.867000,__
+packet,533.908000,__
+packet,533.950000,__
+packet,534.034000,__
+packet,534.075000,__
+packet,534.117000,__
+packet,534.200000,K_
+packet,534.367000,__
+packet,534.284000,__
+packet,534.242000,__
+packet,534.325000,__
+packet,534.576000,__
+packet,534.451000,__
+packet,534.409000,__
+packet,534.492000,__
+packet,534.534000,__
+packet,534.743000,__
+packet,534.659000,__
+packet,534.617000,__
+packet,534.701000,__
+packet,534.868000,__
+packet,534.784000,__
+packet,534.826000,__
+packet,535.076000,__
+packet,534.951000,__
+packet,534.909000,__
+packet,534.993000,__
+packet,535.035000,__
+packet,535.243000,__
+packet,535.160000,__
+packet,535.118000,__
+packet,535.201000,__
+packet,535.410000,__
+packet,535.326000,__
+packet,535.285000,__
+packet,535.368000,__
+packet,535.577000,__
+packet,535.493000,__
+packet,535.452000,__
+packet,535.535000,__
+packet,535.744000,__
+packet,535.660000,__
+packet,535.618000,__
+packet,535.702000,__
+packet,535.869000,__
+packet,535.785000,__
+packet,535.827000,__
+packet,536.077000,__
+packet,535.952000,__
+packet,535.910000,__
+packet,535.994000,__
+packet,536.036000,__
+packet,536.244000,__
+packet,536.161000,__
+packet,536.119000,__
+packet,536.202000,__
+packet,536.411000,__
+packet,536.327000,__
+packet,536.286000,__
+packet,536.369000,__
+packet,536.578000,__
+packet,536.494000,__
+packet,536.453000,__
+packet,536.536000,__
+packet,536.745000,__
+packet,536.661000,__
+packet,536.619000,__
+packet,536.703000,__
+packet,536.870000,__
+packet,536.786000,__
+packet,536.828000,__
+packet,537.037000,__
+packet,536.953000,__
+packet,536.911000,__
+packet,536.995000,__
+packet,537.203000,__
+packet,537.120000,__
+packet,537.078000,__
+packet,537.162000,__
+packet,537.328000,__
+packet,537.245000,__
+packet,537.287000,__
+packet,537.454000,__
+packet,537.370000,__
+packet,537.412000,__
+packet,537.620000,__
+packet,537.537000,__
+packet,537.495000,__
+packet,537.579000,__
+packet,537.787000,__
+packet,537.704000,__
+packet,537.662000,__
+packet,537.746000,__
+packet,538.121000,__
+packet,537.954000,__
+packet,537.829000,__
+packet,537.871000,__
+packet,537.912000,__
+packet,537.996000,__
+packet,538.038000,__
+packet,538.079000,__
+packet,538.329000,__
+packet,538.204000,__
+packet,538.163000,__
+packet,538.246000,__
+packet,538.288000,__
+packet,538.580000,__
+packet,538.455000,__
+packet,538.371000,__
+packet,538.413000,__
+packet,538.496000,__
+packet,538.538000,__
+packet,538.621000,__
+packet,538.788000,__
+packet,538.705000,__
+packet,538.663000,__
+packet,538.747000,__
+packet,538.872000,__
+packet,538.830000,__
+packet,539.164000,__
+packet,538.997000,__
+packet,538.913000,__
+packet,538.955000,__
+packet,539.039000,__
+packet,539.080000,__
+packet,539.122000,__
+packet,539.372000,__
+packet,539.247000,__
+packet,539.205000,__
+packet,539.289000,__
+packet,539.330000,__
+packet,539.581000,__
+packet,539.456000,__
+packet,539.414000,__
+packet,539.497000,__
+packet,539.539000,__
+packet,539.873000,__
+packet,539.706000,__
+packet,539.622000,__
+packet,539.664000,__
+packet,539.748000,__
+packet,539.789000,__
+packet,539.831000,__
+packet,540.040000,__
+packet,539.956000,__
+packet,539.914000,__
+packet,539.998000,__
+packet,540.206000,__
+packet,540.123000,__
+packet,540.081000,__
+packet,540.165000,__
+packet,540.457000,__
+packet,540.331000,__
+packet,540.248000,__
+packet,540.290000,__
+packet,540.373000,__
+packet,540.415000,__
+packet,540.790000,__
+packet,540.623000,__
+packet,540.498000,__
+packet,540.540000,__
+packet,540.582000,__
+packet,540.665000,__
+packet,540.707000,__
+packet,540.749000,__
+packet,540.999000,__
+packet,540.874000,__
+packet,540.832000,__
+packet,540.915000,__
+packet,540.957000,__
+packet,541.124000,__
+packet,541.041000,__
+packet,541.082000,__
+packet,541.207000,__
+packet,541.166000,__
+packet,541.499000,__
+packet,541.332000,__
+packet,541.249000,__
+packet,541.291000,__
+packet,541.374000,__
+packet,541.416000,__
+packet,541.458000,__
+packet,541.583000,__
+packet,541.541000,__
+packet,541.750000,__
+packet,541.666000,__
+packet,541.624000,__
+packet,541.708000,__
+packet,541.833000,__
+packet,541.791000,__
+packet,542.208000,__
+packet,542.000000,__
+packet,541.875000,__
+packet,541.916000,__
+packet,541.958000,__
+packet,542.042000,__
+packet,542.083000,__
+packet,542.125000,__
+packet,542.167000,__
+packet,542.417000,__
+packet,542.292000,__
+packet,542.250000,__
+packet,542.333000,__
+packet,542.375000,__
+packet,542.500000,__
+packet,542.459000,__
+packet,542.667000,__
+packet,542.584000,__
+packet,542.542000,__
+packet,542.625000,__
+packet,542.834000,__
+packet,542.751000,__
+packet,542.709000,__
+packet,542.792000,__
+packet,542.876000,__
+packet,543.043000,__
+packet,542.959000,__
+packet,542.917000,__
+packet,543.001000,__
+packet,543.126000,__
+packet,543.084000,__
+packet,543.293000,__
+packet,543.209000,__
+packet,543.168000,__
+packet,543.251000,__
+packet,543.334000,__
+packet,543.376000,K_
+packet,543.418000,__
+packet,543.460000,__
+packet,543.501000,__
+packet,543.543000,__
+packet,543.585000,__
+packet,543.626000,__
+packet,543.668000,__
+packet,543.710000,__
+packet,543.793000,__
+packet,543.752000,__
+packet,543.877000,__
+packet,543.835000,__
+packet,543.918000,__
+packet,544.002000,__
+packet,543.960000,__
+packet,544.085000,__
+packet,544.044000,__
+packet,544.210000,__
+packet,544.127000,__
+packet,544.169000,__
+packet,544.335000,__
+packet,544.252000,__
+packet,544.294000,__
+packet,544.461000,__
+packet,544.377000,__
+packet,544.419000,__
+packet,544.544000,__
+packet,544.502000,__
+packet,544.669000,__
+packet,544.586000,__
+packet,544.627000,__
+packet,544.711000,K_
+packet,544.794000,__
+packet,544.753000,__
+packet,544.836000,__
+packet,544.878000,__
+packet,544.919000,__
+packet,545.003000,__
+packet,544.961000,__
+packet,545.253000,__
+packet,545.128000,__
+packet,545.045000,__
+packet,545.086000,__
+packet,545.170000,__
+packet,545.211000,__
+packet,545.420000,__
+packet,545.336000,__
+packet,545.295000,__
+packet,545.378000,__
+packet,545.462000,__
+packet,545.670000,__
+packet,545.545000,__
+packet,545.503000,__
+packet,545.587000,__
+packet,545.628000,__
+packet,545.712000,__
+packet,545.754000,__
+packet,545.795000,__
+packet,545.837000,__
+packet,545.879000,__
+packet,545.962000,__
+packet,545.920000,__
+packet,546.004000,__
+packet,546.046000,__
+packet,546.087000,__
+packet,546.129000,__
+packet,546.171000,__
+packet,546.212000,__
+packet,546.296000,__
+packet,546.254000,__
+packet,546.337000,__
+packet,546.463000,__
+packet,546.379000,__
+packet,546.421000,__
+packet,546.629000,__
+packet,546.546000,__
+packet,546.504000,__
+packet,546.588000,__
+packet,546.838000,__
+packet,546.713000,__
+packet,546.671000,__
+packet,546.755000,__
+packet,546.796000,__
+packet,546.880000,__
+packet,547.005000,__
+packet,546.921000,__
+packet,546.963000,__
+packet,547.047000,K_
+packet,547.213000,__
+packet,547.130000,__
+packet,547.088000,__
+packet,547.172000,__
+packet,547.338000,__
+packet,547.255000,__
+packet,547.297000,__
+packet,547.380000,__
+packet,547.422000,__
+packet,547.714000,__
+packet,547.547000,__
+packet,547.464000,__
+packet,547.505000,__
+packet,547.589000,__
+packet,547.630000,__
+packet,547.672000,__
+packet,547.881000,__
+packet,547.797000,__
+packet,547.756000,__
+packet,547.839000,__
+packet,547.922000,__
+packet,547.964000,__
+packet,548.048000,__
+packet,548.006000,__
+packet,548.173000,__
+packet,548.089000,__
+packet,548.131000,__
+packet,548.339000,__
+packet,548.256000,__
+packet,548.214000,__
+packet,548.298000,__
+packet,548.381000,__
+packet,548.506000,__
+packet,548.423000,__
+packet,548.465000,__
+packet,548.673000,__
+packet,548.590000,__
+packet,548.548000,__
+packet,548.631000,__
+packet,548.882000,__
+packet,548.757000,__
+packet,548.715000,__
+packet,548.798000,__
+packet,548.840000,__
+packet,549.007000,__
+packet,548.923000,__
+packet,548.965000,__
+packet,549.174000,__
+packet,549.090000,__
+packet,549.049000,__
+packet,549.132000,__
+packet,549.382000,__
+packet,549.257000,__
+packet,549.215000,__
+packet,549.299000,__
+packet,549.340000,__
+packet,549.632000,__
+packet,549.507000,__
+packet,549.424000,__
+packet,549.466000,__
+packet,549.549000,__
+packet,549.591000,__
+packet,549.758000,__
+packet,549.674000,__
+packet,549.716000,__
+packet,549.966000,__
+packet,549.841000,__
+packet,549.799000,__
+packet,549.883000,__
+packet,549.924000,__
+packet,550.091000,__
+packet,550.008000,__
+packet,550.050000,__
+packet,550.300000,__
+packet,550.175000,__
+packet,550.133000,__
+packet,550.216000,__
+packet,550.258000,__
+packet,550.383000,__
+packet,550.341000,__
+packet,550.508000,__
+packet,550.425000,__
+packet,550.467000,__
+packet,550.675000,__
+packet,550.592000,__
+packet,550.550000,__
+packet,550.633000,__
+packet,550.842000,__
+packet,550.759000,__
+packet,550.717000,__
+packet,550.800000,__
+packet,551.009000,__
+packet,550.925000,__
+packet,550.884000,__
+packet,550.967000,__
+packet,551.176000,__
+packet,551.092000,__
+packet,551.051000,__
+packet,551.134000,__
+packet,551.342000,__
+packet,551.259000,__
+packet,551.217000,__
+packet,551.301000,__
+packet,551.509000,__
+packet,551.426000,__
+packet,551.384000,__
+packet,551.468000,__
+packet,551.801000,__
+packet,551.634000,__
+packet,551.551000,__
+packet,551.593000,__
+packet,551.676000,__
+packet,551.718000,__
+packet,551.760000,__
+packet,552.010000,__
+packet,551.885000,__
+packet,551.843000,__
+packet,551.926000,__
+packet,551.968000,__
+packet,552.052000,K_
+packet,552.177000,__
+packet,552.093000,__
+packet,552.135000,__
+packet,552.385000,__
+packet,552.260000,__
+packet,552.218000,__
+packet,552.302000,__
+packet,552.343000,__
+packet,552.469000,__
+packet,552.427000,__
+packet,552.844000,__
+packet,552.635000,__
+packet,552.510000,__
+packet,552.552000,__
+packet,552.594000,__
+packet,552.677000,__
+packet,552.719000,__
+packet,552.761000,__
+packet,552.802000,__
+packet,553.053000,__
+packet,552.927000,__
+packet,552.886000,__
+packet,552.969000,__
+packet,553.011000,__
+packet,553.136000,__
+packet,553.094000,__
+packet,553.261000,__
+packet,553.178000,__
+packet,553.219000,__
+packet,553.428000,__
+packet,553.344000,__
+packet,553.303000,__
+packet,553.386000,__
+packet,553.636000,__
+packet,553.511000,__
+packet,553.470000,__
+packet,553.553000,__
+packet,553.595000,__
+packet,553.678000,__
+packet,553.720000,__
+packet,553.803000,__
+packet,553.762000,__
+packet,553.887000,__
+packet,553.845000,__
+packet,554.012000,__
+packet,553.928000,__
+packet,553.970000,__
+packet,554.095000,__
+packet,554.054000,__
+packet,554.137000,__
+packet,554.262000,__
+packet,554.179000,__
+packet,554.220000,__
+packet,554.387000,__
+packet,554.304000,__
+packet,554.345000,__
+packet,554.512000,__
+packet,554.429000,__
+packet,554.471000,__
+packet,554.596000,__
+packet,554.554000,__
+packet,554.637000,__
+packet,554.846000,__
+packet,554.721000,__
+packet,554.679000,__
+packet,554.763000,__
+packet,554.804000,__
+packet,554.971000,__
+packet,554.888000,__
+packet,554.929000,__
+packet,555.013000,__
+packet,555.055000,K_
+packet,555.221000,__
+packet,555.138000,__
+packet,555.096000,__
+packet,555.180000,__
+packet,555.430000,__
+packet,555.305000,__
+packet,555.263000,__
+packet,555.346000,__
+packet,555.388000,__
+packet,555.555000,__
+packet,555.472000,__
+packet,555.513000,__
+packet,555.722000,__
+packet,555.638000,__
+packet,555.597000,__
+packet,555.680000,__
+packet,555.805000,__
+packet,555.764000,__
+packet,555.972000,__
+packet,555.889000,__
+packet,555.847000,__
+packet,555.930000,__
+packet,556.056000,__
+packet,556.014000,__
+packet,556.139000,__
+packet,556.097000,__
+packet,556.222000,__
+packet,556.181000,__
+packet,556.306000,__
+packet,556.264000,__
+packet,556.473000,__
+packet,556.389000,__
+packet,556.347000,__
+packet,556.431000,__
+packet,556.514000,K_
+packet,556.598000,__
+packet,556.556000,__
+packet,556.723000,__
+packet,556.639000,__
+packet,556.681000,__
+packet,556.765000,__
+packet,556.848000,__
+packet,556.806000,__
+packet,556.890000,__
+packet,556.931000,__
+packet,556.973000,__
+packet,557.057000,__
+packet,557.015000,__
+packet,557.098000,__
+packet,557.140000,__
+packet,557.182000,__
+packet,557.223000,__
+packet,557.265000,__
+packet,557.432000,__
+packet,557.348000,__
+packet,557.307000,__
+packet,557.390000,__
+packet,557.599000,__
+packet,557.515000,__
+packet,557.474000,__
+packet,557.557000,__
+packet,557.640000,__
+packet,557.682000,__
+packet,557.724000,__
+packet,557.766000,__
+packet,557.807000,__
+packet,557.974000,__
+packet,557.891000,__
+packet,557.849000,__
+packet,557.932000,__
+packet,558.016000,__
+packet,558.058000,__
+packet,558.099000,__
+packet,558.183000,__
+packet,558.141000,__
+packet,558.266000,__
+packet,558.224000,__
+packet,558.475000,__
+packet,558.349000,__
+packet,558.308000,__
+packet,558.391000,__
+packet,558.433000,__
+packet,558.600000,__
+packet,558.516000,__
+packet,558.558000,__
+packet,558.850000,__
+packet,558.725000,__
+packet,558.641000,__
+packet,558.683000,__
+packet,558.767000,__
+packet,558.808000,__
+packet,559.017000,__
+packet,558.933000,__
+packet,558.892000,__
+packet,558.975000,__
+packet,559.309000,__
+packet,559.142000,__
+packet,559.059000,__
+packet,559.100000,__
+packet,559.184000,__
+packet,559.225000,__
+packet,559.267000,__
+packet,559.434000,__
+packet,559.350000,__
+packet,559.392000,__
+packet,559.601000,__
+packet,559.517000,__
+packet,559.476000,__
+packet,559.559000,__
+packet,559.726000,__
+packet,559.642000,__
+packet,559.684000,__
+packet,559.976000,__
+packet,559.851000,__
+packet,559.768000,__
+packet,559.809000,__
+packet,559.893000,__
+packet,559.934000,__
+packet,560.226000,__
+packet,560.101000,__
+packet,560.018000,__
+packet,560.060000,__
+packet,560.143000,__
+packet,560.185000,__
+packet,560.393000,__
+packet,560.310000,__
+packet,560.268000,__
+packet,560.351000,__
+packet,560.518000,__
+packet,560.435000,__
+packet,560.477000,__
+packet,560.685000,__
+packet,560.602000,__
+packet,560.560000,__
+packet,560.643000,__
+packet,560.769000,__
+packet,560.727000,__
+packet,560.935000,__
+packet,560.852000,__
+packet,560.810000,__
+packet,560.894000,__
+packet,561.019000,__
+packet,560.977000,__
+packet,561.061000,__
+packet,561.102000,K_
+packet,561.144000,__
+packet,561.311000,__
+packet,561.227000,__
+packet,561.186000,__
+packet,561.269000,__
+packet,561.478000,__
+packet,561.394000,__
+packet,561.352000,__
+packet,561.436000,__
+packet,561.603000,__
+packet,561.519000,__
+packet,561.561000,__
+packet,561.644000,__
+packet,561.728000,__
+packet,561.686000,__
+packet,561.811000,__
+packet,561.770000,__
+packet,561.853000,__
+packet,561.895000,__
+packet,561.978000,__
+packet,561.936000,__
+packet,562.062000,__
+packet,562.020000,__
+packet,562.103000,__
+packet,562.145000,__
+packet,562.187000,__
+packet,562.228000,__
+packet,562.270000,__
+packet,562.312000,__
+packet,562.353000,__
+packet,562.437000,__
+packet,562.395000,__
+packet,562.687000,__
+packet,562.562000,__
+packet,562.479000,__
+packet,562.520000,__
+packet,562.604000,__
+packet,562.645000,__
+packet,562.729000,__
+packet,562.854000,__
+packet,562.771000,__
+packet,562.812000,__
+packet,562.979000,__
+packet,562.896000,__
+packet,562.937000,__
+packet,563.021000,__
+packet,563.104000,__
+packet,563.063000,__
+packet,563.188000,__
+packet,563.146000,__
+packet,563.229000,__
+packet,563.271000,__
+packet,563.313000,__
+packet,563.354000,__
+packet,563.521000,__
+packet,563.438000,__
+packet,563.396000,__
+packet,563.480000,__
+packet,563.646000,__
+packet,563.563000,__
+packet,563.605000,__
+packet,563.897000,__
+packet,563.772000,__
+packet,563.688000,__
+packet,563.730000,__
+packet,563.813000,__
+packet,563.855000,__
+packet,564.105000,__
+packet,563.980000,__
+packet,563.938000,__
+packet,564.022000,__
+packet,564.064000,__
+packet,564.189000,__
+packet,564.147000,__
+packet,564.230000,K_
+packet,564.314000,__
+packet,564.272000,__
+packet,564.397000,__
+packet,564.355000,__
+packet,564.606000,__
+packet,564.481000,__
+packet,564.439000,__
+packet,564.522000,__
+packet,564.564000,__
+packet,564.689000,__
+packet,564.647000,__
+packet,564.856000,__
+packet,564.773000,__
+packet,564.731000,__
+packet,564.814000,__
+packet,565.148000,__
+packet,564.981000,__
+packet,564.898000,__
+packet,564.939000,__
+packet,565.023000,__
+packet,565.065000,__
+packet,565.106000,__
+packet,565.440000,__
+packet,565.273000,__
+packet,565.190000,__
+packet,565.231000,__
+packet,565.315000,__
+packet,565.356000,__
+packet,565.398000,__
+packet,565.607000,__
+packet,565.523000,__
+packet,565.482000,__
+packet,565.565000,__
+packet,565.899000,__
+packet,565.732000,__
+packet,565.648000,__
+packet,565.690000,__
+packet,565.774000,__
+packet,565.815000,__
+packet,565.857000,__
+packet,566.024000,__
+packet,565.940000,__
+packet,565.982000,__
+packet,566.149000,__
+packet,566.066000,__
+packet,566.107000,__
+packet,566.316000,__
+packet,566.232000,__
+packet,566.191000,__
+packet,566.274000,__
+packet,566.524000,__
+packet,566.399000,__
+packet,566.357000,__
+packet,566.441000,__
+packet,566.483000,__
+packet,566.775000,__
+packet,566.649000,__
+packet,566.566000,__
+packet,566.608000,__
+packet,566.691000,__
+packet,566.733000,__
+packet,566.816000,K_
+packet,566.983000,__
+packet,566.900000,__
+packet,566.858000,__
+packet,566.941000,__
+packet,567.150000,__
+packet,567.067000,__
+packet,567.025000,__
+packet,567.108000,__
+packet,567.442000,__
+packet,567.275000,__
+packet,567.192000,__
+packet,567.233000,__
+packet,567.317000,__
+packet,567.358000,__
+packet,567.400000,__
+packet,567.609000,__
+packet,567.525000,__
+packet,567.484000,__
+packet,567.567000,__
+packet,567.734000,__
+packet,567.650000,__
+packet,567.692000,__
+packet,568.109000,__
+packet,567.901000,__
+packet,567.776000,__
+packet,567.817000,__
+packet,567.859000,__
+packet,567.942000,__
+packet,567.984000,__
+packet,568.026000,__
+packet,568.068000,__
+packet,568.485000,__
+packet,568.276000,__
+packet,568.151000,__
+packet,568.193000,__
+packet,568.234000,__
+packet,568.318000,__
+packet,568.359000,__
+packet,568.401000,__
+packet,568.443000,__
+packet,568.777000,__
+packet,568.610000,__
+packet,568.526000,__
+packet,568.568000,__
+packet,568.651000,__
+packet,568.693000,__
+packet,568.735000,__
+packet,569.027000,__
+packet,568.902000,__
+packet,568.818000,__
+packet,568.860000,__
+packet,568.943000,__
+packet,568.985000,__
+packet,569.277000,__
+packet,569.152000,__
+packet,569.069000,__
+packet,569.110000,__
+packet,569.194000,__
+packet,569.235000,__
+packet,569.444000,__
+packet,569.360000,__
+packet,569.319000,__
+packet,569.402000,__
+packet,569.527000,__
+packet,569.486000,__
+packet,569.694000,__
+packet,569.611000,__
+packet,569.569000,__
+packet,569.652000,__
+packet,569.861000,__
+packet,569.778000,__
+packet,569.736000,__
+packet,569.819000,__
+packet,570.236000,__
+packet,570.028000,__
+packet,569.903000,__
+packet,569.944000,__
+packet,569.986000,__
+packet,570.070000,__
+packet,570.111000,__
+packet,570.153000,__
+packet,570.195000,__
+packet,570.320000,__
+packet,570.278000,__
+packet,570.528000,__
+packet,570.403000,__
+packet,570.361000,__
+packet,570.445000,__
+packet,570.487000,__
+packet,570.779000,__
+packet,570.653000,__
+packet,570.570000,__
+packet,570.612000,__
+packet,570.695000,__
+packet,570.737000,__
+packet,570.945000,__
+packet,570.862000,__
+packet,570.820000,__
+packet,570.904000,__
+packet,571.071000,__
+packet,570.987000,__
+packet,571.029000,__
+packet,571.112000,K_
+packet,571.279000,__
+packet,571.196000,__
+packet,571.154000,__
+packet,571.237000,__
+packet,571.654000,__
+packet,571.446000,__
+packet,571.321000,__
+packet,571.362000,__
+packet,571.404000,__
+packet,571.488000,__
+packet,571.529000,__
+packet,571.571000,__
+packet,571.613000,__
+packet,571.863000,__
+packet,571.738000,__
+packet,571.696000,__
+packet,571.780000,__
+packet,571.821000,__
+packet,571.905000,__
+packet,572.113000,__
+packet,571.988000,__
+packet,571.946000,__
+packet,572.030000,__
+packet,572.072000,__
+packet,572.280000,__
+packet,572.197000,__
+packet,572.155000,__
+packet,572.238000,__
+packet,572.405000,__
+packet,572.322000,__
+packet,572.363000,__
+packet,572.489000,__
+packet,572.447000,__
+packet,572.781000,__
+packet,572.614000,__
+packet,572.530000,__
+packet,572.572000,__
+packet,572.655000,__
+packet,572.697000,__
+packet,572.739000,__
+packet,572.947000,__
+packet,572.864000,__
+packet,572.822000,__
+packet,572.906000,__
+packet,573.198000,__
+packet,573.073000,__
+packet,572.989000,__
+packet,573.031000,__
+packet,573.114000,__
+packet,573.156000,__
+packet,573.364000,__
+packet,573.281000,__
+packet,573.239000,__
+packet,573.323000,__
+packet,573.490000,__
+packet,573.406000,__
+packet,573.448000,__
+packet,573.615000,__
+packet,573.531000,__
+packet,573.573000,__
+packet,573.782000,__
+packet,573.698000,__
+packet,573.656000,__
+packet,573.740000,__
+packet,573.823000,__
+packet,573.948000,__
+packet,573.865000,__
+packet,573.907000,__
+packet,574.115000,__
+packet,574.032000,__
+packet,573.990000,__
+packet,574.074000,__
+packet,574.282000,__
+packet,574.199000,__
+packet,574.157000,__
+packet,574.240000,__
+packet,574.324000,K_
+packet,574.532000,__
+packet,574.407000,__
+packet,574.365000,__
+packet,574.449000,__
+packet,574.491000,__
+packet,574.616000,__
+packet,574.574000,__
+packet,574.657000,__
+packet,574.783000,__
+packet,574.699000,__
+packet,574.741000,__
+packet,574.866000,__
+packet,574.824000,__
+packet,574.908000,__
+packet,574.991000,__
+packet,574.949000,__
+packet,575.116000,__
+packet,575.033000,__
+packet,575.075000,__
+packet,575.158000,__
+packet,575.283000,__
+packet,575.200000,__
+packet,575.241000,__
+packet,575.325000,__
+packet,575.533000,__
+packet,575.408000,__
+packet,575.366000,__
+packet,575.450000,__
+packet,575.492000,__
+packet,575.575000,__
+packet,575.742000,__
+packet,575.658000,__
+packet,575.617000,__
+packet,575.700000,__
+packet,575.992000,__
+packet,575.867000,__
+packet,575.784000,__
+packet,575.825000,__
+packet,575.909000,__
+packet,575.950000,__
+packet,576.201000,__
+packet,576.076000,__
+packet,576.034000,__
+packet,576.117000,__
+packet,576.159000,__
+packet,576.242000,K_
+packet,576.451000,__
+packet,576.326000,__
+packet,576.284000,__
+packet,576.367000,__
+packet,576.409000,__
+packet,576.493000,__
+packet,576.701000,__
+packet,576.576000,__
+packet,576.534000,__
+packet,576.618000,__
+packet,576.659000,__
+packet,576.743000,__
+packet,576.910000,__
+packet,576.826000,__
+packet,576.785000,__
+packet,576.868000,__
+packet,577.077000,__
+packet,576.993000,__
+packet,576.951000,__
+packet,577.035000,__
+packet,577.202000,__
+packet,577.118000,__
+packet,577.160000,__
+packet,577.368000,__
+packet,577.285000,__
+packet,577.243000,__
+packet,577.327000,__
+packet,577.452000,__
+packet,577.410000,__
+packet,577.577000,__
+packet,577.494000,__
+packet,577.535000,__
+packet,577.702000,__
+packet,577.619000,__
+packet,577.660000,__
+packet,577.786000,__
+packet,577.744000,__
+packet,577.827000,__
+packet,577.911000,__
+packet,577.869000,__
+packet,578.078000,__
+packet,577.994000,__
+packet,577.952000,__
+packet,578.036000,__
+packet,578.119000,__
+packet,578.161000,__
+packet,578.369000,__
+packet,578.244000,__
+packet,578.203000,__
+packet,578.286000,__
+packet,578.328000,__
+packet,578.536000,__
+packet,578.453000,__
+packet,578.411000,__
+packet,578.495000,__
+packet,578.703000,__
+packet,578.620000,__
+packet,578.578000,__
+packet,578.661000,__
+packet,578.870000,__
+packet,578.787000,__
+packet,578.745000,__
+packet,578.828000,__
+packet,579.245000,__
+packet,579.037000,__
+packet,578.912000,__
+packet,578.953000,__
+packet,578.995000,__
+packet,579.079000,__
+packet,579.120000,__
+packet,579.162000,__
+packet,579.204000,__
+packet,579.412000,__
+packet,579.329000,__
+packet,579.287000,__
+packet,579.370000,__
+packet,579.662000,__
+packet,579.537000,__
+packet,579.454000,__
+packet,579.496000,__
+packet,579.579000,__
+packet,579.621000,__
+packet,579.704000,__
+packet,579.746000,K_
+packet,579.829000,__
+packet,579.788000,__
+packet,579.996000,__
+packet,579.913000,__
+packet,579.871000,__
+packet,579.954000,__
+packet,580.163000,__
+packet,580.080000,__
+packet,580.038000,__
+packet,580.121000,__
+packet,580.455000,__
+packet,580.288000,__
+packet,580.205000,__
+packet,580.246000,__
+packet,580.330000,__
+packet,580.371000,__
+packet,580.413000,__
+packet,580.789000,__
+packet,580.622000,__
+packet,580.497000,__
+packet,580.538000,__
+packet,580.580000,__
+packet,580.663000,__
+packet,580.705000,__
+packet,580.747000,__
+packet,580.955000,__
+packet,580.872000,__
+packet,580.830000,__
+packet,580.914000,__
+packet,581.122000,__
+packet,581.039000,__
+packet,580.997000,__
+packet,581.081000,__
+packet,581.414000,__
+packet,581.247000,__
+packet,581.164000,__
+packet,581.206000,__
+packet,581.289000,__
+packet,581.331000,__
+packet,581.372000,__
+packet,581.664000,__
+packet,581.539000,__
+packet,581.456000,__
+packet,581.498000,__
+packet,581.581000,__
+packet,581.623000,__
+packet,581.706000,__
+packet,581.748000,K_
+packet,581.831000,__
+packet,581.790000,__
+packet,581.998000,__
+packet,581.915000,__
+packet,581.873000,__
+packet,581.956000,__
+packet,582.165000,__
+packet,582.082000,__
+packet,582.040000,__
+packet,582.123000,__
+packet,582.373000,__
+packet,582.248000,__
+packet,582.207000,__
+packet,582.290000,__
+packet,582.332000,__
+packet,582.540000,__
+packet,582.457000,__
+packet,582.415000,__
+packet,582.499000,__
+packet,582.665000,__
+packet,582.582000,__
+packet,582.624000,__
+packet,582.832000,__
+packet,582.749000,__
+packet,582.707000,__
+packet,582.791000,__
+packet,583.041000,__
+packet,582.916000,__
+packet,582.874000,__
+packet,582.957000,__
+packet,582.999000,__
+packet,583.166000,__
+packet,583.083000,__
+packet,583.124000,__
+packet,583.333000,__
+packet,583.249000,__
+packet,583.208000,__
+packet,583.291000,__
+packet,583.541000,__
+packet,583.416000,__
+packet,583.374000,__
+packet,583.458000,__
+packet,583.500000,__
+packet,583.666000,__
+packet,583.583000,__
+packet,583.625000,__
+packet,583.833000,__
+packet,583.750000,__
+packet,583.708000,__
+packet,583.792000,__
+packet,583.875000,__
+packet,583.917000,K_
+packet,584.000000,__
+packet,583.958000,__
+packet,584.167000,__
+packet,584.084000,__
+packet,584.042000,__
+packet,584.125000,__
+packet,584.334000,__
+packet,584.250000,__
+packet,584.209000,__
+packet,584.292000,__
+packet,584.501000,__
+packet,584.417000,__
+packet,584.375000,__
+packet,584.459000,__
+packet,584.542000,__
+packet,584.709000,__
+packet,584.626000,__
+packet,584.584000,__
+packet,584.667000,__
+packet,584.876000,__
+packet,584.793000,__
+packet,584.751000,__
+packet,584.834000,__
+packet,585.001000,__
+packet,584.918000,__
+packet,584.959000,__
+packet,585.168000,__
+packet,585.085000,__
+packet,585.043000,__
+packet,585.126000,__
+packet,585.335000,__
+packet,585.251000,__
+packet,585.210000,__
+packet,585.293000,__
+packet,585.502000,__
+packet,585.418000,__
+packet,585.376000,__
+packet,585.460000,__
+packet,585.543000,__
+packet,585.585000,K_
+packet,585.668000,__
+packet,585.627000,__
+packet,585.710000,__
+packet,585.835000,__
+packet,585.752000,__
+packet,585.794000,__
+packet,585.877000,__
+packet,586.044000,__
+packet,585.960000,__
+packet,585.919000,__
+packet,586.002000,__
+packet,586.211000,__
+packet,586.127000,__
+packet,586.086000,__
+packet,586.169000,__
+packet,586.336000,__
+packet,586.252000,__
+packet,586.294000,__
+packet,586.544000,__
+packet,586.419000,__
+packet,586.377000,__
+packet,586.461000,__
+packet,586.503000,__
+packet,586.669000,__
+packet,586.586000,__
+packet,586.628000,__
+packet,586.878000,__
+packet,586.753000,__
+packet,586.711000,__
+packet,586.795000,__
+packet,586.836000,__
+packet,587.045000,__
+packet,586.961000,__
+packet,586.920000,__
+packet,587.003000,__
+packet,587.087000,K_
+packet,587.212000,__
+packet,587.128000,__
+packet,587.170000,__
+packet,587.337000,__
+packet,587.253000,__
+packet,587.295000,__
+packet,587.545000,__
+packet,587.420000,__
+packet,587.378000,__
+packet,587.462000,__
+packet,587.504000,__
+packet,587.670000,__
+packet,587.587000,__
+packet,587.629000,__
+packet,587.879000,__
+packet,587.754000,__
+packet,587.712000,__
+packet,587.796000,__
+packet,587.837000,__
+packet,588.046000,__
+packet,587.962000,__
+packet,587.921000,__
+packet,588.004000,__
+packet,588.213000,__
+packet,588.129000,__
+packet,588.088000,__
+packet,588.171000,__
+packet,588.379000,__
+packet,588.296000,__
+packet,588.254000,__
+packet,588.338000,__
+packet,588.546000,__
+packet,588.463000,__
+packet,588.421000,__
+packet,588.505000,__
+packet,588.713000,__
+packet,588.630000,__
+packet,588.588000,__
+packet,588.671000,__
+packet,588.838000,__
+packet,588.755000,__
+packet,588.797000,__
+packet,589.047000,__
+packet,588.922000,__
+packet,588.880000,__
+packet,588.963000,__
+packet,589.005000,__
+packet,589.214000,__
+packet,589.130000,__
+packet,589.089000,__
+packet,589.172000,__
+packet,589.339000,__
+packet,589.255000,__
+packet,589.297000,__
+packet,589.547000,__
+packet,589.422000,__
+packet,589.380000,__
+packet,589.464000,__
+packet,589.506000,__
+packet,589.714000,__
+packet,589.631000,__
+packet,589.589000,__
+packet,589.672000,__
+packet,589.881000,__
+packet,589.798000,__
+packet,589.756000,__
+packet,589.839000,__
+packet,590.006000,__
+packet,589.923000,__
+packet,589.964000,__
+packet,590.173000,__
+packet,590.090000,__
+packet,590.048000,__
+packet,590.131000,__
+packet,590.340000,__
+packet,590.256000,__
+packet,590.215000,__
+packet,590.298000,__
+packet,590.381000,__
+packet,590.423000,K_
+packet,590.548000,__
+packet,590.465000,__
+packet,590.507000,__
+packet,590.715000,__
+packet,590.632000,__
+packet,590.590000,__
+packet,590.673000,__
+packet,590.965000,__
+packet,590.840000,__
+packet,590.757000,__
+packet,590.799000,__
+packet,590.882000,__
+packet,590.924000,__
+packet,591.091000,__
+packet,591.007000,__
+packet,591.049000,__
+packet,591.299000,__
+packet,591.174000,__
+packet,591.132000,__
+packet,591.216000,__
+packet,591.257000,__
+packet,591.424000,__
+packet,591.341000,__
+packet,591.382000,__
+packet,591.633000,__
+packet,591.508000,__
+packet,591.466000,__
+packet,591.549000,__
+packet,591.591000,__
+packet,591.674000,__
+packet,591.883000,__
+packet,591.758000,__
+packet,591.716000,__
+packet,591.800000,__
+packet,591.841000,__
+packet,592.008000,__
+packet,591.925000,__
+packet,591.966000,__
+packet,592.217000,__
+packet,592.092000,__
+packet,592.050000,__
+packet,592.133000,__
+packet,592.175000,__
+packet,592.383000,__
+packet,592.300000,__
+packet,592.258000,__
+packet,592.342000,__
+packet,592.550000,__
+packet,592.467000,__
+packet,592.425000,__
+packet,592.509000,__
+packet,592.759000,__
+packet,592.634000,__
+packet,592.592000,__
+packet,592.675000,__
+packet,592.717000,__
+packet,592.926000,__
+packet,592.842000,__
+packet,592.801000,__
+packet,592.884000,__
+packet,593.134000,__
+packet,593.009000,__
+packet,592.967000,__
+packet,593.051000,__
+packet,593.093000,__
+packet,593.384000,__
+packet,593.259000,__
+packet,593.176000,__
+packet,593.218000,__
+packet,593.301000,__
+packet,593.343000,__
+packet,593.510000,__
+packet,593.426000,__
+packet,593.468000,__
+packet,593.676000,__
+packet,593.593000,__
+packet,593.551000,__
+packet,593.635000,__
+packet,593.843000,__
+packet,593.760000,__
+packet,593.718000,__
+packet,593.802000,__
+packet,594.094000,__
+packet,593.968000,__
+packet,593.885000,__
+packet,593.927000,__
+packet,594.010000,__
+packet,594.052000,__
+packet,594.260000,__
+packet,594.177000,__
+packet,594.135000,__
+packet,594.219000,__
+packet,594.427000,__
+packet,594.344000,__
+packet,594.302000,__
+packet,594.385000,__
+packet,594.636000,__
+packet,594.511000,__
+packet,594.469000,__
+packet,594.552000,__
+packet,594.594000,__
+packet,594.677000,__
+packet,594.886000,__
+packet,594.761000,__
+packet,594.719000,__
+packet,594.803000,__
+packet,594.844000,__
+packet,595.011000,__
+packet,594.928000,__
+packet,594.969000,__
+packet,595.178000,__
+packet,595.095000,__
+packet,595.053000,__
+packet,595.136000,__
+packet,595.428000,__
+packet,595.303000,__
+packet,595.220000,__
+packet,595.261000,__
+packet,595.345000,__
+packet,595.386000,__
+packet,595.720000,__
+packet,595.553000,__
+packet,595.470000,__
+packet,595.512000,__
+packet,595.595000,__
+packet,595.637000,__
+packet,595.678000,__
+packet,595.845000,__
+packet,595.762000,__
+packet,595.804000,__
+packet,596.012000,__
+packet,595.929000,__
+packet,595.887000,__
+packet,595.970000,__
+packet,596.054000,__
+packet,596.221000,__
+packet,596.137000,__
+packet,596.096000,__
+packet,596.179000,__
+packet,596.387000,__
+packet,596.304000,__
+packet,596.262000,__
+packet,596.346000,__
+packet,596.638000,__
+packet,596.513000,__
+packet,596.429000,__
+packet,596.471000,__
+packet,596.554000,__
+packet,596.596000,__
+packet,596.888000,__
+packet,596.763000,__
+packet,596.679000,__
+packet,596.721000,__
+packet,596.805000,__
+packet,596.846000,__
+packet,596.930000,K_
+packet,597.097000,__
+packet,597.013000,__
+packet,596.971000,__
+packet,597.055000,__
+packet,597.388000,__
+packet,597.222000,__
+packet,597.138000,__
+packet,597.180000,__
+packet,597.263000,__
+packet,597.305000,__
+packet,597.347000,__
+packet,597.555000,__
+packet,597.472000,__
+packet,597.430000,__
+packet,597.514000,__
+packet,597.722000,__
+packet,597.639000,__
+packet,597.597000,__
+packet,597.680000,__
+packet,597.889000,__
+packet,597.806000,__
+packet,597.764000,__
+packet,597.847000,__
+packet,597.931000,__
+packet,598.056000,__
+packet,597.972000,__
+packet,598.014000,__
+packet,598.264000,__
+packet,598.139000,__
+packet,598.098000,__
+packet,598.181000,__
+packet,598.223000,__
+packet,598.431000,__
+packet,598.348000,__
+packet,598.306000,__
+packet,598.389000,__
+packet,598.681000,__
+packet,598.556000,__
+packet,598.473000,__
+packet,598.515000,__
+packet,598.598000,__
+packet,598.640000,__
+packet,598.890000,__
+packet,598.765000,__
+packet,598.723000,__
+packet,598.807000,__
+packet,598.848000,__
+packet,598.932000,__
+packet,599.015000,__
+packet,598.973000,__
+packet,599.140000,__
+packet,599.057000,__
+packet,599.099000,__
+packet,599.182000,__
+packet,599.224000,__
+packet,599.265000,__
+packet,599.390000,__
+packet,599.307000,__
+packet,599.349000,__
+packet,599.432000,__
+packet,599.474000,__
+packet,599.557000,__
+packet,599.516000,__
+packet,599.599000,__
+packet,599.641000,__
+packet,599.724000,__
+packet,599.682000,__
+packet,599.808000,__
+packet,599.766000,__
+packet,599.849000,__
+packet,599.933000,__
+packet,599.891000,__
+packet,599.974000,__
+packet,600.100000,__
+packet,600.016000,__
+packet,600.058000,__
+packet,600.225000,__
+packet,600.141000,__
+packet,600.183000,__
+packet,600.350000,__
+packet,600.266000,__
+packet,600.308000,__
+packet,600.391000,__
+packet,600.475000,__
+packet,600.433000,__
+packet,600.558000,__
+packet,600.517000,__
+packet,600.642000,__
+packet,600.600000,__
+packet,600.683000,__
+packet,600.725000,__
+packet,600.809000,__
+packet,600.767000,__
+packet,600.892000,__
+packet,600.850000,__
+packet,600.934000,__
+packet,600.975000,__
+packet,601.101000,__
+packet,601.017000,__
+packet,601.059000,__
+packet,601.267000,__
+packet,601.184000,__
+packet,601.142000,__
+packet,601.226000,__
+packet,601.309000,__
+packet,601.351000,__
+packet,601.476000,__
+packet,601.392000,__
+packet,601.434000,__
+packet,601.518000,__
+packet,601.601000,__
+packet,601.559000,__
+packet,601.726000,__
+packet,601.643000,__
+packet,601.684000,__
+packet,601.810000,__
+packet,601.768000,__
+packet,601.851000,__
+packet,601.893000,__
+packet,601.935000,__
+packet,601.976000,__
+packet,602.018000,__
+packet,602.060000,__
+packet,602.143000,__
+packet,602.102000,__
+packet,602.227000,__
+packet,602.185000,__
+packet,602.352000,__
+packet,602.268000,__
+packet,602.310000,__
+packet,602.519000,__
+packet,602.435000,__
+packet,602.393000,__
+packet,602.477000,__
+packet,602.685000,__
+packet,602.602000,__
+packet,602.560000,__
+packet,602.644000,__
+packet,602.852000,__
+packet,602.769000,__
+packet,602.727000,__
+packet,602.811000,__
+packet,602.894000,__
+packet,602.936000,__
+packet,603.103000,__
+packet,603.019000,__
+packet,602.977000,__
+packet,603.061000,__
+packet,603.269000,__
+packet,603.186000,__
+packet,603.144000,__
+packet,603.228000,__
+packet,603.311000,__
+packet,603.353000,__
+packet,603.394000,__
+packet,603.436000,__
+packet,603.561000,__
+packet,603.478000,__
+packet,603.520000,__
+packet,603.686000,__
+packet,603.603000,__
+packet,603.645000,__
+packet,603.770000,__
+packet,603.728000,__
+packet,603.895000,__
+packet,603.812000,__
+packet,603.853000,__
+packet,604.062000,__
+packet,603.978000,__
+packet,603.937000,__
+packet,604.020000,__
+packet,604.145000,__
+packet,604.104000,__
+packet,604.187000,__
+packet,604.229000,__
+packet,604.270000,__
+packet,604.354000,__
+packet,604.312000,__
+packet,604.395000,__
+packet,604.437000,__
+packet,604.479000,__
+packet,604.521000,__
+packet,604.646000,__
+packet,604.562000,__
+packet,604.604000,__
+packet,604.687000,__
+packet,604.771000,__
+packet,604.729000,__
+packet,604.979000,__
+packet,604.854000,__
+packet,604.813000,__
+packet,604.896000,__
+packet,604.938000,__
+packet,605.230000,__
+packet,605.105000,__
+packet,605.021000,__
+packet,605.063000,__
+packet,605.146000,__
+packet,605.188000,__
+packet,605.396000,__
+packet,605.313000,__
+packet,605.271000,__
+packet,605.355000,__
+packet,605.563000,__
+packet,605.480000,__
+packet,605.438000,__
+packet,605.522000,__
+packet,605.647000,__
+packet,605.605000,__
+packet,605.688000,K_
+packet,605.814000,__
+packet,605.730000,__
+packet,605.772000,__
+packet,606.022000,__
+packet,605.897000,__
+packet,605.855000,__
+packet,605.939000,__
+packet,605.980000,__
+packet,606.189000,__
+packet,606.106000,__
+packet,606.064000,__
+packet,606.147000,__
+packet,606.314000,__
+packet,606.231000,__
+packet,606.272000,__
+packet,606.481000,__
+packet,606.397000,__
+packet,606.356000,__
+packet,606.439000,__
+packet,606.689000,__
+packet,606.564000,__
+packet,606.523000,__
+packet,606.606000,__
+packet,606.648000,__
+packet,606.856000,__
+packet,606.773000,__
+packet,606.731000,__
+packet,606.815000,__
+packet,606.981000,__
+packet,606.898000,__
+packet,606.940000,__
+packet,607.190000,__
+packet,607.065000,__
+packet,607.023000,__
+packet,607.107000,__
+packet,607.148000,__
+packet,607.357000,__
+packet,607.273000,__
+packet,607.232000,__
+packet,607.315000,__
+packet,607.524000,__
+packet,607.440000,__
+packet,607.398000,__
+packet,607.482000,__
+packet,607.649000,__
+packet,607.565000,__
+packet,607.607000,__
+packet,607.816000,__
+packet,607.732000,__
+packet,607.690000,__
+packet,607.774000,__
+packet,607.982000,__
+packet,607.899000,__
+packet,607.857000,__
+packet,607.941000,__
+packet,608.149000,__
+packet,608.066000,__
+packet,608.024000,__
+packet,608.108000,__
+packet,608.316000,__
+packet,608.233000,__
+packet,608.191000,__
+packet,608.274000,__
+packet,608.483000,__
+packet,608.399000,__
+packet,608.358000,__
+packet,608.441000,__
+packet,608.650000,__
+packet,608.566000,__
+packet,608.525000,__
+packet,608.608000,__
+packet,608.817000,__
+packet,608.733000,__
+packet,608.691000,__
+packet,608.775000,__
+packet,608.983000,__
+packet,608.900000,__
+packet,608.858000,__
+packet,608.942000,__
+packet,609.150000,__
+packet,609.067000,__
+packet,609.025000,__
+packet,609.109000,__
+packet,609.317000,__
+packet,609.234000,__
+packet,609.192000,__
+packet,609.275000,__
+packet,609.526000,__
+packet,609.400000,__
+packet,609.359000,__
+packet,609.442000,__
+packet,609.484000,__
+packet,609.692000,__
+packet,609.609000,__
+packet,609.567000,__
+packet,609.651000,__
+packet,609.818000,__
+packet,609.734000,__
+packet,609.776000,__
+packet,610.026000,__
+packet,609.901000,__
+packet,609.859000,__
+packet,609.943000,__
+packet,609.984000,__
+packet,610.193000,__
+packet,610.110000,__
+packet,610.068000,__
+packet,610.151000,__
+packet,610.360000,__
+packet,610.276000,__
+packet,610.235000,__
+packet,610.318000,__
+packet,610.443000,__
+packet,610.401000,__
+packet,610.485000,K_
+packet,610.568000,__
+packet,610.527000,__
+packet,610.735000,__
+packet,610.652000,__
+packet,610.610000,__
+packet,610.693000,__
+packet,610.944000,__
+packet,610.819000,__
+packet,610.777000,__
+packet,610.860000,__
+packet,610.902000,__
+packet,611.069000,__
+packet,610.985000,__
+packet,611.027000,__
+packet,611.236000,__
+packet,611.152000,__
+packet,611.111000,__
+packet,611.194000,__
+packet,611.444000,__
+packet,611.319000,__
+packet,611.277000,__
+packet,611.361000,__
+packet,611.402000,__
+packet,611.569000,__
+packet,611.486000,__
+packet,611.528000,__
+packet,611.778000,__
+packet,611.653000,__
+packet,611.611000,__
+packet,611.694000,__
+packet,611.736000,__
+packet,611.820000,__
+packet,611.986000,__
+packet,611.903000,__
+packet,611.861000,__
+packet,611.945000,__
+packet,612.153000,__
+packet,612.070000,__
+packet,612.028000,__
+packet,612.112000,__
+packet,612.320000,__
+packet,612.237000,__
+packet,612.195000,__
+packet,612.278000,__
+packet,612.445000,__
+packet,612.362000,__
+packet,612.403000,__
+packet,612.570000,__
+packet,612.487000,__
+packet,612.529000,__
+packet,612.779000,__
+packet,612.654000,__
+packet,612.612000,__
+packet,612.695000,__
+packet,612.737000,__
+packet,612.946000,__
+packet,612.862000,__
+packet,612.821000,__
+packet,612.904000,__
+packet,613.071000,__
+packet,612.987000,__
+packet,613.029000,__
+packet,613.238000,__
+packet,613.154000,__
+packet,613.113000,__
+packet,613.196000,__
+packet,613.446000,__
+packet,613.321000,__
+packet,613.279000,__
+packet,613.363000,__
+packet,613.404000,__
+packet,613.571000,__
+packet,613.488000,__
+packet,613.530000,__
+packet,613.780000,__
+packet,613.655000,__
+packet,613.613000,__
+packet,613.696000,__
+packet,613.738000,__
+packet,613.905000,__
+packet,613.822000,__
+packet,613.863000,__
+packet,614.072000,__
+packet,613.988000,__
+packet,613.947000,__
+packet,614.030000,__
+packet,614.280000,__
+packet,614.155000,__
+packet,614.114000,__
+packet,614.197000,__
+packet,614.239000,__
+packet,614.447000,__
+packet,614.364000,__
+packet,614.322000,__
+packet,614.405000,__
+packet,614.572000,__
+packet,614.489000,__
+packet,614.531000,__
+packet,614.697000,__
+packet,614.614000,__
+packet,614.656000,__
+packet,614.823000,__
+packet,614.739000,__
+packet,614.781000,__
+packet,614.989000,__
+packet,614.906000,__
+packet,614.864000,__
+packet,614.948000,__
+packet,615.198000,__
+packet,615.073000,__
+packet,615.031000,__
+packet,615.115000,__
+packet,615.156000,__
+packet,615.240000,K_
+packet,615.365000,__
+packet,615.281000,__
+packet,615.323000,__
+packet,615.490000,__
+packet,615.406000,__
+packet,615.448000,__
+packet,615.657000,__
+packet,615.573000,__
+packet,615.532000,__
+packet,615.615000,__
+packet,615.824000,__
+packet,615.740000,__
+packet,615.698000,__
+packet,615.782000,__
+packet,616.032000,__
+packet,615.907000,__
+packet,615.865000,__
+packet,615.949000,__
+packet,615.990000,__
+packet,616.199000,__
+packet,616.116000,__
+packet,616.074000,__
+packet,616.157000,__
+packet,616.324000,__
+packet,616.241000,__
+packet,616.282000,__
+packet,616.491000,__
+packet,616.407000,__
+packet,616.366000,__
+packet,616.449000,__
+packet,616.699000,__
+packet,616.574000,__
+packet,616.533000,__
+packet,616.616000,__
+packet,616.658000,__
+packet,616.866000,__
+packet,616.783000,__
+packet,616.741000,__
+packet,616.825000,__
+packet,617.033000,__
+packet,616.950000,__
+packet,616.908000,__
+packet,616.991000,__
+packet,617.158000,__
+packet,617.075000,__
+packet,617.117000,__
+packet,617.200000,__
+packet,617.325000,__
+packet,617.242000,__
+packet,617.283000,__
+packet,617.492000,__
+packet,617.408000,__
+packet,617.367000,__
+packet,617.450000,__
+packet,617.534000,__
+packet,617.700000,__
+packet,617.617000,__
+packet,617.575000,__
+packet,617.659000,__
+packet,617.826000,__
+packet,617.742000,__
+packet,617.784000,__
+packet,617.992000,__
+packet,617.909000,__
+packet,617.867000,__
+packet,617.951000,__
+packet,618.159000,__
+packet,618.076000,__
+packet,618.034000,__
+packet,618.118000,__
+packet,618.326000,__
+packet,618.243000,__
+packet,618.201000,__
+packet,618.284000,__
+packet,618.493000,__
+packet,618.409000,__
+packet,618.368000,__
+packet,618.451000,__
+packet,618.660000,__
+packet,618.576000,__
+packet,618.535000,__
+packet,618.618000,__
+packet,618.827000,__
+packet,618.743000,__
+packet,618.701000,__
+packet,618.785000,__
+packet,618.993000,__
+packet,618.910000,__
+packet,618.868000,__
+packet,618.952000,__
+packet,619.202000,__
+packet,619.077000,__
+packet,619.035000,__
+packet,619.119000,__
+packet,619.160000,__
+packet,619.327000,__
+packet,619.244000,__
+packet,619.285000,__
+packet,619.494000,__
+packet,619.410000,__
+packet,619.369000,__
+packet,619.452000,__
+packet,619.661000,__
+packet,619.577000,__
+packet,619.536000,__
+packet,619.619000,__
+packet,619.828000,__
+packet,619.744000,__
+packet,619.702000,__
+packet,619.786000,__
+packet,620.036000,__
+packet,619.911000,__
+packet,619.869000,__
+packet,619.953000,__
+packet,619.994000,__
+packet,620.203000,__
+packet,620.120000,__
+packet,620.078000,__
+packet,620.161000,__
+packet,620.370000,__
+packet,620.286000,__
+packet,620.245000,__
+packet,620.328000,__
+packet,620.495000,__
+packet,620.411000,__
+packet,620.453000,__
+packet,620.662000,__
+packet,620.578000,__
+packet,620.537000,__
+packet,620.620000,__
+packet,620.829000,__
+packet,620.745000,__
+packet,620.703000,__
+packet,620.787000,__
+packet,620.995000,__
+packet,620.912000,__
+packet,620.870000,__
+packet,620.954000,__
+packet,621.162000,__
+packet,621.079000,__
+packet,621.037000,__
+packet,621.121000,__
+packet,621.329000,__
+packet,621.246000,__
+packet,621.204000,__
+packet,621.287000,__
+packet,621.496000,__
+packet,621.412000,__
+packet,621.371000,__
+packet,621.454000,__
+packet,621.663000,__
+packet,621.579000,__
+packet,621.538000,__
+packet,621.621000,__
+packet,621.830000,__
+packet,621.746000,__
+packet,621.704000,__
+packet,621.788000,__
+packet,621.996000,__
+packet,621.913000,__
+packet,621.871000,__
+packet,621.955000,__
+packet,622.163000,__
+packet,622.080000,__
+packet,622.038000,__
+packet,622.122000,__
+packet,622.330000,__
+packet,622.247000,__
+packet,622.205000,__
+packet,622.288000,__
+packet,622.497000,__
+packet,622.413000,__
+packet,622.372000,__
+packet,622.455000,__
+packet,622.664000,__
+packet,622.580000,__
+packet,622.539000,__
+packet,622.622000,__
+packet,622.831000,__
+packet,622.747000,__
+packet,622.705000,__
+packet,622.789000,__
+packet,622.997000,__
+packet,622.914000,__
+packet,622.872000,__
+packet,622.956000,__
+packet,623.164000,__
+packet,623.081000,__
+packet,623.039000,__
+packet,623.123000,__
+packet,623.331000,__
+packet,623.248000,__
+packet,623.206000,__
+packet,623.289000,__
+packet,623.498000,__
+packet,623.414000,__
+packet,623.373000,__
+packet,623.456000,__
+packet,623.665000,__
+packet,623.581000,__
+packet,623.540000,__
+packet,623.623000,__
+packet,623.873000,__
+packet,623.748000,__
+packet,623.706000,__
+packet,623.790000,__
+packet,623.832000,__
+packet,623.998000,__
+packet,623.915000,__
+packet,623.957000,__
+packet,624.207000,__
+packet,624.082000,__
+packet,624.040000,__
+packet,624.124000,__
+packet,624.165000,__
+packet,624.332000,__
+packet,624.249000,__
+packet,624.290000,__
+packet,624.541000,__
+packet,624.415000,__
+packet,624.374000,__
+packet,624.457000,__
+packet,624.499000,__
+packet,624.666000,__
+packet,624.582000,__
+packet,624.624000,__
+packet,624.749000,__
+packet,624.707000,__
+packet,624.791000,__
+packet,624.916000,__
+packet,624.833000,__
+packet,624.874000,__
+packet,624.999000,__
+packet,624.958000,__
+packet,625.125000,__
+packet,625.041000,__
+packet,625.083000,__
+packet,625.208000,__
+packet,625.166000,__
+packet,625.333000,__
+packet,625.250000,__
+packet,625.291000,__
+packet,625.416000,__
+packet,625.375000,__
+packet,625.458000,__
+packet,625.500000,__
+packet,625.542000,__
+packet,625.583000,__
+packet,625.625000,K_
+packet,625.792000,__
+packet,625.708000,__
+packet,625.667000,__
+packet,625.750000,__
+packet,625.875000,__
+packet,625.834000,__
+packet,626.000000,__
+packet,625.917000,__
+packet,625.959000,__
+packet,626.209000,__
+packet,626.084000,__
+packet,626.042000,__
+packet,626.126000,__
+packet,626.167000,__
+packet,626.376000,__
+packet,626.292000,__
+packet,626.251000,__
+packet,626.334000,__
+packet,626.543000,__
+packet,626.459000,__
+packet,626.417000,__
+packet,626.501000,__
+packet,626.793000,__
+packet,626.668000,__
+packet,626.584000,__
+packet,626.626000,__
+packet,626.709000,__
+packet,626.751000,__
+packet,627.085000,__
+packet,626.918000,__
+packet,626.835000,__
+packet,626.876000,__
+packet,626.960000,__
+packet,627.001000,__
+packet,627.043000,__
+packet,627.460000,__
+packet,627.252000,__
+packet,627.127000,__
+packet,627.168000,__
+packet,627.210000,__
+packet,627.293000,__
+packet,627.335000,__
+packet,627.377000,__
+packet,627.418000,__
+packet,627.752000,__
+packet,627.585000,__
+packet,627.502000,__
+packet,627.544000,__
+packet,627.627000,__
+packet,627.669000,__
+packet,627.710000,__
+packet,627.877000,__
+packet,627.794000,__
+packet,627.836000,__
+packet,628.044000,__
+packet,627.961000,__
+packet,627.919000,__
+packet,628.002000,__
+packet,628.211000,__
+packet,628.128000,__
+packet,628.086000,__
+packet,628.169000,__
+packet,628.378000,__
+packet,628.294000,__
+packet,628.253000,__
+packet,628.336000,__
+packet,628.628000,__
+packet,628.503000,__
+packet,628.419000,__
+packet,628.461000,__
+packet,628.545000,__
+packet,628.586000,__
+packet,628.878000,__
+packet,628.753000,__
+packet,628.670000,__
+packet,628.711000,__
+packet,628.795000,__
+packet,628.837000,__
+packet,629.129000,__
+packet,629.003000,__
+packet,628.920000,__
+packet,628.962000,__
+packet,629.045000,__
+packet,629.087000,__
+packet,629.379000,__
+packet,629.254000,__
+packet,629.170000,__
+packet,629.212000,__
+packet,629.295000,__
+packet,629.337000,__
+packet,629.546000,__
+packet,629.462000,__
+packet,629.420000,__
+packet,629.504000,__
+packet,629.587000,K_
+packet,629.629000,__
+packet,629.963000,__
+packet,629.796000,__
+packet,629.671000,__
+packet,629.712000,__
+packet,629.754000,__
+packet,629.838000,__
+packet,629.879000,__
+packet,629.921000,__
+packet,630.296000,__
+packet,630.130000,__
+packet,630.004000,__
+packet,630.046000,__
+packet,630.088000,__
+packet,630.171000,__
+packet,630.213000,__
+packet,630.255000,__
+packet,630.630000,__
+packet,630.463000,__
+packet,630.338000,__
+packet,630.380000,__
+packet,630.421000,__
+packet,630.505000,__
+packet,630.547000,__
+packet,630.588000,__
+packet,630.964000,__
+packet,630.797000,__
+packet,630.672000,__
+packet,630.713000,__
+packet,630.755000,__
+packet,630.839000,__
+packet,630.880000,__
+packet,630.922000,__
+packet,631.005000,K_
+packet,631.047000,__
+packet,631.256000,__
+packet,631.131000,__
+packet,631.089000,__
+packet,631.172000,__
+packet,631.214000,__
+packet,631.339000,__
+packet,631.297000,__
+packet,631.548000,__
+packet,631.422000,__
+packet,631.381000,__
+packet,631.464000,__
+packet,631.506000,__
+packet,631.631000,__
+packet,631.589000,__
+packet,631.673000,__
+packet,631.923000,__
+packet,631.798000,__
+packet,631.714000,__
+packet,631.756000,__
+packet,631.840000,__
+packet,631.881000,__
+packet,632.132000,__
+packet,632.006000,__
+packet,631.965000,__
+packet,632.048000,__
+packet,632.090000,__
+packet,632.215000,__
+packet,632.173000,__
+packet,632.423000,__
+packet,632.298000,__
+packet,632.257000,__
+packet,632.340000,__
+packet,632.382000,__
+packet,632.507000,__
+packet,632.465000,__
+packet,632.549000,__
+packet,632.590000,K_
+packet,632.632000,__
+packet,632.715000,__
+packet,632.674000,__
+packet,632.882000,__
+packet,632.799000,__
+packet,632.757000,__
+packet,632.841000,__
+packet,633.049000,__
+packet,632.966000,__
+packet,632.924000,__
+packet,633.007000,__
+packet,633.216000,__
+packet,633.133000,__
+packet,633.091000,__
+packet,633.174000,__
+packet,633.341000,__
+packet,633.258000,__
+packet,633.299000,__
+packet,633.550000,__
+packet,633.424000,__
+packet,633.383000,__
+packet,633.466000,__
+packet,633.508000,__
+packet,633.716000,__
+packet,633.633000,__
+packet,633.591000,__
+packet,633.675000,__
+packet,633.842000,__
+packet,633.758000,__
+packet,633.800000,__
+packet,634.008000,__
+packet,633.925000,__
+packet,633.883000,__
+packet,633.967000,__
+packet,634.134000,__
+packet,634.050000,__
+packet,634.092000,__
+packet,634.175000,K_
+packet,634.217000,__
+packet,634.259000,__
+packet,634.467000,__
+packet,634.342000,__
+packet,634.300000,__
+packet,634.384000,__
+packet,634.425000,__
+packet,634.592000,__
+packet,634.509000,__
+packet,634.551000,__
+packet,634.717000,__
+packet,634.634000,__
+packet,634.676000,__
+packet,634.884000,__
+packet,634.801000,__
+packet,634.759000,__
+packet,634.843000,__
+packet,635.260000,__
+packet,635.051000,__
+packet,634.926000,__
+packet,634.968000,__
+packet,635.009000,__
+packet,635.093000,__
+packet,635.135000,__
+packet,635.176000,__
+packet,635.218000,__
+packet,635.635000,__
+packet,635.426000,__
+packet,635.301000,__
+packet,635.343000,__
+packet,635.385000,__
+packet,635.468000,__
+packet,635.510000,__
+packet,635.552000,__
+packet,635.593000,__
+packet,635.677000,K_
+packet,635.802000,__
+packet,635.718000,__
+packet,635.760000,__
+packet,635.969000,__
+packet,635.885000,__
+packet,635.844000,__
+packet,635.927000,__
+packet,636.094000,__
+packet,636.010000,__
+packet,636.052000,__
+packet,636.261000,__
+packet,636.177000,__
+packet,636.136000,__
+packet,636.219000,__
+packet,636.469000,__
+packet,636.344000,__
+packet,636.302000,__
+packet,636.386000,__
+packet,636.427000,__
+packet,636.594000,__
+packet,636.511000,__
+packet,636.553000,__
+packet,636.761000,__
+packet,636.678000,__
+packet,636.636000,__
+packet,636.719000,__
+packet,636.970000,__
+packet,636.845000,__
+packet,636.803000,__
+packet,636.886000,__
+packet,636.928000,__
+packet,637.137000,__
+packet,637.053000,__
+packet,637.011000,__
+packet,637.095000,__
+packet,637.262000,__
+packet,637.178000,__
+packet,637.220000,__
+packet,637.470000,__
+packet,637.345000,__
+packet,637.303000,__
+packet,637.387000,__
+packet,637.428000,__
+packet,637.637000,__
+packet,637.554000,__
+packet,637.512000,__
+packet,637.595000,__
+packet,637.762000,__
+packet,637.679000,__
+packet,637.720000,__
+packet,637.971000,__
+packet,637.846000,__
+packet,637.804000,__
+packet,637.887000,__
+packet,637.929000,__
+packet,638.096000,__
+packet,638.012000,__
+packet,638.054000,__
+packet,638.263000,__
+packet,638.179000,__
+packet,638.138000,__
+packet,638.221000,__
+packet,638.471000,__
+packet,638.346000,__
+packet,638.304000,__
+packet,638.388000,__
+packet,638.429000,__
+packet,638.555000,__
+packet,638.513000,__
+packet,638.596000,K_
+packet,638.763000,__
+packet,638.680000,__
+packet,638.638000,__
+packet,638.721000,__
+packet,638.972000,__
+packet,638.847000,__
+packet,638.805000,__
+packet,638.888000,__
+packet,638.930000,__
+packet,639.097000,__
+packet,639.013000,__
+packet,639.055000,__
+packet,639.264000,__
+packet,639.180000,__
+packet,639.139000,__
+packet,639.222000,__
+packet,639.472000,__
+packet,639.347000,__
+packet,639.305000,__
+packet,639.389000,__
+packet,639.430000,__
+packet,639.639000,__
+packet,639.556000,__
+packet,639.514000,__
+packet,639.597000,__
+packet,639.806000,__
+packet,639.722000,__
+packet,639.681000,__
+packet,639.764000,__
+packet,639.931000,__
+packet,639.848000,__
+packet,639.889000,__
+packet,640.014000,__
+packet,639.973000,__
+packet,640.181000,__
+packet,640.098000,__
+packet,640.056000,__
+packet,640.140000,__
+packet,640.223000,__
+packet,640.306000,__
+packet,640.265000,__
+packet,640.348000,__
+packet,640.515000,__
+packet,640.431000,__
+packet,640.390000,__
+packet,640.473000,__
+packet,640.723000,__
+packet,640.598000,__
+packet,640.557000,__
+packet,640.640000,__
+packet,640.682000,__
+packet,640.890000,__
+packet,640.807000,__
+packet,640.765000,__
+packet,640.849000,__
+packet,641.015000,__
+packet,640.932000,__
+packet,640.974000,__
+packet,641.182000,__
+packet,641.099000,__
+packet,641.057000,__
+packet,641.141000,__
+packet,641.391000,__
+packet,641.266000,__
+packet,641.224000,__
+packet,641.307000,__
+packet,641.349000,__
+packet,641.516000,__
+packet,641.432000,__
+packet,641.474000,__
+packet,641.724000,__
+packet,641.599000,__
+packet,641.558000,__
+packet,641.641000,__
+packet,641.683000,__
+packet,641.891000,__
+packet,641.808000,__
+packet,641.766000,__
+packet,641.850000,__
+packet,642.058000,__
+packet,641.975000,__
+packet,641.933000,__
+packet,642.016000,__
+packet,642.183000,__
+packet,642.100000,__
+packet,642.142000,__
+packet,642.350000,__
+packet,642.267000,__
+packet,642.225000,__
+packet,642.308000,__
+packet,642.559000,__
+packet,642.433000,__
+packet,642.392000,__
+packet,642.475000,__
+packet,642.517000,__
+packet,642.600000,__
+packet,642.642000,__
+packet,642.684000,K_
+packet,642.934000,__
+packet,642.809000,__
+packet,642.725000,__
+packet,642.767000,__
+packet,642.851000,__
+packet,642.892000,__
+packet,643.268000,__
+packet,643.101000,__
+packet,642.976000,__
+packet,643.017000,__
+packet,643.059000,__
+packet,643.143000,__
+packet,643.184000,__
+packet,643.226000,__
+packet,643.643000,__
+packet,643.434000,__
+packet,643.309000,__
+packet,643.351000,__
+packet,643.393000,__
+packet,643.476000,__
+packet,643.518000,__
+packet,643.560000,__
+packet,643.601000,__
+packet,643.810000,__
+packet,643.726000,__
+packet,643.685000,__
+packet,643.768000,__
+packet,643.977000,__
+packet,643.893000,__
+packet,643.852000,__
+packet,643.935000,__
+packet,644.144000,__
+packet,644.060000,__
+packet,644.018000,__
+packet,644.102000,__
+packet,644.310000,__
+packet,644.227000,__
+packet,644.185000,__
+packet,644.269000,__
+packet,644.435000,__
+packet,644.352000,__
+packet,644.394000,__
+packet,644.561000,__
+packet,644.477000,__
+packet,644.519000,__
+packet,644.727000,__
+packet,644.644000,__
+packet,644.602000,__
+packet,644.686000,__
+packet,644.894000,__
+packet,644.811000,__
+packet,644.769000,__
+packet,644.853000,__
+packet,644.978000,__
+packet,644.936000,__
+packet,645.228000,__
+packet,645.103000,__
+packet,645.019000,__
+packet,645.061000,__
+packet,645.145000,__
+packet,645.186000,__
+packet,645.436000,__
+packet,645.311000,__
+packet,645.270000,__
+packet,645.353000,__
+packet,645.395000,__
+packet,645.478000,K_
+packet,645.603000,__
+packet,645.520000,__
+packet,645.562000,__
+packet,645.770000,__
+packet,645.687000,__
+packet,645.645000,__
+packet,645.728000,__
+packet,645.895000,__
+packet,645.812000,__
+packet,645.854000,__
+packet,646.104000,__
+packet,645.979000,__
+packet,645.937000,__
+packet,646.020000,__
+packet,646.062000,__
+packet,646.271000,__
+packet,646.187000,__
+packet,646.146000,__
+packet,646.229000,__
+packet,646.396000,__
+packet,646.312000,__
+packet,646.354000,__
+packet,646.604000,__
+packet,646.479000,__
+packet,646.437000,__
+packet,646.521000,__
+packet,646.563000,__
+packet,646.771000,__
+packet,646.688000,__
+packet,646.646000,__
+packet,646.729000,__
+packet,646.938000,__
+packet,646.855000,__
+packet,646.813000,__
+packet,646.896000,__
+packet,646.980000,K_
+packet,647.147000,__
+packet,647.063000,__
+packet,647.021000,__
+packet,647.105000,__
+packet,647.397000,__
+packet,647.272000,__
+packet,647.188000,__
+packet,647.230000,__
+packet,647.313000,__
+packet,647.355000,__
+packet,647.772000,__
+packet,647.564000,__
+packet,647.438000,__
+packet,647.480000,__
+packet,647.522000,__
+packet,647.605000,__
+packet,647.647000,__
+packet,647.689000,__
+packet,647.730000,__
+packet,647.939000,__
+packet,647.856000,__
+packet,647.814000,__
+packet,647.897000,__
+packet,648.148000,__
+packet,648.022000,__
+packet,647.981000,__
+packet,648.064000,__
+packet,648.106000,__
+packet,648.273000,__
+packet,648.189000,__
+packet,648.231000,__
+packet,648.314000,__
+packet,648.356000,__
+packet,648.398000,__
+packet,648.439000,__
+packet,648.481000,__
+packet,648.523000,__
+packet,648.565000,__
+packet,648.606000,__
+packet,648.857000,__
+packet,648.731000,__
+packet,648.648000,__
+packet,648.690000,__
+packet,648.773000,__
+packet,648.815000,__
+packet,648.898000,__
+packet,648.940000,__
+packet,648.982000,__
+packet,649.023000,__
+packet,649.065000,__
+packet,649.149000,__
+packet,649.107000,__
+packet,649.274000,__
+packet,649.190000,__
+packet,649.232000,__
+packet,649.482000,__
+packet,649.357000,__
+packet,649.315000,__
+packet,649.399000,__
+packet,649.440000,__
+packet,649.607000,__
+packet,649.524000,__
+packet,649.566000,__
+packet,649.816000,__
+packet,649.691000,__
+packet,649.649000,__
+packet,649.732000,__
+packet,649.774000,__
+packet,649.983000,__
+packet,649.899000,__
+packet,649.858000,__
+packet,649.941000,__
+packet,650.066000,__
+packet,650.024000,__
+packet,650.108000,__
+packet,650.191000,__
+packet,650.150000,__
+packet,650.358000,__
+packet,650.275000,__
+packet,650.233000,__
+packet,650.316000,__
+packet,650.525000,__
+packet,650.441000,__
+packet,650.400000,__
+packet,650.483000,__
+packet,650.692000,__
+packet,650.608000,__
+packet,650.567000,__
+packet,650.650000,__
+packet,650.942000,__
+packet,650.817000,__
+packet,650.733000,__
+packet,650.775000,__
+packet,650.859000,__
+packet,650.900000,__
+packet,651.109000,__
+packet,651.025000,__
+packet,650.984000,__
+packet,651.067000,__
+packet,651.276000,__
+packet,651.192000,__
+packet,651.151000,__
+packet,651.234000,__
+packet,651.401000,__
+packet,651.317000,__
+packet,651.359000,__
+packet,651.442000,K_
+packet,651.484000,__
+packet,651.693000,__
+packet,651.568000,__
+packet,651.526000,__
+packet,651.609000,__
+packet,651.651000,__
+packet,651.901000,__
+packet,651.776000,__
+packet,651.734000,__
+packet,651.818000,__
+packet,651.860000,__
+packet,652.026000,__
+packet,651.943000,__
+packet,651.985000,__
+packet,652.193000,__
+packet,652.110000,__
+packet,652.068000,__
+packet,652.152000,__
+packet,652.360000,__
+packet,652.277000,__
+packet,652.235000,__
+packet,652.318000,__
+packet,652.527000,__
+packet,652.443000,__
+packet,652.402000,__
+packet,652.485000,__
+packet,652.735000,__
+packet,652.610000,__
+packet,652.569000,__
+packet,652.652000,__
+packet,652.694000,__
+packet,652.861000,__
+packet,652.777000,__
+packet,652.819000,__
+packet,653.027000,__
+packet,652.944000,__
+packet,652.902000,__
+packet,652.986000,__
+packet,653.194000,__
+packet,653.111000,__
+packet,653.069000,__
+packet,653.153000,__
+packet,653.361000,__
+packet,653.278000,__
+packet,653.236000,__
+packet,653.319000,__
+packet,653.611000,__
+packet,653.486000,__
+packet,653.403000,__
+packet,653.444000,__
+packet,653.528000,__
+packet,653.570000,__
+packet,653.778000,__
+packet,653.695000,__
+packet,653.653000,__
+packet,653.736000,__
+packet,654.070000,__
+packet,653.903000,__
+packet,653.820000,__
+packet,653.862000,__
+packet,653.945000,__
+packet,653.987000,__
+packet,654.028000,__
+packet,654.279000,__
+packet,654.154000,__
+packet,654.112000,__
+packet,654.195000,__
+packet,654.237000,__
+packet,654.487000,__
+packet,654.362000,__
+packet,654.320000,__
+packet,654.404000,__
+packet,654.445000,__
+packet,654.571000,__
+packet,654.529000,__
+packet,654.737000,__
+packet,654.654000,__
+packet,654.612000,__
+packet,654.696000,__
+packet,654.904000,__
+packet,654.821000,__
+packet,654.779000,__
+packet,654.863000,__
+packet,654.946000,K_
+packet,655.029000,__
+packet,654.988000,__
+packet,655.196000,__
+packet,655.113000,__
+packet,655.071000,__
+packet,655.155000,__
+packet,655.363000,__
+packet,655.280000,__
+packet,655.238000,__
+packet,655.321000,__
+packet,655.530000,__
+packet,655.446000,__
+packet,655.405000,__
+packet,655.488000,__
+packet,655.738000,__
+packet,655.613000,__
+packet,655.572000,__
+packet,655.655000,__
+packet,655.697000,__
+packet,655.864000,__
+packet,655.780000,__
+packet,655.822000,__
+packet,656.072000,__
+packet,655.947000,__
+packet,655.905000,__
+packet,655.989000,__
+packet,656.030000,__
+packet,656.322000,__
+packet,656.197000,__
+packet,656.114000,__
+packet,656.156000,__
+packet,656.239000,__
+packet,656.281000,__
+packet,656.573000,__
+packet,656.447000,__
+packet,656.364000,__
+packet,656.406000,__
+packet,656.489000,__
+packet,656.531000,__
+packet,656.698000,__
+packet,656.614000,__
+packet,656.656000,__
+packet,656.906000,__
+packet,656.781000,__
+packet,656.739000,__
+packet,656.823000,__
+packet,656.865000,__
+packet,657.031000,__
+packet,656.948000,__
+packet,656.990000,__
+packet,657.157000,__
+packet,657.073000,__
+packet,657.115000,__
+packet,657.323000,__
+packet,657.240000,__
+packet,657.198000,__
+packet,657.282000,__
+packet,657.407000,__
+packet,657.365000,__
+packet,657.448000,K_
+packet,657.615000,__
+packet,657.532000,__
+packet,657.490000,__
+packet,657.574000,__
+packet,657.782000,__
+packet,657.699000,__
+packet,657.657000,__
+packet,657.740000,__
+packet,657.991000,__
+packet,657.866000,__
+packet,657.824000,__
+packet,657.907000,__
+packet,657.949000,__
+packet,658.241000,__
+packet,658.116000,__
+packet,658.032000,__
+packet,658.074000,__
+packet,658.158000,__
+packet,658.199000,__
+packet,658.324000,__
+packet,658.283000,__
+packet,658.575000,__
+packet,658.449000,__
+packet,658.366000,__
+packet,658.408000,__
+packet,658.491000,__
+packet,658.533000,__
+packet,658.741000,__
+packet,658.658000,__
+packet,658.616000,__
+packet,658.700000,__
+packet,658.867000,__
+packet,658.783000,__
+packet,658.825000,__
+packet,659.117000,__
+packet,658.992000,__
+packet,658.908000,__
+packet,658.950000,__
+packet,659.033000,__
+packet,659.075000,__
+packet,659.284000,__
+packet,659.200000,__
+packet,659.159000,__
+packet,659.242000,__
+packet,659.492000,__
+packet,659.367000,__
+packet,659.325000,__
+packet,659.409000,__
+packet,659.450000,__
+packet,659.659000,__
+packet,659.576000,__
+packet,659.534000,__
+packet,659.617000,__
+packet,659.868000,__
+packet,659.742000,__
+packet,659.701000,__
+packet,659.784000,__
+packet,659.826000,__
+packet,660.118000,__
+packet,659.993000,__
+packet,659.909000,__
+packet,659.951000,__
+packet,660.034000,__
+packet,660.076000,__
+packet,660.160000,__
+packet,660.201000,K_
+packet,660.243000,__
+packet,660.493000,__
+packet,660.368000,__
+packet,660.285000,__
+packet,660.326000,__
+packet,660.410000,__
+packet,660.451000,__
+packet,660.743000,__
+packet,660.618000,__
+packet,660.535000,__
+packet,660.577000,__
+packet,660.660000,__
+packet,660.702000,__
+packet,660.910000,__
+packet,660.827000,__
+packet,660.785000,__
+packet,660.869000,__
+packet,660.994000,__
+packet,660.952000,__
+packet,661.119000,__
+packet,661.035000,__
+packet,661.077000,__
+packet,661.202000,__
+packet,661.161000,__
+packet,661.411000,__
+packet,661.286000,__
+packet,661.244000,__
+packet,661.327000,__
+packet,661.369000,__
+packet,661.494000,__
+packet,661.452000,__
+packet,661.619000,__
+packet,661.536000,__
+packet,661.578000,__
+packet,661.870000,__
+packet,661.744000,__
+packet,661.661000,__
+packet,661.703000,__
+packet,661.786000,__
+packet,661.828000,__
+packet,661.911000,__
+packet,661.953000,K_
+packet,662.078000,__
+packet,661.995000,__
+packet,662.036000,__
+packet,662.203000,__
+packet,662.120000,__
+packet,662.162000,__
+packet,662.412000,__
+packet,662.287000,__
+packet,662.245000,__
+packet,662.328000,__
+packet,662.370000,__
+packet,662.662000,__
+packet,662.537000,__
+packet,662.453000,__
+packet,662.495000,__
+packet,662.579000,__
+packet,662.620000,__
+packet,662.787000,__
+packet,662.704000,__
+packet,662.745000,__
+packet,662.871000,__
+packet,662.829000,__
+packet,663.037000,__
+packet,662.954000,__
+packet,662.912000,__
+packet,662.996000,__
+packet,663.204000,__
+packet,663.121000,__
+packet,663.079000,__
+packet,663.163000,__
+packet,663.413000,__
+packet,663.288000,__
+packet,663.246000,__
+packet,663.329000,__
+packet,663.371000,__
+packet,663.580000,__
+packet,663.496000,__
+packet,663.454000,__
+packet,663.538000,__
+packet,663.705000,__
+packet,663.621000,__
+packet,663.663000,__
+packet,663.913000,__
+packet,663.788000,__
+packet,663.746000,__
+packet,663.830000,__
+packet,663.872000,__
+packet,664.080000,__
+packet,663.997000,__
+packet,663.955000,__
+packet,664.038000,__
+packet,664.205000,__
+packet,664.122000,__
+packet,664.164000,__
+packet,664.414000,__
+packet,664.289000,__
+packet,664.247000,__
+packet,664.330000,__
+packet,664.372000,__
+packet,664.539000,__
+packet,664.455000,__
+packet,664.497000,__
+packet,664.706000,__
+packet,664.622000,__
+packet,664.581000,__
+packet,664.664000,__
+packet,664.914000,__
+packet,664.789000,__
+packet,664.747000,__
+packet,664.831000,__
+packet,664.873000,__
+packet,665.039000,__
+packet,664.956000,__
+packet,664.998000,__
+packet,665.206000,__
+packet,665.123000,__
+packet,665.081000,__
+packet,665.165000,__
+packet,665.415000,__
+packet,665.290000,__
+packet,665.248000,__
+packet,665.331000,__
+packet,665.373000,__
+packet,665.456000,K_
+packet,665.498000,__
+packet,665.707000,__
+packet,665.582000,__
+packet,665.540000,__
+packet,665.623000,__
+packet,665.665000,__
+packet,665.957000,__
+packet,665.832000,__
+packet,665.748000,__
+packet,665.790000,__
+packet,665.874000,__
+packet,665.915000,__
+packet,666.124000,__
+packet,666.040000,__
+packet,665.999000,__
+packet,666.082000,__
+packet,666.374000,__
+packet,666.249000,__
+packet,666.166000,__
+packet,666.207000,__
+packet,666.291000,__
+packet,666.332000,__
+packet,666.541000,__
+packet,666.457000,__
+packet,666.416000,__
+packet,666.499000,__
+packet,666.624000,__
+packet,666.583000,__
+packet,666.666000,__
+packet,666.708000,K_
+packet,666.833000,__
+packet,666.749000,__
+packet,666.791000,__
+packet,667.000000,__
+packet,666.916000,__
+packet,666.875000,__
+packet,666.958000,__
+packet,667.167000,__
+packet,667.083000,__
+packet,667.041000,__
+packet,667.125000,__
+packet,667.333000,__
+packet,667.250000,__
+packet,667.208000,__
+packet,667.292000,__
+packet,667.500000,__
+packet,667.417000,__
+packet,667.375000,__
+packet,667.458000,__
+packet,667.625000,__
+packet,667.542000,__
+packet,667.584000,__
+packet,667.792000,__
+packet,667.709000,__
+packet,667.667000,__
+packet,667.750000,__
+packet,667.834000,__
+packet,668.001000,__
+packet,667.917000,__
+packet,667.876000,__
+packet,667.959000,__
+packet,668.168000,__
+packet,668.084000,__
+packet,668.042000,__
+packet,668.126000,__
+packet,668.293000,__
+packet,668.209000,__
+packet,668.251000,__
+packet,668.501000,__
+packet,668.376000,__
+packet,668.334000,__
+packet,668.418000,__
+packet,668.459000,__
+packet,668.585000,__
+packet,668.543000,__
+packet,668.751000,__
+packet,668.668000,__
+packet,668.626000,__
+packet,668.710000,__
+packet,669.002000,__
+packet,668.877000,__
+packet,668.793000,__
+packet,668.835000,__
+packet,668.918000,__
+packet,668.960000,__
+packet,669.043000,K_
+packet,669.085000,__
+packet,669.419000,__
+packet,669.252000,__
+packet,669.127000,__
+packet,669.169000,__
+packet,669.210000,__
+packet,669.294000,__
+packet,669.335000,__
+packet,669.377000,__
+packet,669.502000,__
+packet,669.460000,__
+packet,669.752000,__
+packet,669.627000,__
+packet,669.544000,__
+packet,669.586000,__
+packet,669.669000,__
+packet,669.711000,__
+packet,669.836000,__
+packet,669.794000,__
+packet,670.128000,__
+packet,669.961000,__
+packet,669.878000,__
+packet,669.919000,__
+packet,670.003000,__
+packet,670.044000,__
+packet,670.086000,__
+packet,670.420000,__
+packet,670.253000,__
+packet,670.170000,__
+packet,670.211000,__
+packet,670.295000,__
+packet,670.336000,__
+packet,670.378000,__
+packet,670.795000,__
+packet,670.587000,__
+packet,670.461000,__
+packet,670.503000,__
+packet,670.545000,__
+packet,670.628000,__
+packet,670.670000,__
+packet,670.712000,__
+packet,670.753000,__
+packet,671.171000,__
+packet,670.962000,__
+packet,670.837000,__
+packet,670.879000,__
+packet,670.920000,__
+packet,671.004000,__
+packet,671.045000,__
+packet,671.087000,__
+packet,671.129000,__
+packet,671.421000,__
+packet,671.296000,__
+packet,671.212000,__
+packet,671.254000,__
+packet,671.337000,__
+packet,671.379000,__
+packet,671.504000,__
+packet,671.462000,__
+packet,671.880000,__
+packet,671.671000,__
+packet,671.546000,__
+packet,671.588000,__
+packet,671.629000,__
+packet,671.713000,__
+packet,671.754000,__
+packet,671.796000,__
+packet,671.838000,__
+packet,672.130000,__
+packet,672.005000,__
+packet,671.921000,__
+packet,671.963000,__
+packet,672.046000,__
+packet,672.088000,__
+packet,672.422000,__
+packet,672.255000,__
+packet,672.172000,__
+packet,672.213000,__
+packet,672.297000,__
+packet,672.338000,__
+packet,672.380000,__
+packet,672.463000,K_
+packet,672.547000,__
+packet,672.505000,__
+packet,672.630000,__
+packet,672.589000,__
+packet,672.714000,__
+packet,672.672000,__
+packet,672.922000,__
+packet,672.797000,__
+packet,672.755000,__
+packet,672.839000,__
+packet,672.881000,__
+packet,673.089000,__
+packet,673.006000,__
+packet,672.964000,__
+packet,673.047000,__
+packet,673.256000,__
+packet,673.173000,__
+packet,673.131000,__
+packet,673.214000,__
+packet,673.298000,__
+packet,673.506000,__
+packet,673.381000,__
+packet,673.339000,__
+packet,673.423000,__
+packet,673.464000,__
+packet,673.631000,__
+packet,673.548000,__
+packet,673.590000,__
+packet,673.798000,__
+packet,673.715000,__
+packet,673.673000,__
+packet,673.756000,__
+packet,674.007000,__
+packet,673.882000,__
+packet,673.840000,__
+packet,673.923000,__
+packet,673.965000,__
+packet,674.174000,__
+packet,674.090000,__
+packet,674.048000,__
+packet,674.132000,__
+packet,674.299000,__
+packet,674.215000,__
+packet,674.257000,__
+packet,674.424000,__
+packet,674.340000,__
+packet,674.382000,__
+packet,674.757000,__
+packet,674.591000,__
+packet,674.465000,__
+packet,674.507000,__
+packet,674.549000,__
+packet,674.632000,__
+packet,674.674000,__
+packet,674.716000,__
+packet,674.966000,__
+packet,674.841000,__
+packet,674.799000,__
+packet,674.883000,__
+packet,674.924000,__
+packet,675.133000,__
+packet,675.049000,__
+packet,675.008000,__
+packet,675.091000,__
+packet,675.300000,__
+packet,675.216000,__
+packet,675.175000,__
+packet,675.258000,__
+packet,675.508000,__
+packet,675.383000,__
+packet,675.341000,__
+packet,675.425000,__
+packet,675.466000,__
+packet,675.633000,__
+packet,675.550000,__
+packet,675.592000,__
+packet,675.925000,__
+packet,675.758000,__
+packet,675.675000,__
+packet,675.717000,__
+packet,675.800000,__
+packet,675.842000,__
+packet,675.884000,__
+packet,676.092000,__
+packet,676.009000,__
+packet,675.967000,__
+packet,676.050000,__
+packet,676.134000,__
+packet,676.176000,__
+packet,676.217000,K_
+packet,676.301000,__
+packet,676.259000,__
+packet,676.384000,__
+packet,676.342000,__
+packet,676.551000,__
+packet,676.467000,__
+packet,676.426000,__
+packet,676.509000,__
+packet,676.634000,__
+packet,676.593000,__
+packet,676.801000,__
+packet,676.718000,__
+packet,676.676000,__
+packet,676.759000,__
+packet,677.010000,__
+packet,676.885000,__
+packet,676.843000,__
+packet,676.926000,__
+packet,676.968000,__
+packet,677.177000,__
+packet,677.093000,__
+packet,677.051000,__
+packet,677.135000,__
+packet,677.302000,__
+packet,677.218000,__
+packet,677.260000,__
+packet,677.427000,__
+packet,677.343000,__
+packet,677.385000,__
+packet,677.594000,__
+packet,677.510000,__
+packet,677.468000,__
+packet,677.552000,__
+packet,677.719000,__
+packet,677.635000,__
+packet,677.677000,__
+packet,677.886000,__
+packet,677.802000,__
+packet,677.760000,__
+packet,677.844000,__
+packet,678.052000,__
+packet,677.969000,__
+packet,677.927000,__
+packet,678.011000,__
+packet,678.178000,__
+packet,678.094000,__
+packet,678.136000,__
+packet,678.344000,__
+packet,678.261000,__
+packet,678.219000,__
+packet,678.303000,__
+packet,678.511000,__
+packet,678.428000,__
+packet,678.386000,__
+packet,678.469000,__
+packet,678.595000,__
+packet,678.553000,__
+packet,678.678000,__
+packet,678.636000,__
+packet,678.887000,__
+packet,678.761000,__
+packet,678.720000,__
+packet,678.803000,__
+packet,678.845000,__
+packet,679.012000,__
+packet,678.928000,__
+packet,678.970000,__
+packet,679.137000,__
+packet,679.053000,__
+packet,679.095000,__
+packet,679.304000,__
+packet,679.220000,__
+packet,679.179000,__
+packet,679.262000,__
+packet,679.429000,__
+packet,679.345000,__
+packet,679.387000,__
+packet,679.637000,__
+packet,679.512000,__
+packet,679.470000,__
+packet,679.554000,__
+packet,679.596000,__
+packet,679.804000,__
+packet,679.721000,__
+packet,679.679000,__
+packet,679.762000,__
+packet,679.929000,__
+packet,679.846000,__
+packet,679.888000,__
+packet,680.138000,__
+packet,680.013000,__
+packet,679.971000,__
+packet,680.054000,__
+packet,680.096000,__
+packet,680.221000,__
+packet,680.180000,__
+packet,680.346000,__
+packet,680.263000,__
+packet,680.305000,__
+packet,680.513000,__
+packet,680.430000,__
+packet,680.388000,__
+packet,680.471000,__
+packet,680.763000,__
+packet,680.638000,__
+packet,680.555000,__
+packet,680.597000,__
+packet,680.680000,__
+packet,680.722000,__
+packet,680.847000,__
+packet,680.805000,__
+packet,681.014000,__
+packet,680.930000,__
+packet,680.889000,__
+packet,680.972000,__
+packet,681.181000,__
+packet,681.097000,__
+packet,681.055000,__
+packet,681.139000,__
+packet,681.222000,K_
+packet,681.389000,__
+packet,681.306000,__
+packet,681.264000,__
+packet,681.347000,__
+packet,681.556000,__
+packet,681.472000,__
+packet,681.431000,__
+packet,681.514000,__
+packet,681.723000,__
+packet,681.639000,__
+packet,681.598000,__
+packet,681.681000,__
+packet,681.890000,__
+packet,681.806000,__
+packet,681.764000,__
+packet,681.848000,__
+packet,682.015000,__
+packet,681.931000,__
+packet,681.973000,__
+packet,682.223000,__
+packet,682.098000,__
+packet,682.056000,__
+packet,682.140000,__
+packet,682.182000,__
+packet,682.390000,__
+packet,682.307000,__
+packet,682.265000,__
+packet,682.348000,__
+packet,682.515000,__
+packet,682.432000,__
+packet,682.473000,__
+packet,682.640000,__
+packet,682.557000,__
+packet,682.599000,__
+packet,682.849000,__
+packet,682.724000,__
+packet,682.682000,__
+packet,682.765000,__
+packet,682.807000,__
+packet,682.974000,__
+packet,682.891000,__
+packet,682.932000,__
+packet,683.141000,__
+packet,683.057000,__
+packet,683.016000,__
+packet,683.099000,__
+packet,683.349000,__
+packet,683.224000,__
+packet,683.183000,__
+packet,683.266000,__
+packet,683.308000,__
+packet,683.391000,__
+packet,683.600000,__
+packet,683.474000,__
+packet,683.433000,__
+packet,683.516000,__
+packet,683.558000,__
+packet,683.766000,__
+packet,683.683000,__
+packet,683.641000,__
+packet,683.725000,__
+packet,683.933000,__
+packet,683.850000,__
+packet,683.808000,__
+packet,683.892000,__
+packet,684.058000,__
+packet,683.975000,__
+packet,684.017000,__
+packet,684.267000,__
+packet,684.142000,__
+packet,684.100000,__
+packet,684.184000,__
+packet,684.225000,__
+packet,684.392000,__
+packet,684.309000,__
+packet,684.350000,__
+packet,684.601000,__
+packet,684.475000,__
+packet,684.434000,__
+packet,684.517000,__
+packet,684.559000,__
+packet,684.767000,__
+packet,684.684000,__
+packet,684.642000,__
+packet,684.726000,__
+packet,684.893000,__
+packet,684.809000,__
+packet,684.851000,__
+packet,684.934000,__
+packet,684.976000,K_
+packet,685.143000,__
+packet,685.059000,__
+packet,685.018000,__
+packet,685.101000,__
+packet,685.351000,__
+packet,685.226000,__
+packet,685.185000,__
+packet,685.268000,__
+packet,685.310000,__
+packet,685.476000,__
+packet,685.393000,__
+packet,685.435000,__
+packet,685.643000,__
+packet,685.560000,__
+packet,685.518000,__
+packet,685.602000,__
+packet,685.852000,__
+packet,685.727000,__
+packet,685.685000,__
+packet,685.768000,__
+packet,685.810000,__
+packet,686.019000,__
+packet,685.935000,__
+packet,685.894000,__
+packet,685.977000,__
+packet,686.186000,__
+packet,686.102000,__
+packet,686.060000,__
+packet,686.144000,__
+packet,686.352000,__
+packet,686.269000,__
+packet,686.227000,__
+packet,686.311000,__
+packet,686.477000,__
+packet,686.394000,__
+packet,686.436000,__
+packet,686.644000,__
+packet,686.561000,__
+packet,686.519000,__
+packet,686.603000,__
+packet,686.853000,__
+packet,686.728000,__
+packet,686.686000,__
+packet,686.769000,__
+packet,686.811000,__
+packet,687.020000,__
+packet,686.936000,__
+packet,686.895000,__
+packet,686.978000,__
+packet,687.103000,__
+packet,687.061000,__
+packet,687.353000,__
+packet,687.228000,__
+packet,687.145000,__
+packet,687.187000,__
+packet,687.270000,__
+packet,687.312000,__
+packet,687.478000,__
+packet,687.395000,__
+packet,687.437000,__
+packet,687.520000,K_
+packet,687.645000,__
+packet,687.562000,__
+packet,687.604000,__
+packet,687.896000,__
+packet,687.770000,__
+packet,687.687000,__
+packet,687.729000,__
+packet,687.812000,__
+packet,687.854000,__
+packet,688.271000,__
+packet,688.062000,__
+packet,687.937000,__
+packet,687.979000,__
+packet,688.021000,__
+packet,688.104000,__
+packet,688.146000,__
+packet,688.188000,__
+packet,688.229000,__
+packet,688.521000,__
+packet,688.396000,__
+packet,688.313000,__
+packet,688.354000,__
+packet,688.438000,__
+packet,688.479000,__
+packet,688.771000,__
+packet,688.646000,__
+packet,688.563000,__
+packet,688.605000,__
+packet,688.688000,__
+packet,688.730000,__
+packet,689.022000,__
+packet,688.897000,__
+packet,688.813000,__
+packet,688.855000,__
+packet,688.938000,__
+packet,688.980000,__
+packet,689.355000,__
+packet,689.189000,__
+packet,689.063000,__
+packet,689.105000,__
+packet,689.147000,__
+packet,689.230000,__
+packet,689.272000,__
+packet,689.314000,__
+packet,689.647000,__
+packet,689.480000,__
+packet,689.397000,__
+packet,689.439000,__
+packet,689.522000,__
+packet,689.564000,__
+packet,689.606000,__
+packet,689.856000,__
+packet,689.731000,__
+packet,689.689000,__
+packet,689.772000,__
+packet,689.814000,__
+packet,690.231000,__
+packet,690.023000,__
+packet,689.898000,__
+packet,689.939000,__
+packet,689.981000,__
+packet,690.064000,__
+packet,690.106000,__
+packet,690.148000,__
+packet,690.190000,__
+packet,690.273000,__
+packet,690.523000,__
+packet,690.398000,__
+packet,690.315000,__
+packet,690.356000,__
+packet,690.440000,__
+packet,690.481000,__
+packet,690.773000,__
+packet,690.648000,__
+packet,690.565000,__
+packet,690.607000,__
+packet,690.690000,__
+packet,690.732000,__
+packet,691.024000,__
+packet,690.899000,__
+packet,690.815000,__
+packet,690.857000,__
+packet,690.940000,__
+packet,690.982000,__
+packet,691.232000,__
+packet,691.107000,__
+packet,691.065000,__
+packet,691.149000,__
+packet,691.191000,__
+packet,691.274000,K_
+packet,691.441000,__
+packet,691.357000,__
+packet,691.316000,__
+packet,691.399000,__
+packet,691.649000,__
+packet,691.524000,__
+packet,691.482000,__
+packet,691.566000,__
+packet,691.608000,__
+packet,691.900000,__
+packet,691.774000,__
+packet,691.691000,__
+packet,691.733000,__
+packet,691.816000,__
+packet,691.858000,__
+packet,692.275000,__
+packet,692.066000,__
+packet,691.941000,__
+packet,691.983000,__
+packet,692.025000,__
+packet,692.108000,__
+packet,692.150000,__
+packet,692.192000,__
+packet,692.233000,__
+packet,692.400000,__
+packet,692.317000,__
+packet,692.358000,__
+packet,692.567000,__
+packet,692.483000,__
+packet,692.442000,__
+packet,692.525000,__
+packet,692.901000,__
+packet,692.734000,__
+packet,692.609000,__
+packet,692.650000,__
+packet,692.692000,__
+packet,692.775000,__
+packet,692.817000,__
+packet,692.859000,__
+packet,693.151000,__
+packet,693.026000,__
+packet,692.942000,__
+packet,692.984000,__
+packet,693.067000,__
+packet,693.109000,__
+packet,693.401000,__
+packet,693.276000,__
+packet,693.193000,__
+packet,693.234000,__
+packet,693.318000,__
+packet,693.359000,__
+packet,693.735000,__
+packet,693.568000,__
+packet,693.443000,__
+packet,693.484000,__
+packet,693.526000,__
+packet,693.610000,__
+packet,693.651000,__
+packet,693.693000,__
+packet,694.068000,__
+packet,693.902000,__
+packet,693.776000,__
+packet,693.818000,__
+packet,693.860000,__
+packet,693.943000,__
+packet,693.985000,__
+packet,694.027000,__
+packet,694.235000,__
+packet,694.152000,__
+packet,694.110000,__
+packet,694.194000,__
+packet,694.402000,__
+packet,694.319000,__
+packet,694.277000,__
+packet,694.360000,__
+packet,694.611000,__
+packet,694.485000,__
+packet,694.444000,__
+packet,694.527000,__
+packet,694.569000,__
+packet,694.652000,__
+packet,694.861000,__
+packet,694.736000,__
+packet,694.694000,__
+packet,694.777000,__
+packet,694.819000,__
+packet,694.903000,__
+packet,695.069000,__
+packet,694.986000,__
+packet,694.944000,__
+packet,695.028000,__
+packet,695.236000,__
+packet,695.153000,__
+packet,695.111000,__
+packet,695.195000,__
+packet,695.403000,__
+packet,695.320000,__
+packet,695.278000,__
+packet,695.361000,__
+packet,695.612000,__
+packet,695.486000,__
+packet,695.445000,__
+packet,695.528000,__
+packet,695.570000,__
+packet,695.737000,__
+packet,695.653000,__
+packet,695.695000,__
+packet,695.862000,__
+packet,695.778000,__
+packet,695.820000,__
+packet,695.987000,__
+packet,695.904000,__
+packet,695.945000,__
+packet,696.112000,__
+packet,696.029000,__
+packet,696.070000,__
+packet,696.154000,__
+packet,696.237000,__
+packet,696.196000,__
+packet,696.404000,__
+packet,696.321000,__
+packet,696.279000,__
+packet,696.362000,__
+packet,696.487000,__
+packet,696.446000,__
+packet,696.613000,__
+packet,696.529000,__
+packet,696.571000,__
+packet,696.821000,__
+packet,696.696000,__
+packet,696.654000,__
+packet,696.738000,__
+packet,696.779000,__
+packet,696.946000,__
+packet,696.863000,__
+packet,696.905000,__
+packet,697.113000,__
+packet,697.030000,__
+packet,696.988000,__
+packet,697.071000,__
+packet,697.197000,__
+packet,697.155000,__
+packet,697.363000,__
+packet,697.280000,__
+packet,697.238000,__
+packet,697.322000,__
+packet,697.530000,__
+packet,697.447000,__
+packet,697.405000,__
+packet,697.488000,__
+packet,697.697000,__
+packet,697.614000,__
+packet,697.572000,__
+packet,697.655000,__
+packet,697.864000,__
+packet,697.780000,__
+packet,697.739000,__
+packet,697.822000,__
+packet,697.989000,__
+packet,697.906000,__
+packet,697.947000,__
+packet,698.198000,__
+packet,698.072000,__
+packet,698.031000,__
+packet,698.114000,__
+packet,698.156000,__
+packet,698.239000,__
+packet,698.281000,__
+packet,698.323000,K_
+packet,698.364000,__
+packet,698.406000,__
+packet,698.448000,__
+packet,698.489000,__
+packet,698.531000,__
+packet,698.573000,__
+packet,698.781000,__
+packet,698.656000,__
+packet,698.615000,__
+packet,698.698000,__
+packet,698.740000,__
+packet,699.032000,__
+packet,698.907000,__
+packet,698.823000,__
+packet,698.865000,__
+packet,698.948000,__
+packet,698.990000,__
+packet,699.407000,__
+packet,699.199000,__
+packet,699.073000,__
+packet,699.115000,__
+packet,699.157000,__
+packet,699.240000,__
+packet,699.282000,__
+packet,699.324000,__
+packet,699.365000,__
+packet,699.449000,__
+packet,699.490000,K_
+packet,699.574000,__
+packet,699.532000,__
+packet,699.616000,__
+packet,699.657000,__
+packet,699.699000,__
+packet,699.741000,__
+packet,699.782000,__
+packet,699.824000,__
+packet,699.866000,__
+packet,699.908000,__
+packet,699.949000,__
+packet,699.991000,__
+packet,700.033000,__
+packet,700.074000,__
+packet,700.116000,__
+packet,700.158000,__
+packet,700.241000,__
+packet,700.200000,__
+packet,700.533000,__
+packet,700.366000,__
+packet,700.283000,__
+packet,700.325000,__
+packet,700.408000,__
+packet,700.450000,__
+packet,700.491000,__
+packet,700.700000,__
+packet,700.617000,__
+packet,700.575000,__
+packet,700.658000,__
+packet,700.909000,__
+packet,700.783000,__
+packet,700.742000,__
+packet,700.825000,__
+packet,700.867000,__
+packet,701.075000,__
+packet,700.992000,__
+packet,700.950000,__
+packet,701.034000,__
+packet,701.117000,__
+packet,701.159000,__
+packet,701.326000,__
+packet,701.242000,__
+packet,701.201000,__
+packet,701.284000,__
+packet,701.576000,__
+packet,701.451000,__
+packet,701.367000,__
+packet,701.409000,__
+packet,701.492000,__
+packet,701.534000,__
+packet,701.743000,__
+packet,701.659000,__
+packet,701.618000,__
+packet,701.701000,__
+packet,701.910000,__
+packet,701.826000,__
+packet,701.784000,__
+packet,701.868000,__
+packet,702.076000,__
+packet,701.993000,__
+packet,701.951000,__
+packet,702.035000,__
+packet,702.243000,__
+packet,702.160000,__
+packet,702.118000,__
+packet,702.202000,__
+packet,702.410000,__
+packet,702.327000,__
+packet,702.285000,__
+packet,702.368000,__
+packet,702.452000,__
+packet,702.493000,K_
+packet,702.702000,__
+packet,702.577000,__
+packet,702.535000,__
+packet,702.619000,__
+packet,702.660000,__
+packet,702.744000,__
+packet,702.785000,__
+packet,702.827000,__
+packet,702.869000,__
+packet,702.911000,__
+packet,702.952000,__
+packet,702.994000,__
+packet,703.036000,__
+packet,703.077000,__
+packet,703.119000,__
+packet,703.161000,__
+packet,703.203000,__
+packet,703.244000,__
+packet,703.286000,__
+packet,703.328000,__
+packet,703.369000,__
+packet,703.411000,__
+packet,703.453000,__
+packet,703.494000,__
+packet,703.536000,__
+packet,703.578000,__
+packet,703.620000,__
+packet,703.661000,__
+packet,703.703000,__
+packet,703.745000,__
+packet,703.786000,__
+packet,703.828000,__
+packet,703.870000,__
+packet,703.912000,__
+packet,703.953000,__
+packet,703.995000,__
+packet,704.037000,__
+packet,704.078000,__
+packet,704.120000,__
+packet,704.495000,__
+packet,704.287000,__
+packet,704.162000,__
+packet,704.204000,__
+packet,704.245000,__
+packet,704.329000,__
+packet,704.370000,__
+packet,704.412000,__
+packet,704.454000,__
+packet,704.871000,__
+packet,704.662000,__
+packet,704.537000,__
+packet,704.579000,__
+packet,704.621000,__
+packet,704.704000,__
+packet,704.746000,__
+packet,704.787000,__
+packet,704.829000,__
+packet,705.163000,__
+packet,704.996000,__
+packet,704.913000,__
+packet,704.954000,__
+packet,705.038000,__
+packet,705.079000,__
+packet,705.121000,__
+packet,705.538000,__
+packet,705.330000,__
+packet,705.205000,__
+packet,705.246000,__
+packet,705.288000,__
+packet,705.371000,__
+packet,705.413000,__
+packet,705.455000,__
+packet,705.496000,__
+packet,705.914000,__
+packet,705.705000,__
+packet,705.580000,__
+packet,705.622000,__
+packet,705.663000,__
+packet,705.747000,__
+packet,705.788000,__
+packet,705.830000,__
+packet,705.872000,__
+packet,706.289000,__
+packet,706.080000,__
+packet,705.955000,__
+packet,705.997000,__
+packet,706.039000,__
+packet,706.122000,__
+packet,706.164000,__
+packet,706.206000,__
+packet,706.247000,__
+stream,N/A
+format,706.336000
diff --git a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_result.json b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_result.json
new file mode 100644
index 000000000..72bf552cf
--- /dev/null
+++ b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_result.json
@@ -0,0 +1 @@
+{"TotalDuration":7063360000,"KeyframeTicks":[0,103850000,133880000,145150000,165580000,186440000,196450000,209790000,314060000,326990000,396230000,407070000,432520000,476310000,523020000,535540000,550550000,631050000,646480000,665670000,686520000,732400000,772020000,796210000,856690000,887970000,903820000,934270000,983070000,1056060000,1087750000,1187850000,1222050000,1251250000,1265430000,1305470000,1333830000,1345510000,1356770000,1368450000,1427260000,1460630000,1500670000,1540710000,1584500000,1607020000,1627880000,1639550000,1672090000,1685020000,1789290000,1883130000,1909820000,1931510000,1996580000,2017020000,2035370000,2051220000,2065400000,2085000000,2109190000,2120870000,2168420000,2253920000,2295210000,2374460000,2478730000,2582160000,2607190000,2697280000,2783610000,2825320000,2899560000,2929590000,2979230000,3017600000,3048880000,3073490000,3117700000,3141050000,3158160000,3200700000,3279530000,3299960000,3312890000,3332910000,3369200000,3379630000,3438440000,3459290000,3490990000,3533110000,3562730000,3600260000,3624040000,3672000000,3722050000,3753330000,3771270000,3875540000,3957290000,4016100000,4100350000,4114530000,4124540000,4157900000,4180430000,4200450000,4222550000,4252160000,4295960000,4309720000,4328070000,4340590000,4371450000,4400230000,4426920000,4489490000,4512010000,4531190000,4569570000,4599600000,4635460000,4660070000,4680930000,4729310000,4757670000,4777690000,4808550000,4824400000,4851100000,4864440000,4905320000,4955370000,4970380000,5074650000,5095090000,5109270000,5186010000,5204370000,5227720000,5242740000,5266930000,5342000000,5433760000,5447110000,5470470000,5520520000,5550550000,5565140000,5611020000,5642300000,5668160000,5711120000,5743240000,5762420000,5797460000,5817480000,5839170000,5855850000,5870870000,5904230000,5969300000,6056880000,6104850000,6152400000,6256250000,6295870000,6310050000,6325900000,6341750000,6356770000,6385960000,6426840000,6454780000,6469800000,6514420000,6549460000,6574480000,6602010000,6619530000,6654560000,6667080000,6690430000,6724630000,6762170000,6812220000,6849760000,6875200000,6912740000,6983230000,6994900000,7024930000]}
diff --git a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_streamduration.txt b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_streamduration.txt
new file mode 100644
index 000000000..36c9e5772
--- /dev/null
+++ b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_streamduration.txt
@@ -0,0 +1,2398 @@
+packet,0.000000,K_
+packet,0.375000,__
+packet,0.167000,__
+packet,0.042000,__
+packet,0.083000,__
+packet,0.125000,__
+packet,0.209000,__
+packet,0.250000,__
+packet,0.292000,__
+packet,0.334000,__
+packet,0.751000,__
+packet,0.542000,__
+packet,0.417000,__
+packet,0.459000,__
+packet,0.501000,__
+packet,0.584000,__
+packet,0.626000,__
+packet,0.667000,__
+packet,0.709000,__
+packet,0.959000,__
+packet,0.834000,__
+packet,0.792000,__
+packet,0.876000,__
+packet,0.918000,__
+packet,1.001000,__
+packet,1.168000,__
+packet,1.084000,__
+packet,1.043000,__
+packet,1.126000,__
+packet,1.335000,__
+packet,1.251000,__
+packet,1.210000,__
+packet,1.293000,__
+packet,1.460000,__
+packet,1.376000,__
+packet,1.418000,__
+packet,1.668000,__
+packet,1.543000,__
+packet,1.502000,__
+packet,1.585000,__
+packet,1.627000,__
+packet,1.793000,__
+packet,1.710000,__
+packet,1.752000,__
+packet,1.960000,__
+packet,1.877000,__
+packet,1.835000,__
+packet,1.919000,__
+packet,2.127000,__
+packet,2.044000,__
+packet,2.002000,__
+packet,2.085000,__
+packet,2.211000,__
+packet,2.169000,__
+packet,2.377000,__
+packet,2.294000,__
+packet,2.252000,__
+packet,2.336000,__
+packet,2.461000,__
+packet,2.419000,__
+packet,2.503000,__
+packet,2.544000,__
+packet,2.628000,__
+packet,2.586000,__
+packet,2.669000,__
+packet,2.711000,__
+packet,2.794000,__
+packet,2.753000,__
+packet,2.836000,__
+packet,2.878000,__
+packet,2.920000,__
+packet,2.961000,__
+packet,3.003000,__
+packet,3.045000,__
+packet,3.086000,__
+packet,3.128000,__
+packet,3.170000,__
+packet,3.212000,__
+packet,3.337000,__
+packet,3.253000,__
+packet,3.295000,__
+packet,3.420000,__
+packet,3.378000,__
+packet,3.462000,__
+packet,3.504000,__
+packet,3.545000,__
+packet,3.587000,__
+packet,3.629000,__
+packet,3.670000,__
+packet,3.712000,__
+packet,3.754000,__
+packet,3.837000,__
+packet,3.795000,__
+packet,3.879000,__
+packet,3.921000,__
+packet,3.962000,__
+packet,4.004000,__
+packet,4.046000,__
+packet,4.087000,__
+packet,4.129000,__
+packet,4.171000,__
+packet,4.213000,__
+packet,4.254000,__
+packet,4.338000,__
+packet,4.296000,__
+packet,4.421000,__
+packet,4.379000,__
+packet,4.505000,__
+packet,4.463000,__
+packet,4.588000,__
+packet,4.546000,__
+packet,4.630000,__
+packet,4.671000,__
+packet,4.713000,__
+packet,4.838000,__
+packet,4.755000,__
+packet,4.796000,__
+packet,4.880000,__
+packet,4.922000,__
+packet,4.963000,__
+packet,5.005000,__
+packet,5.047000,__
+packet,5.088000,__
+packet,5.130000,__
+packet,5.172000,__
+packet,5.214000,__
+packet,5.297000,__
+packet,5.255000,__
+packet,5.339000,__
+packet,5.380000,__
+packet,5.422000,__
+packet,5.464000,__
+packet,5.506000,__
+packet,5.547000,__
+packet,5.589000,__
+packet,5.631000,__
+packet,5.756000,__
+packet,5.672000,__
+packet,5.714000,__
+packet,5.923000,__
+packet,5.839000,__
+packet,5.797000,__
+packet,5.881000,__
+packet,6.089000,__
+packet,6.006000,__
+packet,5.964000,__
+packet,6.048000,__
+packet,6.256000,__
+packet,6.173000,__
+packet,6.131000,__
+packet,6.215000,__
+packet,6.381000,__
+packet,6.298000,__
+packet,6.340000,__
+packet,6.465000,__
+packet,6.423000,__
+packet,6.590000,__
+packet,6.507000,__
+packet,6.548000,__
+packet,6.632000,__
+packet,6.715000,__
+packet,6.673000,__
+packet,6.757000,__
+packet,6.882000,__
+packet,6.798000,__
+packet,6.840000,__
+packet,6.924000,__
+packet,6.965000,__
+packet,7.007000,__
+packet,7.049000,__
+packet,7.090000,__
+packet,7.132000,__
+packet,7.174000,__
+packet,7.216000,__
+packet,7.257000,__
+packet,7.299000,__
+packet,7.341000,__
+packet,7.382000,__
+packet,7.424000,__
+packet,7.466000,__
+packet,7.508000,__
+packet,7.549000,__
+packet,7.591000,__
+packet,7.633000,__
+packet,7.674000,__
+packet,7.716000,__
+packet,7.758000,__
+packet,7.799000,__
+packet,7.841000,__
+packet,7.966000,__
+packet,7.883000,__
+packet,7.925000,__
+packet,8.050000,__
+packet,8.008000,__
+packet,8.091000,__
+packet,8.133000,__
+packet,8.217000,__
+packet,8.175000,__
+packet,8.258000,__
+packet,8.300000,__
+packet,8.342000,__
+packet,8.383000,__
+packet,8.425000,__
+packet,8.467000,__
+packet,8.509000,__
+packet,8.550000,__
+packet,8.592000,__
+packet,8.634000,__
+packet,8.717000,__
+packet,8.675000,__
+packet,8.759000,__
+packet,8.800000,__
+packet,8.842000,__
+packet,8.884000,__
+packet,8.926000,__
+packet,8.967000,__
+packet,9.009000,__
+packet,9.051000,__
+packet,9.092000,__
+packet,9.134000,__
+packet,9.176000,__
+packet,9.218000,__
+packet,9.259000,__
+packet,9.301000,__
+packet,9.343000,__
+packet,9.384000,__
+packet,9.426000,__
+packet,9.468000,__
+packet,9.510000,__
+packet,9.551000,__
+packet,9.593000,__
+packet,9.635000,__
+packet,9.718000,__
+packet,9.676000,__
+packet,9.801000,__
+packet,9.760000,__
+packet,9.927000,__
+packet,9.843000,__
+packet,9.885000,__
+packet,10.010000,__
+packet,9.968000,__
+packet,10.052000,__
+packet,10.093000,__
+packet,10.177000,__
+packet,10.135000,__
+packet,10.260000,__
+packet,10.219000,__
+packet,10.302000,__
+packet,10.344000,__
+packet,10.385000,K_
+packet,10.427000,__
+packet,10.469000,__
+packet,10.511000,__
+packet,10.552000,__
+packet,10.594000,__
+packet,10.636000,__
+packet,10.677000,__
+packet,10.719000,__
+packet,10.761000,__
+packet,10.802000,__
+packet,10.844000,__
+packet,10.886000,__
+packet,10.928000,__
+packet,10.969000,__
+packet,11.011000,__
+packet,11.053000,__
+packet,11.094000,__
+packet,11.220000,__
+packet,11.136000,__
+packet,11.178000,__
+packet,11.345000,__
+packet,11.261000,__
+packet,11.303000,__
+packet,11.553000,__
+packet,11.428000,__
+packet,11.386000,__
+packet,11.470000,__
+packet,11.512000,__
+packet,11.637000,__
+packet,11.595000,__
+packet,11.762000,__
+packet,11.678000,__
+packet,11.720000,__
+packet,11.845000,__
+packet,11.803000,__
+packet,11.887000,__
+packet,11.929000,__
+packet,11.970000,__
+packet,12.012000,__
+packet,12.054000,__
+packet,12.095000,__
+packet,12.137000,__
+packet,12.179000,__
+packet,12.262000,__
+packet,12.221000,__
+packet,12.304000,__
+packet,12.346000,__
+packet,12.387000,__
+packet,12.429000,__
+packet,12.471000,__
+packet,12.513000,__
+packet,12.554000,__
+packet,12.596000,__
+packet,12.846000,__
+packet,12.721000,__
+packet,12.638000,__
+packet,12.679000,__
+packet,12.763000,__
+packet,12.804000,__
+packet,12.971000,__
+packet,12.888000,__
+packet,12.930000,__
+packet,13.180000,__
+packet,13.055000,__
+packet,13.013000,__
+packet,13.096000,__
+packet,13.138000,__
+packet,13.347000,__
+packet,13.263000,__
+packet,13.222000,__
+packet,13.305000,__
+packet,13.388000,K_
+packet,13.472000,__
+packet,13.430000,__
+packet,13.722000,__
+packet,13.597000,__
+packet,13.514000,__
+packet,13.555000,__
+packet,13.639000,__
+packet,13.680000,__
+packet,13.847000,__
+packet,13.764000,__
+packet,13.805000,__
+packet,13.889000,__
+packet,13.972000,__
+packet,13.931000,__
+packet,14.139000,__
+packet,14.056000,__
+packet,14.014000,__
+packet,14.097000,__
+packet,14.389000,__
+packet,14.264000,__
+packet,14.181000,__
+packet,14.223000,__
+packet,14.306000,__
+packet,14.348000,__
+packet,14.473000,__
+packet,14.431000,__
+packet,14.515000,K_
+packet,14.681000,__
+packet,14.598000,__
+packet,14.556000,__
+packet,14.640000,__
+packet,14.765000,__
+packet,14.723000,__
+packet,14.806000,__
+packet,14.848000,__
+packet,14.890000,__
+packet,14.932000,__
+packet,14.973000,__
+packet,15.015000,__
+packet,15.057000,__
+packet,15.098000,__
+packet,15.140000,__
+packet,15.224000,__
+packet,15.182000,__
+packet,15.265000,__
+packet,15.432000,__
+packet,15.349000,__
+packet,15.307000,__
+packet,15.390000,__
+packet,15.557000,__
+packet,15.474000,__
+packet,15.516000,__
+packet,15.599000,__
+packet,15.641000,__
+packet,15.724000,__
+packet,15.682000,__
+packet,15.766000,__
+packet,15.891000,__
+packet,15.807000,__
+packet,15.849000,__
+packet,15.974000,__
+packet,15.933000,__
+packet,16.016000,__
+packet,16.058000,__
+packet,16.099000,__
+packet,16.225000,__
+packet,16.141000,__
+packet,16.183000,__
+packet,16.266000,__
+packet,16.308000,__
+packet,16.350000,__
+packet,16.391000,__
+packet,16.433000,__
+packet,16.475000,__
+packet,16.517000,__
+packet,16.558000,K_
+packet,16.683000,__
+packet,16.600000,__
+packet,16.642000,__
+packet,16.808000,__
+packet,16.725000,__
+packet,16.767000,__
+packet,16.934000,__
+packet,16.850000,__
+packet,16.892000,__
+packet,17.017000,__
+packet,16.975000,__
+packet,17.100000,__
+packet,17.059000,__
+packet,17.267000,__
+packet,17.184000,__
+packet,17.142000,__
+packet,17.226000,__
+packet,17.434000,__
+packet,17.351000,__
+packet,17.309000,__
+packet,17.392000,__
+packet,17.518000,__
+packet,17.476000,__
+packet,17.684000,__
+packet,17.601000,__
+packet,17.559000,__
+packet,17.643000,__
+packet,17.851000,__
+packet,17.768000,__
+packet,17.726000,__
+packet,17.809000,__
+packet,18.018000,__
+packet,17.935000,__
+packet,17.893000,__
+packet,17.976000,__
+packet,18.101000,__
+packet,18.060000,__
+packet,18.185000,__
+packet,18.143000,__
+packet,18.352000,__
+packet,18.268000,__
+packet,18.227000,__
+packet,18.310000,__
+packet,18.519000,__
+packet,18.435000,__
+packet,18.393000,__
+packet,18.477000,__
+packet,18.602000,__
+packet,18.560000,__
+packet,18.644000,K_
+packet,18.769000,__
+packet,18.685000,__
+packet,18.727000,__
+packet,19.019000,__
+packet,18.894000,__
+packet,18.810000,__
+packet,18.852000,__
+packet,18.936000,__
+packet,18.977000,__
+packet,19.228000,__
+packet,19.102000,__
+packet,19.061000,__
+packet,19.144000,__
+packet,19.186000,__
+packet,19.603000,__
+packet,19.394000,__
+packet,19.269000,__
+packet,19.311000,__
+packet,19.353000,__
+packet,19.436000,__
+packet,19.478000,__
+packet,19.520000,__
+packet,19.561000,__
+packet,19.645000,K_
+packet,19.770000,__
+packet,19.686000,__
+packet,19.728000,__
+packet,19.937000,__
+packet,19.853000,__
+packet,19.811000,__
+packet,19.895000,__
+packet,20.187000,__
+packet,20.062000,__
+packet,19.978000,__
+packet,20.020000,__
+packet,20.103000,__
+packet,20.145000,__
+packet,20.354000,__
+packet,20.270000,__
+packet,20.229000,__
+packet,20.312000,__
+packet,20.646000,__
+packet,20.479000,__
+packet,20.395000,__
+packet,20.437000,__
+packet,20.521000,__
+packet,20.562000,__
+packet,20.604000,__
+packet,20.938000,__
+packet,20.771000,__
+packet,20.687000,__
+packet,20.729000,__
+packet,20.812000,__
+packet,20.854000,__
+packet,20.896000,__
+packet,20.979000,K_
+packet,21.146000,__
+packet,21.063000,__
+packet,21.021000,__
+packet,21.104000,__
+packet,21.271000,__
+packet,21.188000,__
+packet,21.230000,__
+packet,21.438000,__
+packet,21.355000,__
+packet,21.313000,__
+packet,21.396000,__
+packet,21.563000,__
+packet,21.480000,__
+packet,21.522000,__
+packet,21.688000,__
+packet,21.605000,__
+packet,21.647000,__
+packet,21.855000,__
+packet,21.772000,__
+packet,21.730000,__
+packet,21.813000,__
+packet,21.980000,__
+packet,21.897000,__
+packet,21.939000,__
+packet,22.189000,__
+packet,22.064000,__
+packet,22.022000,__
+packet,22.105000,__
+packet,22.147000,__
+packet,22.356000,__
+packet,22.272000,__
+packet,22.231000,__
+packet,22.314000,__
+packet,22.523000,__
+packet,22.439000,__
+packet,22.397000,__
+packet,22.481000,__
+packet,22.731000,__
+packet,22.606000,__
+packet,22.564000,__
+packet,22.648000,__
+packet,22.689000,__
+packet,22.981000,__
+packet,22.856000,__
+packet,22.773000,__
+packet,22.814000,__
+packet,22.898000,__
+packet,22.940000,__
+packet,23.232000,__
+packet,23.106000,__
+packet,23.023000,__
+packet,23.065000,__
+packet,23.148000,__
+packet,23.190000,__
+packet,23.315000,__
+packet,23.273000,__
+packet,23.398000,__
+packet,23.357000,__
+packet,23.565000,__
+packet,23.482000,__
+packet,23.440000,__
+packet,23.524000,__
+packet,23.607000,__
+packet,23.690000,__
+packet,23.649000,__
+packet,23.774000,__
+packet,23.732000,__
+packet,23.941000,__
+packet,23.857000,__
+packet,23.815000,__
+packet,23.899000,__
+packet,23.982000,__
+packet,24.024000,__
+packet,24.066000,__
+packet,24.107000,__
+packet,24.233000,__
+packet,24.149000,__
+packet,24.191000,__
+packet,24.358000,__
+packet,24.274000,__
+packet,24.316000,__
+packet,24.525000,__
+packet,24.441000,__
+packet,24.399000,__
+packet,24.483000,__
+packet,24.650000,__
+packet,24.566000,__
+packet,24.608000,__
+packet,24.775000,__
+packet,24.691000,__
+packet,24.733000,__
+packet,24.983000,__
+packet,24.858000,__
+packet,24.816000,__
+packet,24.900000,__
+packet,24.942000,__
+packet,25.359000,__
+packet,25.150000,__
+packet,25.025000,__
+packet,25.067000,__
+packet,25.108000,__
+packet,25.192000,__
+packet,25.234000,__
+packet,25.275000,__
+packet,25.317000,__
+packet,25.651000,__
+packet,25.484000,__
+packet,25.400000,__
+packet,25.442000,__
+packet,25.526000,__
+packet,25.567000,__
+packet,25.609000,__
+packet,25.734000,__
+packet,25.692000,__
+packet,25.776000,__
+packet,25.943000,__
+packet,25.859000,__
+packet,25.817000,__
+packet,25.901000,__
+packet,26.068000,__
+packet,25.984000,__
+packet,26.026000,__
+packet,26.443000,__
+packet,26.235000,__
+packet,26.109000,__
+packet,26.151000,__
+packet,26.193000,__
+packet,26.276000,__
+packet,26.318000,__
+packet,26.360000,__
+packet,26.401000,__
+packet,26.693000,__
+packet,26.568000,__
+packet,26.485000,__
+packet,26.527000,__
+packet,26.610000,__
+packet,26.652000,__
+packet,26.944000,__
+packet,26.818000,__
+packet,26.735000,__
+packet,26.777000,__
+packet,26.860000,__
+packet,26.902000,__
+packet,27.319000,__
+packet,27.110000,__
+packet,26.985000,__
+packet,27.027000,__
+packet,27.069000,__
+packet,27.152000,__
+packet,27.194000,__
+packet,27.236000,__
+packet,27.277000,__
+packet,27.694000,__
+packet,27.486000,__
+packet,27.361000,__
+packet,27.402000,__
+packet,27.444000,__
+packet,27.528000,__
+packet,27.569000,__
+packet,27.611000,__
+packet,27.653000,__
+packet,27.736000,__
+packet,28.111000,__
+packet,27.903000,__
+packet,27.778000,__
+packet,27.819000,__
+packet,27.861000,__
+packet,27.945000,__
+packet,27.986000,__
+packet,28.028000,__
+packet,28.070000,__
+packet,28.445000,__
+packet,28.278000,__
+packet,28.153000,__
+packet,28.195000,__
+packet,28.237000,__
+packet,28.320000,__
+packet,28.362000,__
+packet,28.403000,__
+packet,28.695000,__
+packet,28.570000,__
+packet,28.487000,__
+packet,28.529000,__
+packet,28.612000,__
+packet,28.654000,__
+packet,28.987000,__
+packet,28.820000,__
+packet,28.737000,__
+packet,28.779000,__
+packet,28.862000,__
+packet,28.904000,__
+packet,28.946000,__
+packet,29.363000,__
+packet,29.154000,__
+packet,29.029000,__
+packet,29.071000,__
+packet,29.112000,__
+packet,29.196000,__
+packet,29.238000,__
+packet,29.279000,__
+packet,29.321000,__
+packet,29.738000,__
+packet,29.530000,__
+packet,29.404000,__
+packet,29.446000,__
+packet,29.488000,__
+packet,29.571000,__
+packet,29.613000,__
+packet,29.655000,__
+packet,29.696000,__
+packet,29.863000,__
+packet,29.780000,__
+packet,29.821000,__
+packet,30.113000,__
+packet,29.988000,__
+packet,29.905000,__
+packet,29.947000,__
+packet,30.030000,__
+packet,30.072000,__
+packet,30.280000,__
+packet,30.197000,__
+packet,30.155000,__
+packet,30.239000,__
+packet,30.572000,__
+packet,30.405000,__
+packet,30.322000,__
+packet,30.364000,__
+packet,30.447000,__
+packet,30.489000,__
+packet,30.531000,__
+packet,30.656000,__
+packet,30.614000,__
+packet,30.989000,__
+packet,30.822000,__
+packet,30.697000,__
+packet,30.739000,__
+packet,30.781000,__
+packet,30.864000,__
+packet,30.906000,__
+packet,30.948000,__
+packet,31.073000,__
+packet,31.031000,__
+packet,31.365000,__
+packet,31.198000,__
+packet,31.114000,__
+packet,31.156000,__
+packet,31.240000,__
+packet,31.281000,__
+packet,31.323000,__
+packet,31.406000,K_
+packet,31.573000,__
+packet,31.490000,__
+packet,31.448000,__
+packet,31.532000,__
+packet,31.698000,__
+packet,31.615000,__
+packet,31.657000,__
+packet,32.074000,__
+packet,31.865000,__
+packet,31.740000,__
+packet,31.782000,__
+packet,31.823000,__
+packet,31.907000,__
+packet,31.949000,__
+packet,31.990000,__
+packet,32.032000,__
+packet,32.449000,__
+packet,32.241000,__
+packet,32.115000,__
+packet,32.157000,__
+packet,32.199000,__
+packet,32.282000,__
+packet,32.324000,__
+packet,32.366000,__
+packet,32.407000,__
+packet,32.658000,__
+packet,32.533000,__
+packet,32.491000,__
+packet,32.574000,__
+packet,32.616000,__
+packet,32.699000,K_
+packet,32.908000,__
+packet,32.783000,__
+packet,32.741000,__
+packet,32.824000,__
+packet,32.866000,__
+packet,33.116000,__
+packet,32.991000,__
+packet,32.950000,__
+packet,33.033000,__
+packet,33.075000,__
+packet,33.367000,__
+packet,33.242000,__
+packet,33.158000,__
+packet,33.200000,__
+packet,33.283000,__
+packet,33.325000,__
+packet,33.617000,__
+packet,33.492000,__
+packet,33.408000,__
+packet,33.450000,__
+packet,33.534000,__
+packet,33.575000,__
+packet,33.825000,__
+packet,33.700000,__
+packet,33.659000,__
+packet,33.742000,__
+packet,33.784000,__
+packet,34.117000,__
+packet,33.951000,__
+packet,33.867000,__
+packet,33.909000,__
+packet,33.992000,__
+packet,34.034000,__
+packet,34.076000,__
+packet,34.368000,__
+packet,34.243000,__
+packet,34.159000,__
+packet,34.201000,__
+packet,34.284000,__
+packet,34.326000,__
+packet,34.576000,__
+packet,34.451000,__
+packet,34.409000,__
+packet,34.493000,__
+packet,34.535000,__
+packet,34.701000,__
+packet,34.618000,__
+packet,34.660000,__
+packet,34.952000,__
+packet,34.826000,__
+packet,34.743000,__
+packet,34.785000,__
+packet,34.868000,__
+packet,34.910000,__
+packet,35.118000,__
+packet,35.035000,__
+packet,34.993000,__
+packet,35.077000,__
+packet,35.410000,__
+packet,35.244000,__
+packet,35.160000,__
+packet,35.202000,__
+packet,35.285000,__
+packet,35.327000,__
+packet,35.369000,__
+packet,35.494000,__
+packet,35.452000,__
+packet,35.744000,__
+packet,35.619000,__
+packet,35.536000,__
+packet,35.577000,__
+packet,35.661000,__
+packet,35.702000,__
+packet,35.911000,__
+packet,35.827000,__
+packet,35.786000,__
+packet,35.869000,__
+packet,36.078000,__
+packet,35.994000,__
+packet,35.953000,__
+packet,36.036000,__
+packet,36.245000,__
+packet,36.161000,__
+packet,36.119000,__
+packet,36.203000,__
+packet,36.370000,__
+packet,36.286000,__
+packet,36.328000,__
+packet,36.537000,__
+packet,36.453000,__
+packet,36.411000,__
+packet,36.495000,__
+packet,36.620000,__
+packet,36.578000,__
+packet,36.662000,__
+packet,36.787000,__
+packet,36.703000,__
+packet,36.745000,__
+packet,36.995000,__
+packet,36.870000,__
+packet,36.828000,__
+packet,36.912000,__
+packet,36.954000,__
+packet,37.162000,__
+packet,37.079000,__
+packet,37.037000,__
+packet,37.120000,__
+packet,37.329000,__
+packet,37.246000,__
+packet,37.204000,__
+packet,37.287000,__
+packet,37.454000,__
+packet,37.371000,__
+packet,37.412000,__
+packet,37.579000,__
+packet,37.496000,__
+packet,37.538000,__
+packet,37.704000,__
+packet,37.621000,__
+packet,37.663000,__
+packet,37.955000,__
+packet,37.829000,__
+packet,37.746000,__
+packet,37.788000,__
+packet,37.871000,__
+packet,37.913000,__
+packet,38.163000,__
+packet,38.038000,__
+packet,37.996000,__
+packet,38.080000,__
+packet,38.121000,__
+packet,38.330000,__
+packet,38.247000,__
+packet,38.205000,__
+packet,38.288000,__
+packet,38.455000,__
+packet,38.372000,__
+packet,38.413000,__
+packet,38.539000,__
+packet,38.497000,__
+packet,38.705000,__
+packet,38.622000,__
+packet,38.580000,__
+packet,38.664000,__
+packet,38.914000,__
+packet,38.789000,__
+packet,38.747000,__
+packet,38.830000,__
+packet,38.872000,__
+packet,39.081000,__
+packet,38.997000,__
+packet,38.956000,__
+packet,39.039000,__
+packet,39.414000,__
+packet,39.248000,__
+packet,39.122000,__
+packet,39.164000,__
+packet,39.206000,__
+packet,39.289000,__
+packet,39.331000,__
+packet,39.373000,__
+packet,39.540000,__
+packet,39.456000,__
+packet,39.498000,__
+packet,39.581000,__
+packet,39.623000,K_
+packet,39.831000,__
+packet,39.706000,__
+packet,39.665000,__
+packet,39.748000,__
+packet,39.790000,__
+packet,39.998000,__
+packet,39.915000,__
+packet,39.873000,__
+packet,39.957000,__
+packet,40.165000,__
+packet,40.082000,__
+packet,40.040000,__
+packet,40.123000,__
+packet,40.290000,__
+packet,40.207000,__
+packet,40.249000,__
+packet,40.499000,__
+packet,40.374000,__
+packet,40.332000,__
+packet,40.415000,__
+packet,40.457000,__
+packet,40.666000,__
+packet,40.582000,__
+packet,40.541000,__
+packet,40.624000,__
+packet,40.707000,K_
+packet,40.832000,__
+packet,40.749000,__
+packet,40.791000,__
+packet,40.999000,__
+packet,40.916000,__
+packet,40.874000,__
+packet,40.958000,__
+packet,41.166000,__
+packet,41.083000,__
+packet,41.041000,__
+packet,41.124000,__
+packet,41.333000,__
+packet,41.250000,__
+packet,41.208000,__
+packet,41.291000,__
+packet,41.500000,__
+packet,41.416000,__
+packet,41.375000,__
+packet,41.458000,__
+packet,41.542000,__
+packet,41.583000,__
+packet,41.792000,__
+packet,41.667000,__
+packet,41.625000,__
+packet,41.708000,__
+packet,41.750000,__
+packet,41.917000,__
+packet,41.833000,__
+packet,41.875000,__
+packet,42.125000,__
+packet,42.000000,__
+packet,41.959000,__
+packet,42.042000,__
+packet,42.084000,__
+packet,42.251000,__
+packet,42.167000,__
+packet,42.209000,__
+packet,42.459000,__
+packet,42.334000,__
+packet,42.292000,__
+packet,42.376000,__
+packet,42.417000,__
+packet,42.626000,__
+packet,42.543000,__
+packet,42.501000,__
+packet,42.584000,__
+packet,42.751000,__
+packet,42.668000,__
+packet,42.709000,__
+packet,42.918000,__
+packet,42.834000,__
+packet,42.793000,__
+packet,42.876000,__
+packet,43.126000,__
+packet,43.001000,__
+packet,42.960000,__
+packet,43.043000,__
+packet,43.085000,__
+packet,43.210000,__
+packet,43.168000,__
+packet,43.252000,K_
+packet,43.418000,__
+packet,43.335000,__
+packet,43.293000,__
+packet,43.377000,__
+packet,43.544000,__
+packet,43.460000,__
+packet,43.502000,__
+packet,43.710000,__
+packet,43.627000,__
+packet,43.585000,__
+packet,43.669000,__
+packet,43.835000,__
+packet,43.752000,__
+packet,43.794000,__
+packet,44.002000,__
+packet,43.919000,__
+packet,43.877000,__
+packet,43.961000,__
+packet,44.169000,__
+packet,44.086000,__
+packet,44.044000,__
+packet,44.127000,__
+packet,44.336000,__
+packet,44.253000,__
+packet,44.211000,__
+packet,44.294000,__
+packet,44.503000,__
+packet,44.419000,__
+packet,44.378000,__
+packet,44.461000,__
+packet,44.670000,__
+packet,44.586000,__
+packet,44.545000,__
+packet,44.628000,__
+packet,44.878000,__
+packet,44.753000,__
+packet,44.711000,__
+packet,44.795000,__
+packet,44.836000,__
+packet,44.962000,__
+packet,44.920000,__
+packet,45.128000,__
+packet,45.045000,__
+packet,45.003000,__
+packet,45.087000,__
+packet,45.212000,__
+packet,45.170000,__
+packet,45.295000,__
+packet,45.254000,__
+packet,45.379000,__
+packet,45.337000,__
+packet,45.546000,__
+packet,45.462000,__
+packet,45.420000,__
+packet,45.504000,__
+packet,45.671000,__
+packet,45.587000,__
+packet,45.629000,__
+packet,45.837000,__
+packet,45.754000,__
+packet,45.712000,__
+packet,45.796000,__
+packet,46.004000,__
+packet,45.921000,__
+packet,45.879000,__
+packet,45.963000,__
+packet,46.088000,__
+packet,46.046000,__
+packet,46.171000,__
+packet,46.129000,__
+packet,46.296000,__
+packet,46.213000,__
+packet,46.255000,__
+packet,46.380000,__
+packet,46.338000,__
+packet,46.421000,__
+packet,46.505000,__
+packet,46.463000,__
+packet,46.672000,__
+packet,46.588000,__
+packet,46.547000,__
+packet,46.630000,__
+packet,46.880000,__
+packet,46.755000,__
+packet,46.713000,__
+packet,46.797000,__
+packet,46.838000,__
+packet,47.005000,__
+packet,46.922000,__
+packet,46.964000,__
+packet,47.089000,__
+packet,47.047000,__
+packet,47.297000,__
+packet,47.172000,__
+packet,47.130000,__
+packet,47.214000,__
+packet,47.256000,__
+packet,47.464000,__
+packet,47.381000,__
+packet,47.339000,__
+packet,47.422000,__
+packet,47.589000,__
+packet,47.506000,__
+packet,47.548000,__
+packet,47.631000,K_
+packet,47.798000,__
+packet,47.714000,__
+packet,47.673000,__
+packet,47.756000,__
+packet,48.006000,__
+packet,47.881000,__
+packet,47.839000,__
+packet,47.923000,__
+packet,47.965000,__
+packet,48.131000,__
+packet,48.048000,__
+packet,48.090000,__
+packet,48.340000,__
+packet,48.215000,__
+packet,48.173000,__
+packet,48.257000,__
+packet,48.298000,__
+packet,48.507000,__
+packet,48.423000,__
+packet,48.382000,__
+packet,48.465000,__
+packet,48.632000,__
+packet,48.549000,__
+packet,48.590000,__
+packet,48.715000,__
+packet,48.674000,__
+packet,48.882000,__
+packet,48.799000,__
+packet,48.757000,__
+packet,48.840000,__
+packet,49.049000,__
+packet,48.966000,__
+packet,48.924000,__
+packet,49.007000,__
+packet,49.216000,__
+packet,49.132000,__
+packet,49.091000,__
+packet,49.174000,__
+packet,49.424000,__
+packet,49.299000,__
+packet,49.258000,__
+packet,49.341000,__
+packet,49.383000,__
+packet,49.591000,__
+packet,49.508000,__
+packet,49.466000,__
+packet,49.550000,__
+packet,49.675000,__
+packet,49.633000,__
+packet,49.841000,__
+packet,49.758000,__
+packet,49.716000,__
+packet,49.800000,__
+packet,50.008000,__
+packet,49.925000,__
+packet,49.883000,__
+packet,49.967000,__
+packet,50.133000,__
+packet,50.050000,__
+packet,50.092000,__
+packet,50.217000,__
+packet,50.175000,__
+packet,50.425000,__
+packet,50.300000,__
+packet,50.259000,__
+packet,50.342000,__
+packet,50.384000,__
+packet,50.592000,__
+packet,50.509000,__
+packet,50.467000,__
+packet,50.551000,__
+packet,50.717000,__
+packet,50.634000,__
+packet,50.676000,__
+packet,50.884000,__
+packet,50.801000,__
+packet,50.759000,__
+packet,50.842000,__
+packet,51.051000,__
+packet,50.968000,__
+packet,50.926000,__
+packet,51.009000,__
+packet,51.218000,__
+packet,51.134000,__
+packet,51.093000,__
+packet,51.176000,__
+packet,51.426000,__
+packet,51.301000,__
+packet,51.260000,__
+packet,51.343000,__
+packet,51.385000,__
+packet,51.593000,__
+packet,51.510000,__
+packet,51.468000,__
+packet,51.552000,__
+packet,51.760000,__
+packet,51.677000,__
+packet,51.635000,__
+packet,51.718000,__
+packet,51.885000,__
+packet,51.802000,__
+packet,51.843000,__
+packet,52.094000,__
+packet,51.969000,__
+packet,51.927000,__
+packet,52.010000,__
+packet,52.052000,__
+packet,52.261000,__
+packet,52.177000,__
+packet,52.135000,__
+packet,52.219000,__
+packet,52.302000,K_
+packet,52.469000,__
+packet,52.386000,__
+packet,52.344000,__
+packet,52.427000,__
+packet,52.594000,__
+packet,52.511000,__
+packet,52.553000,__
+packet,52.761000,__
+packet,52.678000,__
+packet,52.636000,__
+packet,52.719000,__
+packet,52.844000,__
+packet,52.803000,__
+packet,52.928000,__
+packet,52.886000,__
+packet,53.095000,__
+packet,53.011000,__
+packet,52.970000,__
+packet,53.053000,__
+packet,53.262000,__
+packet,53.178000,__
+packet,53.136000,__
+packet,53.220000,__
+packet,53.470000,__
+packet,53.345000,__
+packet,53.303000,__
+packet,53.387000,__
+packet,53.428000,__
+packet,53.512000,__
+packet,53.554000,K_
+packet,53.637000,__
+packet,53.595000,__
+packet,53.887000,__
+packet,53.762000,__
+packet,53.679000,__
+packet,53.720000,__
+packet,53.804000,__
+packet,53.845000,__
+packet,54.096000,__
+packet,53.971000,__
+packet,53.929000,__
+packet,54.012000,__
+packet,54.054000,__
+packet,54.346000,__
+packet,54.221000,__
+packet,54.137000,__
+packet,54.179000,__
+packet,54.263000,__
+packet,54.304000,__
+packet,54.513000,__
+packet,54.429000,__
+packet,54.388000,__
+packet,54.471000,__
+packet,54.763000,__
+packet,54.638000,__
+packet,54.555000,__
+packet,54.596000,__
+packet,54.680000,__
+packet,54.721000,__
+packet,54.930000,__
+packet,54.846000,__
+packet,54.805000,__
+packet,54.888000,__
+packet,55.013000,__
+packet,54.972000,__
+packet,55.055000,K_
+packet,55.180000,__
+packet,55.097000,__
+packet,55.138000,__
+packet,55.305000,__
+packet,55.222000,__
+packet,55.264000,__
+packet,55.430000,__
+packet,55.347000,__
+packet,55.389000,__
+packet,55.556000,__
+packet,55.472000,__
+packet,55.514000,__
+packet,55.722000,__
+packet,55.639000,__
+packet,55.597000,__
+packet,55.681000,__
+packet,56.098000,__
+packet,55.889000,__
+packet,55.764000,__
+packet,55.806000,__
+packet,55.847000,__
+packet,55.931000,__
+packet,55.973000,__
+packet,56.014000,__
+packet,56.056000,__
+packet,56.265000,__
+packet,56.181000,__
+packet,56.139000,__
+packet,56.223000,__
+packet,56.473000,__
+packet,56.348000,__
+packet,56.306000,__
+packet,56.390000,__
+packet,56.431000,__
+packet,56.640000,__
+packet,56.557000,__
+packet,56.515000,__
+packet,56.598000,__
+packet,56.682000,__
+packet,56.807000,__
+packet,56.723000,__
+packet,56.765000,__
+packet,56.848000,__
+packet,56.890000,__
+packet,56.932000,__
+packet,57.057000,__
+packet,56.974000,__
+packet,57.015000,__
+packet,57.099000,__
+packet,57.224000,__
+packet,57.140000,__
+packet,57.182000,__
+packet,57.266000,__
+packet,57.307000,__
+packet,57.474000,__
+packet,57.391000,__
+packet,57.349000,__
+packet,57.432000,__
+packet,57.516000,__
+packet,57.641000,__
+packet,57.558000,__
+packet,57.599000,__
+packet,57.683000,__
+packet,57.724000,__
+packet,57.933000,__
+packet,57.808000,__
+packet,57.766000,__
+packet,57.849000,__
+packet,57.891000,__
+packet,58.058000,__
+packet,57.975000,__
+packet,58.016000,__
+packet,58.267000,__
+packet,58.141000,__
+packet,58.100000,__
+packet,58.183000,__
+packet,58.225000,__
+packet,58.392000,__
+packet,58.308000,__
+packet,58.350000,__
+packet,58.559000,__
+packet,58.475000,__
+packet,58.433000,__
+packet,58.517000,__
+packet,58.725000,__
+packet,58.642000,__
+packet,58.600000,__
+packet,58.684000,__
+packet,58.809000,__
+packet,58.767000,__
+packet,59.017000,__
+packet,58.892000,__
+packet,58.850000,__
+packet,58.934000,__
+packet,58.976000,__
+packet,59.184000,__
+packet,59.101000,__
+packet,59.059000,__
+packet,59.142000,__
+packet,59.518000,__
+packet,59.351000,__
+packet,59.226000,__
+packet,59.268000,__
+packet,59.309000,__
+packet,59.393000,__
+packet,59.434000,__
+packet,59.476000,__
+packet,59.601000,__
+packet,59.560000,__
+packet,59.768000,__
+packet,59.685000,__
+packet,59.643000,__
+packet,59.726000,__
+packet,59.935000,__
+packet,59.851000,__
+packet,59.810000,__
+packet,59.893000,__
+packet,60.269000,__
+packet,60.102000,__
+packet,59.977000,__
+packet,60.018000,__
+packet,60.060000,__
+packet,60.143000,__
+packet,60.185000,__
+packet,60.227000,__
+packet,60.477000,__
+packet,60.352000,__
+packet,60.310000,__
+packet,60.394000,__
+packet,60.435000,__
+packet,60.644000,__
+packet,60.561000,__
+packet,60.519000,__
+packet,60.602000,__
+packet,60.811000,__
+packet,60.727000,__
+packet,60.686000,__
+packet,60.769000,__
+packet,61.019000,__
+packet,60.894000,__
+packet,60.852000,__
+packet,60.936000,__
+packet,60.978000,__
+packet,61.228000,__
+packet,61.103000,__
+packet,61.061000,__
+packet,61.144000,__
+packet,61.186000,__
+packet,61.603000,__
+packet,61.395000,__
+packet,61.270000,__
+packet,61.311000,__
+packet,61.353000,__
+packet,61.436000,__
+packet,61.478000,__
+packet,61.520000,__
+packet,61.562000,__
+packet,61.979000,__
+packet,61.770000,__
+packet,61.645000,__
+packet,61.687000,__
+packet,61.728000,__
+packet,61.812000,__
+packet,61.853000,__
+packet,61.895000,__
+packet,61.937000,__
+packet,62.271000,__
+packet,62.104000,__
+packet,62.020000,__
+packet,62.062000,__
+packet,62.145000,__
+packet,62.187000,__
+packet,62.229000,__
+packet,62.396000,__
+packet,62.312000,__
+packet,62.354000,__
+packet,62.604000,__
+packet,62.479000,__
+packet,62.437000,__
+packet,62.521000,__
+packet,62.563000,__
+packet,62.896000,__
+packet,62.729000,__
+packet,62.646000,__
+packet,62.688000,__
+packet,62.771000,__
+packet,62.813000,__
+packet,62.854000,__
+packet,63.063000,__
+packet,62.980000,__
+packet,62.938000,__
+packet,63.021000,__
+packet,63.105000,K_
+packet,63.355000,__
+packet,63.230000,__
+packet,63.146000,__
+packet,63.188000,__
+packet,63.272000,__
+packet,63.313000,__
+packet,63.605000,__
+packet,63.480000,__
+packet,63.397000,__
+packet,63.438000,__
+packet,63.522000,__
+packet,63.564000,__
+packet,63.855000,__
+packet,63.730000,__
+packet,63.647000,__
+packet,63.689000,__
+packet,63.772000,__
+packet,63.814000,__
+packet,64.106000,__
+packet,63.981000,__
+packet,63.897000,__
+packet,63.939000,__
+packet,64.022000,__
+packet,64.064000,__
+packet,64.231000,__
+packet,64.147000,__
+packet,64.189000,__
+packet,64.606000,__
+packet,64.398000,__
+packet,64.273000,__
+packet,64.314000,__
+packet,64.356000,__
+packet,64.439000,__
+packet,64.481000,__
+packet,64.523000,__
+packet,64.565000,__
+packet,64.648000,K_
+packet,64.773000,__
+packet,64.690000,__
+packet,64.731000,__
+packet,64.898000,__
+packet,64.815000,__
+packet,64.856000,__
+packet,65.107000,__
+packet,64.982000,__
+packet,64.940000,__
+packet,65.023000,__
+packet,65.065000,__
+packet,65.274000,__
+packet,65.190000,__
+packet,65.148000,__
+packet,65.232000,__
+packet,65.649000,__
+packet,65.440000,__
+packet,65.315000,__
+packet,65.357000,__
+packet,65.399000,__
+packet,65.482000,__
+packet,65.524000,__
+packet,65.566000,__
+packet,65.607000,__
+packet,65.816000,__
+packet,65.732000,__
+packet,65.691000,__
+packet,65.774000,__
+packet,66.024000,__
+packet,65.899000,__
+packet,65.857000,__
+packet,65.941000,__
+packet,65.983000,__
+packet,66.191000,__
+packet,66.108000,__
+packet,66.066000,__
+packet,66.149000,__
+packet,66.233000,__
+packet,66.400000,__
+packet,66.316000,__
+packet,66.275000,__
+packet,66.358000,__
+packet,66.525000,__
+packet,66.441000,__
+packet,66.483000,__
+packet,66.567000,K_
+packet,66.733000,__
+packet,66.650000,__
+packet,66.608000,__
+packet,66.692000,__
+packet,66.984000,__
+packet,66.858000,__
+packet,66.775000,__
+packet,66.817000,__
+packet,66.900000,__
+packet,66.942000,__
+packet,67.359000,__
+packet,67.150000,__
+packet,67.025000,__
+packet,67.067000,__
+packet,67.109000,__
+packet,67.192000,__
+packet,67.234000,__
+packet,67.276000,__
+packet,67.317000,__
+packet,67.734000,__
+packet,67.526000,__
+packet,67.401000,__
+packet,67.442000,__
+packet,67.484000,__
+packet,67.568000,__
+packet,67.609000,__
+packet,67.651000,__
+packet,67.693000,__
+packet,67.859000,__
+packet,67.776000,__
+packet,67.818000,__
+packet,68.151000,__
+packet,67.985000,__
+packet,67.901000,__
+packet,67.943000,__
+packet,68.026000,__
+packet,68.068000,__
+packet,68.110000,__
+packet,68.402000,__
+packet,68.277000,__
+packet,68.193000,__
+packet,68.235000,__
+packet,68.318000,__
+packet,68.360000,__
+packet,68.610000,__
+packet,68.485000,__
+packet,68.443000,__
+packet,68.527000,__
+packet,68.569000,__
+packet,68.652000,K_
+packet,68.819000,__
+packet,68.735000,__
+packet,68.694000,__
+packet,68.777000,__
+packet,68.986000,__
+packet,68.902000,__
+packet,68.860000,__
+packet,68.944000,__
+packet,69.361000,__
+packet,69.152000,__
+packet,69.027000,__
+packet,69.069000,__
+packet,69.111000,__
+packet,69.194000,__
+packet,69.236000,__
+packet,69.278000,__
+packet,69.319000,__
+packet,69.444000,__
+packet,69.403000,__
+packet,69.820000,__
+packet,69.611000,__
+packet,69.486000,__
+packet,69.528000,__
+packet,69.570000,__
+packet,69.653000,__
+packet,69.695000,__
+packet,69.736000,__
+packet,69.778000,__
+packet,70.028000,__
+packet,69.903000,__
+packet,69.861000,__
+packet,69.945000,__
+packet,69.987000,__
+packet,70.195000,__
+packet,70.112000,__
+packet,70.070000,__
+packet,70.153000,__
+packet,70.529000,__
+packet,70.362000,__
+packet,70.237000,__
+packet,70.279000,__
+packet,70.320000,__
+packet,70.404000,__
+packet,70.445000,__
+packet,70.487000,__
+packet,70.862000,__
+packet,70.696000,__
+packet,70.571000,__
+packet,70.612000,__
+packet,70.654000,__
+packet,70.737000,__
+packet,70.779000,__
+packet,70.821000,__
+packet,71.029000,__
+packet,70.946000,__
+packet,70.904000,__
+packet,70.988000,__
+packet,71.280000,__
+packet,71.154000,__
+packet,71.071000,__
+packet,71.113000,__
+packet,71.196000,__
+packet,71.238000,__
+packet,71.488000,__
+packet,71.363000,__
+packet,71.321000,__
+packet,71.405000,__
+packet,71.446000,__
+packet,71.863000,__
+packet,71.655000,__
+packet,71.530000,__
+packet,71.572000,__
+packet,71.613000,__
+packet,71.697000,__
+packet,71.738000,__
+packet,71.780000,__
+packet,71.822000,__
+packet,72.114000,__
+packet,71.989000,__
+packet,71.905000,__
+packet,71.947000,__
+packet,72.030000,__
+packet,72.072000,__
+packet,72.281000,__
+packet,72.197000,__
+packet,72.155000,__
+packet,72.239000,__
+packet,72.406000,__
+packet,72.322000,__
+packet,72.364000,__
+packet,72.614000,__
+packet,72.489000,__
+packet,72.447000,__
+packet,72.531000,__
+packet,72.573000,__
+packet,72.739000,__
+packet,72.656000,__
+packet,72.698000,__
+packet,73.031000,__
+packet,72.864000,__
+packet,72.781000,__
+packet,72.823000,__
+packet,72.906000,__
+packet,72.948000,__
+packet,72.990000,__
+packet,73.198000,__
+packet,73.115000,__
+packet,73.073000,__
+packet,73.156000,__
+packet,73.240000,K_
+packet,73.407000,__
+packet,73.323000,__
+packet,73.282000,__
+packet,73.365000,__
+packet,73.532000,__
+packet,73.448000,__
+packet,73.490000,__
+packet,73.699000,__
+packet,73.615000,__
+packet,73.574000,__
+packet,73.657000,__
+packet,73.865000,__
+packet,73.782000,__
+packet,73.740000,__
+packet,73.824000,__
+packet,74.032000,__
+packet,73.949000,__
+packet,73.907000,__
+packet,73.991000,__
+packet,74.199000,__
+packet,74.116000,__
+packet,74.074000,__
+packet,74.157000,__
+packet,74.283000,__
+packet,74.241000,__
+packet,74.408000,__
+packet,74.324000,__
+packet,74.366000,__
+packet,74.533000,__
+packet,74.449000,__
+packet,74.491000,__
+packet,74.700000,__
+packet,74.616000,__
+packet,74.575000,__
+packet,74.658000,__
+packet,74.866000,__
+packet,74.783000,__
+packet,74.741000,__
+packet,74.825000,__
+packet,75.033000,__
+packet,74.950000,__
+packet,74.908000,__
+packet,74.992000,__
+packet,75.200000,__
+packet,75.117000,__
+packet,75.075000,__
+packet,75.158000,__
+packet,75.409000,__
+packet,75.284000,__
+packet,75.242000,__
+packet,75.325000,__
+packet,75.367000,__
+packet,75.784000,__
+packet,75.576000,__
+packet,75.450000,__
+packet,75.492000,__
+packet,75.534000,__
+packet,75.617000,__
+packet,75.659000,__
+packet,75.701000,__
+packet,75.742000,__
+packet,75.826000,__
+packet,76.201000,__
+packet,75.993000,__
+packet,75.867000,__
+packet,75.909000,__
+packet,75.951000,__
+packet,76.034000,__
+packet,76.076000,__
+packet,76.118000,__
+packet,76.159000,__
+packet,76.368000,__
+packet,76.285000,__
+packet,76.243000,__
+packet,76.326000,__
+packet,76.451000,__
+packet,76.410000,__
+packet,76.618000,__
+packet,76.535000,__
+packet,76.493000,__
+packet,76.577000,__
+packet,76.827000,__
+packet,76.702000,__
+packet,76.660000,__
+packet,76.743000,__
+packet,76.785000,__
+packet,76.952000,__
+packet,76.868000,__
+packet,76.910000,__
+packet,77.160000,__
+packet,77.035000,__
+packet,76.994000,__
+packet,77.077000,__
+packet,77.119000,__
+packet,77.202000,K_
+packet,77.369000,__
+packet,77.286000,__
+packet,77.244000,__
+packet,77.327000,__
+packet,77.536000,__
+packet,77.452000,__
+packet,77.411000,__
+packet,77.494000,__
+packet,77.661000,__
+packet,77.578000,__
+packet,77.619000,__
+packet,77.828000,__
+packet,77.744000,__
+packet,77.703000,__
+packet,77.786000,__
+packet,77.953000,__
+packet,77.869000,__
+packet,77.911000,__
+packet,78.036000,__
+packet,77.995000,__
+packet,78.245000,__
+packet,78.120000,__
+packet,78.078000,__
+packet,78.161000,__
+packet,78.203000,__
+packet,78.328000,__
+packet,78.287000,__
+packet,78.495000,__
+packet,78.412000,__
+packet,78.370000,__
+packet,78.453000,__
+packet,78.620000,__
+packet,78.537000,__
+packet,78.579000,__
+packet,78.787000,__
+packet,78.704000,__
+packet,78.662000,__
+packet,78.745000,__
+packet,79.037000,__
+packet,78.912000,__
+packet,78.829000,__
+packet,78.870000,__
+packet,78.954000,__
+packet,78.996000,__
+packet,79.288000,__
+packet,79.162000,__
+packet,79.079000,__
+packet,79.121000,__
+packet,79.204000,__
+packet,79.246000,__
+packet,79.538000,__
+packet,79.413000,__
+packet,79.329000,__
+packet,79.371000,__
+packet,79.454000,__
+packet,79.496000,__
+packet,79.580000,__
+packet,79.621000,K_
+packet,79.663000,__
+packet,79.997000,__
+packet,79.830000,__
+packet,79.705000,__
+packet,79.746000,__
+packet,79.788000,__
+packet,79.871000,__
+packet,79.913000,__
+packet,79.955000,__
+packet,80.038000,__
+packet,80.247000,__
+packet,80.122000,__
+packet,80.080000,__
+packet,80.163000,__
+packet,80.205000,__
+packet,80.372000,__
+packet,80.289000,__
+packet,80.330000,__
+packet,80.539000,__
+packet,80.455000,__
+packet,80.414000,__
+packet,80.497000,__
+packet,80.706000,__
+packet,80.622000,__
+packet,80.581000,__
+packet,80.664000,__
+packet,80.872000,__
+packet,80.789000,__
+packet,80.747000,__
+packet,80.831000,__
+packet,81.039000,__
+packet,80.956000,__
+packet,80.914000,__
+packet,80.998000,__
+packet,81.248000,__
+packet,81.123000,__
+packet,81.081000,__
+packet,81.164000,__
+packet,81.206000,__
+packet,81.290000,__
+packet,81.456000,__
+packet,81.373000,__
+packet,81.331000,__
+packet,81.415000,__
+packet,81.623000,__
+packet,81.540000,__
+packet,81.498000,__
+packet,81.582000,__
+packet,81.999000,__
+packet,81.790000,__
+packet,81.665000,__
+packet,81.707000,__
+packet,81.748000,__
+packet,81.832000,__
+packet,81.873000,__
+packet,81.915000,__
+packet,81.957000,__
+packet,82.040000,__
+packet,82.249000,__
+packet,82.124000,__
+packet,82.082000,__
+packet,82.165000,__
+packet,82.207000,__
+packet,82.291000,__
+packet,82.541000,__
+packet,82.416000,__
+packet,82.332000,__
+packet,82.374000,__
+packet,82.457000,__
+packet,82.499000,__
+packet,82.916000,__
+packet,82.708000,__
+packet,82.583000,__
+packet,82.624000,__
+packet,82.666000,__
+packet,82.749000,__
+packet,82.791000,__
+packet,82.833000,__
+packet,82.874000,__
+packet,83.166000,__
+packet,83.041000,__
+packet,82.958000,__
+packet,83.000000,__
+packet,83.083000,__
+packet,83.125000,__
+packet,83.458000,__
+packet,83.292000,__
+packet,83.208000,__
+packet,83.250000,__
+packet,83.333000,__
+packet,83.375000,__
+packet,83.417000,__
+packet,83.584000,__
+packet,83.500000,__
+packet,83.542000,__
+packet,83.667000,__
+packet,83.625000,__
+packet,83.792000,__
+packet,83.709000,__
+packet,83.750000,__
+packet,83.959000,__
+packet,83.875000,__
+packet,83.834000,__
+packet,83.917000,__
+packet,84.167000,__
+packet,84.042000,__
+packet,84.001000,__
+packet,84.084000,__
+packet,84.126000,__
+packet,84.293000,__
+packet,84.209000,__
+packet,84.251000,__
+packet,84.459000,__
+packet,84.376000,__
+packet,84.334000,__
+packet,84.418000,__
+packet,84.751000,__
+packet,84.585000,__
+packet,84.501000,__
+packet,84.543000,__
+packet,84.626000,__
+packet,84.668000,__
+packet,84.710000,__
+packet,84.918000,__
+packet,84.835000,__
+packet,84.793000,__
+packet,84.876000,__
+packet,85.168000,__
+packet,85.043000,__
+packet,84.960000,__
+packet,85.002000,__
+packet,85.085000,__
+packet,85.127000,__
+packet,85.502000,__
+packet,85.335000,__
+packet,85.210000,__
+packet,85.252000,__
+packet,85.294000,__
+packet,85.377000,__
+packet,85.419000,__
+packet,85.460000,__
+packet,85.586000,__
+packet,85.544000,__
+packet,85.627000,__
+packet,85.669000,K_
+packet,85.752000,__
+packet,85.711000,__
+packet,85.919000,__
+packet,85.836000,__
+packet,85.794000,__
+packet,85.877000,__
+packet,86.044000,__
+packet,85.961000,__
+packet,86.003000,__
+packet,86.253000,__
+packet,86.128000,__
+packet,86.086000,__
+packet,86.169000,__
+packet,86.211000,__
+packet,86.461000,__
+packet,86.336000,__
+packet,86.295000,__
+packet,86.378000,__
+packet,86.420000,__
+packet,86.628000,__
+packet,86.545000,__
+packet,86.503000,__
+packet,86.587000,__
+packet,86.795000,__
+packet,86.712000,__
+packet,86.670000,__
+packet,86.753000,__
+packet,86.962000,__
+packet,86.878000,__
+packet,86.837000,__
+packet,86.920000,__
+packet,87.129000,__
+packet,87.045000,__
+packet,87.004000,__
+packet,87.087000,__
+packet,87.296000,__
+packet,87.212000,__
+packet,87.170000,__
+packet,87.254000,__
+packet,87.462000,__
+packet,87.379000,__
+packet,87.337000,__
+packet,87.421000,__
+packet,87.838000,__
+packet,87.629000,__
+packet,87.504000,__
+packet,87.546000,__
+packet,87.588000,__
+packet,87.671000,__
+packet,87.713000,__
+packet,87.754000,__
+packet,87.796000,__
+packet,87.921000,__
+packet,87.879000,__
+packet,88.046000,__
+packet,87.963000,__
+packet,88.005000,__
+packet,88.255000,__
+packet,88.130000,__
+packet,88.088000,__
+packet,88.171000,__
+packet,88.213000,__
+packet,88.297000,__
+packet,88.463000,__
+packet,88.380000,__
+packet,88.338000,__
+packet,88.422000,__
+packet,88.630000,__
+packet,88.547000,__
+packet,88.505000,__
+packet,88.589000,__
+packet,88.755000,__
+packet,88.672000,__
+packet,88.714000,__
+packet,88.797000,K_
+packet,88.880000,__
+packet,88.839000,__
+packet,88.922000,__
+packet,88.964000,__
+packet,89.131000,__
+packet,89.047000,__
+packet,89.006000,__
+packet,89.089000,__
+packet,89.506000,__
+packet,89.298000,__
+packet,89.172000,__
+packet,89.214000,__
+packet,89.256000,__
+packet,89.339000,__
+packet,89.381000,__
+packet,89.423000,__
+packet,89.464000,__
+packet,89.756000,__
+packet,89.631000,__
+packet,89.548000,__
+packet,89.590000,__
+packet,89.673000,__
+packet,89.715000,__
+packet,89.881000,__
+packet,89.798000,__
+packet,89.840000,__
+packet,90.090000,__
+packet,89.965000,__
+packet,89.923000,__
+packet,90.007000,__
+packet,90.048000,__
+packet,90.340000,__
+packet,90.215000,__
+packet,90.132000,__
+packet,90.173000,__
+packet,90.257000,__
+packet,90.299000,__
+packet,90.382000,K_
+packet,90.591000,__
+packet,90.465000,__
+packet,90.424000,__
+packet,90.507000,__
+packet,90.549000,__
+packet,90.841000,__
+packet,90.716000,__
+packet,90.632000,__
+packet,90.674000,__
+packet,90.757000,__
+packet,90.799000,__
+packet,90.882000,__
+packet,91.049000,__
+packet,90.966000,__
+packet,90.924000,__
+packet,91.008000,__
+packet,91.258000,__
+packet,91.133000,__
+packet,91.091000,__
+packet,91.174000,__
+packet,91.216000,__
+packet,91.550000,__
+packet,91.383000,__
+packet,91.300000,__
+packet,91.341000,__
+packet,91.425000,__
+packet,91.466000,__
+packet,91.508000,__
+packet,91.758000,__
+packet,91.633000,__
+packet,91.592000,__
+packet,91.675000,__
+packet,91.717000,__
+packet,92.009000,__
+packet,91.883000,__
+packet,91.800000,__
+packet,91.842000,__
+packet,91.925000,__
+packet,91.967000,__
+packet,92.259000,__
+packet,92.134000,__
+packet,92.050000,__
+packet,92.092000,__
+packet,92.175000,__
+packet,92.217000,__
+packet,92.634000,__
+packet,92.426000,__
+packet,92.301000,__
+packet,92.342000,__
+packet,92.384000,__
+packet,92.467000,__
+packet,92.509000,__
+packet,92.551000,__
+packet,92.593000,__
+packet,92.926000,__
+packet,92.759000,__
+packet,92.676000,__
+packet,92.718000,__
+packet,92.801000,__
+packet,92.843000,__
+packet,92.884000,__
+packet,93.176000,__
+packet,93.051000,__
+packet,92.968000,__
+packet,93.010000,__
+packet,93.093000,__
+packet,93.135000,__
+packet,93.385000,__
+packet,93.260000,__
+packet,93.218000,__
+packet,93.302000,__
+packet,93.343000,__
+packet,93.427000,K_
+packet,93.468000,__
+packet,93.552000,__
+packet,93.510000,__
+packet,93.719000,__
+packet,93.635000,__
+packet,93.594000,__
+packet,93.677000,__
+packet,93.969000,__
+packet,93.844000,__
+packet,93.760000,__
+packet,93.802000,__
+packet,93.885000,__
+packet,93.927000,__
+packet,94.094000,__
+packet,94.011000,__
+packet,94.052000,__
+packet,94.136000,__
+packet,94.303000,__
+packet,94.219000,__
+packet,94.177000,__
+packet,94.261000,__
+packet,94.511000,__
+packet,94.386000,__
+packet,94.344000,__
+packet,94.428000,__
+packet,94.469000,__
+packet,94.636000,__
+packet,94.553000,__
+packet,94.595000,__
+packet,94.803000,__
+packet,94.720000,__
+packet,94.678000,__
+packet,94.761000,__
+packet,94.886000,__
+packet,94.845000,__
+packet,95.012000,__
+packet,94.928000,__
+packet,94.970000,__
+packet,95.053000,__
+packet,95.220000,__
+packet,95.137000,__
+packet,95.095000,__
+packet,95.178000,__
+packet,95.387000,__
+packet,95.304000,__
+packet,95.262000,__
+packet,95.345000,__
+packet,95.679000,__
+packet,95.512000,__
+packet,95.429000,__
+packet,95.470000,__
+packet,95.554000,__
+packet,95.596000,__
+packet,95.637000,__
+packet,95.762000,__
+packet,95.721000,__
+packet,96.138000,__
+packet,95.929000,__
+packet,95.804000,__
+packet,95.846000,__
+packet,95.887000,__
+packet,95.971000,__
+packet,96.013000,__
+packet,96.054000,__
+packet,96.096000,__
+packet,96.430000,__
+packet,96.263000,__
+packet,96.179000,__
+packet,96.221000,__
+packet,96.305000,__
+packet,96.346000,__
+packet,96.388000,__
+packet,96.722000,__
+packet,96.555000,__
+packet,96.471000,__
+packet,96.513000,__
+packet,96.597000,__
+packet,96.638000,__
+packet,96.680000,__
+packet,96.930000,__
+packet,96.805000,__
+packet,96.763000,__
+packet,96.847000,__
+packet,96.888000,__
+packet,97.014000,__
+packet,96.972000,__
+packet,97.055000,__
+packet,97.264000,__
+packet,97.139000,__
+packet,97.097000,__
+packet,97.180000,__
+packet,97.222000,__
+packet,97.306000,__
+packet,97.431000,__
+packet,97.347000,__
+packet,97.389000,__
+packet,97.556000,__
+packet,97.472000,__
+packet,97.514000,__
+packet,97.806000,__
+packet,97.681000,__
+packet,97.598000,__
+packet,97.639000,__
+packet,97.723000,__
+packet,97.764000,__
+packet,97.931000,__
+packet,97.848000,__
+packet,97.889000,__
+packet,98.056000,__
+packet,97.973000,__
+packet,98.015000,__
+packet,98.181000,__
+packet,98.098000,__
+packet,98.140000,__
+packet,98.265000,__
+packet,98.223000,__
+packet,98.307000,K_
+packet,98.390000,__
+packet,98.348000,__
+packet,98.515000,__
+packet,98.432000,__
+packet,98.473000,__
+packet,98.599000,__
+packet,98.557000,__
+packet,98.765000,__
+packet,98.682000,__
+packet,98.640000,__
+packet,98.724000,__
+packet,98.974000,__
+packet,98.849000,__
+packet,98.807000,__
+packet,98.890000,__
+packet,98.932000,__
+packet,99.016000,__
+packet,99.182000,__
+packet,99.099000,__
+packet,99.057000,__
+packet,99.141000,__
+packet,99.391000,__
+packet,99.266000,__
+packet,99.224000,__
+packet,99.308000,__
+packet,99.349000,__
+packet,99.641000,__
+packet,99.516000,__
+packet,99.433000,__
+packet,99.474000,__
+packet,99.558000,__
+packet,99.600000,__
+packet,99.891000,__
+packet,99.766000,__
+packet,99.683000,__
+packet,99.725000,__
+packet,99.808000,__
+packet,99.850000,__
+stream,100
+format,101
diff --git a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_streamduration_result.json b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_streamduration_result.json
new file mode 100644
index 000000000..05494ea4a
--- /dev/null
+++ b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/FfProbe/Test Data/keyframes_streamduration_result.json
@@ -0,0 +1 @@
+{"TotalDuration":1000000000,"KeyframeTicks":[0,103850000,133880000,145150000,165580000,186440000,196450000,209790000,314060000,326990000,396230000,407070000,432520000,476310000,523020000,535540000,550550000,631050000,646480000,665670000,686520000,732400000,772020000,796210000,856690000,887970000,903820000,934270000,983070000]}
diff --git a/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj
new file mode 100644
index 000000000..23c46d0bf
--- /dev/null
+++ b/tests/Jellyfin.MediaEncoding.Keyframes.Tests/Jellyfin.MediaEncoding.Keyframes.Tests.csproj
@@ -0,0 +1,53 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <TargetFramework>net6.0</TargetFramework>
+ <IsPackable>false</IsPackable>
+ <CodeAnalysisRuleSet>../jellyfin-tests.ruleset</CodeAnalysisRuleSet>
+ <RootNamespace>Jellyfin.MediaEncoding.Keyframes</RootNamespace>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
+ <PackageReference Include="xunit" Version="2.4.1" />
+ <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ <PrivateAssets>all</PrivateAssets>
+ </PackageReference>
+ <PackageReference Include="coverlet.collector" Version="3.1.2">
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ <PrivateAssets>all</PrivateAssets>
+ </PackageReference>
+ </ItemGroup>
+
+ <!-- Code Analyzers -->
+ <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="../../src/Jellyfin.MediaEncoding.Keyframes/Jellyfin.MediaEncoding.Keyframes.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <None Update="FfProbe/Test Data/keyframes.txt">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ <None Update="FfProbe/Test Data/keyframes_result.json">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ <None Update="FfProbe/Test Data/keyframes_streamduration.txt">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ <None Update="FfProbe/Test Data/keyframes_streamduration_result.json">
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+
+</Project>
diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj
index f366f553a..e7534e308 100644
--- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj
+++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj
@@ -21,7 +21,7 @@
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="AutoFixture.AutoMoq" Version="4.17.0" />
<PackageReference Include="AutoFixture.Xunit2" Version="4.17.0" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
@@ -30,6 +30,10 @@
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj
index 3b6259abd..22db5bea2 100644
--- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj
+++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj
@@ -10,12 +10,16 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
</ItemGroup>
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj
index 4c95e78b1..59b7e1cbe 100644
--- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj
+++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj
@@ -15,7 +15,7 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
<ItemGroup>
@@ -24,6 +24,10 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj
index 7f9b60b9e..3d3288df6 100644
--- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj
+++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj
@@ -15,13 +15,17 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="FsCheck.Xunit" Version="2.16.4" />
<PackageReference Include="Moq" Version="4.16.1" />
</ItemGroup>
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj
index 4338c812d..9f571273f 100644
--- a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj
+++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj
@@ -20,7 +20,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
- <PackageReference Include="coverlet.collector" Version="3.1.0">
+ <PackageReference Include="coverlet.collector" Version="3.1.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
@@ -28,6 +28,10 @@
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs
index 2ba5c47d7..c0931dbcf 100644
--- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs
+++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs
@@ -41,10 +41,7 @@ namespace Jellyfin.Providers.Tests.Manager
[Fact]
public void ValidateImages_EmptyItemEmptyProviders_NoChange()
{
- var itemImageProvider = GetItemImageProvider(null, null);
- var changed = itemImageProvider.ValidateImages(new Video(), Enumerable.Empty<ILocalImageProvider>(), null);
-
- Assert.False(changed);
+ ValidateImages_Test(ImageType.Primary, 0, true, 0, false, 0);
}
private static TheoryData<ImageType, int> GetImageTypesWithCount()
@@ -53,7 +50,6 @@ namespace Jellyfin.Providers.Tests.Manager
{
// minimal test cases that hit different handling
{ ImageType.Primary, 1 },
- { ImageType.Backdrop, 1 },
{ ImageType.Backdrop, 2 }
};
@@ -64,43 +60,34 @@ namespace Jellyfin.Providers.Tests.Manager
[MemberData(nameof(GetImageTypesWithCount))]
public void ValidateImages_EmptyItemAndPopulatedProviders_AddsImages(ImageType imageType, int imageCount)
{
- // Has to exist for querying DateModified time on file, results stored but not checked so not populating
- BaseItem.FileSystem = Mock.Of<IFileSystem>();
-
- var item = new Video();
- var imageProvider = GetImageProvider(imageType, imageCount, true);
-
- var itemImageProvider = GetItemImageProvider(null, null);
- var changed = itemImageProvider.ValidateImages(item, new[] { imageProvider }, null);
-
- Assert.True(changed);
- Assert.Equal(imageCount, item.GetImages(imageType).Count());
+ ValidateImages_Test(imageType, 0, true, imageCount, true, imageCount);
}
[Theory]
[MemberData(nameof(GetImageTypesWithCount))]
public void ValidateImages_PopulatedItemWithGoodPathsAndEmptyProviders_NoChange(ImageType imageType, int imageCount)
{
- var item = GetItemWithImages(imageType, imageCount, true);
-
- var itemImageProvider = GetItemImageProvider(null, null);
- var changed = itemImageProvider.ValidateImages(item, Enumerable.Empty<ILocalImageProvider>(), null);
-
- Assert.False(changed);
- Assert.Equal(imageCount, item.GetImages(imageType).Count());
+ ValidateImages_Test(imageType, imageCount, true, 0, false, imageCount);
}
[Theory]
[MemberData(nameof(GetImageTypesWithCount))]
public void ValidateImages_PopulatedItemWithBadPathsAndEmptyProviders_RemovesImage(ImageType imageType, int imageCount)
{
- var item = GetItemWithImages(imageType, imageCount, false);
+ ValidateImages_Test(imageType, imageCount, false, 0, true, 0);
+ }
+
+ private void ValidateImages_Test(ImageType imageType, int initialImageCount, bool initialPathsValid, int providerImageCount, bool expectedChange, int expectedImageCount)
+ {
+ var item = GetItemWithImages(imageType, initialImageCount, initialPathsValid);
+
+ var imageProvider = GetImageProvider(imageType, providerImageCount, true);
var itemImageProvider = GetItemImageProvider(null, null);
- var changed = itemImageProvider.ValidateImages(item, Enumerable.Empty<ILocalImageProvider>(), null);
+ var actualChange = itemImageProvider.ValidateImages(item, new[] { imageProvider }, null);
- Assert.True(changed);
- Assert.Empty(item.GetImages(imageType));
+ Assert.Equal(expectedChange, actualChange);
+ Assert.Equal(expectedImageCount, item.GetImages(imageType).Count());
}
[Fact]
@@ -137,20 +124,23 @@ namespace Jellyfin.Providers.Tests.Manager
}
[Theory]
- [MemberData(nameof(GetImageTypesWithCount))]
- public void MergeImages_PopulatedItemWithGoodPathsAndSameNewImages_NoChange(ImageType imageType, int imageCount)
+ [InlineData(ImageType.Primary, 1, false)]
+ [InlineData(ImageType.Backdrop, 2, false)]
+ [InlineData(ImageType.Primary, 1, true)]
+ [InlineData(ImageType.Backdrop, 2, true)]
+ public void MergeImages_PopulatedItemWithGoodPathsAndSameNewImages_ResetIfTimeChanges(ImageType imageType, int imageCount, bool updateTime)
{
var oldTime = new DateTime(1970, 1, 1);
+ var updatedTime = updateTime ? new DateTime(2021, 1, 1) : oldTime;
- // match update time with time added to item images (unix epoch)
var fileSystem = new Mock<IFileSystem>();
fileSystem.Setup(fs => fs.GetLastWriteTimeUtc(It.IsAny<FileSystemMetadata>()))
- .Returns(oldTime);
+ .Returns(updatedTime);
BaseItem.FileSystem = fileSystem.Object;
// all valid paths - matching for strictly updating
var item = GetItemWithImages(imageType, imageCount, true);
- // set size to non-zero to allow for updates to occur
+ // set size to non-zero to allow for image size reset to occur
foreach (var image in item.GetImages(imageType))
{
image.DateModified = oldTime;
@@ -163,45 +153,52 @@ namespace Jellyfin.Providers.Tests.Manager
var itemImageProvider = GetItemImageProvider(null, fileSystem);
var changed = itemImageProvider.MergeImages(item, images);
- Assert.False(changed);
+ if (updateTime)
+ {
+ Assert.True(changed);
+ // before and after paths are the same, verify updated by size reset to 0
+ var typedImages = item.GetImages(imageType).ToArray();
+ Assert.Equal(imageCount, typedImages.Length);
+ foreach (var image in typedImages)
+ {
+ Assert.Equal(updatedTime, image.DateModified);
+ Assert.Equal(0, image.Height);
+ Assert.Equal(0, image.Width);
+ }
+ }
+ else
+ {
+ Assert.False(changed);
+ }
}
[Theory]
- [MemberData(nameof(GetImageTypesWithCount))]
- public void MergeImages_PopulatedItemWithGoodPathsAndSameNewImagesWithNewTimestamps_ResetsImageSizes(ImageType imageType, int imageCount)
+ [InlineData(ImageType.Primary, 0)]
+ [InlineData(ImageType.Primary, 1)]
+ [InlineData(ImageType.Backdrop, 2)]
+ public void RemoveImages_DeletesImages_WhenFound(ImageType imageType, int imageCount)
{
- var oldTime = new DateTime(1970, 1, 1);
- var updatedTime = new DateTime(2021, 1, 1);
-
- var fileSystem = new Mock<IFileSystem>();
- fileSystem.Setup(fs => fs.GetLastWriteTimeUtc(It.IsAny<FileSystemMetadata>()))
- .Returns(updatedTime);
- BaseItem.FileSystem = fileSystem.Object;
+ var item = GetItemWithImages(imageType, imageCount, false);
- // all valid paths - matching for strictly updating
- var item = GetItemWithImages(imageType, imageCount, true);
- // set size to non-zero to allow for image size reset to occur
- foreach (var image in item.GetImages(imageType))
+ var mockFileSystem = new Mock<IFileSystem>(MockBehavior.Strict);
+ if (imageCount > 0)
{
- image.DateModified = oldTime;
- image.Height = 1;
- image.Width = 1;
+ mockFileSystem.Setup(fs => fs.DeleteFile("invalid path 0"))
+ .Verifiable();
}
- var images = GetImages(imageType, imageCount, true);
-
- var itemImageProvider = GetItemImageProvider(null, fileSystem);
- var changed = itemImageProvider.MergeImages(item, images);
-
- Assert.True(changed);
- // before and after paths are the same, verify updated by size reset to 0
- Assert.Equal(imageCount, item.GetImages(imageType).Count());
- foreach (var image in item.GetImages(imageType))
+ if (imageCount > 1)
{
- Assert.Equal(updatedTime, image.DateModified);
- Assert.Equal(0, image.Height);
- Assert.Equal(0, image.Width);
+ mockFileSystem.Setup(fs => fs.DeleteFile("invalid path 1"))
+ .Verifiable();
}
+
+ var itemImageProvider = GetItemImageProvider(Mock.Of<IProviderManager>(), mockFileSystem);
+ var result = itemImageProvider.RemoveImages(item);
+
+ Assert.Equal(imageCount != 0, result);
+ Assert.Empty(item.GetImages(imageType));
+ mockFileSystem.Verify();
}
[Theory]
@@ -336,8 +333,7 @@ namespace Jellyfin.Providers.Tests.Manager
remoteInfo[i] = new RemoteImageInfo
{
Type = imageType,
- Url = "image url " + i,
- Width = 1 // min width is set to 0, this will always pass
+ Url = "image url " + i
};
}
@@ -403,11 +399,10 @@ namespace Jellyfin.Providers.Tests.Manager
var remoteInfo = new RemoteImageInfo[targetImageCount];
for (int i = 0; i < targetImageCount; i++)
{
- remoteInfo[i] = new RemoteImageInfo()
+ remoteInfo[i] = new RemoteImageInfo
{
Type = imageType,
- Url = "image url " + i,
- Width = 1 // min width is set to 0, this will always pass
+ Url = "image url " + i
};
}
@@ -449,11 +444,10 @@ namespace Jellyfin.Providers.Tests.Manager
var remoteInfo = new RemoteImageInfo[remoteInfoCount];
for (int i = 0; i < remoteInfoCount; i++)
{
- remoteInfo[i] = new RemoteImageInfo()
+ remoteInfo[i] = new RemoteImageInfo
{
Type = imageType,
- Url = "image url " + i,
- Width = 1 // min width is set to 0, this will always pass
+ Url = "image url " + i
};
}
@@ -500,6 +494,62 @@ namespace Jellyfin.Providers.Tests.Manager
Assert.Equal(imageCount, item.GetImages(imageType).Count());
}
+ [Theory]
+ [InlineData(9, false)]
+ [InlineData(10, true)]
+ [InlineData(null, true)]
+ public async void RefreshImages_ProviderRemote_FiltersByWidth(int? remoteImageWidth, bool expectedToUpdate)
+ {
+ var imageType = ImageType.Primary;
+
+ var item = new Video();
+
+ var libraryOptions = new LibraryOptions
+ {
+ TypeOptions = new[]
+ {
+ new TypeOptions
+ {
+ Type = item.GetType().Name,
+ ImageOptions = new[]
+ {
+ new ImageOption
+ {
+ Type = imageType,
+ MinWidth = 10
+ }
+ }
+ }
+ }
+ };
+
+ var remoteProvider = new Mock<IRemoteImageProvider>(MockBehavior.Strict);
+ remoteProvider.Setup(rp => rp.Name).Returns("MockRemoteProvider");
+ remoteProvider.Setup(rp => rp.GetSupportedImages(item))
+ .Returns(new[] { imageType });
+
+ var refreshOptions = new ImageRefreshOptions(Mock.Of<IDirectoryService>());
+
+ // set width on image from remote
+ var remoteInfo = new[]
+ {
+ new RemoteImageInfo()
+ {
+ Type = imageType,
+ Url = "image url",
+ Width = remoteImageWidth
+ }
+ };
+
+ var providerManager = new Mock<IProviderManager>(MockBehavior.Strict);
+ providerManager.Setup(pm => pm.GetAvailableRemoteImages(It.IsAny<BaseItem>(), It.IsAny<RemoteImageQuery>(), It.IsAny<CancellationToken>()))
+ .ReturnsAsync(remoteInfo);
+ var itemImageProvider = GetItemImageProvider(providerManager.Object, null);
+ var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List<IImageProvider> { remoteProvider.Object }, refreshOptions, CancellationToken.None);
+
+ Assert.Equal(expectedToUpdate, result.UpdateType.HasFlag(ItemUpdateType.ImageUpdate));
+ }
+
private static ItemImageProvider GetItemImageProvider(IProviderManager? providerManager, Mock<IFileSystem>? mockFileSystem)
{
// strict to ensure this isn't accidentally used where a prepared mock is intended
@@ -586,7 +636,6 @@ namespace Jellyfin.Providers.Tests.Manager
{
Type = type,
Limit = count,
- MinWidth = 0
}
}
}
diff --git a/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs b/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs
new file mode 100644
index 000000000..b74b331b7
--- /dev/null
+++ b/tests/Jellyfin.Providers.Tests/Manager/MetadataServiceTests.cs
@@ -0,0 +1,378 @@
+using System;
+using System.Collections.Generic;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Providers.Manager;
+using Xunit;
+
+namespace Jellyfin.Providers.Tests.Manager
+{
+ public class MetadataServiceTests
+ {
+ [Theory]
+ [InlineData(false, false)]
+ [InlineData(true, false)]
+ [InlineData(true, true)]
+ public void MergeBaseItemData_MergeMetadataSettings_MergesWhenSet(bool mergeMetadataSettings, bool defaultDate)
+ {
+ var newLocked = new[] { MetadataField.Cast };
+ var newString = "new";
+ var newDate = DateTime.Now;
+
+ var oldLocked = new[] { MetadataField.Genres };
+ var oldString = "old";
+ var oldDate = DateTime.UnixEpoch;
+
+ var source = new MetadataResult<Movie>
+ {
+ Item = new Movie
+ {
+ LockedFields = newLocked,
+ IsLocked = true,
+ PreferredMetadataCountryCode = newString,
+ PreferredMetadataLanguage = newString,
+ DateCreated = newDate
+ }
+ };
+ if (defaultDate)
+ {
+ source.Item.DateCreated = default;
+ }
+
+ var target = new MetadataResult<Movie>
+ {
+ Item = new Movie
+ {
+ LockedFields = oldLocked,
+ IsLocked = false,
+ PreferredMetadataCountryCode = oldString,
+ PreferredMetadataLanguage = oldString,
+ DateCreated = oldDate
+ }
+ };
+
+ MetadataService<Movie, MovieInfo>.MergeBaseItemData(source, target, Array.Empty<MetadataField>(), true, mergeMetadataSettings);
+
+ if (mergeMetadataSettings)
+ {
+ Assert.Equal(newLocked, target.Item.LockedFields);
+ Assert.True(target.Item.IsLocked);
+ Assert.Equal(newString, target.Item.PreferredMetadataCountryCode);
+ Assert.Equal(newString, target.Item.PreferredMetadataLanguage);
+ Assert.Equal(defaultDate ? oldDate : newDate, target.Item.DateCreated);
+ }
+ else
+ {
+ Assert.Equal(oldLocked, target.Item.LockedFields);
+ Assert.False(target.Item.IsLocked);
+ Assert.Equal(oldString, target.Item.PreferredMetadataCountryCode);
+ Assert.Equal(oldString, target.Item.PreferredMetadataLanguage);
+ Assert.Equal(oldDate, target.Item.DateCreated);
+ }
+ }
+
+ [Theory]
+ [InlineData("Name", MetadataField.Name, false)]
+ [InlineData("OriginalTitle", null, false)]
+ [InlineData("OfficialRating", MetadataField.OfficialRating)]
+ [InlineData("CustomRating")]
+ [InlineData("Tagline")]
+ [InlineData("Overview", MetadataField.Overview)]
+ [InlineData("DisplayOrder", null, false)]
+ [InlineData("ForcedSortName", null, false)]
+ public void MergeBaseItemData_StringField_ReplacesAppropriately(string propName, MetadataField? lockField = null, bool replacesWithEmpty = true)
+ {
+ var oldValue = "Old";
+ var newValue = "New";
+
+ // Use type Series to hit DisplayOrder
+ Assert.False(TestMergeBaseItemData<Series, SeriesInfo>(propName, oldValue, newValue, null, false, out _));
+ if (lockField != null)
+ {
+ Assert.False(TestMergeBaseItemData<Series, SeriesInfo>(propName, oldValue, newValue, lockField, true, out _));
+ Assert.False(TestMergeBaseItemData<Series, SeriesInfo>(propName, null, newValue, lockField, false, out _));
+ Assert.False(TestMergeBaseItemData<Series, SeriesInfo>(propName, string.Empty, newValue, lockField, false, out _));
+ }
+
+ Assert.True(TestMergeBaseItemData<Series, SeriesInfo>(propName, oldValue, newValue, null, true, out _));
+ Assert.True(TestMergeBaseItemData<Series, SeriesInfo>(propName, null, newValue, null, false, out _));
+ Assert.True(TestMergeBaseItemData<Series, SeriesInfo>(propName, string.Empty, newValue, null, false, out _));
+
+ var replacedWithEmpty = TestMergeBaseItemData<Series, SeriesInfo>(propName, oldValue, string.Empty, null, true, out _);
+ Assert.Equal(replacesWithEmpty, replacedWithEmpty);
+ }
+
+ [Theory]
+ [InlineData("Genres", MetadataField.Genres)]
+ [InlineData("Studios", MetadataField.Studios)]
+ [InlineData("Tags", MetadataField.Tags)]
+ [InlineData("ProductionLocations", MetadataField.ProductionLocations)]
+ [InlineData("AlbumArtists")]
+ public void MergeBaseItemData_StringArrayField_ReplacesAppropriately(string propName, MetadataField? lockField = null)
+ {
+ // Note that arrays are replaced, not merged
+ var oldValue = new[] { "Old" };
+ var newValue = new[] { "New" };
+
+ // Use type Audio to hit AlbumArtists
+ Assert.False(TestMergeBaseItemData<Audio, SongInfo>(propName, oldValue, newValue, null, false, out _));
+ if (lockField != null)
+ {
+ Assert.False(TestMergeBaseItemData<Audio, SongInfo>(propName, oldValue, newValue, lockField, true, out _));
+ Assert.False(TestMergeBaseItemData<Audio, SongInfo>(propName, Array.Empty<string>(), newValue, lockField, false, out _));
+ }
+
+ Assert.True(TestMergeBaseItemData<Audio, SongInfo>(propName, oldValue, newValue, null, true, out _));
+ Assert.True(TestMergeBaseItemData<Audio, SongInfo>(propName, Array.Empty<string>(), newValue, null, false, out _));
+
+ Assert.True(TestMergeBaseItemData<Audio, SongInfo>(propName, oldValue, Array.Empty<string>(), null, true, out _));
+ }
+
+ private static TheoryData<string, object, object> MergeBaseItemData_SimpleField_ReplacesAppropriately_TestData()
+ => new()
+ {
+ { "IndexNumber", 1, 2 },
+ { "ParentIndexNumber", 1, 2 },
+ { "ProductionYear", 1, 2 },
+ { "CommunityRating", 1.0f, 2.0f },
+ { "CriticRating", 1.0f, 2.0f },
+ { "EndDate", DateTime.UnixEpoch, DateTime.Now },
+ { "PremiereDate", DateTime.UnixEpoch, DateTime.Now },
+ { "Video3DFormat", Video3DFormat.HalfSideBySide, Video3DFormat.FullSideBySide }
+ };
+
+ [Theory]
+ [MemberData(nameof(MergeBaseItemData_SimpleField_ReplacesAppropriately_TestData))]
+ public void MergeBaseItemData_SimpleField_ReplacesAppropriately(string propName, object oldValue, object newValue)
+ {
+ // Use type Movie to allow testing of Video3DFormat
+ Assert.False(TestMergeBaseItemData<Movie, MovieInfo>(propName, oldValue, newValue, null, false, out _));
+
+ Assert.True(TestMergeBaseItemData<Movie, MovieInfo>(propName, oldValue, newValue, null, true, out _));
+ Assert.True(TestMergeBaseItemData<Movie, MovieInfo>(propName, null, newValue, null, false, out _));
+
+ Assert.True(TestMergeBaseItemData<Movie, MovieInfo>(propName, oldValue, null, null, true, out _));
+ }
+
+ [Fact]
+ public void MergeBaseItemData_MergeTrailers_ReplacesAppropriately()
+ {
+ string propName = "RemoteTrailers";
+ var oldValue = new[]
+ {
+ new MediaUrl
+ {
+ Name = "Name 1",
+ Url = "URL 1"
+ }
+ };
+ var newValue = new[]
+ {
+ new MediaUrl
+ {
+ Name = "Name 2",
+ Url = "URL 2"
+ }
+ };
+
+ Assert.False(TestMergeBaseItemData<Movie, MovieInfo>(propName, oldValue, newValue, null, false, out _));
+
+ Assert.True(TestMergeBaseItemData<Movie, MovieInfo>(propName, oldValue, newValue, null, true, out _));
+ Assert.True(TestMergeBaseItemData<Movie, MovieInfo>(propName, Array.Empty<MediaUrl>(), newValue, null, false, out _));
+
+ Assert.True(TestMergeBaseItemData<Movie, MovieInfo>(propName, oldValue, Array.Empty<MediaUrl>(), null, true, out _));
+ }
+
+ [Fact]
+ public void MergeBaseItemData_ProviderIds_MergesAppropriately()
+ {
+ var propName = "ProviderIds";
+ var oldValue = new Dictionary<string, string>
+ {
+ { "provider 1", "id 1" }
+ };
+
+ // overwrite provider id
+ var overwriteNewValue = new Dictionary<string, string>
+ {
+ { "provider 1", "id 2" }
+ };
+ Assert.False(TestMergeBaseItemData<Movie, MovieInfo>(propName, new Dictionary<string, string>(oldValue), overwriteNewValue, null, false, out _));
+ TestMergeBaseItemData<Movie, MovieInfo>(propName, new Dictionary<string, string>(oldValue), overwriteNewValue, null, true, out var overwritten);
+ Assert.Equal(overwriteNewValue, overwritten);
+
+ // merge without overwriting
+ var mergeNewValue = new Dictionary<string, string>
+ {
+ { "provider 1", "id 2" },
+ { "provider 2", "id 3" }
+ };
+ TestMergeBaseItemData<Movie, MovieInfo>(propName, new Dictionary<string, string>(oldValue), mergeNewValue, null, false, out var merged);
+ var actual = (Dictionary<string, string>)merged!;
+ Assert.Equal("id 1", actual["provider 1"]);
+ Assert.Equal("id 3", actual["provider 2"]);
+
+ // empty source results in no change
+ TestMergeBaseItemData<Movie, MovieInfo>(propName, new Dictionary<string, string>(oldValue), new Dictionary<string, string>(), null, true, out var notOverwritten);
+ Assert.Equal(oldValue, notOverwritten);
+ }
+
+ [Fact]
+ public void MergeBaseItemData_MergePeople_MergesAppropriately()
+ {
+ // PersonInfo in list is changed by merge, create new for every call
+ List<PersonInfo> GetOldValue()
+ => new()
+ {
+ new PersonInfo
+ {
+ Name = "Name 1",
+ ProviderIds = new Dictionary<string, string>
+ {
+ { "Provider 1", "1234" }
+ }
+ }
+ };
+
+ object? result;
+ List<PersonInfo> actual;
+
+ // overwrite provider id
+ var overwriteNewValue = new List<PersonInfo>
+ {
+ new()
+ {
+ Name = "Name 2"
+ }
+ };
+ Assert.False(TestMergeBaseItemDataPerson(GetOldValue(), overwriteNewValue, null, false, out result));
+ // People not already in target are not merged into it from source
+ actual = (List<PersonInfo>)result!;
+ Assert.Single(actual);
+ Assert.Equal("Name 1", actual[0].Name);
+
+ Assert.True(TestMergeBaseItemDataPerson(GetOldValue(), overwriteNewValue, null, true, out _));
+ Assert.True(TestMergeBaseItemDataPerson(new List<PersonInfo>(), overwriteNewValue, null, false, out _));
+ Assert.True(TestMergeBaseItemDataPerson(null, overwriteNewValue, null, false, out _));
+
+ Assert.False(TestMergeBaseItemDataPerson(GetOldValue(), overwriteNewValue, MetadataField.Cast, true, out _));
+
+ // providers merge but don't overwrite existing keys
+ var mergeNewValue = new List<PersonInfo>
+ {
+ new()
+ {
+ Name = "Name 1",
+ ProviderIds = new Dictionary<string, string>
+ {
+ { "Provider 1", "5678" },
+ { "Provider 2", "5678" }
+ }
+ }
+ };
+ TestMergeBaseItemDataPerson(GetOldValue(), mergeNewValue, null, false, out result);
+ actual = (List<PersonInfo>)result!;
+ Assert.Single(actual);
+ Assert.Equal("Name 1", actual[0].Name);
+ Assert.Equal(2, actual[0].ProviderIds.Count);
+ Assert.Equal("1234", actual[0].ProviderIds["Provider 1"]);
+ Assert.Equal("5678", actual[0].ProviderIds["Provider 2"]);
+
+ // picture adds if missing but won't overwrite (forcing overwrites entire list, not entries in merged PersonInfo)
+ var mergePicture1 = new List<PersonInfo>
+ {
+ new()
+ {
+ Name = "Name 1",
+ ImageUrl = "URL 1"
+ }
+ };
+ TestMergeBaseItemDataPerson(GetOldValue(), mergePicture1, null, false, out result);
+ actual = (List<PersonInfo>)result!;
+ Assert.Single(actual);
+ Assert.Equal("Name 1", actual[0].Name);
+ Assert.Equal("URL 1", actual[0].ImageUrl);
+ var mergePicture2 = new List<PersonInfo>
+ {
+ new()
+ {
+ Name = "Name 1",
+ ImageUrl = "URL 2"
+ }
+ };
+ TestMergeBaseItemDataPerson(mergePicture1, mergePicture2, null, false, out result);
+ actual = (List<PersonInfo>)result!;
+ Assert.Single(actual);
+ Assert.Equal("Name 1", actual[0].Name);
+ Assert.Equal("URL 1", actual[0].ImageUrl);
+
+ // empty source can be forced to overwrite a target with data
+ Assert.True(TestMergeBaseItemDataPerson(GetOldValue(), new List<PersonInfo>(), null, true, out _));
+ }
+
+ private static bool TestMergeBaseItemDataPerson(List<PersonInfo>? oldValue, List<PersonInfo>? newValue, MetadataField? lockField, bool replaceData, out object? actualValue)
+ {
+ var source = new MetadataResult<Movie>
+ {
+ Item = new Movie(),
+ People = newValue
+ };
+
+ var target = new MetadataResult<Movie>
+ {
+ Item = new Movie(),
+ People = oldValue
+ };
+
+ var lockedFields = lockField == null ? Array.Empty<MetadataField>() : new[] { (MetadataField)lockField };
+ MetadataService<Movie, MovieInfo>.MergeBaseItemData(source, target, lockedFields, replaceData, false);
+
+ actualValue = target.People;
+ return newValue?.Equals(actualValue) ?? actualValue == null;
+ }
+
+ /// <summary>
+ /// Makes a call to <see cref="MetadataService{TItemType,TIdType}.MergeBaseItemData"/> with the provided parameters and returns whether the target changed or not.
+ ///
+ /// Reflection is used to allow testing of all fields using the same logic, rather than relying on copy/pasting test code for each field.
+ /// </summary>
+ /// <param name="propName">The property to test.</param>
+ /// <param name="oldValue">The initial value in the target object.</param>
+ /// <param name="newValue">The initial value in the source object.</param>
+ /// <param name="lockField">The metadata field that locks this property if the field should be locked, or <c>null</c> to leave unlocked.</param>
+ /// <param name="replaceData">Passed through to <see cref="MetadataService{TItemType,TIdType}.MergeBaseItemData"/>.</param>
+ /// <param name="actualValue">The resulting value set to the target.</param>
+ /// <typeparam name="TItemType">The <see cref="BaseItem"/> type to test on.</typeparam>
+ /// <typeparam name="TIdType">The <see cref="BaseItem"/> info type.</typeparam>
+ /// <returns><c>true</c> if the property on the target updates to match the source value when<see cref="MetadataService{TItemType,TIdType}.MergeBaseItemData"/> is called.</returns>
+ private static bool TestMergeBaseItemData<TItemType, TIdType>(string propName, object? oldValue, object? newValue, MetadataField? lockField, bool replaceData, out object? actualValue)
+ where TItemType : BaseItem, IHasLookupInfo<TIdType>, new()
+ where TIdType : ItemLookupInfo, new()
+ {
+ var property = typeof(TItemType).GetProperty(propName)!;
+
+ var source = new MetadataResult<TItemType>
+ {
+ Item = new TItemType()
+ };
+ property.SetValue(source.Item, newValue);
+
+ var target = new MetadataResult<TItemType>
+ {
+ Item = new TItemType()
+ };
+ property.SetValue(target.Item, oldValue);
+
+ var lockedFields = lockField == null ? Array.Empty<MetadataField>() : new[] { (MetadataField)lockField };
+ // generic type doesn't actually matter to call the static method, just has to be filled in
+ MetadataService<TItemType, TIdType>.MergeBaseItemData(source, target, lockedFields, replaceData, false);
+
+ actualValue = property.GetValue(target.Item);
+ return newValue?.Equals(actualValue) ?? actualValue == null;
+ }
+ }
+}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
index f9228b1a7..3146f277f 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
+++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj
@@ -26,11 +26,15 @@
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs
index de4421320..f5c8cc970 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs
@@ -60,7 +60,8 @@ public class FindExtrasTests
"/movies/Up/Up.mkv",
"/movies/Up/Up - trailer.mkv",
"/movies/Up/Up - sample.mkv",
- "/movies/Up/Up something else.mkv"
+ "/movies/Up/Up something else.mkv",
+ "/movies/Up/Up-extra.mkv"
};
var files = paths.Select(p => new FileSystemMetadata
@@ -71,10 +72,11 @@ public class FindExtrasTests
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
- Assert.Equal(2, extras.Count);
- Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
- Assert.Equal(typeof(Trailer), extras[0].GetType());
- Assert.Equal(ExtraType.Sample, extras[1].ExtraType);
+ Assert.Equal(3, extras.Count);
+ Assert.Equal(ExtraType.Unknown, extras[0].ExtraType);
+ Assert.Equal(ExtraType.Trailer, extras[1].ExtraType);
+ Assert.Equal(typeof(Trailer), extras[1].GetType());
+ Assert.Equal(ExtraType.Sample, extras[2].ExtraType);
}
[Fact]
@@ -92,7 +94,8 @@ public class FindExtrasTests
"/movies/Up/behind the scenes",
"/movies/Up/behind the scenes.mkv",
"/movies/Up/Up - sample.mkv",
- "/movies/Up/Up something else.mkv"
+ "/movies/Up/Up something else.mkv",
+ "/movies/Up/extras"
};
_fileSystemMock.Setup(f => f.GetFiles(
@@ -140,6 +143,21 @@ public class FindExtrasTests
}
}).Verifiable();
+ _fileSystemMock.Setup(f => f.GetFiles(
+ "/movies/Up/extras",
+ It.IsAny<string[]>(),
+ false,
+ false))
+ .Returns(new List<FileSystemMetadata>
+ {
+ new()
+ {
+ FullName = "/movies/Up/extras/Honest Trailer.mkv",
+ Name = "Honest Trailer.mkv",
+ IsDirectory = false
+ }
+ }).Verifiable();
+
var files = paths.Select(p => new FileSystemMetadata
{
FullName = p,
@@ -150,17 +168,19 @@ public class FindExtrasTests
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
_fileSystemMock.Verify();
- Assert.Equal(6, extras.Count);
- Assert.Equal(ExtraType.Trailer, extras[0].ExtraType);
- Assert.Equal(typeof(Trailer), extras[0].GetType());
+ Assert.Equal(7, extras.Count);
+ Assert.Equal(ExtraType.Unknown, extras[0].ExtraType);
+ Assert.Equal(typeof(Video), extras[0].GetType());
Assert.Equal(ExtraType.Trailer, extras[1].ExtraType);
Assert.Equal(typeof(Trailer), extras[1].GetType());
- Assert.Equal(ExtraType.BehindTheScenes, extras[2].ExtraType);
- Assert.Equal(ExtraType.Sample, extras[3].ExtraType);
- Assert.Equal(ExtraType.ThemeSong, extras[4].ExtraType);
- Assert.Equal(typeof(Audio), extras[4].GetType());
+ Assert.Equal(ExtraType.Trailer, extras[2].ExtraType);
+ Assert.Equal(typeof(Trailer), extras[2].GetType());
+ Assert.Equal(ExtraType.BehindTheScenes, extras[3].ExtraType);
+ Assert.Equal(ExtraType.Sample, extras[4].ExtraType);
Assert.Equal(ExtraType.ThemeSong, extras[5].ExtraType);
Assert.Equal(typeof(Audio), extras[5].GetType());
+ Assert.Equal(ExtraType.ThemeSong, extras[6].ExtraType);
+ Assert.Equal(typeof(Audio), extras[6].GetType());
}
[Fact]
diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs
new file mode 100644
index 000000000..f2efcddba
--- /dev/null
+++ b/tests/Jellyfin.Server.Implementations.Tests/Library/MovieResolverTests.cs
@@ -0,0 +1,34 @@
+using Emby.Naming.Common;
+using Emby.Server.Implementations.Library.Resolvers.Movies;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.IO;
+using Moq;
+using Xunit;
+
+namespace Jellyfin.Server.Implementations.Tests.Library;
+
+public class MovieResolverTests
+{
+ private static readonly NamingOptions _namingOptions = new();
+
+ [Fact]
+ public void Resolve_GivenLocalAlternateVersion_ResolvesToVideo()
+ {
+ var movieResolver = new MovieResolver(Mock.Of<IImageProcessor>(), _namingOptions);
+ var itemResolveArgs = new ItemResolveArgs(
+ Mock.Of<IServerApplicationPaths>(),
+ Mock.Of<IDirectoryService>())
+ {
+ Parent = null,
+ FileInfo = new FileSystemMetadata
+ {
+ FullName = "/movies/Black Panther (2018)/Black Panther (2018) - 1080p 3D.mk3d"
+ }
+ };
+
+ Assert.NotNull(movieResolver.Resolve(itemResolveArgs));
+ }
+}
diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj
index e8fc495f9..6cc879896 100644
--- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj
+++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj
@@ -15,7 +15,7 @@
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="Xunit.Priority" Version="1.1.6" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="Moq" Version="4.16.1" />
</ItemGroup>
@@ -28,6 +28,10 @@
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj
index b25b06c7b..64cf3a6bb 100644
--- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj
+++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj
@@ -15,12 +15,16 @@
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
<PackageReference Include="Moq" Version="4.16.1" />
</ItemGroup>
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj
index 55cdfa2e0..1bb2115cc 100644
--- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj
@@ -17,11 +17,15 @@
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
- <PackageReference Include="coverlet.collector" Version="3.1.0" />
+ <PackageReference Include="coverlet.collector" Version="3.1.2" />
</ItemGroup>
<!-- Code Analyzers -->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
+ </PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs
index 3e726f23d..4f4ae5afb 100644
--- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs
@@ -123,6 +123,20 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers
}
[Fact]
+ public void Parse_GivenFileWithThumbWithoutAspect_Success()
+ {
+ var result = new MetadataResult<Episode>
+ {
+ Item = new Episode()
+ };
+
+ _parser.Fetch(result, "Test Data/Sonarr-Thumb.nfo", CancellationToken.None);
+
+ Assert.Single(result.RemoteImages.Where(x => x.Type == ImageType.Primary));
+ Assert.Equal("https://artworks.thetvdb.com/banners/episodes/359095/7081317.jpg", result.RemoteImages.First(x => x.Type == ImageType.Primary).Url);
+ }
+
+ [Fact]
public void Fetch_WithNullItem_ThrowsArgumentException()
{
var result = new MetadataResult<Episode>();
diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Sonarr-Thumb.nfo b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Sonarr-Thumb.nfo
new file mode 100644
index 000000000..fb86768ef
--- /dev/null
+++ b/tests/Jellyfin.XbmcMetadata.Tests/Test Data/Sonarr-Thumb.nfo
@@ -0,0 +1,34 @@
+<episodedetails>
+ <title>Sometimes a Genius's Every Action Is at the Mercy of X</title>
+ <season>1</season>
+ <episode>8</episode>
+ <aired>2019-05-26</aired>
+ <plot>After Nariyuki wins a smartphone in a lottery, he can't wait to use it for apps like the dictionary, schedule managing, and the like. He also learns that studying in the bathtub is effective and quickly puts the method into practice.</plot>
+ <uniqueid type="sonarr" default="true">4289</uniqueid>
+ <thumb>https://artworks.thetvdb.com/banners/episodes/359095/7081317.jpg</thumb>
+ <watched>false</watched>
+ <fileinfo>
+ <streamdetails>
+ <video>
+ <aspect>1.77777779</aspect>
+ <bitrate>2208901</bitrate>
+ <codec>x265</codec>
+ <framerate>23.976</framerate>
+ <height>1080</height>
+ <scantype></scantype>
+ <width>1920</width>
+ <duration>23.683416666666666</duration>
+ <durationinseconds>1421</durationinseconds>
+ </video>
+ <audio>
+ <bitrate>1468567</bitrate>
+ <channels>2</channels>
+ <codec>FLAC</codec>
+ <language>Japanese / Japanese</language>
+ </audio>
+ <subtitle>
+ <language>English</language>
+ </subtitle>
+ </streamdetails>
+ </fileinfo>
+</episodedetails>