[
  {
    "path": ".gitignore",
    "content": "# Prerequisites\n*.d\n\n# Object files\n*.o\n*.ko\n*.obj\n*.elf\n\n# Linker output\n*.ilk\n*.map\n*.exp\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Libraries\n*.lib\n*.la\n*.lo\n\n# Shared objects (inc. Windows DLLs)\n*.dll\n*.so\n*.so.*\n*.dylib\n\n# Executables\n*.exe\n*.out\n*.app\n*.i*86\n*.x86_64\n*.hex\n\n# Debug files\n*.dSYM/\n*.su\n*.idb\n*.pdb\n\n# Kernel Module Compile Results\n*.mod*\n*.cmd\n.tmp_versions/\nmodules.order\nModule.symvers\nMkfile.old\ndkms.conf\n\n# VDS\n*.vs\n*.rco\n*.rcd\n*.pptx\neboot.bin\neboot2.bin\nparam.sfo\nparam2.sfo\nPSVita_Debug\nPSVita_Release\nRES_RCO_TMP"
  },
  {
    "path": "NetStream/CONTENTS/sce_sys/livearea/contents/template.xml",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<livearea style=\"a1\" format-ver=\"01.03\" content-rev=\"1\">\n\t\n\t<livearea-background>\n\t\t<image>labg.png</image>\n\t</livearea-background>\n\t\n\t<gate>\n\t\t<startup-image>gate.png</startup-image>\n\t</gate>\n\t\n\t<frame id=\"frame3\">\n\t\t<liveitem>\t<lang>ja</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>en</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>fr</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>es</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>de</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>it</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>nl</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>pt</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>ru</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>ko</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>ch</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>zh</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>fi</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>sv</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>da</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>no</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>pl</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>en-gb</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>pt-br</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\t\t<liveitem>\t<lang>tr</lang> <image valign=\"top\">title-en.png</image> </liveitem>\n\n\t\t<liveitem default=\"on\">\t\n\t\t\t<image valign=\"top\">title-en.png</image> \n\t\t</liveitem>\n\t</frame>\n</livearea>\n\n"
  },
  {
    "path": "NetStream/NetStream.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|PSVita\">\n      <Configuration>Debug</Configuration>\n      <Platform>PSVita</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|PSVita\">\n      <Configuration>Release</Configuration>\n      <Platform>PSVita</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"source\\browsers\\ftp_server_browser.cpp\" />\n    <ClCompile Include=\"source\\browsers\\http_server_browser.cpp\" />\n    <ClCompile Include=\"source\\browsers\\hvdb_tracks_browser.cpp\" />\n    <ClCompile Include=\"source\\browsers\\local_server_browser.cpp\" />\n    <ClCompile Include=\"source\\hvdb_utils.cpp\" />\n    <ClCompile Include=\"source\\menus\\menu_hvdb.cpp\" />\n    <ClCompile Include=\"source\\np_utils.cpp\" />\n    <ClCompile Include=\"source\\debug.cpp\" />\n    <ClCompile Include=\"source\\dialog.cpp\" />\n    <ClCompile Include=\"source\\downloader.cpp\" />\n    <ClCompile Include=\"source\\event.cpp\" />\n    <ClCompile Include=\"source\\ftpparse.c\" />\n    <ClCompile Include=\"source\\main.cpp\" />\n    <ClCompile Include=\"source\\menus\\menu_first.cpp\" />\n    <ClCompile Include=\"source\\menus\\menu_generic.cpp\" />\n    <ClCompile Include=\"source\\menus\\menu_player_simple.cpp\" />\n    <ClCompile Include=\"source\\menus\\menu_server.cpp\" />\n    <ClCompile Include=\"source\\menus\\menu_settings.cpp\" />\n    <ClCompile Include=\"source\\menus\\menu_youtube.cpp\" />\n    <ClCompile Include=\"source\\menus\\menu_player_youtube.cpp\" />\n    <ClCompile Include=\"source\\option_menu.cpp\" />\n    <ClCompile Include=\"source\\paf_runtime.cpp\" />\n    <ClCompile Include=\"source\\players\\player_av.cpp\" />\n    <ClCompile Include=\"source\\players\\player_beav.cpp\" />\n    <ClCompile Include=\"source\\players\\player_fmod.cpp\" />\n    <ClCompile Include=\"source\\subs\\subs_generic.cpp\" />\n    <ClCompile Include=\"source\\subs\\subs_srt.cpp\" />\n    <ClCompile Include=\"source\\tex_pool.cpp\" />\n    <ClCompile Include=\"source\\tw_utils.cpp\" />\n    <ClCompile Include=\"source\\utils.cpp\" />\n    <ClCompile Include=\"source\\yt_utils.cpp\" />\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"include\\browsers\\ftp_server_browser.h\" />\n    <ClInclude Include=\"include\\browsers\\generic_server_browser.h\" />\n    <ClInclude Include=\"include\\browsers\\http_server_browser.h\" />\n    <ClInclude Include=\"include\\browsers\\hvdb_tracks_browser.h\" />\n    <ClInclude Include=\"include\\browsers\\local_server_browser.h\" />\n    <ClInclude Include=\"include\\hvdb_utils.h\" />\n    <ClInclude Include=\"include\\menus\\menu_hvdb.h\" />\n    <ClInclude Include=\"include\\menus\\menu_hvdb_tracks.h\" />\n    <ClInclude Include=\"include\\np_utils.h\" />\n    <ClInclude Include=\"include\\common.h\" />\n    <ClInclude Include=\"include\\debug.h\" />\n    <ClInclude Include=\"include\\dialog.h\" />\n    <ClInclude Include=\"include\\downloader.h\" />\n    <ClInclude Include=\"include\\event.h\" />\n    <ClInclude Include=\"include\\ftpparse.h\" />\n    <ClInclude Include=\"include\\main.h\" />\n    <ClInclude Include=\"include\\menus\\menu_first.h\" />\n    <ClInclude Include=\"include\\menus\\menu_ftp.h\" />\n    <ClInclude Include=\"include\\menus\\menu_generic.h\" />\n    <ClInclude Include=\"include\\menus\\menu_http.h\" />\n    <ClInclude Include=\"include\\menus\\menu_local.h\" />\n    <ClInclude Include=\"include\\menus\\menu_player_simple.h\" />\n    <ClInclude Include=\"include\\menus\\menu_server.h\" />\n    <ClInclude Include=\"include\\menus\\menu_settings.h\" />\n    <ClInclude Include=\"include\\menus\\menu_youtube.h\" />\n    <ClInclude Include=\"include\\menus\\menu_player_youtube.h\" />\n    <ClInclude Include=\"include\\option_menu.h\" />\n    <ClInclude Include=\"include\\players\\player_av.h\" />\n    <ClInclude Include=\"include\\players\\player_beav.h\" />\n    <ClInclude Include=\"include\\players\\player_fmod.h\" />\n    <ClInclude Include=\"include\\players\\player_generic.h\" />\n    <ClInclude Include=\"include\\subs\\subs_generic.h\" />\n    <ClInclude Include=\"include\\subs\\subs_srt.h\" />\n    <ClInclude Include=\"include\\tex_pool.h\" />\n    <ClInclude Include=\"include\\tw_utils.h\" />\n    <ClInclude Include=\"include\\utils.h\" />\n    <ClInclude Include=\"include\\yt_utils.h\" />\n  </ItemGroup>\n  <ItemGroup>\n    <Xml Include=\"RES_RCO\\file\\netstream_settings.xml\">\n      <SubType>Designer</SubType>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_en.xml\" />\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_es.xml\" />\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_fr.xml\" />\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_it.xml\" />\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_ja.xml\" />\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_pl.xml\" />\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_pt-br.xml\" />\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_pt.xml\" />\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_ru.xml\" />\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_zh-s.xml\" />\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_zh-t.xml\" />\n    <Xml Include=\"RES_RCO\\netstream_plugin.xml\">\n      <SubType>Designer</SubType>\n    </Xml>\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{CA4F859F-6FE6-413C-A24A-44CF552FCE91}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|PSVita'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|PSVita'\" Label=\"Configuration\">\n    <ConfigurationType>Application</ConfigurationType>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <PropertyGroup Condition=\"'$(DebuggerFlavor)'=='PSVitaDebugger'\" Label=\"OverrideDebuggerDefaults\">\n    <!--LocalDebuggerCommand>$(TargetPath)</LocalDebuggerCommand-->\n    <!--LocalDebuggerReboot>false</LocalDebuggerReboot-->\n    <!--LocalDebuggerCommandArguments></LocalDebuggerCommandArguments-->\n    <!--LocalDebuggerTarget></LocalDebuggerTarget-->\n    <!--LocalDebuggerWorkingDirectory>$(ProjectDir)</LocalDebuggerWorkingDirectory-->\n    <!--LocalMappingFile></LocalMappingFile-->\n    <!--LocalRunCommandLine></LocalRunCommandLine-->\n  </PropertyGroup>\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|PSVita'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|PSVita'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup />\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|PSVita'\">\n    <ClCompile>\n      <PreprocessorDefinitions>_DEBUG;SCE_PAF_TOOL_PRX;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <AdditionalIncludeDirectories>$(SCE_PSP2_SDK_DIR)\\target\\include\\vdsuite\\user;$(SCE_PSP2_SDK_DIR)\\target\\include\\vdsuite\\common;$(ProjectDir)libs\\include;$(ProjectDir)include;$(SCE_PSP2_SDK_DIR)\\target\\include\\vdsuite\\user\\psp2_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <CppLanguageStd>Cpp11</CppLanguageStd>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <AdditionalOptions>--no-standard-libraries </AdditionalOptions>\n      <AdditionalLibraryDirectories>$(SCE_PSP2_SDK_DIR)\\target\\lib\\vdsuite;$(ProjectDir)libs\\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n      <GenerateSnMapFile>FullMapFile</GenerateSnMapFile>\n      <AdditionalDependencies>-ltaihen_stub;-lSceRtcUser_stub;-lSceIpmi_stub;-lSceSysmem_stub;-lSceThreadMgr_stub;-lSceThreadmgrCoredumpTime_stub;-lSceModuleMgr_stub;-lSceProcessMgr_stub;-lSceTouch_stub;-lSceAppMgr_stub;-lSceAppMgrUser_stub;-lSceAppUtil_stub;-lSceAudio_stub;-lSceCtrl_stub;-lSceDisplay_stub;-lScePower_stub;-lSceSysmodule_stub;-lSceRegMgr_stub;-lSceDbg_stub;-lScePafThread_stub;-lScePafStdc_stub;-lScePafToplevel_stub;-lScePafResource_stub;-lScePafWidget_stub;-lScePafMisc_stub;-lScePafCommon_stub;-lScePafGraphics_stub;-lSceLibKernel_stub;-lSceNet_stub;-lSceNetCtl_stub;-lSceAppSettings_stub;-lSceCommonGuiDialog_stub;-lSceCommonDialog_stub;-lSceHttp_stub;-lSceSsl_stub;-lSceIniFileProcessor_stub;-lSceAvPlayerPSVita_stub;-lSceBeavCorePlayer_stub;-lSceDmacmgr_stub;-lSceFiber_stub;-lSceVshBridge_stub;-lSceNpManager_stub;-lSceNpCommon_stub;-lSceNpBasic_stub;-lSceNpTus_stub;-ltaihenUnsafe_stub;-lFourthTube_stub;-lLootkit_stub;-lhvdb_stub;-lcurl_stub;-lfmodstudio_stub;-lfmodngpext_stub;-lsnc;-lPafFileExt;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n    <PostBuildEvent>\n      <Command>\"$(SCE_PSP2_SDK_DIR)/host_tools/build/bin/vdsuite-pubprx.exe\" --boot-param \"$(ProjectDir)ebootparam.bin\" \"$(LocalDebuggerCommand)\" \"$(OutDir)eboot.bin\"</Command>\n    </PostBuildEvent>\n    <PreBuildEvent>\n      <Command>\"$(SCE_PSP2_SDK_DIR)/host_tools/build/rco/bin/psp2pafhashgen.exe\" -i \"$(ProjectDir)RES_RCO\\netstream_plugin.xml\" -o \"$(ProjectDir)include\\netstream_plugin.h\"\n\"$(SCE_PSP2_SDK_DIR)/host_tools/build/rco/bin/psp2pafhashgen.exe\" -i \"$(ProjectDir)RES_RCO\\file\\netstream_settings.xml\" -o \"$(ProjectDir)include\\netstream_settings.h\"\n\"$(SCE_PSP2_SDK_DIR)/host_tools/build/rco/bin/psp2pafhashgen.exe\" -i \"$(ProjectDir)RES_RCO\\locale\\netstream_locale_en.xml\" -o \"$(ProjectDir)include\\netstream_locale.h\"</Command>\n      <Message>VDSUITE: generate PAF hashlist</Message>\n    </PreBuildEvent>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|PSVita'\">\n    <ClCompile>\n      <PreprocessorDefinitions>NDEBUG;SCE_DBG_LOGGING_ENABLED=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\n      <OptimizationLevel>Level3</OptimizationLevel>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <AdditionalIncludeDirectories>$(SCE_PSP2_SDK_DIR)\\target\\include\\vdsuite\\user;$(SCE_PSP2_SDK_DIR)\\target\\include\\vdsuite\\common;$(ProjectDir)libs\\include;$(ProjectDir)include;$(SCE_PSP2_SDK_DIR)\\target\\include\\vdsuite\\user\\psp2_compat;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <CppLanguageStd>Cpp11</CppLanguageStd>\n      <MultiProcessorCompilation>true</MultiProcessorCompilation>\n    </ClCompile>\n    <Link>\n      <AdditionalLibraryDirectories>$(SCE_PSP2_SDK_DIR)\\target\\lib\\vdsuite;$(ProjectDir)libs\\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n    </Link>\n    <Link>\n      <InfoStripping>StripSymsAndDebug</InfoStripping>\n    </Link>\n    <Link>\n      <DataStripping>StripFuncsAndData</DataStripping>\n    </Link>\n    <Link>\n      <DuplicateStripping>true</DuplicateStripping>\n      <AdditionalOptions>--no-standard-libraries</AdditionalOptions>\n      <AdditionalDependencies>-ltaihen_stub;-lSceRtcUser_stub;-lSceIpmi_stub;-lSceSysmem_stub;-lSceThreadMgr_stub;-lSceThreadmgrCoredumpTime_stub;-lSceModuleMgr_stub;-lSceProcessMgr_stub;-lSceTouch_stub;-lSceAppMgr_stub;-lSceAppMgrUser_stub;-lSceAppUtil_stub;-lSceAudio_stub;-lSceCtrl_stub;-lSceDisplay_stub;-lScePower_stub;-lSceSysmodule_stub;-lSceRegMgr_stub;-lSceDbg_stub;-lScePafThread_stub;-lScePafStdc_stub;-lScePafToplevel_stub;-lScePafResource_stub;-lScePafWidget_stub;-lScePafMisc_stub;-lScePafCommon_stub;-lScePafGraphics_stub;-lSceLibKernel_stub;-lSceNet_stub;-lSceNetCtl_stub;-lSceAppSettings_stub;-lSceCommonGuiDialog_stub;-lSceCommonDialog_stub;-lSceHttp_stub;-lSceSsl_stub;-lSceIniFileProcessor_stub;-lSceAvPlayerPSVita_stub;-lSceBeavCorePlayer_stub;-lSceDmacmgr_stub;-lSceFiber_stub;-lSceVshBridge_stub;-lSceNpManager_stub;-lSceNpCommon_stub;-lSceNpBasic_stub;-lSceNpTus_stub;-ltaihenUnsafe_stub;-lFourthTube_stub;-lLootkit_stub;-lhvdb_stub;-lcurl_stub;-lfmodstudio_stub;-lfmodngpext_stub;-lsnc;-lPafFileExt;%(AdditionalDependencies)</AdditionalDependencies>\n    </Link>\n    <PostBuildEvent>\n      <Command>call \"$(ProjectDir)gen_rco.bat\"\n\"$(SCE_PSP2_SDK_DIR)/host_tools/build/bin/vdsuite-pubprx.exe\" --strip --compress --boot-param \"$(ProjectDir)ebootparam.bin\" \"$(LocalDebuggerCommand)\" \"$(OutDir)eboot.bin\"\n\"$(SCE_PSP2_SDK_DIR)/host_tools/build/bin/vdsuite-pubsfo.exe\" \"$(ProjectDir)param.sfx\" \"$(OutDir)param.sfo\"\n\"$(SCE_PSP2_SDK_DIR)/host_tools/build/bin/vdsuite-pubgen.exe\" --file \"$(OutDir)eboot.bin\" eboot.bin  --file \"$(OutDir)param.sfo\" sce_sys/param.sfo --file \"$(ProjectDir)CONTENTS/sce_sys/icon0.png\" sce_sys/icon0.png --file \"$(ProjectDir)CONTENTS/sce_sys/pic0.png\" sce_sys/pic0.png --file \"$(ProjectDir)CONTENTS/sce_sys/livearea\" sce_sys/livearea --file \"$(ProjectDir)CONTENTS/sce_sys/manual\" sce_sys/manual --file \"$(ProjectDir)CONTENTS/module\" module  --file \"$(ProjectDir)CONTENTS/netstream_plugin.rco\" netstream_plugin.rco \"$(OutDir)$(ProjectName).vpk\"\ncopy /Y \"$(OutDir)eboot.bin\" \"$(ProjectDir)CONTENTS/eboot.bin\"\ncopy /Y \"$(OutDir)param.sfo\" \"$(ProjectDir)CONTENTS/sce_sys/param.sfo\"\n\"$(SCE_ROOT_DIR)/PSP2/Tools/Publishing Tools/bin/ext/make_pkg.exe\" --output $(OutDir) \"$(ProjectDir)package.conf\" $(ProjectDir)</Command>\n    </PostBuildEvent>\n    <PostBuildEvent>\n      <Message>VDSUITE: Building packages</Message>\n    </PostBuildEvent>\n    <PreBuildEvent>\n      <Command>\n      </Command>\n      <Message>\n      </Message>\n    </PreBuildEvent>\n  </ItemDefinitionGroup>\n  <Import Condition=\"'$(ConfigurationType)' == 'Makefile' and Exists('$(VCTargetsPath)\\Platforms\\$(Platform)\\SCE.Makefile.$(Platform).targets')\" Project=\"$(VCTargetsPath)\\Platforms\\$(Platform)\\SCE.Makefile.$(Platform).targets\" />\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "NetStream/NetStream.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cxx;cc;s;asm</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hpp</Extensions>\n    </Filter>\n    <Filter Include=\"Source Files\\menus\">\n      <UniqueIdentifier>{46cc97e8-968f-4244-9a90-70ff8461f55e}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\menus\">\n      <UniqueIdentifier>{846ca004-6b98-44d7-aef8-7a0982f51f14}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\resource\">\n      <UniqueIdentifier>{784adb2a-2159-4d72-ba10-3c360fe3bb22}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\players\">\n      <UniqueIdentifier>{fbf463f0-23d6-426a-920e-d57c6fc940e0}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\players\">\n      <UniqueIdentifier>{ebaf1957-7ba0-40ce-a4b3-c3fbf14b8060}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\browsers\">\n      <UniqueIdentifier>{c1271002-95d8-4ece-9b10-de876141361f}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\browsers\">\n      <UniqueIdentifier>{0601fe77-e2f9-480e-8377-27578763de4a}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Source Files\\subs\">\n      <UniqueIdentifier>{02e6370e-4def-44f0-b9b3-f761cfa3fc9a}</UniqueIdentifier>\n    </Filter>\n    <Filter Include=\"Header Files\\subs\">\n      <UniqueIdentifier>{92115278-5319-4fda-b0eb-0787c9ec7d91}</UniqueIdentifier>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"source\\debug.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\main.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\paf_runtime.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\dialog.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\utils.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\yt_utils.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\menus\\menu_generic.cpp\">\n      <Filter>Source Files\\menus</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\menus\\menu_first.cpp\">\n      <Filter>Source Files\\menus</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\menus\\menu_settings.cpp\">\n      <Filter>Source Files\\menus</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\menus\\menu_player_simple.cpp\">\n      <Filter>Source Files\\menus</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\menus\\menu_youtube.cpp\">\n      <Filter>Source Files\\menus</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\menus\\menu_player_youtube.cpp\">\n      <Filter>Source Files\\menus</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\downloader.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\option_menu.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\menus\\menu_server.cpp\">\n      <Filter>Source Files\\menus</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\tw_utils.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\ftpparse.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\tex_pool.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\event.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\np_utils.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\menus\\menu_hvdb.cpp\">\n      <Filter>Source Files\\menus</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\hvdb_utils.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\players\\player_av.cpp\">\n      <Filter>Source Files\\players</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\players\\player_beav.cpp\">\n      <Filter>Source Files\\players</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\players\\player_fmod.cpp\">\n      <Filter>Source Files\\players</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\browsers\\ftp_server_browser.cpp\">\n      <Filter>Source Files\\browsers</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\browsers\\http_server_browser.cpp\">\n      <Filter>Source Files\\browsers</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\browsers\\local_server_browser.cpp\">\n      <Filter>Source Files\\browsers</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\subs\\subs_generic.cpp\">\n      <Filter>Source Files\\subs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\subs\\subs_srt.cpp\">\n      <Filter>Source Files\\subs</Filter>\n    </ClCompile>\n    <ClCompile Include=\"source\\browsers\\hvdb_tracks_browser.cpp\">\n      <Filter>Source Files\\browsers</Filter>\n    </ClCompile>\n  </ItemGroup>\n  <ItemGroup>\n    <ClInclude Include=\"include\\common.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\debug.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\dialog.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\main.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\utils.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_settings.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_youtube.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\yt_utils.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_generic.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_first.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_http.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_player_simple.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_player_youtube.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\downloader.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_local.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\option_menu.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_ftp.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_server.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\tw_utils.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\ftpparse.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\tex_pool.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\event.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\np_utils.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_hvdb.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\hvdb_utils.h\">\n      <Filter>Header Files</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\players\\player_av.h\">\n      <Filter>Header Files\\players</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\players\\player_beav.h\">\n      <Filter>Header Files\\players</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\players\\player_fmod.h\">\n      <Filter>Header Files\\players</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\players\\player_generic.h\">\n      <Filter>Header Files\\players</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\browsers\\ftp_server_browser.h\">\n      <Filter>Header Files\\browsers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\browsers\\generic_server_browser.h\">\n      <Filter>Header Files\\browsers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\browsers\\http_server_browser.h\">\n      <Filter>Header Files\\browsers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\browsers\\local_server_browser.h\">\n      <Filter>Header Files\\browsers</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\subs\\subs_generic.h\">\n      <Filter>Header Files\\subs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\subs\\subs_srt.h\">\n      <Filter>Header Files\\subs</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\menus\\menu_hvdb_tracks.h\">\n      <Filter>Header Files\\menus</Filter>\n    </ClInclude>\n    <ClInclude Include=\"include\\browsers\\hvdb_tracks_browser.h\">\n      <Filter>Header Files\\browsers</Filter>\n    </ClInclude>\n  </ItemGroup>\n  <ItemGroup>\n    <Xml Include=\"RES_RCO\\netstream_plugin.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_en.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\file\\netstream_settings.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_es.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_ja.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_zh-s.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_zh-t.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_ru.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_pl.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_pt.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_pt-br.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_it.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n    <Xml Include=\"RES_RCO\\locale\\netstream_locale_fr.xml\">\n      <Filter>Source Files\\resource</Filter>\n    </Xml>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NetStream/NetStream.vcxproj.user",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup />\n</Project>"
  },
  {
    "path": "NetStream/RES_RCO/file/netstream_settings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<application_settings version=\"1.0\" bg_color=\"17.0, 75.0, 168.0, 255.0\">\n  <setting_list id=\"ns_setting\" title=\"msg_settings\">\n    <setting_list id=\"http_setting\" title=\"msg_settings_http\" style=\"edit\" icon=\"tex_spanner\">\n      <text_field id=\"http_host\" title=\"msg_http_host\" max_length=\"255\" min_length=\"0\" keyboard_type=\"url\" key=\"http_host\" default_value=\"\"/>\n      <text_field id=\"http_port\" title=\"msg_http_port\" max_length=\"31\" min_length=\"0\" keyboard_type=\"numeral\" key=\"http_port\" default_value=\"\"/>\n      <text_field id=\"http_user\" title=\"msg_http_user\" max_length=\"255\" min_length=\"0\" keyboard_type=\"alphabet\" key=\"http_user\" default_value=\"\"/>\n      <text_field id=\"http_password\" title=\"msg_http_password\" max_length=\"255\" min_length=\"0\" keyboard_type=\"alphabet\" key=\"http_password\" default_value=\"\"/>\n    </setting_list>\n    <setting_list id=\"ftp_setting\" title=\"msg_settings_ftp\" style=\"edit\" icon=\"tex_spanner\">\n      <text_field id=\"ftp_host\" title=\"msg_ftp_host\" max_length=\"255\" min_length=\"0\" keyboard_type=\"url\" key=\"ftp_host\" default_value=\"\"/>\n      <text_field id=\"ftp_port\" title=\"msg_ftp_port\" max_length=\"31\" min_length=\"0\" keyboard_type=\"numeral\" key=\"ftp_port\" default_value=\"\"/>\n      <text_field id=\"ftp_user\" title=\"msg_ftp_user\" max_length=\"255\" min_length=\"0\" keyboard_type=\"alphabet\" key=\"ftp_user\" default_value=\"\"/>\n      <text_field id=\"ftp_password\" title=\"msg_ftp_password\" max_length=\"255\" min_length=\"0\" keyboard_type=\"alphabet\" key=\"ftp_password\" default_value=\"\"/>\n      <toggle_switch id=\"ftp_nlst\" title=\"msg_ftp_nlst\" hint=\"msg_ftp_nlst_hint\" key=\"ftp_nlst\" default_value=\"0\" />\n    </setting_list>\n    <setting_list id=\"hvdb_account_setting\" title=\"msg_settings_account\" style=\"edit\" icon=\"tex_spanner\">\n      <text_field id=\"hvdb_host\" title=\"msg_hvdb_host\" max_length=\"255\" min_length=\"0\" keyboard_type=\"url\" key=\"hvdb_host\" default_value=\"\"/>\n      <text_field id=\"hvdb_user\" title=\"msg_hvdb_user\" max_length=\"255\" min_length=\"0\" keyboard_type=\"alphabet\" key=\"hvdb_user\" default_value=\"\"/>\n      <text_field id=\"hvdb_password\" title=\"msg_hvdb_password\" max_length=\"255\" min_length=\"0\" keyboard_type=\"alphabet\" key=\"hvdb_password\" default_value=\"\"/>\n    </setting_list>\n    <setting_list id=\"hvdb_search_setting\" title=\"msg_settings_search\" icon=\"tex_spanner\">\n      <list id=\"list_hvdb_search_sort\" title=\"msg_hvdb_search_sort\" key=\"hvdb_search_sort\" default_value=\"0\">\n        <list_item id=\"list_hvdb_search_sort_00\" title=\"msg_option_hvdb_search_sort_0\" value=\"0\" />\n        <list_item id=\"list_hvdb_search_sort_01\" title=\"msg_option_hvdb_search_sort_1\" value=\"1\" />\n      </list>\n      <list id=\"list_hvdb_search_sort_type\" title=\"msg_hvdb_search_sort_type\" key=\"hvdb_search_sort_type\" default_value=\"1\">\n        <list_item id=\"list_hvdb_search_sort_type_00\" title=\"msg_option_hvdb_search_sort_type_0\" value=\"0\" />\n        <list_item id=\"list_hvdb_search_sort_type_01\" title=\"msg_option_hvdb_search_sort_type_1\" value=\"1\" />\n        <list_item id=\"list_hvdb_search_sort_type_02\" title=\"msg_option_hvdb_search_sort_type_2\" value=\"2\" />\n        <list_item id=\"list_hvdb_search_sort_type_03\" title=\"msg_option_hvdb_search_sort_type_3\" value=\"3\" />\n        <list_item id=\"list_hvdb_search_sort_type_04\" title=\"msg_option_hvdb_search_sort_type_4\" value=\"4\" />\n        <list_item id=\"list_hvdb_search_sort_type_05\" title=\"msg_option_hvdb_search_sort_type_5\" value=\"5\" />\n        <list_item id=\"list_hvdb_search_sort_type_06\" title=\"msg_option_hvdb_search_sort_type_6\" value=\"6\" />\n        <list_item id=\"list_hvdb_search_sort_type_07\" title=\"msg_option_hvdb_search_sort_type_7\" value=\"7\" />\n        <list_item id=\"list_hvdb_search_sort_type_08\" title=\"msg_option_hvdb_search_sort_type_8\" value=\"8\" />\n      </list>\n      <list id=\"list_hvdb_search_filter\" title=\"msg_hvdb_search_filter\" key=\"hvdb_search_filter\" default_value=\"5\">\n        <list_item id=\"list_hvdb_search_filter_00\" title=\"msg_option_hvdb_search_filter_0\" value=\"0\" />\n        <list_item id=\"list_hvdb_search_filter_01\" title=\"msg_option_hvdb_search_filter_1\" value=\"1\" />\n        <list_item id=\"list_hvdb_search_filter_02\" title=\"msg_option_hvdb_search_filter_2\" value=\"2\" />\n        <list_item id=\"list_hvdb_search_filter_03\" title=\"msg_option_hvdb_search_filter_3\" value=\"3\" />\n        <list_item id=\"list_hvdb_search_filter_04\" title=\"msg_option_hvdb_search_filter_4\" value=\"4\" />\n        <list_item id=\"list_hvdb_search_filter_05\" title=\"msg_option_hvdb_search_filter_5\" value=\"5\" />\n      </list>\n    </setting_list>\n    <setting_list id=\"hvdb_player_setting\" title=\"msg_settings_player\" icon=\"tex_spanner\">\n      <toggle_switch id=\"toggle_hvdb_banner\" title=\"msg_toggle_hvdb_banner\" key=\"hvdb_show_banner\" default_value=\"1\" />\n    </setting_list>\n    <setting_list id=\"local_setting\" title=\"msg_settings_local\" icon=\"tex_spanner\">\n      <text_field id=\"local_playlist_prefix\" title=\"msg_local_playlist_prefix\" max_length=\"255\" min_length=\"0\" keyboard_type=\"url\" key=\"local_playlist_prefix\" default_value=\"\"/>\n      <list id=\"list_local_sort_name\" title=\"msg_local_sort_name\" key=\"local_sort_name\" default_value=\"0\">\n        <list_item id=\"list_local_sort_name_00\" title=\"msg_option_local_sort_name_0\" value=\"0\" />\n        <list_item id=\"list_local_sort_name_01\" title=\"msg_option_local_sort_name_1\" value=\"1\" />\n      </list>\n      <list id=\"list_local_sort_type\" title=\"msg_local_sort_type\" key=\"local_sort_type\" default_value=\"0\">\n        <list_item id=\"list_local_sort_type_00\" title=\"msg_option_local_sort_type_0\" value=\"0\" />\n        <list_item id=\"list_local_sort_type_01\" title=\"msg_option_local_sort_type_1\" value=\"1\" />\n      </list>\n    </setting_list>\n    <setting_list id=\"youtube_search_setting\" title=\"msg_settings_search\" icon=\"tex_spanner\">\n      <list id=\"list_youtube_search_region\" title=\"msg_youtube_search_region\" key=\"yt_search_region\" default_value=\"0\">\n        <list_item id=\"list_youtube_search_region_00\" title=\"msg_option_search_region_0\" value=\"0\" />\n      </list>\n      <list id=\"list_youtube_search_sort\" title=\"msg_youtube_search_sort\" key=\"yt_search_sort\" default_value=\"0\">\n        <list_item id=\"list_youtube_search_sort_00\" title=\"msg_option_search_sort_0\" value=\"0\" />\n        <list_item id=\"list_youtube_search_sort_01\" title=\"msg_option_search_sort_1\" value=\"1\" />\n        <list_item id=\"list_youtube_search_sort_02\" title=\"msg_option_search_sort_2\" value=\"2\" />\n        <list_item id=\"list_youtube_search_sort_03\" title=\"msg_option_search_sort_3\" value=\"3\" />\n      </list>\n      <list id=\"list_youtube_search_date\" title=\"msg_youtube_search_date\" key=\"yt_search_date\" default_value=\"5\">\n        <list_item id=\"list_youtube_search_date_00\" title=\"msg_option_search_date_0\" value=\"0\" />\n        <list_item id=\"list_youtube_search_date_01\" title=\"msg_option_search_date_1\" value=\"1\" />\n        <list_item id=\"list_youtube_search_date_02\" title=\"msg_option_search_date_2\" value=\"2\" />\n        <list_item id=\"list_youtube_search_date_03\" title=\"msg_option_search_date_3\" value=\"3\" />\n        <list_item id=\"list_youtube_search_date_04\" title=\"msg_option_search_date_4\" value=\"4\" />\n        <list_item id=\"list_youtube_search_date_05\" title=\"msg_option_search_date_5\" value=\"5\" />\n      </list>\n      <list id=\"list_youtube_search_dur\" title=\"msg_youtube_search_dur\" key=\"yt_search_dur\" default_value=\"3\">\n        <list_item id=\"list_youtube_search_dur_00\" title=\"msg_option_search_dur_0\" value=\"0\" />\n        <list_item id=\"list_youtube_search_dur_01\" title=\"msg_option_search_dur_1\" value=\"1\" />\n        <list_item id=\"list_youtube_search_dur_02\" title=\"msg_option_search_dur_2\" value=\"2\" />\n        <list_item id=\"list_youtube_search_dur_03\" title=\"msg_option_search_dur_3\" value=\"3\" />\n      </list>\n      <list id=\"list_youtube_search_feature\" title=\"msg_youtube_search_feature\" key=\"yt_search_feature\" default_value=\"1\">\n        <list_item id=\"list_youtube_search_feature_00\" title=\"msg_option_search_feature_0\" value=\"0\" />\n        <list_item id=\"list_youtube_search_feature_01\" title=\"msg_option_search_feature_1\" value=\"1\" />\n      </list>\n      <text_field id=\"text_field_youtube_search_proxy\" title=\"msg_youtube_search_proxy\" max_length=\"255\" min_length=\"0\" keyboard_type=\"url\" key=\"yt_search_proxy\" default_value=\"\"/>\n    </setting_list>\n    <setting_list id=\"youtube_comment_setting\" title=\"msg_settings_comment\" icon=\"tex_spanner\">\n      <list id=\"list_youtube_comment_sort\" title=\"msg_youtube_comment_sort\" key=\"yt_comment_sort\" default_value=\"0\">\n        <list_item id=\"llist_youtube_comment_sort_00\" title=\"msg_option_comment_sort_0\" value=\"0\" />\n        <list_item id=\"llist_youtube_comment_sort_01\" title=\"msg_option_comment_sort_1\" value=\"1\" />\n      </list>\n    </setting_list>\n    <setting_list id=\"youtube_quality_setting\" title=\"msg_settings_quality\" icon=\"tex_spanner\">\n      <list id=\"list_youtube_quality_vod_video\" title=\"msg_youtube_quality_vod_video\" key=\"yt_quality_vod_video\" default_value=\"8\">\n        <list_item id=\"list_youtube_quality_vod_video_00\" title=\"msg_option_youtube_quality_vod_video_0\" value=\"31\" />\n        <list_item id=\"list_youtube_quality_vod_video_01\" title=\"msg_option_youtube_quality_vod_video_1\" value=\"1\" />\n        <list_item id=\"list_youtube_quality_vod_video_02\" title=\"msg_option_youtube_quality_vod_video_2\" value=\"2\" />\n        <list_item id=\"list_youtube_quality_vod_video_03\" title=\"msg_option_youtube_quality_vod_video_3\" value=\"4\" />\n        <list_item id=\"list_youtube_quality_vod_video_04\" title=\"msg_option_youtube_quality_vod_video_4\" value=\"8\" />\n        <list_item id=\"list_youtube_quality_vod_video_05\" title=\"msg_option_youtube_quality_vod_video_5\" value=\"16\" />\n      </list>\n      <list id=\"list_youtube_quality_live\" title=\"msg_youtube_quality_live\" key=\"yt_quality_live\" default_value=\"3\">\n        <list_item id=\"list_youtube_quality_live_00\" title=\"msg_option_youtube_quality_live_0\" value=\"0\" />\n        <list_item id=\"list_youtube_quality_live_01\" title=\"msg_option_youtube_quality_live_1\" value=\"1\" />\n        <list_item id=\"list_youtube_quality_live_02\" title=\"msg_option_youtube_quality_live_2\" value=\"2\" />\n        <list_item id=\"list_youtube_quality_live_03\" title=\"msg_option_youtube_quality_live_3\" value=\"3\" />\n        <list_item id=\"list_youtube_quality_live_04\" title=\"msg_option_youtube_quality_live_4\" value=\"4\" />\n      </list>\n    </setting_list>\n    <setting_list id=\"youtube_player_setting\" title=\"msg_settings_player\" icon=\"tex_spanner\">\n      <toggle_switch id=\"toggle_youtube_min\" title=\"msg_toggle_youtube_min\" key=\"yt_min\" default_value=\"1\" />\n    </setting_list>\n    <setting_list id=\"cloud_sync_setting\" title=\"msg_settings_cloud_sync\" icon=\"tex_spanner\">\n      <toggle_switch id=\"toggle_cloud_sync\" title=\"msg_toggle_cloud_sync\" hint=\"msg_cloud_sync_hint\" key=\"cloud_sync\" default_value=\"0\" />\n      <toggle_switch id=\"toggle_cloud_sync_auto\" title=\"msg_toggle_cloud_sync_auto\" key=\"cloud_sync_auto\" default_value=\"0\" />\n    </setting_list>\n    <setting_list id=\"verinfo_setting\" title=\"msg_settings_verinfo\" style=\"edit\" icon=\"tex_spanner\">\n      <label id=\"label_verinfo\" title=\"msg_verinfo\" style=\"heading\" />\n    </setting_list>\n  </setting_list>\n</application_settings>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_en.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<stringset>\n\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\n  <string src=\"HTTP Server\" id=\"msg_fpmenu_item_2\" />\n  <string src=\"FTP Server\" id=\"msg_fpmenu_item_3\" />\n  <string src=\"Local Storage\" id=\"msg_fpmenu_item_4\" />\n\n  <string src=\"History\" id=\"msg_youtube_history\" />\n  <string src=\"Description\" id=\"msg_youtube_description\" />\n  <string src=\"Load more comments...\" id=\"msg_youtube_comment_more\" />\n  <string src=\"Comment Details\" id=\"msg_youtube_comment_detail\" />\n  <string src=\"Comment Replies\" id=\"msg_youtube_comment_reply\" />\n  <string src=\" likes\" id=\"msg_youtube_comment_like_count\" />\n\n  <string src=\"Next Page\" id=\"msg_next_page\" />\n  <string src=\"Previous Page\" id=\"msg_previous_page\" />\n\n  <string src=\"Settings\" id=\"msg_settings\" />\n  <string src=\"HTTP Server\" id=\"msg_settings_http\" />\n  <string src=\"FTP Server\" id=\"msg_settings_ftp\" />\n  <string src=\"Account\" id=\"msg_settings_account\" />\n  <string src=\"Local Storage\" id=\"msg_settings_local\" />\n  <string src=\"Search\" id=\"msg_settings_search\" />\n  <string src=\"Comments\" id=\"msg_settings_comment\" />\n  <string src=\"Quality\" id=\"msg_settings_quality\" />\n  <string src=\"Player\" id=\"msg_settings_player\" />\n  <string src=\"Cloud Sync\" id=\"msg_settings_cloud_sync\" />\n  <string src=\"Build Information\" id=\"msg_settings_verinfo\" />\n  \n  <string src=\"Host Address\" id=\"msg_http_host\" />\n  <string src=\"Port\" id=\"msg_http_port\" />\n  <string src=\"User\" id=\"msg_http_user\" />\n  <string src=\"Password\" id=\"msg_http_password\" />\n\n  <string src=\"Host Address\" id=\"msg_ftp_host\" />\n  <string src=\"Port\" id=\"msg_ftp_port\" />\n  <string src=\"User\" id=\"msg_ftp_user\" />\n  <string src=\"Password\" id=\"msg_ftp_password\" />\n  <string src=\"Use NLST\" id=\"msg_ftp_nlst\" />\n  <string src=\"Enabling this option will make NetStream send NLST command to FTP server instead of the LIST command. This option makes operation faster but may not be supported by some FTP servers.\" id=\"msg_ftp_nlst_hint\" />\n  \n  <string src=\"Host Address\" id=\"msg_hvdb_host\" />\n  <string src=\"User\" id=\"msg_hvdb_user\" />\n  <string src=\"Password\" id=\"msg_hvdb_password\" />\n\n  <string src=\"Prefix For Relative .m3u8 Playlists\" id=\"msg_local_playlist_prefix\" />\n  <string src=\"Sort By Name\" id=\"msg_local_sort_name\" />\n  <string src=\"Sort By Type\" id=\"msg_local_sort_type\" />\n  <string src=\"Ascending\" id=\"msg_option_local_sort_name_0\" />\n  <string src=\"Descending\" id=\"msg_option_local_sort_name_1\" />\n  <string src=\"Folders First\" id=\"msg_option_local_sort_type_0\" />\n  <string src=\"Files First\" id=\"msg_option_local_sort_type_1\" />\n\n  <string src=\"VOD Video Quality\" id=\"msg_youtube_quality_vod_video\" />\n  <string src=\"VOD Audio Quality\" id=\"msg_youtube_quality_vod_audio\" />\n  <string src=\"Default Live Quality\" id=\"msg_youtube_quality_live\" />\n\n  <string src=\"Region\" id=\"msg_youtube_search_region\" />\n  <string src=\"Sort\" id=\"msg_youtube_search_sort\" />\n  <string src=\"Date\" id=\"msg_youtube_search_date\" />\n  <string src=\"Duration\" id=\"msg_youtube_search_dur\" />\n  <string src=\"Feature\" id=\"msg_youtube_search_feature\" />\n  <string src=\"Proxy Server\" id=\"msg_youtube_search_proxy\" />\n  <string src=\"Sort\" id=\"msg_youtube_comment_sort\" />\n\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\n\n  <string src=\"Relevance\" id=\"msg_option_search_sort_0\" />\n  <string src=\"Rating\" id=\"msg_option_search_sort_1\" />\n  <string src=\"Date\" id=\"msg_option_search_sort_2\" />\n  <string src=\"View Count\" id=\"msg_option_search_sort_3\" />\n  \n  <string src=\"Hour\" id=\"msg_option_search_date_0\" />\n  <string src=\"Today\" id=\"msg_option_search_date_1\" />\n  <string src=\"Week\" id=\"msg_option_search_date_2\" />\n  <string src=\"Month\" id=\"msg_option_search_date_3\" />\n  <string src=\"Year\" id=\"msg_option_search_date_4\" />\n  <string src=\"Any\" id=\"msg_option_search_date_5\" />\n\n  <string src=\"Short\" id=\"msg_option_search_dur_0\" />\n  <string src=\"Medium\" id=\"msg_option_search_dur_1\" />\n  <string src=\"Long\" id=\"msg_option_search_dur_2\" />\n  <string src=\"Any\" id=\"msg_option_search_dur_3\" />\n\n  <string src=\"Live\" id=\"msg_option_search_feature_0\" />\n  <string src=\"None\" id=\"msg_option_search_feature_1\" />\n  \n  <string src=\"Top\" id=\"msg_option_comment_sort_0\" />\n  <string src=\"New\" id=\"msg_option_comment_sort_1\" />\n\n  <string src=\"Auto\" id=\"msg_option_youtube_quality_vod_video_0\" />\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\n\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\n\n  <string src=\"Sort Order\" id=\"msg_hvdb_search_sort\" />\n  <string src=\"Sort Type\" id=\"msg_hvdb_search_sort_type\" />\n  <string src=\"Progress Filter\" id=\"msg_hvdb_search_filter\" />\n\n  <string src=\"Ascending\" id=\"msg_option_hvdb_search_sort_0\" />\n  <string src=\"Descending\" id=\"msg_option_hvdb_search_sort_1\" />\n\n  <string src=\"Create Date\" id=\"msg_option_hvdb_search_sort_type_0\" />\n  <string src=\"Release Date\" id=\"msg_option_hvdb_search_sort_type_1\" />\n  <string src=\"Purchase Count\" id=\"msg_option_hvdb_search_sort_type_2\" />\n  <string src=\"Price\" id=\"msg_option_hvdb_search_sort_type_3\" />\n  <string src=\"Rating\" id=\"msg_option_hvdb_search_sort_type_4\" />\n  <string src=\"Review Count\" id=\"msg_option_hvdb_search_sort_type_5\" />\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\n  <string src=\"Update Date\" id=\"msg_option_hvdb_search_sort_type_8\" />\n\n  <string src=\"Marked\" id=\"msg_option_hvdb_search_filter_0\" />\n  <string src=\"Listening\" id=\"msg_option_hvdb_search_filter_1\" />\n  <string src=\"Listened\" id=\"msg_option_hvdb_search_filter_2\" />\n  <string src=\"Replay\" id=\"msg_option_hvdb_search_filter_3\" />\n  <string src=\"Postponed\" id=\"msg_option_hvdb_search_filter_4\" />\n  <string src=\"Any\" id=\"msg_option_hvdb_search_filter_5\" />\n\n  <string src=\"Show Work Banner\" id=\"msg_toggle_hvdb_banner\" />\n\n  <string src=\"Use Cloud Sync\" id=\"msg_toggle_cloud_sync\" />\n  <string src=\"Sync Data Automatically\" id=\"msg_toggle_cloud_sync_auto\" />\n  <string src=\"Cloud sync option allows you to sync various data such as YouTube history and favourites, with cloud storage. This feature uses cloud storage provided by PlayStation™Network. Please restart this application after enabling this feature.\" id=\"msg_cloud_sync_hint\" />\n\n  <string src=\"Start Minimized\" id=\"msg_toggle_youtube_min\" />\n\n  <string src=\"Refresh\" id=\"msg_settings_hvdb_refresh\" />\n\n  <string src=\"Cloud Upload\" id=\"msg_settings_youtube_cloud_upload\" />\n  <string src=\"Cloud Download\" id=\"msg_settings_youtube_cloud_download\" />\n  <string src=\"Clear History\" id=\"msg_settings_youtube_clean_history\" />\n  <string src=\"Clear Favourites\" id=\"msg_settings_youtube_clean_fav\" />\n  <string src=\"All history records will be deleted. Do you want to continue?\" id=\"msg_settings_youtube_clean_history_confirm\" />\n  <string src=\"All favourites will be deleted. Do you want to continue?\" id=\"msg_settings_youtube_clean_fav_confirm\" />\n  <string src=\"Download\" id=\"msg_settings_youtube_download\" />\n  <string src=\"Download Audio\" id=\"msg_settings_youtube_download_audio\" />\n  <string src=\"Download has been added to the download queue.\" id=\"msg_settings_youtube_download_begin\" />\n\n  <string src=\"Select Quality\" id=\"msg_quality_select_dialog_title\" />\n\n  <string src=\"PlayStation™Network error has occured. Cloud data sync will not be available. If you enabled cloud sync option, please restart this application before using it.\" id=\"msg_error_psn_connection\" />\n\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_es.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<stringset>\n\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\n  <string src=\"Servidor HTTP\" id=\"msg_fpmenu_item_2\" />\n  <string src=\"Servidor FTP\" id=\"msg_fpmenu_item_3\" />\n  <string src=\"Almacenamiento local\" id=\"msg_fpmenu_item_4\" />\n\n  <string src=\"Historial\" id=\"msg_youtube_history\" />\n  <string src=\"Descripción\" id=\"msg_youtube_description\" />\n  <string src=\"Cargar más comentarios...\" id=\"msg_youtube_comment_more\" />\n  <string src=\"Detalles del comentario\" id=\"msg_youtube_comment_detail\" />\n  <string src=\"Respuestas\" id=\"msg_youtube_comment_reply\" />\n  <string src=\" me gusta\" id=\"msg_youtube_comment_like_count\" />\n\n  <string src=\"Página siguiente\" id=\"msg_next_page\" />\n  <string src=\"Página anterior\" id=\"msg_previous_page\" />\n\n  <string src=\"Configuración\" id=\"msg_settings\" />\n  <string src=\"Servidor HTTP\" id=\"msg_settings_http\" />\n  <string src=\"Servidor FTP\" id=\"msg_settings_ftp\" />\n  <string src=\"Account\" id=\"msg_settings_account\" />\n  <string src=\"Almacenamiento local\" id=\"msg_settings_local\" />\n  <string src=\"Búsqueda\" id=\"msg_settings_search\" />\n  <string src=\"Comentarios\" id=\"msg_settings_comment\" />\n  <string src=\"Calidad\" id=\"msg_settings_quality\" />\n  <string src=\"Reproductor\" id=\"msg_settings_player\" />\n  <string src=\"Sincronización en la nube\" id=\"msg_settings_cloud_sync\" />\n  <string src=\"Información de compilación\" id=\"msg_settings_verinfo\" />\n  \n  <string src=\"Dirección de Host\" id=\"msg_http_host\" />\n  <string src=\"Puerto\" id=\"msg_http_port\" />\n  <string src=\"Usuario\" id=\"msg_http_user\" />\n  <string src=\"Contraseña\" id=\"msg_http_password\" />\n\n  <string src=\"Dirección de Host\" id=\"msg_ftp_host\" />\n  <string src=\"Puerto\" id=\"msg_ftp_port\" />\n  <string src=\"Usuario\" id=\"msg_ftp_user\" />\n  <string src=\"Contraseña\" id=\"msg_ftp_password\" />\n  <string src=\"Utilizar NLST\" id=\"msg_ftp_nlst\" />\n  <string src=\"Si activas esta opción, NetStream enviará el comando NLST al servidor FTP en lugar del comando LIST. Esta opción agiliza el funcionamiento, pero algunos servidores FTP podrían no admitirla.\" id=\"msg_ftp_nlst_hint\" />\n\n  <string src=\"Host Address\" id=\"msg_hvdb_host\" />\n  <string src=\"User\" id=\"msg_hvdb_user\" />\n  <string src=\"Password\" id=\"msg_hvdb_password\" />\n\n  <string src=\"Prefijo para listas de reproducción .m3u8 relativas\" id=\"msg_local_playlist_prefix\" />\n  <string src=\"Ordenar por nombre\" id=\"msg_local_sort_name\" />\n  <string src=\"Ordenar por tipo\" id=\"msg_local_sort_type\" />\n  <string src=\"Ascendente\" id=\"msg_option_local_sort_name_0\" />\n  <string src=\"Descendente\" id=\"msg_option_local_sort_name_1\" />\n  <string src=\"Carpetas primero\" id=\"msg_option_local_sort_type_0\" />\n  <string src=\"Archivos primero\" id=\"msg_option_local_sort_type_1\" />\n\n  <string src=\"VOD Video Quality\" id=\"msg_youtube_quality_vod_video\" />\n  <string src=\"VOD Audio Quality\" id=\"msg_youtube_quality_vod_audio\" />\n  <string src=\"Default Live Quality\" id=\"msg_youtube_quality_live\" />\n\n  <string src=\"Región\" id=\"msg_youtube_search_region\" />\n  <string src=\"Ordenar por\" id=\"msg_youtube_search_sort\" />\n  <string src=\"Fecha de carga\" id=\"msg_youtube_search_date\" />\n  <string src=\"Duration\" id=\"msg_youtube_search_dur\" />\n  <string src=\"Feature\" id=\"msg_youtube_search_feature\" />\n  <string src=\"Proxy Server\" id=\"msg_youtube_search_proxy\" />\n  <string src=\"Ordenar por\" id=\"msg_youtube_comment_sort\" />\n\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\n  \n  <string src=\"Relevancia\" id=\"msg_option_search_sort_0\" />\n  <string src=\"Calificación\" id=\"msg_option_search_sort_1\" />\n  <string src=\"Fecha\" id=\"msg_option_search_sort_2\" />\n  <string src=\"Vistas\" id=\"msg_option_search_sort_3\" />\n  \n  <string src=\"Última hora\" id=\"msg_option_search_date_0\" />\n  <string src=\"Hoy\" id=\"msg_option_search_date_1\" />\n  <string src=\"Semana\" id=\"msg_option_search_date_2\" />\n  <string src=\"Mes\" id=\"msg_option_search_date_3\" />\n  <string src=\"Año\" id=\"msg_option_search_date_4\" />\n  <string src=\"Cualquiera\" id=\"msg_option_search_date_5\" />\n\n  <string src=\"Short\" id=\"msg_option_search_dur_0\" />\n  <string src=\"Medium\" id=\"msg_option_search_dur_1\" />\n  <string src=\"Long\" id=\"msg_option_search_dur_2\" />\n  <string src=\"Any\" id=\"msg_option_search_dur_3\" />\n\n  <string src=\"Live\" id=\"msg_option_search_feature_0\" />\n  <string src=\"None\" id=\"msg_option_search_feature_1\" />\n\n  <string src=\"Mejores\" id=\"msg_option_comment_sort_0\" />\n  <string src=\"Recientes\" id=\"msg_option_comment_sort_1\" />\n\n  <string src=\"Auto\" id=\"msg_option_youtube_quality_vod_video_0\" />\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\n\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\n\n  <string src=\"Sort Order\" id=\"msg_hvdb_search_sort\" />\n  <string src=\"Sort Type\" id=\"msg_hvdb_search_sort_type\" />\n  <string src=\"Progress Filter\" id=\"msg_hvdb_search_filter\" />\n\n  <string src=\"Ascending\" id=\"msg_option_hvdb_search_sort_0\" />\n  <string src=\"Descending\" id=\"msg_option_hvdb_search_sort_1\" />\n\n  <string src=\"Create Date\" id=\"msg_option_hvdb_search_sort_type_0\" />\n  <string src=\"Release Date\" id=\"msg_option_hvdb_search_sort_type_1\" />\n  <string src=\"Purchase Count\" id=\"msg_option_hvdb_search_sort_type_2\" />\n  <string src=\"Price\" id=\"msg_option_hvdb_search_sort_type_3\" />\n  <string src=\"Rating\" id=\"msg_option_hvdb_search_sort_type_4\" />\n  <string src=\"Review Count\" id=\"msg_option_hvdb_search_sort_type_5\" />\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\n  <string src=\"Update Date\" id=\"msg_option_hvdb_search_sort_type_8\" />\n\n  <string src=\"Marked\" id=\"msg_option_hvdb_search_filter_0\" />\n  <string src=\"Listening\" id=\"msg_option_hvdb_search_filter_1\" />\n  <string src=\"Listened\" id=\"msg_option_hvdb_search_filter_2\" />\n  <string src=\"Replay\" id=\"msg_option_hvdb_search_filter_3\" />\n  <string src=\"Postponed\" id=\"msg_option_hvdb_search_filter_4\" />\n  <string src=\"Any\" id=\"msg_option_hvdb_search_filter_5\" />\n\n  <string src=\"Show Work Banner\" id=\"msg_toggle_hvdb_banner\" />\n\n  <string src=\"Use Cloud Sync\" id=\"msg_toggle_cloud_sync\" />\n  <string src=\"Sincronizar datos automáticamente\" id=\"msg_toggle_cloud_sync_auto\" />\n  <string src=\"Cloud sync option allows you to sync various data such as YouTube history and favourites, with cloud storage. This feature uses cloud storage provided by PlayStation™Network. Please restart this application after enabling this feature.\" id=\"msg_cloud_sync_hint\" />\n\n  <string src=\"Inicio minimizado\" id=\"msg_toggle_youtube_min\" />\n\n  <string src=\"Refresh\" id=\"msg_settings_hvdb_refresh\" />\n\n  <string src=\"Upload To Cloud\" id=\"msg_settings_youtube_cloud_upload\" />\n  <string src=\"Get From Cloud\" id=\"msg_settings_youtube_cloud_download\" />\n  <string src=\"Borrar historial\" id=\"msg_settings_youtube_clean_history\" />\n  <string src=\"Borrar favoritos\" id=\"msg_settings_youtube_clean_fav\" />\n  <string src=\"Se borrará todo de historial. ¿Continuar?\" id=\"msg_settings_youtube_clean_history_confirm\" />\n  <string src=\"Se borrarán todos los favoritos. ¿Continuar?\" id=\"msg_settings_youtube_clean_fav_confirm\" />\n  <string src=\"Descargar\" id=\"msg_settings_youtube_download\" />\n  <string src=\"Descargar audio\" id=\"msg_settings_youtube_download_audio\" />\n  <string src=\"La descarga se ha añadido a la cola.\" id=\"msg_settings_youtube_download_begin\" />\n\n  <string src=\"Select Quality\" id=\"msg_quality_select_dialog_title\" />\n\n  <string src=\"PlayStation™Network error has occured. Cloud data sync will not be available. If you enabled cloud sync option, please restart this application before using it.\" id=\"msg_error_psn_connection\" />\n\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_fr.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<stringset>\n\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\n  <string src=\"Serveur HTTP\" id=\"msg_fpmenu_item_2\" />\n  <string src=\"Serveur FTP\" id=\"msg_fpmenu_item_3\" />\n  <string src=\"Stockage local\" id=\"msg_fpmenu_item_4\" />\n\n  <string src=\"Historique\" id=\"msg_youtube_history\" />\n  <string src=\"Description\" id=\"msg_youtube_description\" />\n  <string src=\"Charger plus de commentaires...\" id=\"msg_youtube_comment_more\" />\n  <string src=\"Détails du commentaire\" id=\"msg_youtube_comment_detail\" />\n  <string src=\"Réponses au commentaire\" id=\"msg_youtube_comment_reply\" />\n  <string src=\"J'aime\" id=\"msg_youtube_comment_like_count\" />\n\n  <string src=\"Page suivante\" id=\"msg_next_page\" />\n  <string src=\"Page précédente\" id=\"msg_previous_page\" />\n\n  <string src=\"Paramètres\" id=\"msg_settings\" />\n  <string src=\"Serveur HTTP\" id=\"msg_settings_http\" />\n  <string src=\"Serveur FTP\" id=\"msg_settings_ftp\" />\n  <string src=\"Account\" id=\"msg_settings_account\" />\n  <string src=\"Stockage local\" id=\"msg_settings_local\" />\n  <string src=\"Recherche\" id=\"msg_settings_search\" />\n  <string src=\"Commentaires\" id=\"msg_settings_comment\" />\n  <string src=\"Qualité\" id=\"msg_settings_quality\" />\n  <string src=\"Lecteur\" id=\"msg_settings_player\" />\n  <string src=\"Cloud Sync\" id=\"msg_settings_cloud_sync\" />\n  <string src=\"Informations système\" id=\"msg_settings_verinfo\" />\n  \n  <string src=\"Adresse de l'hôte\" id=\"msg_http_host\" />\n  <string src=\"Port\" id=\"msg_http_port\" />\n  <string src=\"Utilisateur\" id=\"msg_http_user\" />\n  <string src=\"Mot de passe\" id=\"msg_http_password\" />\n\n  <string src=\"Adresse de l'hôte\" id=\"msg_ftp_host\" />\n  <string src=\"Port\" id=\"msg_ftp_port\" />\n  <string src=\"Utilisateur\" id=\"msg_ftp_user\" />\n  <string src=\"Mot de passe\" id=\"msg_ftp_password\" />\n  <string src=\"Utiliser NLST\" id=\"msg_ftp_nlst\" />\n  <string src=\"Si cette option est activée, NetStream enverra la commande NLST au serveur FTP au lieu de la commande LIST. Cette option rend le fonctionnement plus rapide mais peut ne pas être prise en charge par certains serveurs FTP.\" id=\"msg_ftp_nlst_hint\" />\n\n  <string src=\"Host Address\" id=\"msg_hvdb_host\" />\n  <string src=\"User\" id=\"msg_hvdb_user\" />\n  <string src=\"Password\" id=\"msg_hvdb_password\" />\n\n  <string src=\"Préfixe pour les playlists .m3u8 relatives\" id=\"msg_local_playlist_prefix\" />\n  <string src=\"Trier par nom\" id=\"msg_local_sort_name\" />\n  <string src=\"Trier par type\" id=\"msg_local_sort_type\" />\n  <string src=\"Croissant\" id=\"msg_option_local_sort_name_0\" />\n  <string src=\"Décroissant\" id=\"msg_option_local_sort_name_1\" />\n  <string src=\"Dossiers en premier\" id=\"msg_option_local_sort_type_0\" />\n  <string src=\"Fichiers en premier\" id=\"msg_option_local_sort_type_1\" />\n\n  <string src=\"VOD Video Quality\" id=\"msg_youtube_quality_vod_video\" />\n  <string src=\"VOD Audio Quality\" id=\"msg_youtube_quality_vod_audio\" />\n  <string src=\"Default Live Quality\" id=\"msg_youtube_quality_live\" />\n\n  <string src=\"Région\" id=\"msg_youtube_search_region\" />\n  <string src=\"Trier\" id=\"msg_youtube_search_sort\" />\n  <string src=\"Date\" id=\"msg_youtube_search_date\" />\n  <string src=\"Duration\" id=\"msg_youtube_search_dur\" />\n  <string src=\"Feature\" id=\"msg_youtube_search_feature\" />\n  <string src=\"Proxy Server\" id=\"msg_youtube_search_proxy\" />\n  <string src=\"Trier\" id=\"msg_youtube_comment_sort\" />\n\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\n  \n  <string src=\"Pertinence\" id=\"msg_option_search_sort_0\" />\n  <string src=\"Avis\" id=\"msg_option_search_sort_1\" />\n  <string src=\"Date de mise en ligne\" id=\"msg_option_search_sort_2\" />\n  <string src=\"Nombre de vues\" id=\"msg_option_search_sort_3\" />\n  \n  <string src=\"Dernière heure\" id=\"msg_option_search_date_0\" />\n  <string src=\"Aujourd'hui\" id=\"msg_option_search_date_1\" />\n  <string src=\"Cette semaine\" id=\"msg_option_search_date_2\" />\n  <string src=\"Ce mois-ci\" id=\"msg_option_search_date_3\" />\n  <string src=\"Cette année\" id=\"msg_option_search_date_4\" />\n  <string src=\"Peu importe\" id=\"msg_option_search_date_5\" />\n\n  <string src=\"Short\" id=\"msg_option_search_dur_0\" />\n  <string src=\"Medium\" id=\"msg_option_search_dur_1\" />\n  <string src=\"Long\" id=\"msg_option_search_dur_2\" />\n  <string src=\"Any\" id=\"msg_option_search_dur_3\" />\n\n  <string src=\"Live\" id=\"msg_option_search_feature_0\" />\n  <string src=\"None\" id=\"msg_option_search_feature_1\" />\n\n  <string src=\"Top des commentaires\" id=\"msg_option_comment_sort_0\" />\n  <string src=\"Plus récents d'abord\" id=\"msg_option_comment_sort_1\" />\n\n  <string src=\"Auto\" id=\"msg_option_youtube_quality_vod_video_0\" />\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\n\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\n\n  <string src=\"Sort Order\" id=\"msg_hvdb_search_sort\" />\n  <string src=\"Sort Type\" id=\"msg_hvdb_search_sort_type\" />\n  <string src=\"Progress Filter\" id=\"msg_hvdb_search_filter\" />\n\n  <string src=\"Ascending\" id=\"msg_option_hvdb_search_sort_0\" />\n  <string src=\"Descending\" id=\"msg_option_hvdb_search_sort_1\" />\n\n  <string src=\"Create Date\" id=\"msg_option_hvdb_search_sort_type_0\" />\n  <string src=\"Release Date\" id=\"msg_option_hvdb_search_sort_type_1\" />\n  <string src=\"Purchase Count\" id=\"msg_option_hvdb_search_sort_type_2\" />\n  <string src=\"Price\" id=\"msg_option_hvdb_search_sort_type_3\" />\n  <string src=\"Rating\" id=\"msg_option_hvdb_search_sort_type_4\" />\n  <string src=\"Review Count\" id=\"msg_option_hvdb_search_sort_type_5\" />\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\n  <string src=\"Update Date\" id=\"msg_option_hvdb_search_sort_type_8\" />\n\n  <string src=\"Marked\" id=\"msg_option_hvdb_search_filter_0\" />\n  <string src=\"Listening\" id=\"msg_option_hvdb_search_filter_1\" />\n  <string src=\"Listened\" id=\"msg_option_hvdb_search_filter_2\" />\n  <string src=\"Replay\" id=\"msg_option_hvdb_search_filter_3\" />\n  <string src=\"Postponed\" id=\"msg_option_hvdb_search_filter_4\" />\n  <string src=\"Any\" id=\"msg_option_hvdb_search_filter_5\" />\n\n  <string src=\"Show Work Banner\" id=\"msg_toggle_hvdb_banner\" />\n\n  <string src=\"Use Cloud Sync\" id=\"msg_toggle_cloud_sync\" />\n  <string src=\"Sync Data Automatically\" id=\"msg_toggle_cloud_sync_auto\" />\n  <string src=\"Cloud sync option allows you to sync various data such as YouTube history and favourites, with cloud storage. This feature uses cloud storage provided by PlayStation™Network. Please restart this application after enabling this feature.\" id=\"msg_cloud_sync_hint\" />\n\n  <string src=\"Démarrer en mode réduit\" id=\"msg_toggle_youtube_min\" />\n\n  <string src=\"Refresh\" id=\"msg_settings_hvdb_refresh\" />\n\n  <string src=\"Upload To Cloud\" id=\"msg_settings_youtube_cloud_upload\" />\n  <string src=\"Get From Cloud\" id=\"msg_settings_youtube_cloud_download\" />\n  <string src=\"Effacer l'historique\" id=\"msg_settings_youtube_clean_history\" />\n  <string src=\"Effacer les favoris\" id=\"msg_settings_youtube_clean_fav\" />\n  <string src=\"Tout le contenu de l'historique sera supprimé. Voulez-vous continuer ?\" id=\"msg_settings_youtube_clean_history_confirm\" />\n  <string src=\"Tous les favoris seront supprimés. Voulez-vous continuer ?\" id=\"msg_settings_youtube_clean_fav_confirm\" />\n  <string src=\"Télécharger\" id=\"msg_settings_youtube_download\" />\n  <string src=\"Télécharger l'audio\" id=\"msg_settings_youtube_download_audio\" />\n  <string src=\"Le fichier a été ajouté à la file d'attente des téléchargements.\" id=\"msg_settings_youtube_download_begin\" />\n\n  <string src=\"Select Quality\" id=\"msg_quality_select_dialog_title\" />\n\n  <string src=\"PlayStation™Network error has occured. Cloud data sync will not be available. If you enabled cloud sync option, please restart this application before using it.\" id=\"msg_error_psn_connection\" />\n\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_it.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<stringset>\n\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\n  <string src=\"HTTP Server\" id=\"msg_fpmenu_item_2\" />\n  <string src=\"FTP Server\" id=\"msg_fpmenu_item_3\" />\n  <string src=\"Memoria locale\" id=\"msg_fpmenu_item_4\" />\n\n  <string src=\"Cronologia\" id=\"msg_youtube_history\" />\n  <string src=\"Descrizione\" id=\"msg_youtube_description\" />\n  <string src=\"Carica altri commenti...\" id=\"msg_youtube_comment_more\" />\n  <string src=\"Dettagli Commento\" id=\"msg_youtube_comment_detail\" />\n  <string src=\"Risposte ai commenti\" id=\"msg_youtube_comment_reply\" />\n  <string src=\" likes\" id=\"msg_youtube_comment_like_count\" />\n\n  <string src=\"Pagina successiva\" id=\"msg_next_page\" />\n  <string src=\"Pagina precedente\" id=\"msg_previous_page\" />\n\n  <string src=\"Impostazioni\" id=\"msg_settings\" />\n  <string src=\"HTTP Server\" id=\"msg_settings_http\" />\n  <string src=\"FTP Server\" id=\"msg_settings_ftp\" />\n  <string src=\"Account\" id=\"msg_settings_account\" />\n  <string src=\"Memoria locale\" id=\"msg_settings_local\" />\n  <string src=\"Cerca\" id=\"msg_settings_search\" />\n  <string src=\"Commenti\" id=\"msg_settings_comment\" />\n  <string src=\"Qualità\" id=\"msg_settings_quality\" />\n  <string src=\"Player\" id=\"msg_settings_player\" />\n  <string src=\"Cloud Sync\" id=\"msg_settings_cloud_sync\" />\n  <string src=\"Informazioni della Build\" id=\"msg_settings_verinfo\" />\n  \n  <string src=\"Indirizzo Host\" id=\"msg_http_host\" />\n  <string src=\"Porta\" id=\"msg_http_port\" />\n  <string src=\"Utente\" id=\"msg_http_user\" />\n  <string src=\"Password\" id=\"msg_http_password\" />\n\n  <string src=\"Indirizzo Host\" id=\"msg_ftp_host\" />\n  <string src=\"Porta\" id=\"msg_ftp_port\" />\n  <string src=\"Utente\" id=\"msg_ftp_user\" />\n  <string src=\"Password\" id=\"msg_ftp_password\" />\n  <string src=\"Usa NLST\" id=\"msg_ftp_nlst\" />\n  <string src=\"Abilitando questa opzione, NetStream invierà il comando NLST al server FTP invece del comando LIST. Questa opzione rende l'operazione più veloce ma potrebbe non essere supportata da alcuni server FTP.\" id=\"msg_ftp_nlst_hint\" />\n\n  <string src=\"Host Address\" id=\"msg_hvdb_host\" />\n  <string src=\"User\" id=\"msg_hvdb_user\" />\n  <string src=\"Password\" id=\"msg_hvdb_password\" />\n\n  <string src=\"Prefisso per Relativo .m3u8 Playlists\" id=\"msg_local_playlist_prefix\" />\n  <string src=\"Sort By Name\" id=\"msg_local_sort_name\" />\n  <string src=\"Sort By Type\" id=\"msg_local_sort_type\" />\n  <string src=\"Ascending\" id=\"msg_option_local_sort_name_0\" />\n  <string src=\"Descending\" id=\"msg_option_local_sort_name_1\" />\n  <string src=\"Folders First\" id=\"msg_option_local_sort_type_0\" />\n  <string src=\"Files First\" id=\"msg_option_local_sort_type_1\" />\n\n  <string src=\"VOD Video Quality\" id=\"msg_youtube_quality_vod_video\" />\n  <string src=\"VOD Audio Quality\" id=\"msg_youtube_quality_vod_audio\" />\n  <string src=\"Default Live Quality\" id=\"msg_youtube_quality_live\" />\n\n  <string src=\"Regione\" id=\"msg_youtube_search_region\" />\n  <string src=\"Ordina per\" id=\"msg_youtube_search_sort\" />\n  <string src=\"Data\" id=\"msg_youtube_search_date\" />\n  <string src=\"Duration\" id=\"msg_youtube_search_dur\" />\n  <string src=\"Feature\" id=\"msg_youtube_search_feature\" />\n  <string src=\"Proxy Server\" id=\"msg_youtube_search_proxy\" />\n  <string src=\"Ordina per\" id=\"msg_youtube_comment_sort\" />\n\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\n  \n  <string src=\"Rilevanza\" id=\"msg_option_search_sort_0\" />\n  <string src=\"Valutazione\" id=\"msg_option_search_sort_1\" />\n  <string src=\"Data\" id=\"msg_option_search_sort_2\" />\n  <string src=\"Visualizza conteggio\" id=\"msg_option_search_sort_3\" />\n  \n  <string src=\"Ora\" id=\"msg_option_search_date_0\" />\n  <string src=\"Oggi\" id=\"msg_option_search_date_1\" />\n  <string src=\"Settimana\" id=\"msg_option_search_date_2\" />\n  <string src=\"Mese\" id=\"msg_option_search_date_3\" />\n  <string src=\"Anno\" id=\"msg_option_search_date_4\" />\n  <string src=\"Qualsiasi\" id=\"msg_option_search_date_5\" />\n  \n  <string src=\"Short\" id=\"msg_option_search_dur_0\" />\n  <string src=\"Medium\" id=\"msg_option_search_dur_1\" />\n  <string src=\"Long\" id=\"msg_option_search_dur_2\" />\n  <string src=\"Any\" id=\"msg_option_search_dur_3\" />\n\n  <string src=\"Live\" id=\"msg_option_search_feature_0\" />\n  <string src=\"None\" id=\"msg_option_search_feature_1\" />\n  \n  <string src=\"Recente\" id=\"msg_option_comment_sort_0\" />\n  <string src=\"Nuovo\" id=\"msg_option_comment_sort_1\" />\n\n  <string src=\"Auto\" id=\"msg_option_youtube_quality_vod_video_0\" />\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\n\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\n\n  <string src=\"Sort Order\" id=\"msg_hvdb_search_sort\" />\n  <string src=\"Sort Type\" id=\"msg_hvdb_search_sort_type\" />\n  <string src=\"Progress Filter\" id=\"msg_hvdb_search_filter\" />\n\n  <string src=\"Ascending\" id=\"msg_option_hvdb_search_sort_0\" />\n  <string src=\"Descending\" id=\"msg_option_hvdb_search_sort_1\" />\n\n  <string src=\"Create Date\" id=\"msg_option_hvdb_search_sort_type_0\" />\n  <string src=\"Release Date\" id=\"msg_option_hvdb_search_sort_type_1\" />\n  <string src=\"Purchase Count\" id=\"msg_option_hvdb_search_sort_type_2\" />\n  <string src=\"Price\" id=\"msg_option_hvdb_search_sort_type_3\" />\n  <string src=\"Rating\" id=\"msg_option_hvdb_search_sort_type_4\" />\n  <string src=\"Review Count\" id=\"msg_option_hvdb_search_sort_type_5\" />\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\n  <string src=\"Update Date\" id=\"msg_option_hvdb_search_sort_type_8\" />\n\n  <string src=\"Marked\" id=\"msg_option_hvdb_search_filter_0\" />\n  <string src=\"Listening\" id=\"msg_option_hvdb_search_filter_1\" />\n  <string src=\"Listened\" id=\"msg_option_hvdb_search_filter_2\" />\n  <string src=\"Replay\" id=\"msg_option_hvdb_search_filter_3\" />\n  <string src=\"Postponed\" id=\"msg_option_hvdb_search_filter_4\" />\n  <string src=\"Any\" id=\"msg_option_hvdb_search_filter_5\" />\n\n  <string src=\"Show Work Banner\" id=\"msg_toggle_hvdb_banner\" />\n\n  <string src=\"Use Cloud Sync\" id=\"msg_toggle_cloud_sync\" />\n  <string src=\"Sync Data Automatically\" id=\"msg_toggle_cloud_sync_auto\" />\n  <string src=\"Cloud sync option allows you to sync various data such as YouTube history and favourites, with cloud storage. This feature uses cloud storage provided by PlayStation™Network. Please restart this application after enabling this feature.\" id=\"msg_cloud_sync_hint\" />\n\n  <string src=\"Avvia ridotto a icona\" id=\"msg_toggle_youtube_min\" />\n\n  <string src=\"Refresh\" id=\"msg_settings_hvdb_refresh\" />\n\n  <string src=\"Upload To Cloud\" id=\"msg_settings_youtube_cloud_upload\" />\n  <string src=\"Get From Cloud\" id=\"msg_settings_youtube_cloud_download\" />\n  <string src=\"Pulisci Cronologia\" id=\"msg_settings_youtube_clean_history\" />\n  <string src=\"Pulisci i preferiti\" id=\"msg_settings_youtube_clean_fav\" />\n  <string src=\"Tutti i record della cronologia verranno eliminati. Vuoi continuare?\" id=\"msg_settings_youtube_clean_history_confirm\" />\n  <string src=\"Tutti i preferiti verranno eliminati. Vuoi continuare?\" id=\"msg_settings_youtube_clean_fav_confirm\" />\n  <string src=\"Scaricare\" id=\"msg_settings_youtube_download\" />\n  <string src=\"Scarica l'audio\" id=\"msg_settings_youtube_download_audio\" />\n  <string src=\"Il download è stato aggiunto alla coda di download.\" id=\"msg_settings_youtube_download_begin\" />\n\n  <string src=\"Select Quality\" id=\"msg_quality_select_dialog_title\" />\n\n  <string src=\"PlayStation™Network error has occured. Cloud data sync will not be available. If you enabled cloud sync option, please restart this application before using it.\" id=\"msg_error_psn_connection\" />\n\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_ja.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<stringset>\n\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\n  <string src=\"HTTPサーバー\" id=\"msg_fpmenu_item_2\" />\n  <string src=\"FTPサーバー\" id=\"msg_fpmenu_item_3\" />\n  <string src=\"ローカルストレージ\" id=\"msg_fpmenu_item_4\" />\n\n  <string src=\"履歴\" id=\"msg_youtube_history\" />\n  <string src=\"説明\" id=\"msg_youtube_description\" />\n  <string src=\"さらにコメントを読み込む...\" id=\"msg_youtube_comment_more\" />\n  <string src=\"コメントの詳細\" id=\"msg_youtube_comment_detail\" />\n  <string src=\"コメントの返信\" id=\"msg_youtube_comment_reply\" />\n  <string src=\"いいね数\" id=\"msg_youtube_comment_like_count\" />\n\n  <string src=\"次のページ\" id=\"msg_next_page\" />\n  <string src=\"前のページ\" id=\"msg_previous_page\" />\n\n  <string src=\"設定\" id=\"msg_settings\" />\n  <string src=\"HTTPサーバー\" id=\"msg_settings_http\" />\n  <string src=\"FTPサーバー\" id=\"msg_settings_ftp\" />\n  <string src=\"Account\" id=\"msg_settings_account\" />\n  <string src=\"ローカルストレージ\" id=\"msg_settings_local\" />\n  <string src=\"検索\" id=\"msg_settings_search\" />\n  <string src=\"コメント\" id=\"msg_settings_comment\" />\n  <string src=\"画質\" id=\"msg_settings_quality\" />\n  <string src=\"プレイヤー\" id=\"msg_settings_player\" />\n  <string src=\"Cloud Sync\" id=\"msg_settings_cloud_sync\" />\n  <string src=\"ビルド情報\" id=\"msg_settings_verinfo\" />\n  \n  <string src=\"ホストアドレス\" id=\"msg_http_host\" />\n  <string src=\"ポート\" id=\"msg_http_port\" />\n  <string src=\"ユーザー名\" id=\"msg_http_user\" />\n  <string src=\"パスワード\" id=\"msg_http_password\" />\n\n  <string src=\"ホストアドレス\" id=\"msg_ftp_host\" />\n  <string src=\"ポート\" id=\"msg_ftp_port\" />\n  <string src=\"ユーザー名\" id=\"msg_ftp_user\" />\n  <string src=\"パスワード\" id=\"msg_ftp_password\" />\n  <string src=\"NLSTを使用する\" id=\"msg_ftp_nlst\" />\n  <string src=\"このオプションを有効にすると、NetStreamはLISTコマンドの代わりにNLSTコマンドをFTPサーバーに送信するようになります。このオプションは動作を高速化しますが、一部のFTPサーバーではサポートされていない場合があります。\" id=\"msg_ftp_nlst_hint\" />\n\n  <string src=\"Host Address\" id=\"msg_hvdb_host\" />\n  <string src=\"User\" id=\"msg_hvdb_user\" />\n  <string src=\"Password\" id=\"msg_hvdb_password\" />\n\n  <string src=\"相対的な.m3u8プレイリストのプレフィックス\" id=\"msg_local_playlist_prefix\" />\n  <string src=\"名前順の並べ替え\" id=\"msg_local_sort_name\" />\n  <string src=\"タイプ別の並べ替え\" id=\"msg_local_sort_type\" />\n  <string src=\"昇順\" id=\"msg_option_local_sort_name_0\" />\n  <string src=\"降順\" id=\"msg_option_local_sort_name_1\" />\n  <string src=\"フォルダーを先に\" id=\"msg_option_local_sort_type_0\" />\n  <string src=\"ファイルを先に\" id=\"msg_option_local_sort_type_1\" />\n\n  <string src=\"VOD Video Quality\" id=\"msg_youtube_quality_vod_video\" />\n  <string src=\"VOD Audio Quality\" id=\"msg_youtube_quality_vod_audio\" />\n  <string src=\"Default Live Quality\" id=\"msg_youtube_quality_live\" />\n\n  <string src=\"地域\" id=\"msg_youtube_search_region\" />\n  <string src=\"並べ替え\" id=\"msg_youtube_search_sort\" />\n  <string src=\"日付\" id=\"msg_youtube_search_date\" />\n  <string src=\"Duration\" id=\"msg_youtube_search_dur\" />\n  <string src=\"Feature\" id=\"msg_youtube_search_feature\" />\n  <string src=\"Proxy Server\" id=\"msg_youtube_search_proxy\" />\n  <string src=\"並べ替え\" id=\"msg_youtube_comment_sort\" />\n\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\n  \n  <string src=\"関連性\" id=\"msg_option_search_sort_0\" />\n  <string src=\"評価\" id=\"msg_option_search_sort_1\" />\n  <string src=\"日付\" id=\"msg_option_search_sort_2\" />\n  <string src=\"視聴数\" id=\"msg_option_search_sort_3\" />\n  \n  <string src=\"時間\" id=\"msg_option_search_date_0\" />\n  <string src=\"今日\" id=\"msg_option_search_date_1\" />\n  <string src=\"週\" id=\"msg_option_search_date_2\" />\n  <string src=\"月\" id=\"msg_option_search_date_3\" />\n  <string src=\"年\" id=\"msg_option_search_date_4\" />\n  <string src=\"全て\" id=\"msg_option_search_date_5\" />\n\n  <string src=\"Short\" id=\"msg_option_search_dur_0\" />\n  <string src=\"Medium\" id=\"msg_option_search_dur_1\" />\n  <string src=\"Long\" id=\"msg_option_search_dur_2\" />\n  <string src=\"Any\" id=\"msg_option_search_dur_3\" />\n\n  <string src=\"Live\" id=\"msg_option_search_feature_0\" />\n  <string src=\"None\" id=\"msg_option_search_feature_1\" />\n  \n  <string src=\"評価順\" id=\"msg_option_comment_sort_0\" />\n  <string src=\"新しい順\" id=\"msg_option_comment_sort_1\" />\n\n  <string src=\"Auto\" id=\"msg_option_youtube_quality_vod_video_0\" />\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\n\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\n\n  <string src=\"Sort Order\" id=\"msg_hvdb_search_sort\" />\n  <string src=\"Sort Type\" id=\"msg_hvdb_search_sort_type\" />\n  <string src=\"Progress Filter\" id=\"msg_hvdb_search_filter\" />\n\n  <string src=\"Ascending\" id=\"msg_option_hvdb_search_sort_0\" />\n  <string src=\"Descending\" id=\"msg_option_hvdb_search_sort_1\" />\n\n  <string src=\"Create Date\" id=\"msg_option_hvdb_search_sort_type_0\" />\n  <string src=\"Release Date\" id=\"msg_option_hvdb_search_sort_type_1\" />\n  <string src=\"Purchase Count\" id=\"msg_option_hvdb_search_sort_type_2\" />\n  <string src=\"Price\" id=\"msg_option_hvdb_search_sort_type_3\" />\n  <string src=\"Rating\" id=\"msg_option_hvdb_search_sort_type_4\" />\n  <string src=\"Review Count\" id=\"msg_option_hvdb_search_sort_type_5\" />\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\n  <string src=\"Update Date\" id=\"msg_option_hvdb_search_sort_type_8\" />\n\n  <string src=\"Marked\" id=\"msg_option_hvdb_search_filter_0\" />\n  <string src=\"Listening\" id=\"msg_option_hvdb_search_filter_1\" />\n  <string src=\"Listened\" id=\"msg_option_hvdb_search_filter_2\" />\n  <string src=\"Replay\" id=\"msg_option_hvdb_search_filter_3\" />\n  <string src=\"Postponed\" id=\"msg_option_hvdb_search_filter_4\" />\n  <string src=\"Any\" id=\"msg_option_hvdb_search_filter_5\" />\n\n  <string src=\"Show Work Banner\" id=\"msg_toggle_hvdb_banner\" />\n\n  <string src=\"Use Cloud Sync\" id=\"msg_toggle_cloud_sync\" />\n  <string src=\"Sync Data Automatically\" id=\"msg_toggle_cloud_sync_auto\" />\n  <string src=\"Cloud sync option allows you to sync various data such as YouTube history and favourites, with cloud storage. This feature uses cloud storage provided by PlayStation™Network. Please restart this application after enabling this feature.\" id=\"msg_cloud_sync_hint\" />\n\n  <string src=\"最小化して開始する\" id=\"msg_toggle_youtube_min\" />\n\n  <string src=\"Refresh\" id=\"msg_settings_hvdb_refresh\" />\n\n  <string src=\"Upload To Cloud\" id=\"msg_settings_youtube_cloud_upload\" />\n  <string src=\"Get From Cloud\" id=\"msg_settings_youtube_cloud_download\" />\n  <string src=\"履歴の消去\" id=\"msg_settings_youtube_clean_history\" />\n  <string src=\"お気に入りの消去\" id=\"msg_settings_youtube_clean_fav\" />\n  <string src=\"全ての履歴が削除されます。 続けますか？\" id=\"msg_settings_youtube_clean_history_confirm\" />\n  <string src=\"全てのお気に入りが削除されます。 続けますか？\" id=\"msg_settings_youtube_clean_fav_confirm\" />\n  <string src=\"動画をダウンロードする\" id=\"msg_settings_youtube_download\" />\n  <string src=\"音声をダウンロードする\" id=\"msg_settings_youtube_download_audio\" />\n  <string src=\"ダウンロードがキューに追加されました。\" id=\"msg_settings_youtube_download_begin\" />\n\n  <string src=\"Select Quality\" id=\"msg_quality_select_dialog_title\" />\n\n  <string src=\"PlayStation™Network error has occured. Cloud data sync will not be available. If you enabled cloud sync option, please restart this application before using it.\" id=\"msg_error_psn_connection\" />\n\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_pl.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<stringset>\r\n\r\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\r\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\r\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\r\n  <string src=\"Serwer HTTP\" id=\"msg_fpmenu_item_2\" />\r\n  <string src=\"Serwer FTP\" id=\"msg_fpmenu_item_3\" />\r\n  <string src=\"Pamięć konsoli\" id=\"msg_fpmenu_item_4\" />\r\n\r\n  <string src=\"Historia\" id=\"msg_youtube_history\" />\r\n  <string src=\"Opis\" id=\"msg_youtube_description\" />\r\n  <string src=\"Załaduj więcej komentarzy...\" id=\"msg_youtube_comment_more\" />\r\n  <string src=\"Szczegóły komentarza\" id=\"msg_youtube_comment_detail\" />\r\n  <string src=\"Odpowiedzi na komentarze\" id=\"msg_youtube_comment_reply\" />\r\n  <string src=\" lajki\" id=\"msg_youtube_comment_like_count\" />\r\n\r\n  <string src=\"Następna strona\" id=\"msg_next_page\" />\r\n  <string src=\"Poprzednia strona\" id=\"msg_previous_page\" />\r\n\r\n  <string src=\"Ustawienia\" id=\"msg_settings\" />\r\n  <string src=\"Serwer HTTP\" id=\"msg_settings_http\" />\r\n  <string src=\"Serwer FTP\" id=\"msg_settings_ftp\" />\r\n  <string src=\"Account\" id=\"msg_settings_account\" />\r\n  <string src=\"Pamięć konsoli\" id=\"msg_settings_local\" />\r\n  <string src=\"Wyszukiwarka\" id=\"msg_settings_search\" />\r\n  <string src=\"Komentarze\" id=\"msg_settings_comment\" />\r\n  <string src=\"Jakość\" id=\"msg_settings_quality\" />\r\n  <string src=\"Odtwarzacz\" id=\"msg_settings_player\" />\r\n  <string src=\"Cloud Sync\" id=\"msg_settings_cloud_sync\" />\r\n  <string src=\"Informacje o kompilacji\" id=\"msg_settings_verinfo\" />\r\n  \r\n  <string src=\"Adres hosta\" id=\"msg_http_host\" />\r\n  <string src=\"Port\" id=\"msg_http_port\" />\r\n  <string src=\"Użytkownik\" id=\"msg_http_user\" />\r\n  <string src=\"Hasło\" id=\"msg_http_password\" />\r\n\r\n  <string src=\"Adres hosta\" id=\"msg_ftp_host\" />\r\n  <string src=\"Port\" id=\"msg_ftp_port\" />\r\n  <string src=\"Użytkownik\" id=\"msg_ftp_user\" />\r\n  <string src=\"Hasło\" id=\"msg_ftp_password\" />\r\n  <string src=\"Użyj NLST\" id=\"msg_ftp_nlst\" />\r\n  <string src=\"Włączenie tej opcji spowoduje, że NetStream wyśle polecenie NLST do serwera FTP zamiast polecenia LIST. Ta opcja przyspiesza działanie, ale może nie być obsługiwana przez niektóre serwery FTP.\" id=\"msg_ftp_nlst_hint\" />\r\n\r\n  <string src=\"Host Address\" id=\"msg_hvdb_host\" />\r\n  <string src=\"User\" id=\"msg_hvdb_user\" />\r\n  <string src=\"Password\" id=\"msg_hvdb_password\" />\r\n\r\n  <string src=\"Prefix For Relative .m3u8 Playlists\" id=\"msg_local_playlist_prefix\" />\r\n  <string src=\"Sort By Name\" id=\"msg_local_sort_name\" />\r\n  <string src=\"Sort By Type\" id=\"msg_local_sort_type\" />\r\n  <string src=\"Ascending\" id=\"msg_option_local_sort_name_0\" />\r\n  <string src=\"Descending\" id=\"msg_option_local_sort_name_1\" />\r\n  <string src=\"Folders First\" id=\"msg_option_local_sort_type_0\" />\r\n  <string src=\"Files First\" id=\"msg_option_local_sort_type_1\" />\r\n\r\n  <string src=\"VOD Video Quality\" id=\"msg_youtube_quality_vod_video\" />\r\n  <string src=\"VOD Audio Quality\" id=\"msg_youtube_quality_vod_audio\" />\r\n  <string src=\"Default Live Quality\" id=\"msg_youtube_quality_live\" />\r\n\r\n  <string src=\"Region\" id=\"msg_youtube_search_region\" />\r\n  <string src=\"Sortowanie\" id=\"msg_youtube_search_sort\" />\r\n  <string src=\"Data\" id=\"msg_youtube_search_date\" />\r\n  <string src=\"Duration\" id=\"msg_youtube_search_dur\" />\r\n  <string src=\"Feature\" id=\"msg_youtube_search_feature\" />\r\n  <string src=\"Proxy Server\" id=\"msg_youtube_search_proxy\" />\r\n  <string src=\"Sortowanie\" id=\"msg_youtube_comment_sort\" />\r\n\r\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\r\n  \r\n  <string src=\"Trafność\" id=\"msg_option_search_sort_0\" />\r\n  <string src=\"Ocena\" id=\"msg_option_search_sort_1\" />\r\n  <string src=\"Data\" id=\"msg_option_search_sort_2\" />\r\n  <string src=\"Liczba wyświetleń\" id=\"msg_option_search_sort_3\" />\r\n  \r\n  <string src=\"Ostatnia godzina\" id=\"msg_option_search_date_0\" />\r\n  <string src=\"Dzisiaj\" id=\"msg_option_search_date_1\" />\r\n  <string src=\"Ten tydzień\" id=\"msg_option_search_date_2\" />\r\n  <string src=\"Ten miesiąc\" id=\"msg_option_search_date_3\" />\r\n  <string src=\"Ten rok\" id=\"msg_option_search_date_4\" />\r\n  <string src=\"Kiedykolwiek\" id=\"msg_option_search_date_5\" />\r\n\r\n  <string src=\"Short\" id=\"msg_option_search_dur_0\" />\r\n  <string src=\"Medium\" id=\"msg_option_search_dur_1\" />\r\n  <string src=\"Long\" id=\"msg_option_search_dur_2\" />\r\n  <string src=\"Any\" id=\"msg_option_search_dur_3\" />\r\n\r\n  <string src=\"Live\" id=\"msg_option_search_feature_0\" />\r\n  <string src=\"None\" id=\"msg_option_search_feature_1\" />\r\n  \r\n  <string src=\"Najlepsze\" id=\"msg_option_comment_sort_0\" />\r\n  <string src=\"Nowe\" id=\"msg_option_comment_sort_1\" />\r\n\r\n  <string src=\"Auto\" id=\"msg_option_youtube_quality_vod_video_0\" />\r\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\r\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\r\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\r\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\r\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\r\n\r\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\r\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\r\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\r\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\r\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\r\n\r\n  <string src=\"Sort Order\" id=\"msg_hvdb_search_sort\" />\r\n  <string src=\"Sort Type\" id=\"msg_hvdb_search_sort_type\" />\r\n  <string src=\"Progress Filter\" id=\"msg_hvdb_search_filter\" />\r\n\r\n  <string src=\"Ascending\" id=\"msg_option_hvdb_search_sort_0\" />\r\n  <string src=\"Descending\" id=\"msg_option_hvdb_search_sort_1\" />\r\n\r\n  <string src=\"Create Date\" id=\"msg_option_hvdb_search_sort_type_0\" />\r\n  <string src=\"Release Date\" id=\"msg_option_hvdb_search_sort_type_1\" />\r\n  <string src=\"Purchase Count\" id=\"msg_option_hvdb_search_sort_type_2\" />\r\n  <string src=\"Price\" id=\"msg_option_hvdb_search_sort_type_3\" />\r\n  <string src=\"Rating\" id=\"msg_option_hvdb_search_sort_type_4\" />\r\n  <string src=\"Review Count\" id=\"msg_option_hvdb_search_sort_type_5\" />\r\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\r\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\r\n  <string src=\"Update Date\" id=\"msg_option_hvdb_search_sort_type_8\" />\r\n\r\n  <string src=\"Marked\" id=\"msg_option_hvdb_search_filter_0\" />\r\n  <string src=\"Listening\" id=\"msg_option_hvdb_search_filter_1\" />\r\n  <string src=\"Listened\" id=\"msg_option_hvdb_search_filter_2\" />\r\n  <string src=\"Replay\" id=\"msg_option_hvdb_search_filter_3\" />\r\n  <string src=\"Postponed\" id=\"msg_option_hvdb_search_filter_4\" />\r\n  <string src=\"Any\" id=\"msg_option_hvdb_search_filter_5\" />\r\n\r\n  <string src=\"Show Work Banner\" id=\"msg_toggle_hvdb_banner\" />\r\n\r\n  <string src=\"Use Cloud Sync\" id=\"msg_toggle_cloud_sync\" />\r\n  <string src=\"Sync Data Automatically\" id=\"msg_toggle_cloud_sync_auto\" />\r\n  <string src=\"Cloud sync option allows you to sync various data such as YouTube history and favourites, with cloud storage. This feature uses cloud storage provided by PlayStation™Network. Please restart this application after enabling this feature.\" id=\"msg_cloud_sync_hint\" />\r\n\r\n  <string src=\"Uruchom zminimalizowany\" id=\"msg_toggle_youtube_min\" />\r\n\r\n  <string src=\"Refresh\" id=\"msg_settings_hvdb_refresh\" />\r\n\r\n  <string src=\"Upload To Cloud\" id=\"msg_settings_youtube_cloud_upload\" />\r\n  <string src=\"Get From Cloud\" id=\"msg_settings_youtube_cloud_download\" />\r\n  <string src=\"Wyczyść historię\" id=\"msg_settings_youtube_clean_history\" />\r\n  <string src=\"Wyczyść ulubione\" id=\"msg_settings_youtube_clean_fav\" />\r\n  <string src=\"Wszystkie rekordy historii zostaną usunięte. Czy chcesz kontynuować?\" id=\"msg_settings_youtube_clean_history_confirm\" />\r\n  <string src=\"Wszystkie ulubione zostaną usunięte. Czy chcesz kontynuować?\" id=\"msg_settings_youtube_clean_fav_confirm\" />\r\n  <string src=\"Pobierz\" id=\"msg_settings_youtube_download\" />\r\n  <string src=\"Pobierz dźwięk\" id=\"msg_settings_youtube_download_audio\" />\r\n  <string src=\"Pobieranie zostało dodane do kolejki.\" id=\"msg_settings_youtube_download_begin\" />\r\n\r\n  <string src=\"Select Quality\" id=\"msg_quality_select_dialog_title\" />\r\n\r\n  <string src=\"PlayStation™Network error has occured. Cloud data sync will not be available. If you enabled cloud sync option, please restart this application before using it.\" id=\"msg_error_psn_connection\" />\r\n\r\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_pt-br.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<stringset>\n\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\n  <string src=\"Servidor HTTP\" id=\"msg_fpmenu_item_2\" />\n  <string src=\"Servidor FTP\" id=\"msg_fpmenu_item_3\" />\n  <string src=\"Armazenamento Local\" id=\"msg_fpmenu_item_4\" />\n\n  <string src=\"Histórico\" id=\"msg_youtube_history\" />\n  <string src=\"Descrição\" id=\"msg_youtube_description\" />\n  <string src=\"Carregar mais comentários...\" id=\"msg_youtube_comment_more\" />\n  <string src=\"Detalhes do Comentário\" id=\"msg_youtube_comment_detail\" />\n  <string src=\"Respostas do Comentário\" id=\"msg_youtube_comment_reply\" />\n  <string src=\" gosteis\" id=\"msg_youtube_comment_like_count\" />\n\n  <string src=\"Próxima Página\" id=\"msg_next_page\" />\n  <string src=\"Página Anterior\" id=\"msg_previous_page\" />\n\n  <string src=\"Configurações\" id=\"msg_settings\" />\n  <string src=\"Servidor HTTP\" id=\"msg_settings_http\" />\n  <string src=\"Servidor FTP\" id=\"msg_settings_ftp\" />\n  <string src=\"Account\" id=\"msg_settings_account\" />\n  <string src=\"Armazenamento Local\" id=\"msg_settings_local\" />\n  <string src=\"Buscar\" id=\"msg_settings_search\" />\n  <string src=\"Comentários\" id=\"msg_settings_comment\" />\n  <string src=\"Qualidade\" id=\"msg_settings_quality\" />\n  <string src=\"Reprodução\" id=\"msg_settings_player\" />\n  <string src=\"Sincronizar na Nuvem\" id=\"msg_settings_cloud_sync\" />\n  <string src=\"Informação de Versão\" id=\"msg_settings_verinfo\" />\n  \n  <string src=\"Endereço IP\" id=\"msg_http_host\" />\n  <string src=\"Porta\" id=\"msg_http_port\" />\n  <string src=\"Usuário\" id=\"msg_http_user\" />\n  <string src=\"Senha\" id=\"msg_http_password\" />\n\n  <string src=\"Endereço IP\" id=\"msg_ftp_host\" />\n  <string src=\"Porta\" id=\"msg_ftp_port\" />\n  <string src=\"Usuário\" id=\"msg_ftp_user\" />\n  <string src=\"Senha\" id=\"msg_ftp_password\" />\n  <string src=\"Usar NLST\" id=\"msg_ftp_nlst\" />\n  <string src=\"Habilitar essa opção vai fazer o NetStream enviar comandos NLST para o servidor FTP ao invés do comando LIST. Essa opção acaba sendo mais rápida, contudo não é suportada por alguns servidores FTP.\" id=\"msg_ftp_nlst_hint\" />\n\n  <string src=\"Host Address\" id=\"msg_hvdb_host\" />\n  <string src=\"User\" id=\"msg_hvdb_user\" />\n  <string src=\"Password\" id=\"msg_hvdb_password\" />\n\n  <string src=\"Prefixo para Playlists .m3u8 Relativas\" id=\"msg_local_playlist_prefix\" />\n  <string src=\"Organizar por Nome\" id=\"msg_local_sort_name\" />\n  <string src=\"Organizar por Tipo\" id=\"msg_local_sort_type\" />\n  <string src=\"Crescente\" id=\"msg_option_local_sort_name_0\" />\n  <string src=\"Decresecente\" id=\"msg_option_local_sort_name_1\" />\n  <string src=\"Pastas Primeiro\" id=\"msg_option_local_sort_type_0\" />\n  <string src=\"Arquivos Primeiro\" id=\"msg_option_local_sort_type_1\" />\n\n  <string src=\"VOD Video Quality\" id=\"msg_youtube_quality_vod_video\" />\n  <string src=\"VOD Audio Quality\" id=\"msg_youtube_quality_vod_audio\" />\n  <string src=\"Default Live Quality\" id=\"msg_youtube_quality_live\" />\n\n  <string src=\"Região\" id=\"msg_youtube_search_region\" />\n  <string src=\"Organizar\" id=\"msg_youtube_search_sort\" />\n  <string src=\"Data\" id=\"msg_youtube_search_date\" />\n  <string src=\"Duration\" id=\"msg_youtube_search_dur\" />\n  <string src=\"Feature\" id=\"msg_youtube_search_feature\" />\n  <string src=\"Proxy Server\" id=\"msg_youtube_search_proxy\" />\n  <string src=\"Organizar\" id=\"msg_youtube_comment_sort\" />\n\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\n  \n  <string src=\"Relevância\" id=\"msg_option_search_sort_0\" />\n  <string src=\"Classificação\" id=\"msg_option_search_sort_1\" />\n  <string src=\"Data\" id=\"msg_option_search_sort_2\" />\n  <string src=\"Visualizações\" id=\"msg_option_search_sort_3\" />\n  \n  <string src=\"Hora\" id=\"msg_option_search_date_0\" />\n  <string src=\"Hoje\" id=\"msg_option_search_date_1\" />\n  <string src=\"Semana\" id=\"msg_option_search_date_2\" />\n  <string src=\"Mês\" id=\"msg_option_search_date_3\" />\n  <string src=\"Ano\" id=\"msg_option_search_date_4\" />\n  <string src=\"Qualquer\" id=\"msg_option_search_date_5\" />\n\n  <string src=\"Short\" id=\"msg_option_search_dur_0\" />\n  <string src=\"Medium\" id=\"msg_option_search_dur_1\" />\n  <string src=\"Long\" id=\"msg_option_search_dur_2\" />\n  <string src=\"Any\" id=\"msg_option_search_dur_3\" />\n\n  <string src=\"Live\" id=\"msg_option_search_feature_0\" />\n  <string src=\"None\" id=\"msg_option_search_feature_1\" />\n  \n  <string src=\"Relevância\" id=\"msg_option_comment_sort_0\" />\n  <string src=\"Novos\" id=\"msg_option_comment_sort_1\" />\n\n  <string src=\"Auto\" id=\"msg_option_youtube_quality_vod_video_0\" />\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\n\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\n\n  <string src=\"Sort Order\" id=\"msg_hvdb_search_sort\" />\n  <string src=\"Sort Type\" id=\"msg_hvdb_search_sort_type\" />\n  <string src=\"Progress Filter\" id=\"msg_hvdb_search_filter\" />\n\n  <string src=\"Ascending\" id=\"msg_option_hvdb_search_sort_0\" />\n  <string src=\"Descending\" id=\"msg_option_hvdb_search_sort_1\" />\n\n  <string src=\"Create Date\" id=\"msg_option_hvdb_search_sort_type_0\" />\n  <string src=\"Release Date\" id=\"msg_option_hvdb_search_sort_type_1\" />\n  <string src=\"Purchase Count\" id=\"msg_option_hvdb_search_sort_type_2\" />\n  <string src=\"Price\" id=\"msg_option_hvdb_search_sort_type_3\" />\n  <string src=\"Rating\" id=\"msg_option_hvdb_search_sort_type_4\" />\n  <string src=\"Review Count\" id=\"msg_option_hvdb_search_sort_type_5\" />\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\n  <string src=\"Update Date\" id=\"msg_option_hvdb_search_sort_type_8\" />\n\n  <string src=\"Marked\" id=\"msg_option_hvdb_search_filter_0\" />\n  <string src=\"Listening\" id=\"msg_option_hvdb_search_filter_1\" />\n  <string src=\"Listened\" id=\"msg_option_hvdb_search_filter_2\" />\n  <string src=\"Replay\" id=\"msg_option_hvdb_search_filter_3\" />\n  <string src=\"Postponed\" id=\"msg_option_hvdb_search_filter_4\" />\n  <string src=\"Any\" id=\"msg_option_hvdb_search_filter_5\" />\n\n  <string src=\"Show Work Banner\" id=\"msg_toggle_hvdb_banner\" />\n\n  <string src=\"Use Cloud Sync\" id=\"msg_toggle_cloud_sync\" />\n  <string src=\"Sincronizar Dados Automaticamente\" id=\"msg_toggle_cloud_sync_auto\" />\n  <string src=\"Cloud sync option allows you to sync various data such as YouTube history and favourites, with cloud storage. This feature uses cloud storage provided by PlayStation™Network. Please restart this application after enabling this feature.\" id=\"msg_cloud_sync_hint\" />\n\n  <string src=\"Iniciar Minimizado\" id=\"msg_toggle_youtube_min\" />\n\n  <string src=\"Refresh\" id=\"msg_settings_hvdb_refresh\" />\n\n  <string src=\"Upload To Cloud\" id=\"msg_settings_youtube_cloud_upload\" />\n  <string src=\"Get From Cloud\" id=\"msg_settings_youtube_cloud_download\" />\n  <string src=\"Limpar Histórico\" id=\"msg_settings_youtube_clean_history\" />\n  <string src=\"Limpar Favoritos\" id=\"msg_settings_youtube_clean_fav\" />\n  <string src=\"Todo o histórico de vídeos vai ser apagado! Deseja continuar?\" id=\"msg_settings_youtube_clean_history_confirm\" />\n  <string src=\"Todos os favoritos vão ser apagados! Deseja continuar?\" id=\"msg_settings_youtube_clean_fav_confirm\" />\n  <string src=\"Baixar\" id=\"msg_settings_youtube_download\" />\n  <string src=\"Baixar áudio\" id=\"msg_settings_youtube_download_audio\" />\n  <string src=\"O vídeo foi adicionado a fila de Downloads.\" id=\"msg_settings_youtube_download_begin\" />\n\n  <string src=\"Select Quality\" id=\"msg_quality_select_dialog_title\" />\n\n  <string src=\"PlayStation™Network error has occured. Cloud data sync will not be available. If you enabled cloud sync option, please restart this application before using it.\" id=\"msg_error_psn_connection\" />\n\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_pt.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<stringset>\n\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\n  <string src=\"Servidor HTTP\" id=\"msg_fpmenu_item_2\" />\n  <string src=\"Servidor FTP\" id=\"msg_fpmenu_item_3\" />\n  <string src=\"Armazenamento local\" id=\"msg_fpmenu_item_4\" />\n\n  <string src=\"Histórico\" id=\"msg_youtube_history\" />\n  <string src=\"Descrição\" id=\"msg_youtube_description\" />\n  <string src=\"Carregar mais comentários...\" id=\"msg_youtube_comment_more\" />\n  <string src=\"Detalhes do comentário\" id=\"msg_youtube_comment_detail\" />\n  <string src=\"Respostas ao comentário\" id=\"msg_youtube_comment_reply\" />\n  <string src=\" gostos\" id=\"msg_youtube_comment_like_count\" />\n\n  <string src=\"Página seguinte\" id=\"msg_next_page\" />\n  <string src=\"Página anterior\" id=\"msg_previous_page\" />\n\n  <string src=\"Configurações\" id=\"msg_settings\" />\n  <string src=\"Servidor HTTP\" id=\"msg_settings_http\" />\n  <string src=\"Servidor FTP\" id=\"msg_settings_ftp\" />\n  <string src=\"Account\" id=\"msg_settings_account\" />\n  <string src=\"Armazenamento local\" id=\"msg_settings_local\" />\n  <string src=\"Pesquisar\" id=\"msg_settings_search\" />\n  <string src=\"Comentários\" id=\"msg_settings_comment\" />\n  <string src=\"Qualidade\" id=\"msg_settings_quality\" />\n  <string src=\"Reprodutor\" id=\"msg_settings_player\" />\n  <string src=\"Cloud Sync\" id=\"msg_settings_cloud_sync\" />\n  <string src=\"Informação da versão\" id=\"msg_settings_verinfo\" />\n  \n  <string src=\"Endereço de host\" id=\"msg_http_host\" />\n  <string src=\"Porto\" id=\"msg_http_port\" />\n  <string src=\"Utilizador\" id=\"msg_http_user\" />\n  <string src=\"Senha\" id=\"msg_http_password\" />\n\n  <string src=\"Endereço de host\" id=\"msg_ftp_host\" />\n  <string src=\"Porto\" id=\"msg_ftp_port\" />\n  <string src=\"Utilizador\" id=\"msg_ftp_user\" />\n  <string src=\"Senha\" id=\"msg_ftp_password\" />\n  <string src=\"Usar NLST\" id=\"msg_ftp_nlst\" />\n  <string src=\"Activar esta opção fará com que o NetStream envie o comando NLST para o servidor FTP em vez do comando LIST. Esta opção torna a operação mais rápida mas pode não ser suportado por alguns servidores FTP.\" id=\"msg_ftp_nlst_hint\" />\n\n  <string src=\"Host Address\" id=\"msg_hvdb_host\" />\n  <string src=\"User\" id=\"msg_hvdb_user\" />\n  <string src=\"Password\" id=\"msg_hvdb_password\" />\n\n  <string src=\"Prefixo para listas de reprodução .m3u8 relativas\" id=\"msg_local_playlist_prefix\" />\n  <string src=\"Sort By Name\" id=\"msg_local_sort_name\" />\n  <string src=\"Sort By Type\" id=\"msg_local_sort_type\" />\n  <string src=\"Ascending\" id=\"msg_option_local_sort_name_0\" />\n  <string src=\"Descending\" id=\"msg_option_local_sort_name_1\" />\n  <string src=\"Folders First\" id=\"msg_option_local_sort_type_0\" />\n  <string src=\"Files First\" id=\"msg_option_local_sort_type_1\" />\n\n  <string src=\"VOD Video Quality\" id=\"msg_youtube_quality_vod_video\" />\n  <string src=\"VOD Audio Quality\" id=\"msg_youtube_quality_vod_audio\" />\n  <string src=\"Default Live Quality\" id=\"msg_youtube_quality_live\" />\n\n  <string src=\"Região\" id=\"msg_youtube_search_region\" />\n  <string src=\"Ordenar\" id=\"msg_youtube_search_sort\" />\n  <string src=\"Data\" id=\"msg_youtube_search_date\" />\n  <string src=\"Duration\" id=\"msg_youtube_search_dur\" />\n  <string src=\"Feature\" id=\"msg_youtube_search_feature\" />\n  <string src=\"Proxy Server\" id=\"msg_youtube_search_proxy\" />\n  <string src=\"Ordenar\" id=\"msg_youtube_comment_sort\" />\n\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\n  \n  <string src=\"Relevância\" id=\"msg_option_search_sort_0\" />\n  <string src=\"Classificação\" id=\"msg_option_search_sort_1\" />\n  <string src=\"Data\" id=\"msg_option_search_sort_2\" />\n  <string src=\"Número de visualizações\" id=\"msg_option_search_sort_3\" />\n  \n  <string src=\"Hora\" id=\"msg_option_search_date_0\" />\n  <string src=\"Hoje\" id=\"msg_option_search_date_1\" />\n  <string src=\"Semana\" id=\"msg_option_search_date_2\" />\n  <string src=\"Mês\" id=\"msg_option_search_date_3\" />\n  <string src=\"Ano\" id=\"msg_option_search_date_4\" />\n  <string src=\"Qualquer\" id=\"msg_option_search_date_5\" />\n\n  <string src=\"Short\" id=\"msg_option_search_dur_0\" />\n  <string src=\"Medium\" id=\"msg_option_search_dur_1\" />\n  <string src=\"Long\" id=\"msg_option_search_dur_2\" />\n  <string src=\"Any\" id=\"msg_option_search_dur_3\" />\n\n  <string src=\"Live\" id=\"msg_option_search_feature_0\" />\n  <string src=\"None\" id=\"msg_option_search_feature_1\" />\n  \n  <string src=\"Mais relevantes\" id=\"msg_option_comment_sort_0\" />\n  <string src=\"Novos\" id=\"msg_option_comment_sort_1\" />\n\n  <string src=\"Auto\" id=\"msg_option_youtube_quality_vod_video_0\" />\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\n\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\n\n  <string src=\"Sort Order\" id=\"msg_hvdb_search_sort\" />\n  <string src=\"Sort Type\" id=\"msg_hvdb_search_sort_type\" />\n  <string src=\"Progress Filter\" id=\"msg_hvdb_search_filter\" />\n\n  <string src=\"Ascending\" id=\"msg_option_hvdb_search_sort_0\" />\n  <string src=\"Descending\" id=\"msg_option_hvdb_search_sort_1\" />\n\n  <string src=\"Create Date\" id=\"msg_option_hvdb_search_sort_type_0\" />\n  <string src=\"Release Date\" id=\"msg_option_hvdb_search_sort_type_1\" />\n  <string src=\"Purchase Count\" id=\"msg_option_hvdb_search_sort_type_2\" />\n  <string src=\"Price\" id=\"msg_option_hvdb_search_sort_type_3\" />\n  <string src=\"Rating\" id=\"msg_option_hvdb_search_sort_type_4\" />\n  <string src=\"Review Count\" id=\"msg_option_hvdb_search_sort_type_5\" />\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\n  <string src=\"Update Date\" id=\"msg_option_hvdb_search_sort_type_8\" />\n\n  <string src=\"Marked\" id=\"msg_option_hvdb_search_filter_0\" />\n  <string src=\"Listening\" id=\"msg_option_hvdb_search_filter_1\" />\n  <string src=\"Listened\" id=\"msg_option_hvdb_search_filter_2\" />\n  <string src=\"Replay\" id=\"msg_option_hvdb_search_filter_3\" />\n  <string src=\"Postponed\" id=\"msg_option_hvdb_search_filter_4\" />\n  <string src=\"Any\" id=\"msg_option_hvdb_search_filter_5\" />\n\n  <string src=\"Show Work Banner\" id=\"msg_toggle_hvdb_banner\" />\n\n  <string src=\"Use Cloud Sync\" id=\"msg_toggle_cloud_sync\" />\n  <string src=\"Sync Data Automatically\" id=\"msg_toggle_cloud_sync_auto\" />\n  <string src=\"Cloud sync option allows you to sync various data such as YouTube history and favourites, with cloud storage. This feature uses cloud storage provided by PlayStation™Network. Please restart this application after enabling this feature.\" id=\"msg_cloud_sync_hint\" />\n\n  <string src=\"Iniciar minimizado\" id=\"msg_toggle_youtube_min\" />\n\n  <string src=\"Refresh\" id=\"msg_settings_hvdb_refresh\" />\n\n  <string src=\"Upload To Cloud\" id=\"msg_settings_youtube_cloud_upload\" />\n  <string src=\"Get From Cloud\" id=\"msg_settings_youtube_cloud_download\" />\n  <string src=\"Apagar histórico\" id=\"msg_settings_youtube_clean_history\" />\n  <string src=\"Apagar favoritos\" id=\"msg_settings_youtube_clean_fav\" />\n  <string src=\"Todos os registos de histórico serão apagados. Deseja continuar?\" id=\"msg_settings_youtube_clean_history_confirm\" />\n  <string src=\"Todos os favoritos serão apagados. Deseja continuar?\" id=\"msg_settings_youtube_clean_fav_confirm\" />\n  <string src=\"Descarregar\" id=\"msg_settings_youtube_download\" />\n  <string src=\"Descarregar áudio\" id=\"msg_settings_youtube_download_audio\" />\n  <string src=\"A transferência foi adicionada à lista de transferências.\" id=\"msg_settings_youtube_download_begin\" />\n\n  <string src=\"Select Quality\" id=\"msg_quality_select_dialog_title\" />\n\n  <string src=\"PlayStation™Network error has occured. Cloud data sync will not be available. If you enabled cloud sync option, please restart this application before using it.\" id=\"msg_error_psn_connection\" />\n\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_ru.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<stringset>\n\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\n  <string src=\"HTTP-сервер\" id=\"msg_fpmenu_item_2\" />\n  <string src=\"FTP-сервер\" id=\"msg_fpmenu_item_3\" />\n  <string src=\"Память системы\" id=\"msg_fpmenu_item_4\" />\n\n  <string src=\"История\" id=\"msg_youtube_history\" />\n  <string src=\"Описание\" id=\"msg_youtube_description\" />\n  <string src=\"Загрузить больше...\" id=\"msg_youtube_comment_more\" />\n  <string src=\"Детали комментария\" id=\"msg_youtube_comment_detail\" />\n  <string src=\"Ответы комментария\" id=\"msg_youtube_comment_reply\" />\n  <string src=\" лайков\" id=\"msg_youtube_comment_like_count\" />\n\n  <string src=\"Следующая страница\" id=\"msg_next_page\" />\n  <string src=\"Предыдущая страница\" id=\"msg_previous_page\" />\n\n  <string src=\"Настройки\" id=\"msg_settings\" />\n  <string src=\"HTTP-сервер\" id=\"msg_settings_http\" />\n  <string src=\"FTP-сервер\" id=\"msg_settings_ftp\" />\n  <string src=\"Аккаунт\" id=\"msg_settings_account\" />\n  <string src=\"Память системы\" id=\"msg_settings_local\" />\n  <string src=\"Поиск\" id=\"msg_settings_search\" />\n  <string src=\"Комментарии\" id=\"msg_settings_comment\" />\n  <string src=\"Качество\" id=\"msg_settings_quality\" />\n  <string src=\"Проигрыватель\" id=\"msg_settings_player\" />\n  <string src=\"Синхронизация данных\" id=\"msg_settings_cloud_sync\" />\n  <string src=\"Информация о приложении\" id=\"msg_settings_verinfo\" />\n  \n  <string src=\"Адрес\" id=\"msg_http_host\" />\n  <string src=\"Порт\" id=\"msg_http_port\" />\n  <string src=\"Пользователь\" id=\"msg_http_user\" />\n  <string src=\"Пароль\" id=\"msg_http_password\" />\n\n  <string src=\"Адрес\" id=\"msg_ftp_host\" />\n  <string src=\"Порт\" id=\"msg_ftp_port\" />\n  <string src=\"Пользователь\" id=\"msg_ftp_user\" />\n  <string src=\"Пароль\" id=\"msg_ftp_password\" />\n  <string src=\"Использовать NLST\" id=\"msg_ftp_nlst\" />\n  <string src=\"Включение этой опции позволяет NetStream отправлять на FTP-сервер команду NLST вместо команды LIST. Эта опция ускоряет работу приложения, но может не поддерживаться некоторыми FTP-серверами.\" id=\"msg_cloud_sync_hint\" />\n\n  <string src=\"Адрес\" id=\"msg_hvdb_host\" />\n  <string src=\"Пользователь\" id=\"msg_hvdb_user\" />\n  <string src=\"Пароль\" id=\"msg_hvdb_password\" />\n  \n  <string src=\"Префикс для относительных плейлистов .m3u8\" id=\"msg_local_playlist_prefix\" />\n  <string src=\"Сортировка по имени\" id=\"msg_local_sort_name\" />\n  <string src=\"Сортировка по типу\" id=\"msg_local_sort_type\" />\n  <string src=\"Возрастающая\" id=\"msg_option_local_sort_name_0\" />\n  <string src=\"Нисходящая\" id=\"msg_option_local_sort_name_1\" />\n  <string src=\"Сначала папки\" id=\"msg_option_local_sort_type_0\" />\n  <string src=\"Сначала файлы\" id=\"msg_option_local_sort_type_1\" />\n\n  <string src=\"Качество видео\" id=\"msg_youtube_quality_vod_video\" />\n  <string src=\"Качество аудио\" id=\"msg_youtube_quality_vod_audio\" />\n  <string src=\"Качество прямых трансляций по умолчанию\" id=\"msg_youtube_quality_live\" />\n\n  <string src=\"Регион\" id=\"msg_youtube_search_region\" />\n  <string src=\"Сортировка\" id=\"msg_youtube_search_sort\" />\n  <string src=\"Фильтр по дате загрузки\" id=\"msg_youtube_search_date\" />\n  <string src=\"Длительность\" id=\"msg_youtube_search_dur\" />\n  <string src=\"Особенности\" id=\"msg_youtube_search_feature\" />\n  <string src=\"Прокси сервер\" id=\"msg_youtube_search_proxy\" />\n  <string src=\"Сортировка\" id=\"msg_youtube_comment_sort\" />\n\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\n  \n  <string src=\"По релевантности\" id=\"msg_option_search_sort_0\" />\n  <string src=\"По рейтингу\" id=\"msg_option_search_sort_1\" />\n  <string src=\"По дате загрузки\" id=\"msg_option_search_sort_2\" />\n  <string src=\"По числу просмотров\" id=\"msg_option_search_sort_3\" />\n  \n  <string src=\"За последний час\" id=\"msg_option_search_date_0\" />\n  <string src=\"Сегодня\" id=\"msg_option_search_date_1\" />\n  <string src=\"За эту неделю\" id=\"msg_option_search_date_2\" />\n  <string src=\"За этот месяц\" id=\"msg_option_search_date_3\" />\n  <string src=\"За этот год\" id=\"msg_option_search_date_4\" />\n  <string src=\"Любая дата\" id=\"msg_option_search_date_5\" />\n\n  <string src=\"Короткие\" id=\"msg_option_search_dur_0\" />\n  <string src=\"Средние\" id=\"msg_option_search_dur_1\" />\n  <string src=\"Длинные\" id=\"msg_option_search_dur_2\" />\n  <string src=\"Любые\" id=\"msg_option_search_dur_3\" />\n\n  <string src=\"Прямая трансляция\" id=\"msg_option_search_feature_0\" />\n  <string src=\"Нет\" id=\"msg_option_search_feature_1\" />\n  \n  <string src=\"Сначала популярные\" id=\"msg_option_comment_sort_0\" />\n  <string src=\"Сначала новые\" id=\"msg_option_comment_sort_1\" />\n\n  <string src=\"Авто\" id=\"msg_option_youtube_quality_vod_video_0\" />\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\n\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\n\n  <string src=\"Порядок сортировки\" id=\"msg_hvdb_search_sort\" />\n  <string src=\"Вид сортировки\" id=\"msg_hvdb_search_sort_type\" />\n  <string src=\"Фильтр\" id=\"msg_hvdb_search_filter\" />\n\n  <string src=\"Возрастающая\" id=\"msg_option_hvdb_search_sort_0\" />\n  <string src=\"Нисходящая\" id=\"msg_option_hvdb_search_sort_1\" />\n\n  <string src=\"Дата создания\" id=\"msg_option_hvdb_search_sort_type_0\" />\n  <string src=\"Дата релиза\" id=\"msg_option_hvdb_search_sort_type_1\" />\n  <string src=\"Количество покупок\" id=\"msg_option_hvdb_search_sort_type_2\" />\n  <string src=\"Цена\" id=\"msg_option_hvdb_search_sort_type_3\" />\n  <string src=\"Оценка\" id=\"msg_option_hvdb_search_sort_type_4\" />\n  <string src=\"Количество обзоров\" id=\"msg_option_hvdb_search_sort_type_5\" />\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\n  <string src=\"Дата обновления\" id=\"msg_option_hvdb_search_sort_type_8\" />\n\n  <string src=\"Отмечено\" id=\"msg_option_hvdb_search_filter_0\" />\n  <string src=\"Прослушивается\" id=\"msg_option_hvdb_search_filter_1\" />\n  <string src=\"Прослушано\" id=\"msg_option_hvdb_search_filter_2\" />\n  <string src=\"Повтор\" id=\"msg_option_hvdb_search_filter_3\" />\n  <string src=\"Отложено\" id=\"msg_option_hvdb_search_filter_4\" />\n  <string src=\"Любой\" id=\"msg_option_hvdb_search_filter_5\" />\n\n  <string src=\"Показывать обложку\" id=\"msg_toggle_hvdb_banner\" />\n\n  <string src=\"Использовать синхронизацию\" id=\"msg_toggle_cloud_sync\" />\n  <string src=\"Синхронизировать автоматически\" id=\"msg_toggle_cloud_sync_auto\" />\n  <string src=\"Эта опция позволяет осуществлять синхронизацию некоторых данных приложения, таких как история и избранное YouTube, с облаком PlayStation™Network. После включения данной опции приложение необходимо перезапустить для применения изменений.\" id=\"msg_ftp_nlst_hint\" />\n\n  <string src=\"Запускать в минимизированном виде\" id=\"msg_toggle_youtube_min\" />\n\n  <string src=\"Обновить\" id=\"msg_settings_hvdb_refresh\" />\n\n  <string src=\"Загрузить в облако\" id=\"msg_settings_youtube_cloud_upload\" />\n  <string src=\"Получить из облака\" id=\"msg_settings_youtube_cloud_download\" />\n  <string src=\"Очистить историю\" id=\"msg_settings_youtube_clean_history\" />\n  <string src=\"Очистить избранное\" id=\"msg_settings_youtube_clean_fav\" />\n  <string src=\"Все записи в истории просмотров будут удалены. Продолжить?\" id=\"msg_settings_youtube_clean_history_confirm\" />\n  <string src=\"Все записи в списке избранного будут удалены. Продолжить?\" id=\"msg_settings_youtube_clean_fav_confirm\" />\n  <string src=\"Загрузить\" id=\"msg_settings_youtube_download\" />\n  <string src=\"Загрузить аудио\" id=\"msg_settings_youtube_download_audio\" />\n  <string src=\"Загрузка была начата успешно.\" id=\"msg_settings_youtube_download_begin\" />\n\n  <string src=\"Выбор качества\" id=\"msg_quality_select_dialog_title\" />\n\n  <string src=\"Произошла ошибка PlayStation™Network. Синхронизация данных с облаком будет недоступна. Убедитесь, что приложение было перезапущенно после включения синхронизации с облаком.\" id=\"msg_error_psn_connection\" />\n\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_zh-s.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<stringset>\n\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\n  <string src=\"HTTP 服务器\" id=\"msg_fpmenu_item_2\" />\n  <string src=\"FTP 服务器\" id=\"msg_fpmenu_item_3\" />\n  <string src=\"本地存储\" id=\"msg_fpmenu_item_4\" />\n\n  <string src=\"历史\" id=\"msg_youtube_history\" />\n  <string src=\"描述\" id=\"msg_youtube_description\" />\n  <string src=\"加载更多评论...\" id=\"msg_youtube_comment_more\" />\n  <string src=\"评论详情\" id=\"msg_youtube_comment_detail\" />\n  <string src=\"评论回复\" id=\"msg_youtube_comment_reply\" />\n  <string src=\"喜欢\" id=\"msg_youtube_comment_like_count\" />\n\n  <string src=\"下一页\" id=\"msg_next_page\" />\n  <string src=\"上一页\" id=\"msg_previous_page\" />\n\n  <string src=\"设置\" id=\"msg_settings\" />\n  <string src=\"HTTP 服务器\" id=\"msg_settings_http\" />\n  <string src=\"FTP 服务器\" id=\"msg_settings_ftp\" />\n  <string src=\"Account\" id=\"msg_settings_account\" />\n  <string src=\"本地存储\" id=\"msg_settings_local\" />\n  <string src=\"搜索\" id=\"msg_settings_search\" />\n  <string src=\"注释\" id=\"msg_settings_comment\" />\n  <string src=\"质量\" id=\"msg_settings_quality\" />\n  <string src=\"播放器\" id=\"msg_settings_player\" />\n  <string src=\"Cloud Sync\" id=\"msg_settings_cloud_sync\" />\n  <string src=\"构建信息\" id=\"msg_settings_verinfo\" />\n  \n  <string src=\"主机地址\" id=\"msg_http_host\" />\n  <string src=\"港口\" id=\"msg_http_port\" />\n  <string src=\"用户\" id=\"msg_http_user\" />\n  <string src=\"密码\" id=\"msg_http_password\" />\n\n  <string src=\"主机地址\" id=\"msg_ftp_host\" />\n  <string src=\"港口\" id=\"msg_ftp_port\" />\n  <string src=\"用户\" id=\"msg_ftp_user\" />\n  <string src=\"密码\" id=\"msg_ftp_password\" />\n  <string src=\"使用NLST\" id=\"msg_ftp_nlst\" />\n  <string src=\"启用这个选项将使NetStream向FTP服务器发送NLST命令而不是LIST命令。这个选项使操作更快，但可能不被某些FTP服务器支持。\" id=\"msg_ftp_nlst_hint\" />\n\n  <string src=\"Host Address\" id=\"msg_hvdb_host\" />\n  <string src=\"User\" id=\"msg_hvdb_user\" />\n  <string src=\"Password\" id=\"msg_hvdb_password\" />\n  \n  <string src=\"Prefix For Relative .m3u8 Playlists\" id=\"msg_local_playlist_prefix\" />\n  <string src=\"Sort By Name\" id=\"msg_local_sort_name\" />\n  <string src=\"Sort By Type\" id=\"msg_local_sort_type\" />\n  <string src=\"Ascending\" id=\"msg_option_local_sort_name_0\" />\n  <string src=\"Descending\" id=\"msg_option_local_sort_name_1\" />\n  <string src=\"Folders First\" id=\"msg_option_local_sort_type_0\" />\n  <string src=\"Files First\" id=\"msg_option_local_sort_type_1\" />\n\n  <string src=\"VOD Video Quality\" id=\"msg_youtube_quality_vod_video\" />\n  <string src=\"VOD Audio Quality\" id=\"msg_youtube_quality_vod_audio\" />\n  <string src=\"Default Live Quality\" id=\"msg_youtube_quality_live\" />\n\n  <string src=\"地区\" id=\"msg_youtube_search_region\" />\n  <string src=\"种类\" id=\"msg_youtube_search_sort\" />\n  <string src=\"日期\" id=\"msg_youtube_search_date\" />\n  <string src=\"Duration\" id=\"msg_youtube_search_dur\" />\n  <string src=\"Feature\" id=\"msg_youtube_search_feature\" />\n  <string src=\"Proxy Server\" id=\"msg_youtube_search_proxy\" />\n  <string src=\"种类\" id=\"msg_youtube_comment_sort\" />\n\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\n  \n  <string src=\"关联\" id=\"msg_option_search_sort_0\" />\n  <string src=\"评分\" id=\"msg_option_search_sort_1\" />\n  <string src=\"日期\" id=\"msg_option_search_sort_2\" />\n  <string src=\"查看次数\" id=\"msg_option_search_sort_3\" />\n  \n  <string src=\"小时\" id=\"msg_option_search_date_0\" />\n  <string src=\"今天\" id=\"msg_option_search_date_1\" />\n  <string src=\"星期\" id=\"msg_option_search_date_2\" />\n  <string src=\"月\" id=\"msg_option_search_date_3\" />\n  <string src=\"年\" id=\"msg_option_search_date_4\" />\n  <string src=\"任何\" id=\"msg_option_search_date_5\" />\n\n  <string src=\"Short\" id=\"msg_option_search_dur_0\" />\n  <string src=\"Medium\" id=\"msg_option_search_dur_1\" />\n  <string src=\"Long\" id=\"msg_option_search_dur_2\" />\n  <string src=\"Any\" id=\"msg_option_search_dur_3\" />\n\n  <string src=\"Live\" id=\"msg_option_search_feature_0\" />\n  <string src=\"None\" id=\"msg_option_search_feature_1\" />\n  \n  <string src=\"最佳\" id=\"msg_option_comment_sort_0\" />\n  <string src=\"新的\" id=\"msg_option_comment_sort_1\" />\n\n  <string src=\"Auto\" id=\"msg_option_youtube_quality_vod_video_0\" />\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\n\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\n\n  <string src=\"Sort Order\" id=\"msg_hvdb_search_sort\" />\n  <string src=\"Sort Type\" id=\"msg_hvdb_search_sort_type\" />\n  <string src=\"Progress Filter\" id=\"msg_hvdb_search_filter\" />\n\n  <string src=\"Ascending\" id=\"msg_option_hvdb_search_sort_0\" />\n  <string src=\"Descending\" id=\"msg_option_hvdb_search_sort_1\" />\n\n  <string src=\"Create Date\" id=\"msg_option_hvdb_search_sort_type_0\" />\n  <string src=\"Release Date\" id=\"msg_option_hvdb_search_sort_type_1\" />\n  <string src=\"Purchase Count\" id=\"msg_option_hvdb_search_sort_type_2\" />\n  <string src=\"Price\" id=\"msg_option_hvdb_search_sort_type_3\" />\n  <string src=\"Rating\" id=\"msg_option_hvdb_search_sort_type_4\" />\n  <string src=\"Review Count\" id=\"msg_option_hvdb_search_sort_type_5\" />\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\n  <string src=\"Update Date\" id=\"msg_option_hvdb_search_sort_type_8\" />\n\n  <string src=\"Marked\" id=\"msg_option_hvdb_search_filter_0\" />\n  <string src=\"Listening\" id=\"msg_option_hvdb_search_filter_1\" />\n  <string src=\"Listened\" id=\"msg_option_hvdb_search_filter_2\" />\n  <string src=\"Replay\" id=\"msg_option_hvdb_search_filter_3\" />\n  <string src=\"Postponed\" id=\"msg_option_hvdb_search_filter_4\" />\n  <string src=\"Any\" id=\"msg_option_hvdb_search_filter_5\" />\n\n  <string src=\"Show Work Banner\" id=\"msg_toggle_hvdb_banner\" />\n\n  <string src=\"Use Cloud Sync\" id=\"msg_toggle_cloud_sync\" />\n  <string src=\"Sync Data Automatically\" id=\"msg_toggle_cloud_sync_auto\" />\n  <string src=\"Cloud sync option allows you to sync various data such as YouTube history and favourites, with cloud storage. This feature uses cloud storage provided by PlayStation™Network. Please restart this application after enabling this feature.\" id=\"msg_cloud_sync_hint\" />\n\n  <string src=\"开始最小化\" id=\"msg_toggle_youtube_min\" />\n\n  <string src=\"Refresh\" id=\"msg_settings_hvdb_refresh\" />\n\n  <string src=\"Upload To Cloud\" id=\"msg_settings_youtube_cloud_upload\" />\n  <string src=\"Get From Cloud\" id=\"msg_settings_youtube_cloud_download\" />\n  <string src=\"清洁历史\" id=\"msg_settings_youtube_clean_history\" />\n  <string src=\"清理收藏夹\" id=\"msg_settings_youtube_clean_fav\" />\n  <string src=\"所有历史记录将被删除。 继续？\" id=\"msg_settings_youtube_clean_history_confirm\" />\n  <string src=\"所有收藏夹都将被删除。 继续？\" id=\"msg_settings_youtube_clean_fav_confirm\" />\n  <string src=\"下载\" id=\"msg_settings_youtube_download\" />\n  <string src=\"下载音频\" id=\"msg_settings_youtube_download_audio\" />\n  <string src=\"下载已添加到队列中。\" id=\"msg_settings_youtube_download_begin\" />\n\n  <string src=\"Select Quality\" id=\"msg_quality_select_dialog_title\" />\n\n  <string src=\"PlayStation™Network error has occured. Cloud data sync will not be available. If you enabled cloud sync option, please restart this application before using it.\" id=\"msg_error_psn_connection\" />\n\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/locale/netstream_locale_zh-t.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<stringset>\n\n  <string src=\"NetStream\" id=\"msg_title_menu_first\" />\n  <string src=\"YouTube\" id=\"msg_fpmenu_item_0\" />\n  <string src=\"Kikoeru\" id=\"msg_fpmenu_item_1\" />\n  <string src=\"HTTP 服務器\" id=\"msg_fpmenu_item_2\" />\n  <string src=\"FTP 服務器\" id=\"msg_fpmenu_item_3\" />\n  <string src=\"本地存儲\" id=\"msg_fpmenu_item_4\" />\n\n  <string src=\"歷史\" id=\"msg_youtube_history\" />\n  <string src=\"描述\" id=\"msg_youtube_description\" />\n  <string src=\"加載更多評論...\" id=\"msg_youtube_comment_more\" />\n  <string src=\"評論詳情\" id=\"msg_youtube_comment_detail\" />\n  <string src=\"評論回复\" id=\"msg_youtube_comment_reply\" />\n  <string src=\"喜歡\" id=\"msg_youtube_comment_like_count\" />\n\n  <string src=\"下一頁\" id=\"msg_next_page\" />\n  <string src=\"上一頁\" id=\"msg_previous_page\" />\n\n  <string src=\"設置\" id=\"msg_settings\" />\n  <string src=\"HTTP 服務器\" id=\"msg_settings_http\" />\n  <string src=\"FTP 服務器\" id=\"msg_settings_ftp\" />\n  <string src=\"Account\" id=\"msg_settings_account\" />\n  <string src=\"本地存儲\" id=\"msg_settings_local\" />\n  <string src=\"搜索\" id=\"msg_settings_search\" />\n  <string src=\"註釋\" id=\"msg_settings_comment\" />\n  <string src=\"質量\" id=\"msg_settings_quality\" />\n  <string src=\"播放器\" id=\"msg_settings_player\" />\n  <string src=\"Cloud Sync\" id=\"msg_settings_cloud_sync\" />\n  <string src=\"構建信息\" id=\"msg_settings_verinfo\" />\n  \n  <string src=\"主機地址\" id=\"msg_http_host\" />\n  <string src=\"港口\" id=\"msg_http_port\" />\n  <string src=\"用戶\" id=\"msg_http_user\" />\n  <string src=\"密碼\" id=\"msg_http_password\" />\n\n  <string src=\"主機地址\" id=\"msg_ftp_host\" />\n  <string src=\"港口\" id=\"msg_ftp_port\" />\n  <string src=\"用戶\" id=\"msg_ftp_user\" />\n  <string src=\"密碼\" id=\"msg_ftp_password\" />\n  <string src=\"使用NLST\" id=\"msg_ftp_nlst\" />\n  <string src=\"啟用此選項將使NetStream向FTP服務器發送NLST命令而不是LIST命令。此選項使操作更快，但某些FTP服務器可能不支持。\" id=\"msg_ftp_nlst_hint\" />\n\n  <string src=\"Host Address\" id=\"msg_hvdb_host\" />\n  <string src=\"User\" id=\"msg_hvdb_user\" />\n  <string src=\"Password\" id=\"msg_hvdb_password\" />\n\n  <string src=\"Prefix For Relative .m3u8 Playlists\" id=\"msg_local_playlist_prefix\" />\n  <string src=\"Sort By Name\" id=\"msg_local_sort_name\" />\n  <string src=\"Sort By Type\" id=\"msg_local_sort_type\" />\n  <string src=\"Ascending\" id=\"msg_option_local_sort_name_0\" />\n  <string src=\"Descending\" id=\"msg_option_local_sort_name_1\" />\n  <string src=\"Folders First\" id=\"msg_option_local_sort_type_0\" />\n  <string src=\"Files First\" id=\"msg_option_local_sort_type_1\" />\n\n  <string src=\"VOD Video Quality\" id=\"msg_youtube_quality_vod_video\" />\n  <string src=\"VOD Audio Quality\" id=\"msg_youtube_quality_vod_audio\" />\n  <string src=\"Default Live Quality\" id=\"msg_youtube_quality_live\" />\n\n  <string src=\"地區\" id=\"msg_youtube_search_region\" />\n  <string src=\"種類\" id=\"msg_youtube_search_sort\" />\n  <string src=\"日期\" id=\"msg_youtube_search_date\" />\n  <string src=\"Duration\" id=\"msg_youtube_search_dur\" />\n  <string src=\"Feature\" id=\"msg_youtube_search_feature\" />\n  <string src=\"Proxy Server\" id=\"msg_youtube_search_proxy\" />\n  <string src=\"種類\" id=\"msg_youtube_comment_sort\" />\n\n  <string src=\"US\" id=\"msg_option_search_region_0\" />\n  \n  <string src=\"關聯\" id=\"msg_option_search_sort_0\" />\n  <string src=\"評分\" id=\"msg_option_search_sort_1\" />\n  <string src=\"日期\" id=\"msg_option_search_sort_2\" />\n  <string src=\"查看次數\" id=\"msg_option_search_sort_3\" />\n  \n  <string src=\"小時\" id=\"msg_option_search_date_0\" />\n  <string src=\"今天\" id=\"msg_option_search_date_1\" />\n  <string src=\"星期\" id=\"msg_option_search_date_2\" />\n  <string src=\"月\" id=\"msg_option_search_date_3\" />\n  <string src=\"年\" id=\"msg_option_search_date_4\" />\n  <string src=\"任何\" id=\"msg_option_search_date_5\" />\n\n  <string src=\"Short\" id=\"msg_option_search_dur_0\" />\n  <string src=\"Medium\" id=\"msg_option_search_dur_1\" />\n  <string src=\"Long\" id=\"msg_option_search_dur_2\" />\n  <string src=\"Any\" id=\"msg_option_search_dur_3\" />\n\n  <string src=\"Live\" id=\"msg_option_search_feature_0\" />\n  <string src=\"None\" id=\"msg_option_search_feature_1\" />\n  \n  <string src=\"最佳\" id=\"msg_option_comment_sort_0\" />\n  <string src=\"新的\" id=\"msg_option_comment_sort_1\" />\n\n  <string src=\"Auto\" id=\"msg_option_youtube_quality_vod_video_0\" />\n  <string src=\"144p\" id=\"msg_option_youtube_quality_vod_video_1\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_vod_video_2\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_vod_video_3\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_vod_video_4\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_vod_video_5\" />\n\n  <string src=\"144p\" id=\"msg_option_youtube_quality_live_0\" />\n  <string src=\"240p\" id=\"msg_option_youtube_quality_live_1\" />\n  <string src=\"360p\" id=\"msg_option_youtube_quality_live_2\" />\n  <string src=\"480p\" id=\"msg_option_youtube_quality_live_3\" />\n  <string src=\"720p\" id=\"msg_option_youtube_quality_live_4\" />\n\n  <string src=\"Sort Order\" id=\"msg_hvdb_search_sort\" />\n  <string src=\"Sort Type\" id=\"msg_hvdb_search_sort_type\" />\n  <string src=\"Progress Filter\" id=\"msg_hvdb_search_filter\" />\n\n  <string src=\"Ascending\" id=\"msg_option_hvdb_search_sort_0\" />\n  <string src=\"Descending\" id=\"msg_option_hvdb_search_sort_1\" />\n\n  <string src=\"Create Date\" id=\"msg_option_hvdb_search_sort_type_0\" />\n  <string src=\"Release Date\" id=\"msg_option_hvdb_search_sort_type_1\" />\n  <string src=\"Purchase Count\" id=\"msg_option_hvdb_search_sort_type_2\" />\n  <string src=\"Price\" id=\"msg_option_hvdb_search_sort_type_3\" />\n  <string src=\"Rating\" id=\"msg_option_hvdb_search_sort_type_4\" />\n  <string src=\"Review Count\" id=\"msg_option_hvdb_search_sort_type_5\" />\n  <string src=\"ID\" id=\"msg_option_hvdb_search_sort_type_6\" />\n  <string src=\"NSFW\" id=\"msg_option_hvdb_search_sort_type_7\" />\n  <string src=\"Update Date\" id=\"msg_option_hvdb_search_sort_type_8\" />\n\n  <string src=\"Marked\" id=\"msg_option_hvdb_search_filter_0\" />\n  <string src=\"Listening\" id=\"msg_option_hvdb_search_filter_1\" />\n  <string src=\"Listened\" id=\"msg_option_hvdb_search_filter_2\" />\n  <string src=\"Replay\" id=\"msg_option_hvdb_search_filter_3\" />\n  <string src=\"Postponed\" id=\"msg_option_hvdb_search_filter_4\" />\n  <string src=\"Any\" id=\"msg_option_hvdb_search_filter_5\" />\n\n  <string src=\"Show Work Banner\" id=\"msg_toggle_hvdb_banner\" />\n\n  <string src=\"Use Cloud Sync\" id=\"msg_toggle_cloud_sync\" />\n  <string src=\"Sync Data Automatically\" id=\"msg_toggle_cloud_sync_auto\" />\n  <string src=\"Cloud sync option allows you to sync various data such as YouTube history and favourites, with cloud storage. This feature uses cloud storage provided by PlayStation™Network. Please restart this application after enabling this feature.\" id=\"msg_cloud_sync_hint\" />\n\n  <string src=\"開始最小化\" id=\"msg_toggle_youtube_min\" />\n\n  <string src=\"Refresh\" id=\"msg_settings_hvdb_refresh\" />\n\n  <string src=\"Upload To Cloud\" id=\"msg_settings_youtube_cloud_upload\" />\n  <string src=\"Get From Cloud\" id=\"msg_settings_youtube_cloud_download\" />\n  <string src=\"清潔歷史\" id=\"msg_settings_youtube_clean_history\" />\n  <string src=\"清理收藏夾\" id=\"msg_settings_youtube_clean_fav\" />\n  <string src=\"所有歷史記錄將被刪除。 繼續？\" id=\"msg_settings_youtube_clean_history_confirm\" />\n  <string src=\"所有收藏夾都將被刪除。 繼續？\" id=\"msg_settings_youtube_clean_fav_confirm\" />\n  <string src=\"下載\" id=\"msg_settings_youtube_download\" />\n  <string src=\"下載音頻\" id=\"msg_settings_youtube_download_audio\" />\n  <string src=\"下載已添加到隊列中。\" id=\"msg_settings_youtube_download_begin\" />\n\n  <string src=\"Select Quality\" id=\"msg_quality_select_dialog_title\" />\n\n  <string src=\"PlayStation™Network error has occured. Cloud data sync will not be available. If you enabled cloud sync option, please restart this application before using it.\" id=\"msg_error_psn_connection\" />\n\n</stringset>"
  },
  {
    "path": "NetStream/RES_RCO/netstream_plugin.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resource version=\"0.1\" type=\"normal\" id=\"netstream_plugin\">\n  <pagetable>\n  \n    <!-- first page -->\n    <page id=\"page_first\">\n      <plane texture=\"tex_common_bg\" id=\"plane_base_bg_page_first\">\n        <layout_hint size=\"960, 544\" />\n      </plane>\n      <template_ref id=\"template_ref_top_title_bar_page_first\" template=\"template_top_title_bar\" />\n      <template_ref id=\"template_ref_list_view_page_first\" template=\"template_list_view_generic\" />\n    </page>\n\n    <!-- generic server page -->\n    <page id=\"page_server_generic\">\n      <plane texture=\"tex_common_bg\" id=\"plane_base_bg_page_server_generic\">\n        <layout_hint size=\"960, 544\" />\n      </plane>\n      <template_ref id=\"template_ref_top_title_bar_page_server_generic\" template=\"template_top_title_bar\" />\n      <plane style=\"_common_style_plane_transparent\" id=\"plane_browser_root_page_server_generic\">\n        <layout_hint size=\"960, 544\" />\n      </plane>\n      <busyindicator style=\"style_busyindicator_big\" texture=\"_common_texture_busy\" id=\"busyindicator_loader_page_server_generic\" >\n        <layout_hint size=\"75, 75\" />\n      </busyindicator>\n      <corner_button style=\"_common_style_corner_bottom_left\" id=\"button_back_page_server_generic\" />\n      <corner_button style=\"_common_style_corner_bottom_right\" id=\"button_settings_page_server_generic\" />\n    </page>\n\n    <!-- youtube browser page -->\n    <page id=\"page_youtube\">\n      <plane texture=\"tex_common_bg\" id=\"plane_base_bg_page_youtube\">\n        <layout_hint size=\"960, 544\" />\n      </plane>\n      <template_ref id=\"template_ref_top_title_bar_page_youtube\" template=\"template_top_title_bar\" />\n      <plane style=\"_common_style_plane_transparent\" id=\"plane_browser_root_page_youtube\">\n        <layout_hint size=\"960, 544\" />\n      </plane>\n      <busyindicator style=\"style_busyindicator_big\" texture=\"_common_texture_busy\" id=\"busyindicator_loader_page_youtube\" >\n        <layout_hint size=\"75, 75\" />\n      </busyindicator>\n      <plane texture=\"_common_texture_option_menu_button_top\" id=\"plane_bottommenu_page_youtube\">\n        <layout_hint size=\"980, 51\" alpha=\"1\" anchor=\"0, 1\" align=\"0, 1\" />\n        <box style=\"_common_default_style_dialog_box\" id=\"box_bottommenu_page_youtube\">\n          <layout_box layout_type=\"2\" bottom_margin=\"0\" top_margin=\"0\" />\n          <button style=\"style_button_yt_search\" id=\"button_yt_btmenu_search\">\n            <layout_hint alpha=\"1\" size=\"135, 39\" pos=\"0, -4.5\" />\n            <focus_hint focus_shape=\"2\" right_id=\"button_yt_btmenu_history\" />\n          </button>\n          <plane texture=\"tex_vertical_separator\" id=\"yt_plane_bottommenu_sep1\">\n            <layout_hint size=\"1, 45\" pos=\"0, -4.5\" />\n          </plane>\n          <button style=\"style_button_yt_history\" id=\"button_yt_btmenu_history\">\n            <layout_hint alpha=\"1\" size=\"135, 39\" pos=\"0, -4.5\" />\n            <focus_hint focus_shape=\"2\" left_id=\"button_yt_btmenu_search\" right_id=\"button_yt_btmenu_favourite\" />\n          </button>\n          <plane texture=\"tex_vertical_separator\" id=\"yt_plane_bottommenu_sep2\">\n            <layout_hint size=\"1, 45\" pos=\"0, -4.5\" />\n          </plane>\n          <button style=\"style_button_yt_favourite\" id=\"button_yt_btmenu_favourite\">\n            <layout_hint alpha=\"1\" size=\"135, 39\" pos=\"0, -4.5\" />\n            <focus_hint focus_shape=\"2\" left_id=\"button_yt_btmenu_history\" />\n          </button>\n        </box>\n      </plane>\n      <corner_button style=\"_common_style_corner_bottom_left\" id=\"button_back_page_youtube\" />\n      <corner_button style=\"_common_style_corner_bottom_right\" id=\"button_settings_page_youtube\" />\n    </page>\n\n    <!-- hvdb browser page -->\n    <page id=\"page_hvdb\">\n      <plane texture=\"tex_common_bg\" id=\"plane_base_bg_page_hvdb\">\n        <layout_hint size=\"960, 544\" />\n      </plane>\n      <template_ref id=\"template_ref_top_title_bar_page_hvdb\" template=\"template_top_title_bar\" />\n      <plane style=\"_common_style_plane_transparent\" id=\"plane_browser_root_page_hvdb\">\n        <layout_hint size=\"960, 544\" />\n      </plane>\n      <busyindicator style=\"style_busyindicator_big\" texture=\"_common_texture_busy\" id=\"busyindicator_loader_page_hvdb\" >\n        <layout_hint size=\"75, 75\" />\n      </busyindicator>\n      <corner_button style=\"_common_style_corner_bottom_left\" id=\"button_back_page_hvdb\" />\n      <corner_button style=\"_common_style_corner_bottom_right\" id=\"button_settings_page_hvdb\" />\n    </page>\n\n    <!-- youtube player page -->\n    <page id=\"page_youtube_player\">\n      <plane texture=\"tex_common_bg\" id=\"plane_base_bg_page_youtube_player\">\n        <layout_hint size=\"960, 544\"/>\n      </plane>\n      <plane style=\"_common_style_plane_transparent\" id=\"plane_root_page_youtube_player\">\n        <layout_hint size=\"960, 544\" />\n      </plane>\n      <text style=\"style_text_youtube_video_title\" auto_scroll=\"1\" id=\"text_video_title\">\n        <layout_hint size=\"480, 0\" anchor=\"1, 2\" align=\"1, 2\" adjust=\"0, 2\" pos=\"13, -41\" />\n      </text>\n      <plane texture=\"tex_black\" id=\"plane_video_dummy\">\n        <layout_hint anchor=\"1, 2\" align=\"1, 2\" size=\"480, 272\" pos=\"13, -79\" />\n      </plane>\n      <text style=\"style_text_youtube_video_stat\" auto_scroll=\"1\" id=\"text_video_stat_0\">\n        <layout_hint size=\"480, 0\" anchor=\"1, 2\" align=\"1, 2\" adjust=\"0, 2\" pos=\"13, -421\" />\n      </text>\n      <text style=\"style_text_youtube_video_stat\" id=\"text_video_stat_1\">\n        <layout_hint size=\"240, 0\" anchor=\"1, 2\" align=\"1, 2\" adjust=\"0, 2\" pos=\"13, -447\" />\n      </text>\n       <text style=\"style_text_youtube_video_stat_right_align\" id=\"text_video_stat_2\">\n        <layout_hint size=\"240, 0\" anchor=\"2, 2\" align=\"2, 2\" adjust=\"0, 2\" pos=\"-467, -447\" />\n      </text>\n      <image_button style=\"style_button_yt_fav\" id=\"button_youtube_fav\">\n        <layout_hint size=\"102, 50\" anchor=\"1, 2\" align=\"1, 2\" pos=\"13, -362\" />\n      </image_button>\n      <image_button style=\"style_button_yt_expand\" id=\"button_youtube_expand\">\n        <layout_hint size=\"102, 50\" anchor=\"2, 2\" align=\"2, 2\" pos=\"-467, -362\" />\n      </image_button>\n      <image_button style=\"style_button_yt_settings\" id=\"button_youtube_settings\">\n        <layout_hint size=\"102, 50\" anchor=\"2, 2\" align=\"2, 2\" pos=\"-589, -362\" />\n      </image_button>\n      <plane texture=\"_common_texture_transparent\" id=\"plane_youtube_live_now\">\n        <layout_hint anchor=\"1, 2\" align=\"1, 2\" size=\"70, 53\" pos=\"138, -350\" />\n      </plane>\n      <plane style=\"_common_style_plane_transparent\" id=\"plane_youtube_companel_base\">\n        <layout_hint anchor=\"1, 2\" align=\"1, 2\" size=\"426, 490\" pos=\"514, -42\" />\n        <plane texture=\"_common_texture_dialog_frame\" id=\"plane_youtube_companel_frame\">\n          <layout_hint adjust=\"1, 1\" />\n        </plane>\n        <plane style=\"_common_style_plane_dialog\" texture=\"_common_texture_dialog_fill_white\" id=\"plane_youtube_companel_fill\">\n          <layout_hint adjust=\"1, 1\" />\n        </plane>\n        <button sound=\"_common_sound_button_enter\" style=\"_common_style_copy_paste_menu_button_left\" id=\"button_yt_companel_description\" label=\"msg_youtube_description\">\n          <layout_hint anchor=\"1, 2\" align=\"1, 2\" size=\"211, 43\" pos=\"2, -2\" />\n          <focus_hint focus_shape=\"3\" />\n        </button>\n        <button sound=\"_common_sound_button_enter\" style=\"_common_style_copy_paste_menu_button_right\" id=\"button_yt_companel_comment\" label=\"msg_settings_comment\">\n          <layout_hint anchor=\"1, 2\" align=\"1, 2\" size=\"211, 43\" pos=\"213, -2\" />\n          <focus_hint focus_shape=\"3\" />\n        </button>\n      </plane>\n      <corner_button style=\"_common_style_corner_bottom_left\" id=\"button_back_page_youtube_player\" />\n      <corner_button style=\"_common_style_corner_bottom_right\" id=\"button_settings_page_youtube_player\" />\n      <plane style=\"style_plane_youtube_loader\" id=\"plane_youtube_loader\">\n        <layout_hint size=\"960, 544\"/>\n        <busyindicator style=\"style_busyindicator_big\" texture=\"_common_texture_busy\" id=\"busyindicator_youtube_loader\" >\n          <layout_hint size=\"75, 75\" />\n        </busyindicator>\n      </plane>\n    </page>\n    \n    <!-- simple player page -->\n    <page id=\"page_player_simple\">\n      <plane texture=\"tex_black\" id=\"plane_video_page_player_simple\">\n        <layout_hint anchor=\"1, 2\" align=\"1, 2\">\n          <resolution id=\"landscape\" size=\"960, 544\" />\n          <resolution id=\"full_hd\" size=\"1920, 1088\" />\n        </layout_hint>\n        <text id=\"text_video_page_player_subs_edge_0\">\n          <layout_hint adjust=\"2, 2\" />\n        </text>\n        <text id=\"text_video_page_player_subs_edge_1\">\n          <layout_hint adjust=\"2, 2\" />\n        </text>\n        <text id=\"text_video_page_player_subs_edge_2\">\n          <layout_hint adjust=\"2, 2\" />\n        </text>\n        <text id=\"text_video_page_player_subs_edge_3\">\n          <layout_hint adjust=\"2, 2\" />\n        </text>\n        <text id=\"text_video_page_player_subs_main\">\n          <layout_hint adjust=\"2, 2\" />\n        </text>\n        <busyindicator style=\"style_busyindicator_big\" texture=\"_common_texture_busy\" id=\"busyindicator_video_page_player_simple\" >\n          <layout_hint>\n            <resolution id=\"landscape\" size=\"75, 75\" />\n            <resolution id=\"full_hd\" size=\"150, 150\" />\n          </layout_hint>\n        </busyindicator>\n        <text style=\"style_text_video_control_panel_acc_left\" id=\"text_video_page_player_simple_acc_left\" >\n          <layout_hint adjust=\"2, 2\" anchor=\"1, 0\" align=\"1, 0\" >\n            <resolution id=\"landscape\" pos=\"60, 0\" />\n            <resolution id=\"full_hd\" pos=\"120, 0\" />\n          </layout_hint>\n        </text>\n        <text style=\"style_text_video_control_panel_acc_right\" id=\"text_video_page_player_simple_acc_right\" >\n          <layout_hint adjust=\"2, 2\" anchor=\"2, 0\" align=\"2, 0\" >\n            <resolution id=\"landscape\" pos=\"-60, 0\" />\n            <resolution id=\"full_hd\" pos=\"-120, 0\" />\n          </layout_hint>\n        </text>\n        <button style=\"_common_default_style_button_transparent\" id=\"button_video_page_control_trigger\">\n          <layout_hint>\n            <resolution id=\"landscape\" size=\"960, 544\" />\n            <resolution id=\"full_hd\" size=\"1920, 1088\" />\n          </layout_hint>\n          <focus_hint enable=\"0\" />\n        </button>\n        <plane_button style=\"style_button_video_big_repeat\" id=\"button_video_page_whole_repeat\">\n          <layout_hint>\n            <resolution id=\"landscape\" size=\"90, 90\" />\n            <resolution id=\"full_hd\" size=\"180, 180\" />\n          </layout_hint>\n          <focus_hint enable=\"0\" />\n        </plane_button>\n        <plane texture=\"_common_texture_transparent\" id=\"plane_statindicator\">\n          <layout_hint anchor=\"1, 2\" align=\"1, 2\">\n            <resolution id=\"landscape\" size=\"1, 1\" pos=\"10, 10\" />\n            <resolution id=\"full_hd\" size=\"1, 1\" pos=\"10, 10\" />\n          </layout_hint>\n        </plane>\n        <plane style=\"style_plane_video_page_control_bg\" texture=\"_common_texture_option_menu_button_top\" id=\"plane_video_control_panel_bg\">\n          <layout_hint anchor=\"0, 1\">\n            <resolution id=\"landscape\" size=\"790, 56\" pos=\"0, 28\" />\n            <resolution id=\"full_hd\" size=\"1700, 112\" pos=\"0, 56\" />\n          </layout_hint>\n          <progressbar_touch style=\"style_video_control_panel_progressbar\" id=\"progressbar_touch_video_control_panel\">\n            <layout_hint>\n              <resolution id=\"landscape\" size=\"538, 10\" pos=\"14, 0\" />\n              <resolution id=\"full_hd\" size=\"1400, 20\" pos=\"0, 0\" />\n            </layout_hint>\n            <text style=\"style_text_video_control_panel_progressbar_label_green\" id=\"text_video_control_panel_progressbar_label_elapsed\" >\n              <layout_hint adjust=\"2, 2\" anchor=\"1, 0\" align=\"2, 0\" >\n                <resolution id=\"landscape\" pos=\"-20, 12\" />\n                <resolution id=\"full_hd\" pos=\"-20, 20\" />\n              </layout_hint>\n            </text>\n            <text style=\"style_text_video_control_panel_progressbar_label_white\" id=\"text_video_control_panel_progressbar_label_total\" >\n              <layout_hint adjust=\"2, 2\" anchor=\"1, 0\" align=\"2, 0\" >\n                <resolution id=\"landscape\" pos=\"-20, -12\" />\n                <resolution id=\"full_hd\" pos=\"-20, -20\" />\n              </layout_hint>\n            </text>\n            <plane_button style=\"style_button_video_control_panel\" id=\"button_video_control_panel_playpause\">\n              <layout_hint anchor=\"2, 0\" align=\"1, 0\" >\n                <resolution id=\"landscape\" pos=\"32, 0\" size=\"48, 80\" />\n                <resolution id=\"full_hd\" pos=\"30, 0\" size=\"90, 80\" />\n              </layout_hint>\n              <focus_hint enable=\"0\" />\n            </plane_button>\n          </progressbar_touch>\n        </plane>\n        <corner_button style=\"_common_style_corner_bottom_left\" id=\"button_back_page_player_simple\" />\n      </plane>\n    </page>\n  \n  </pagetable>\n  \n  <styletable>\n  \n    <!-- option menu styles -->\n    <style_button sound=\"_common_sound_button_enter\" bottom_margin=\"12\" right_margin=\"20\" top_margin=\"12\" left_margin=\"20\" label_obj=\"label_obj1\" bg_obj=\"plane_obj1\" glow_obj=\"plane_obj2\" id=\"style_button_option_single\">\n      <planeobj texture0=\"_common_texture_option_menu_button_single\" id=\"plane_obj1\" />\n      <textobj font_size=\"28\" bold=\"1\" align_y=\"1\" align_x=\"3\" id=\"label_obj1\" />\n      <planeobj texture0=\"_common_texture_option_menu_button_single_glow\" blend=\"2\" id=\"plane_obj2\" />\n    </style_button>\n    <style_button sound=\"_common_sound_button_enter\" bottom_margin=\"12\" right_margin=\"20\" top_margin=\"12\" left_margin=\"20\" label_obj=\"label_obj1\" bg_obj=\"plane_obj1\" glow_obj=\"plane_obj2\" id=\"style_button_option_top\">\n      <planeobj texture0=\"_common_texture_option_menu_button_top\" id=\"plane_obj1\" />\n      <textobj font_size=\"28\" bold=\"1\" align_y=\"1\" align_x=\"3\" id=\"label_obj1\" />\n      <planeobj texture0=\"_common_texture_option_menu_button_top_glow\" blend=\"2\" id=\"plane_obj2\" />\n    </style_button>\n    <style_button sound=\"_common_sound_button_enter\" bottom_margin=\"12\" right_margin=\"20\" top_margin=\"12\" left_margin=\"20\" label_obj=\"label_obj1\" bg_obj=\"plane_obj1\" glow_obj=\"plane_obj2\" id=\"style_button_option_bottom\">\n      <planeobj texture0=\"_common_texture_option_menu_button_bottom\" id=\"plane_obj1\" />\n      <textobj font_size=\"28\" bold=\"1\" align_y=\"1\" align_x=\"3\" id=\"label_obj1\" />\n      <planeobj texture0=\"_common_texture_option_menu_button_bottom_glow\" blend=\"2\" id=\"plane_obj2\" />\n    </style_button>\n    <style_button sound=\"_common_sound_button_enter\" bottom_margin=\"12\" right_margin=\"20\" top_margin=\"12\" left_margin=\"20\" label_obj=\"label_obj1\" bg_obj=\"plane_obj1\" glow_obj=\"plane_obj2\" id=\"style_button_option_middle\">\n      <planeobj texture0=\"_common_texture_option_menu_button_middle\" id=\"plane_obj1\" />\n      <textobj font_size=\"28\" bold=\"1\" align_y=\"1\" align_x=\"3\" id=\"label_obj1\" />\n      <planeobj texture0=\"_common_texture_option_menu_button_middle_glow\" blend=\"2\" id=\"plane_obj2\" />\n    </style_button>\n    <style_text textobj=\"text_obj1\" id=\"style_text_option_menu_ruler\">\n      <textobj font_size=\"28\" bold=\"1\" align_y=\"1\" align_x=\"3\" font_color=\"0, 0, 0, 0\" id=\"text_obj1\" />\n    </style_text>\n    \n    <!-- common stuff -->\n    <style_plane color=\"0, 0, 0, 1\" id=\"style_plane_black\" />\n    <style_busyindicator ball_color=\"0.78, 0.8, 0.85, 1\" ball_size=\"16\" id=\"style_busyindicator_big\" />\n  \n    <!-- top title bar text -->\n    <style_text textobj=\"text_obj1\" id=\"style_text_top_title_bar\">\n      <textobj font_size=\"32\" bold=\"1\" align_y=\"1\" align_x=\"1\" ellipsis=\"1\" id=\"text_obj1\" />\n    </style_text>\n  \n    <!-- generic list view -->\n    <style_list_view color=\"0, 0, 0, 0\" id=\"style_list_view_generic\" sbar_v_margin=\"6, 80, 9\" />\n  \n    <!-- generic list view item -->\n    <style_list_item color=\"1, 1, 1, 0\" id=\"style_list_view_item_generic\" />\n  \n    <!-- generic image button -->\n    <style_image_button layout_type_x=\"1\" layout_type_y=\"0\" color=\"1, 1, 1, 1\" glow_obj=\"plane_obj1\" label_obj=\"text_obj1\" bg_obj=\"plane_obj2\" image_obj=\"plane_obj3\" image_margin=\"10\" id=\"style_image_button_list_button\">\n      <planeobj texture0=\"_common_texture_list_70px\" id=\"plane_obj2\" />\n      <textobj font_size=\"28\" bold=\"1\" max_line_count=\"2\" enlarge_line_pitch=\"1\" line_pitch=\"28\" word_wrap=\"1\" ellipsis=\"1\" align_y=\"1\" id=\"text_obj1\" />\n      <planeobj scale_mode_y=\"3\" scale_mode_x=\"3\" size=\"102, 70\" id=\"plane_obj3\" />\n      <planeobj texture0=\"_common_texture_list_glow_70px\" blend=\"2\" id=\"plane_obj1\" />\n    </style_image_button>\n  \n    <!-- videoplayer control panel styles -->\n    <style_plane color=\"1, 1, 1, 0.5\" id=\"style_plane_video_page_control_bg\" />\n    <style_text textobj=\"text_obj1\" id=\"style_text_video_control_panel_progressbar_label_green\">\n      <textobj font_color=\"0.75, 1, 0.3, 1\" font_size=\"20\" id=\"text_obj1\" />\n    </style_text>\n    <style_text textobj=\"text_obj1\" id=\"style_text_video_control_panel_progressbar_label_white\">\n      <textobj font_size=\"20\" id=\"text_obj1\" />\n    </style_text>\n    <style_progressbar_touch base_obj=\"plane_obj1\" slider_obj=\"plane_obj2\" slider_glow_obj=\"plane_obj3\" glow_obj=\"plane_obj4\" bar_shadow_obj=\"plane_obj5\" shadow_margin=\"0, 0\" bar_fore_obj=\"plane_obj6\" shadow_offset=\"0, -5\" bar_back_obj=\"plane_obj7\" signal_obj=\"plane_obj8\" base_shadow_obj=\"plane_obj9\" id=\"style_video_control_panel_progressbar\">\n      <planeobj scale_mode_y=\"1\" texture0=\"_common_texture_progressbar_base\" id=\"plane_obj1\" />\n      <planeobj color=\"0.659, 1, 0, 1\" scale_mode_y=\"1\" texture0=\"_common_texture_progressbar_bar\" id=\"plane_obj6\" />\n      <planeobj scale_mode_y=\"1\" texture0=\"_common_texture_progressbar_bar_back\" id=\"plane_obj7\" />\n      <planeobj scale_mode_y=\"1\" texture0=\"_common_texture_progressbar_signal\" id=\"plane_obj8\" />\n      <planeobj texture0=\"_common_texture_progressbar_glow\" color=\"0.75, 1, 0, 1\" scale_mode_x=\"1\" scale_mode_y=\"1\" blend=\"2\" id=\"plane_obj4\" scale_value=\"2.5\" />\n      <planeobj color=\"1, 1, 1, 0.7\" scale_mode_y=\"1\" texture0=\"_common_texture_progressbar_shadow\" id=\"plane_obj9\" />\n      <planeobj color=\"0.612, 1, 0, 0.7\" scale_mode_y=\"1\" texture0=\"_common_texture_progressbar_shadow\" id=\"plane_obj5\" />\n      <planeobj texture0=\"_common_texture_progressbar_slider_glow\" color=\"0.659, 1, 0, 1\" scale_mode_x=\"1\" scale_mode_y=\"1\" id=\"plane_obj3\" scale_value=\"0.5, 0.5\" />\n      <planeobj scale_mode_y=\"1\" scale_mode_x=\"1\" texture0=\"_common_texture_progressbar_slider\" id=\"plane_obj2\" scale_value=\"0.5, 0.5\" />\n    </style_progressbar_touch>\n    <style_plane_button image_obj=\"plane_obj1\" glow_obj=\"plane_obj2\" id=\"style_button_video_control_panel\">\n      <planeobj scale_mode_y=\"1\" scale_mode_x=\"1\" texture0=\"tex_button_pause\" id=\"plane_obj1\" />\n      <planeobj texture0=\"_common_texture_icon_glow\" id=\"plane_obj2\" />\n    </style_plane_button>\n    <style_plane_button image_obj=\"plane_obj1\" glow_obj=\"plane_obj2\" sound=\"_common_sound_plane_button_enter\" id=\"style_button_video_big_repeat\">\n      <planeobj texture0=\"tex_button_big_repeat\" id=\"plane_obj1\" />\n      <planeobj texture0=\"_common_texture_icon_glow\" id=\"plane_obj2\" />\n    </style_plane_button>\n    <style_text textobj=\"text_obj1\" id=\"style_text_video_control_panel_acc_left\">\n      <textobj font_size=\"32\" bold=\"1\" align_y=\"0\" align_x=\"0\" ellipsis=\"1\" id=\"text_obj1\" />\n    </style_text>\n    <style_text textobj=\"text_obj1\" id=\"style_text_video_control_panel_acc_right\">\n      <textobj font_size=\"32\" bold=\"1\" align_y=\"0\" align_x=\"0\" ellipsis=\"1\" id=\"text_obj1\" />\n    </style_text>\n\n    <!-- hvdb browser styles -->\n    <style_list_view color=\"0, 0, 0, 0\" id=\"style_list_view_hvdb\" sbar_v_margin=\"6, 29, 9\" />\n    <style_image_button layout_type_x=\"1\" color=\"1, 1, 1, 1\" glow_obj=\"plane_obj1\" label_obj=\"text_obj1\" bg_obj=\"plane_obj2\" image_obj=\"plane_obj3\" image_margin=\"10\" id=\"style_image_button_list_button_hvdb\">\n      <planeobj texture0=\"_common_texture_list_70px\" id=\"plane_obj2\" />\n      <textobj font_size=\"28\" bold=\"1\" max_line_count=\"2\" line_space=\"-28\" word_wrap=\"1\" ellipsis=\"1\" id=\"text_obj1\" />\n      <planeobj scale_mode_y=\"3\" scale_mode_x=\"3\" size=\"120, 90\" id=\"plane_obj3\" />\n      <planeobj texture0=\"_common_texture_list_glow_70px\" blend=\"2\" id=\"plane_obj1\" />\n    </style_image_button>\n    <style_image_button layout_type_x=\"1\" color=\"1, 1, 1, 1\" glow_obj=\"plane_obj1\" label_obj=\"text_obj1\" bg_obj=\"plane_obj2\" image_obj=\"plane_obj3\" image_margin=\"10\" id=\"style_image_button_list_button_hvdb_aligned\">\n      <planeobj texture0=\"_common_texture_list_70px\" id=\"plane_obj2\" />\n      <textobj font_size=\"28\" bold=\"1\" ellipsis=\"1\" align_y=\"1\" id=\"text_obj1\" />\n      <planeobj scale_mode_y=\"3\" scale_mode_x=\"3\" size=\"120, 90\" id=\"plane_obj3\" />\n      <planeobj texture0=\"_common_texture_list_glow_70px\" blend=\"2\" id=\"plane_obj1\" />\n    </style_image_button>\n    <style_text textobj=\"text_obj1\" id=\"style_text_list_button_hvdb_subtext\">\n      <textobj font_size=\"20\" font_color=\"0.9, 0.9, 0.9, 1\" bold=\"1\" ellipsis=\"1\" max_line_count=\"2\" line_space=\"0\" id=\"text_obj1\" />\n    </style_text>\n    \n    <!-- youtube browser styles -->\n    <style_list_view color=\"0, 0, 0, 0\" id=\"style_list_view_youtube\" sbar_v_margin=\"6, 29, 9\" />\n    <style_button sound=\"_common_sound_button_enter\" glow_obj=\"plane_obj1\" bg_obj=\"plane_obj2\" id=\"style_button_yt_search\">\n      <planeobj texture0=\"tex_yt_icon_search\" scale_mode_y=\"1\" scale_mode_x=\"1\" id=\"plane_obj2\" />\n      <planeobj texture0=\"_common_texture_copy_paste_menu_button_middle_glow\" blend=\"1\" id=\"plane_obj1\" />\n    </style_button>\n    <style_button sound=\"_common_sound_button_enter\" glow_obj=\"plane_obj1\" bg_obj=\"plane_obj2\" id=\"style_button_yt_history\">\n      <planeobj texture0=\"tex_yt_icon_history\" scale_mode_y=\"1\" scale_mode_x=\"1\" id=\"plane_obj2\" />\n      <planeobj texture0=\"_common_texture_copy_paste_menu_button_middle_glow\" blend=\"1\" id=\"plane_obj1\" />\n    </style_button>\n    <style_button sound=\"_common_sound_button_enter\" glow_obj=\"plane_obj1\" bg_obj=\"plane_obj2\" id=\"style_button_yt_favourite\">\n      <planeobj texture0=\"tex_yt_icon_favourite\" scale_mode_y=\"1\" scale_mode_x=\"1\" id=\"plane_obj2\" />\n      <planeobj texture0=\"_common_texture_copy_paste_menu_button_middle_glow\" blend=\"1\" id=\"plane_obj1\" />\n    </style_button>\n    <style_text_box sound=\"_common_sound_text_box\" glowobj=\"plane_obj1\" planeobj=\"plane_obj2\" top_margin=\"6\" right_margin=\"16\" left_margin=\"16\" textobj=\"text_obj1\" id=\"style_text_box_top_youtube_search\">\n      <textobj color=\"1, 1, 1, 1\" word_wrap=\"0\" font_size=\"28\" ellipsis=\"1\" id=\"text_obj1\" />\n      <planeobj texture0=\"_common_texture_text_box\" id=\"plane_obj2\" />\n      <planeobj texture0=\"_common_texture_checkbox_textbox_glow\" blend=\"2\" id=\"plane_obj1\" />\n    </style_text_box>\n    <style_image_button sound=\"_common_sound_image_button\" image_obj=\"plane_obj1\" image_back_obj=\"plane_obj2\" glow_obj=\"plane_obj3\" id=\"style_button_yt_top_search\">\n      <planeobj scale_mode_y=\"1\" scale_mode_x=\"1\" scale_value=\"1, 1\" texture0=\"tex_yt_icon_search\" id=\"plane_obj1\" />\n      <planeobj texture0=\"_common_texture_button\" id=\"plane_obj2\" />\n      <planeobj texture0=\"_common_texture_button_glow\" blend=\"2\" id=\"plane_obj3\" />\n    </style_image_button>\n    <style_image_button layout_type_x=\"1\" color=\"1, 1, 1, 1\" glow_obj=\"plane_obj1\" label_obj=\"text_obj1\" bg_obj=\"plane_obj2\" image_obj=\"plane_obj3\" image_margin=\"10\" id=\"style_image_button_list_button_youtube\">\n      <planeobj texture0=\"_common_texture_list_70px\" id=\"plane_obj2\" />\n      <textobj font_size=\"28\" bold=\"1\" max_line_count=\"2\" line_space=\"-28\" word_wrap=\"1\" ellipsis=\"1\" id=\"text_obj1\" />\n      <planeobj scale_mode_y=\"3\" scale_mode_x=\"3\" size=\"120, 90\" id=\"plane_obj3\" />\n      <planeobj texture0=\"_common_texture_list_glow_70px\" blend=\"2\" id=\"plane_obj1\" />\n    </style_image_button>\n    <style_image_button layout_type_x=\"1\" color=\"1, 1, 1, 1\" glow_obj=\"plane_obj1\" label_obj=\"text_obj1\" bg_obj=\"plane_obj2\" image_obj=\"plane_obj3\" image_margin=\"10\" id=\"style_image_button_list_button_youtube_aligned\">\n      <planeobj texture0=\"_common_texture_list_70px\" id=\"plane_obj2\" />\n      <textobj font_size=\"28\" bold=\"1\" ellipsis=\"1\" align_y=\"1\" id=\"text_obj1\" />\n      <planeobj scale_mode_y=\"3\" scale_mode_x=\"3\" size=\"120, 90\" id=\"plane_obj3\" />\n      <planeobj texture0=\"_common_texture_list_glow_70px\" blend=\"2\" id=\"plane_obj1\" />\n    </style_image_button>\n    <style_text textobj=\"text_obj1\" id=\"style_text_list_button_youtube_time\">\n      <textobj font_size=\"16\" ellipsis=\"1\" align_y=\"1\" back_color=\"0, 0, 0, 0.5\" id=\"text_obj1\" />\n    </style_text>\n    <style_text textobj=\"text_obj1\" id=\"style_text_list_button_youtube_subtext\">\n      <textobj font_size=\"20\" font_color=\"0.9, 0.9, 0.9, 1\" bold=\"1\" ellipsis=\"1\" max_line_count=\"2\" line_space=\"0\" id=\"text_obj1\" />\n    </style_text>\n    \n    <!-- youtube player styles -->\n    <style_text textobj=\"text_obj1\" id=\"style_text_youtube_video_title\">\n      <textobj font_size=\"26\" bold=\"1\" ellipsis=\"1\" id=\"text_obj1\" />\n    </style_text>\n    <style_text textobj=\"text_obj1\" id=\"style_text_youtube_video_stat\">\n      <textobj font_size=\"20\" bold=\"1\" ellipsis=\"1\" id=\"text_obj1\" />\n    </style_text>\n    <style_text textobj=\"text_obj1\" id=\"style_text_youtube_video_stat_right_align\">\n      <textobj font_size=\"20\" bold=\"1\" ellipsis=\"1\" align_x=\"2\" id=\"text_obj1\" />\n    </style_text>\n    <style_text textobj=\"text_obj1\" id=\"style_text_youtube_companel\">\n      <textobj font_size=\"20\" ellipsis=\"1\" word_wrap=\"1\" id=\"text_obj1\" />\n    </style_text>\n    <style_image_button sound=\"_common_sound_image_button\" image_obj=\"plane_obj1\" image_back_obj=\"plane_obj2\" glow_obj=\"plane_obj3\" id=\"style_button_yt_expand\">\n      <planeobj scale_mode_y=\"1\" scale_mode_x=\"1\" scale_value=\"1, 1\" texture0=\"tex_button_expand\" id=\"plane_obj1\" />\n      <planeobj texture0=\"_common_texture_button\" id=\"plane_obj2\" />\n      <planeobj texture0=\"_common_texture_button_glow\" blend=\"2\" id=\"plane_obj3\" />\n    </style_image_button>\n    <style_image_button sound=\"_common_sound_image_button\" image_obj=\"plane_obj1\" image_back_obj=\"plane_obj2\" glow_obj=\"plane_obj3\" id=\"style_button_yt_settings\">\n      <planeobj scale_mode_y=\"1\" scale_mode_x=\"1\" scale_value=\"1, 1\" texture0=\"tex_button_settings\" id=\"plane_obj1\" />\n      <planeobj texture0=\"_common_texture_button\" id=\"plane_obj2\" />\n      <planeobj texture0=\"_common_texture_button_glow\" blend=\"2\" id=\"plane_obj3\" />\n    </style_image_button>\n    <style_image_button sound=\"_common_sound_image_button\" image_obj=\"plane_obj1\" image_back_obj=\"plane_obj2\" glow_obj=\"plane_obj3\" id=\"style_button_yt_fav\">\n      <planeobj scale_mode_y=\"1\" scale_mode_x=\"1\" scale_value=\"0.8, 0.8\" texture0=\"tex_yt_icon_favourite_for_player\" id=\"plane_obj1\" />\n      <planeobj texture0=\"_common_texture_button\" id=\"plane_obj2\" />\n      <planeobj texture0=\"_common_texture_button_glow\" blend=\"2\" id=\"plane_obj3\" />\n    </style_image_button>\n    <style_plane color=\"0, 0, 0, 0.5\" id=\"style_plane_youtube_loader\" />\n    <style_button bottom_margin=\"12\" glow_obj=\"plane_obj2\" right_margin=\"20\" top_margin=\"12\" left_margin=\"20\" label_obj=\"text_obj1\" bg_obj=\"plane_obj1\" id=\"style_button_yt_companel\">\n      <planeobj texture0=\"_common_texture_transparent\" id=\"plane_obj1\" />\n      <textobj font_size=\"26\" bold=\"1\" align_y=\"1\" align_x=\"1\" adjust_x=\"1\" adjust_y=\"1\" id=\"text_obj1\" />\n      <planeobj texture0=\"_common_texture_copy_paste_menu_button_middle_glow\" blend=\"1\" id=\"plane_obj2\" />\n    </style_button>\n    <style_list_view color=\"0, 0, 0, 0\" id=\"style_list_view_companel\" sbar_v_margin=\"6, 80, 9\" />\n    <style_scroll_view color=\"0, 0, 0, 0\" id=\"style_scroll_view_companel\" sbar_v_margin=\"6, 56, 4\"/>\n    <style_button sound=\"_common_sound_button_enter\" label_obj=\"text_obj1\" bg_obj=\"plane_obj1\" glow_obj=\"plane_obj2\" bottom_margin=\"8\" right_margin=\"8\" top_margin=\"8\" left_margin=\"8\" id=\"style_button_yt_comment\">\n      <planeobj texture0=\"_common_texture_copy_paste_menu_button_middle\" id=\"plane_obj1\" />\n      <planeobj texture0=\"_common_texture_copy_paste_menu_button_middle_glow\" blend=\"2\" id=\"plane_obj2\" />\n      <textobj font_size=\"20\" ellipsis=\"1\" word_wrap=\"1\" max_line_count=\"2\" id=\"text_obj1\" />\n    </style_button>\n    <style_button sound=\"_common_sound_button_enter\" label_obj=\"text_obj1\" bg_obj=\"plane_obj1\" glow_obj=\"plane_obj2\" id=\"style_button_yt_quality_select\">\n      <planeobj texture0=\"_common_texture_list_70px\" id=\"plane_obj1\" />\n      <planeobj texture0=\"_common_texture_list_glow_70px\" blend=\"2\" id=\"plane_obj2\" />\n      <textobj align_y=\"1\" align_x=\"1\" shadow=\"1\" font_size=\"28f\" bold=\"1\" id=\"text_obj1\" />\n    </style_button>\n\n  </styletable>\n  \n  <templatetable>\n  \n    <!-- option menu templates -->\n    <template fast_open=\"1\" id=\"template_option_menu_base\">\n      <button sound=\"_common_sound_button_back\" style=\"_common_default_style_button_transparent\" id=\"button_option_menu_close\">\n        <layout_hint size=\"960, 544\" />\n        <focus_hint enable=\"0\" />\n        <plane style=\"_common_default_style_plane\" texture=\"_common_texture_option_menu_base_down\" id=\"plane_option_menu_base\">\n          <layout_hint anchor=\"0, 1\" align=\"0, 1\" size=\"214, 12\" pos=\"1920, 1080\" />\n          <text style=\"style_text_option_menu_ruler\" id=\"text_option_menu_ruler\">\n            <layout_hint size=\"0, 0\" adjust=\"2, 2\" pos=\"1920, 1080\" />\n          </text>\n          <box id=\"box_option_menu\">\n            <layout_box anchor=\"1, 2\" align=\"1, 2\" layout_type=\"1\" bottom_margin=\"6\" top_margin=\"6\" right_margin=\"6\" left_margin=\"6\" />\n          </box>\n        </plane>\n      </button>\n    </template>\n    <template fast_open=\"1\" id=\"template_option_menu_button_single\">\n      <button style=\"style_button_option_single\" id=\"button_option_menu_single\" >\n        <layout_hint size=\"202, 60\" />\n      </button>\n    </template>\n    <template fast_open=\"1\" id=\"template_option_menu_button_top\">\n      <button style=\"style_button_option_top\" id=\"button_option_menu_top\" >\n        <layout_hint size=\"202, 60\" />\n      </button>\n    </template>\n    <template fast_open=\"1\" id=\"template_option_menu_button_bottom\">\n      <button style=\"style_button_option_bottom\" id=\"button_option_menu_bottom\" >\n        <layout_hint size=\"202, 60\" />\n      </button>\n    </template>\n    <template fast_open=\"1\" id=\"template_option_menu_button_middle\">\n      <button style=\"style_button_option_middle\" id=\"button_option_menu_middle\" >\n        <layout_hint size=\"202, 60\" />\n        <focus_hint focus_shape=\"2\" />\n      </button>\n    </template>\n    \n    <!-- top title bar template -->\n    <template fast_open=\"1\" id=\"template_top_title_bar\">\n      <plane style=\"_common_style_plane_transparent\" id=\"plane_top\">\n        <layout_hint align=\"0, 2\" size=\"960, 64\" pos=\"0, 240\" />\n        <box style=\"_common_default_style_box\" id=\"box_top\">\n          <layout_box space=\"0\" align=\"0, 0\" pos=\"0, 0\" adjust=\"2, 2\" layout_type=\"2\" size=\"0, 0\" />\n          <text style=\"style_text_top_title_bar\" auto_scroll=\"1\" id=\"text_top\">\n            <layout_hint size=\"760, 0\" align=\"0, 4\" adjust=\"0, 2\" pos=\"0, 0\" />\n          </text>\n        </box>\n        <plane texture=\"_common_texture_ruled_line\" id=\"plane_top_separator\">\n          <layout_hint size=\"960, 2\" pos=\"0, 0\" anchor=\"0, 1\" />\n        </plane>\n      </plane>\n    </template>\n  \n    <!-- generic list item template (image button) -->\n    <template fast_open=\"1\" id=\"template_list_item_generic\">\n      <list_item style=\"style_list_view_item_generic\" id=\"list_item_generic\">\n        <layout_hint size=\"960, 80\" />\n        <image_button sound=\"_common_sound_image_button\" enable_long_press_text_auto_scroll=\"1\" style=\"style_image_button_list_button\" id=\"image_button_list_item\">\n          <focus_hint focus_shape=\"3\" />\n          <layout_hint size=\"840, 80\" />\n        </image_button>\n      </list_item>\n    </template>\n  \n    <!-- generic list view template -->\n    <template fast_open=\"1\" id=\"template_list_view_generic\">\n      <list_view style=\"style_list_view_generic\" id=\"list_view_generic\">\n        <layout_hint align=\"0, 1\" size=\"960, 448\" pos=\"0, -272\" />\n      </list_view>\n    </template>\n\n    <!-- hvdb list view templates -->\n    <template fast_open=\"1\" id=\"template_list_view_hvdb_fav\">\n      <plane style=\"_common_style_plane_transparent\" id=\"plane_list_view_hvdb_fav_root\">\n        <layout_hint size=\"960, 544\" pos=\"0, 0\" />\n        <list_view style=\"style_list_view_hvdb\" id=\"list_view_hvdb\">\n          <layout_hint anchor=\"0, 2\" align=\"0, 2\" size=\"960, 397\" pos=\"0, -96\" />\n        </list_view>\n      </plane>\n    </template>\n    <template fast_open=\"1\" id=\"template_list_item_hvdb\">\n      <list_item style=\"style_list_view_item_generic\" id=\"list_item_hvdb\">\n        <layout_hint size=\"960, 100\" />\n        <image_button sound=\"_common_sound_image_button\" enable_long_press_text_auto_scroll=\"1\" style=\"style_image_button_list_button_hvdb\" id=\"image_button_list_item_hvdb\">\n          <focus_hint focus_shape=\"3\" />\n          <layout_hint size=\"840, 100\" />\n          <text style=\"style_text_list_button_hvdb_time\" id=\"text_list_item_hvdb_time\">\n            <layout_hint align=\"1, 1\" anchor=\"1, 1\" adjust=\"2, 2\" pos=\"0, 5\" />\n          </text>\n          <text style=\"style_text_list_button_hvdb_subtext\" id=\"text_list_item_hvdb_subtext\">\n            <layout_hint align=\"1, 1\" anchor=\"1, 1\" adjust=\"2, 2\" pos=\"130, 5\" />\n          </text>\n        </image_button>\n      </list_item>\n    </template>\n    <template fast_open=\"1\" id=\"template_list_item_hvdb_aligned\">\n      <list_item style=\"style_list_view_item_generic\" id=\"list_item_hvdb_aligned\">\n        <layout_hint size=\"960, 100\" />\n        <image_button sound=\"_common_sound_image_button\" enable_long_press_text_auto_scroll=\"1\" style=\"style_image_button_list_button_hvdb_aligned\" id=\"image_button_list_item_hvdb_aligned\">\n          <focus_hint focus_shape=\"3\" />\n          <layout_hint size=\"840, 100\" />\n        </image_button>\n      </list_item>\n    </template>\n\n    <!-- youtube list view templates -->\n    <template fast_open=\"1\" id=\"template_list_view_youtube_search\">\n      <plane style=\"_common_style_plane_transparent\" id=\"plane_list_view_youtube_search_root\">\n        <layout_hint size=\"960, 544\" pos=\"0, 0\" />\n        <plane style=\"_common_style_plane_transparent\" id=\"plane_top_youtube_search\">\n          <layout_hint align=\"0, 2\" size=\"960, 64\" pos=\"0, 240\" />\n          <box style=\"_common_default_style_box\" id=\"box_top\">\n            <layout_box space=\"16\" align=\"0, 0\" pos=\"0, 0\" adjust=\"2, 2\" layout_type=\"2\" size=\"0, 0\" />\n            <text_box auto_scroll=\"1\" ime_type=\"0\" edit_mode=\"1\" paste_mode=\"1\" edit_auto_transition_mode=\"0\" style=\"style_text_box_top_youtube_search\" id=\"text_box_top_youtube_search\" >\n              <layout_hint pos=\"0, 8\" align=\"0, 4\" size=\"800, 44\" />\n              <focus_hint focus_shape=\"0\" />\n            </text_box>\n            <image_button style=\"style_button_yt_top_search\" id=\"button_top_youtube_search\">\n              <layout_hint size=\"102, 40\" pos=\"0, 2\" align=\"0, 4\" />\n            </image_button>\n          </box>\n          <plane texture=\"_common_texture_ruled_line\" id=\"plane_top_separator\">\n            <layout_hint size=\"960, 2\" pos=\"0, 0\" anchor=\"0, 1\" />\n          </plane>\n        </plane>\n        <list_view style=\"style_list_view_youtube\" id=\"list_view_youtube\">\n          <layout_hint anchor=\"0, 2\" align=\"0, 2\" size=\"960, 397\" pos=\"0, -96\" />\n        </list_view>\n      </plane>\n    </template>\n    <template fast_open=\"1\" id=\"template_list_view_youtube_history\">\n      <plane style=\"_common_style_plane_transparent\" id=\"plane_list_view_youtube_history_root\">\n        <layout_hint size=\"960, 544\" pos=\"0, 0\" />\n        <list_view style=\"style_list_view_youtube\" id=\"list_view_youtube\">\n          <layout_hint anchor=\"0, 2\" align=\"0, 2\" size=\"960, 397\" pos=\"0, -96\" />\n        </list_view>\n      </plane>\n    </template>\n    <template fast_open=\"1\" id=\"template_list_view_youtube_fav\">\n      <plane style=\"_common_style_plane_transparent\" id=\"plane_list_view_youtube_fav_root\">\n        <layout_hint size=\"960, 544\" pos=\"0, 0\" />\n        <plane style=\"_common_style_plane_transparent\" id=\"plane_top_youtube_fav\">\n          <layout_hint align=\"0, 2\" size=\"960, 64\" pos=\"0, 240\" />\n          <box style=\"_common_default_style_box\" id=\"box_top\">\n            <layout_box space=\"16\" align=\"0, 0\" pos=\"0, 0\" adjust=\"2, 2\" layout_type=\"2\" size=\"0, 0\" />\n            <text_box auto_scroll=\"1\" ime_type=\"0\" edit_mode=\"1\" paste_mode=\"1\" edit_auto_transition_mode=\"0\" style=\"style_text_box_top_youtube_search\" id=\"text_box_top_youtube_search\" >\n              <layout_hint pos=\"0, 8\" align=\"0, 4\" size=\"800, 44\" />\n              <focus_hint focus_shape=\"0\" />\n            </text_box>\n            <image_button style=\"style_button_yt_top_search\" id=\"button_top_youtube_search\">\n              <layout_hint size=\"102, 40\" pos=\"0, 2\" align=\"0, 4\" />\n            </image_button>\n          </box>\n          <plane texture=\"_common_texture_ruled_line\" id=\"plane_top_separator\">\n            <layout_hint size=\"960, 2\" pos=\"0, 0\" anchor=\"0, 1\" />\n          </plane>\n        </plane>\n        <list_view style=\"style_list_view_youtube\" id=\"list_view_youtube\">\n          <layout_hint anchor=\"0, 2\" align=\"0, 2\" size=\"960, 397\" pos=\"0, -96\" />\n        </list_view>\n      </plane>\n    </template>\n    <template fast_open=\"1\" id=\"template_list_item_youtube\">\n      <list_item style=\"style_list_view_item_generic\" id=\"list_item_youtube\">\n        <layout_hint size=\"960, 100\" />\n        <image_button sound=\"_common_sound_image_button\" enable_long_press_text_auto_scroll=\"1\" style=\"style_image_button_list_button_youtube\" id=\"image_button_list_item_youtube\">\n          <focus_hint focus_shape=\"3\" />\n          <layout_hint size=\"840, 100\" />\n          <text style=\"style_text_list_button_youtube_time\" id=\"text_list_item_youtube_time\">\n            <layout_hint align=\"1, 1\" anchor=\"1, 1\" adjust=\"2, 2\" pos=\"0, 5\" />\n          </text>\n          <text style=\"style_text_list_button_youtube_subtext\" id=\"text_list_item_youtube_subtext\">\n            <layout_hint align=\"1, 1\" anchor=\"1, 1\" adjust=\"2, 2\" pos=\"130, 5\" />\n          </text>\n        </image_button>\n      </list_item>\n    </template>\n    <template fast_open=\"1\" id=\"template_list_item_youtube_aligned\">\n      <list_item style=\"style_list_view_item_generic\" id=\"list_item_youtube_aligned\">\n        <layout_hint size=\"960, 100\" />\n        <image_button sound=\"_common_sound_image_button\" enable_long_press_text_auto_scroll=\"1\" style=\"style_image_button_list_button_youtube_aligned\" id=\"image_button_list_item_youtube_aligned\">\n          <focus_hint focus_shape=\"3\" />\n          <layout_hint size=\"840, 100\" />\n        </image_button>\n      </list_item>\n    </template>\n    <template fast_open=\"1\" id=\"template_list_view_youtube_companel\">\n      <list_view style=\"style_list_view_companel\" id=\"list_view_youtube_companel\">\n        <layout_hint anchor=\"1, 2\" align=\"1, 2\" size=\"414, 416\" pos=\"6, -54\" />\n      </list_view>\n    </template>\n    <template fast_open=\"1\" id=\"template_scroll_view_youtube_companel\">\n      <scroll_view style=\"style_scroll_view_companel\" id=\"scroll_view_youtube_companel\">\n        <layout_hint anchor=\"1, 2\" align=\"1, 2\" size=\"414, 416\" pos=\"6, -54\" />\n        <text style=\"style_text_youtube_companel\" id=\"text_youtube_companel\">\n          <layout_hint adjust=\"1, 2\" />\n        </text>\n      </scroll_view>\n    </template>\n    <template fast_open=\"1\" id=\"template_list_item_youtube_quality_select\">\n      <list_item style=\"style_list_view_item_generic\" id=\"list_item_youtube_quality_select\">\n        <layout_hint size=\"580, 70\" />\n        <button style=\"style_button_yt_quality_select\" id=\"button_yt_quality_select_item\">\n          <layout_hint adjust=\"1, 1\" />\n          <focus_hint focus_shape=\"3\" />\n        </button>\n      </list_item>\n    </template>\n    <template fast_open=\"1\" id=\"template_list_item_youtube_comment\">\n      <list_item style=\"style_list_view_item_generic\" id=\"list_item_youtube_comment\">\n        <layout_hint size=\"414, 70\" />\n        <button style=\"style_button_yt_comment\" id=\"button_yt_companel_comment_item\">\n          <layout_hint adjust=\"1, 1\" />\n          <focus_hint focus_shape=\"3\" />\n        </button>\n      </list_item>\n    </template>\n    <template fast_open=\"1\" id=\"template_scroll_item_youtube_comment_detail\">\n      <text style=\"style_text_youtube_companel\" id=\"text_youtube_comment_detail\">\n        <layout_hint adjust=\"1, 2\" />\n      </text>\n      <plane texture=\"_common_texture_ruled_line\" id=\"plane_comment_detail_separator\">\n        <layout_hint size=\"736, 2\" pos=\"0, 0\" />\n      </plane>\n      <text style=\"style_text_youtube_companel\" id=\"text_youtube_comment_detail_body\">\n        <layout_hint adjust=\"1, 2\" />\n      </text>\n    </template>\n\n  </templatetable>\n  \n  <stringtable>\n    <locale src=\"RES_RCO_TMP\\netstream_locale_ja.xml.rcs\" id=\"ja\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_en.xml.rcs\" id=\"en\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_en.xml.rcs\" id=\"en-gb\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_fr.xml.rcs\" id=\"fr\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_es.xml.rcs\" id=\"es\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_en.xml.rcs\" id=\"de\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_it.xml.rcs\" id=\"it\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_en.xml.rcs\" id=\"nl\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_pt.xml.rcs\" id=\"pt\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_pt-br.xml.rcs\" id=\"pt-br\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_ru.xml.rcs\" id=\"ru\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_en.xml.rcs\" id=\"ko\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_zh-t.xml.rcs\" id=\"zh-t\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_zh-s.xml.rcs\" id=\"zh-s\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_en.xml.rcs\" id=\"fi\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_en.xml.rcs\" id=\"sv\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_en.xml.rcs\" id=\"da\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_en.xml.rcs\" id=\"no\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_pl.xml.rcs\" id=\"pl\" />\n    <locale src=\"RES_RCO_TMP\\netstream_locale_en.xml.rcs\" id=\"tr\" />\n  </stringtable>\n  \n  <texturetable>\n    <texture origsize=\"4432\" src=\"texture\\tex_yt_icon_search.zlib\" type=\"texture/gim\" id=\"tex_yt_icon_search\" compress=\"on\" />\n    <texture origsize=\"4432\" src=\"texture\\tex_yt_icon_history.zlib\" type=\"texture/gim\" id=\"tex_yt_icon_history\" compress=\"on\" />\n    <texture origsize=\"4432\" src=\"texture\\tex_yt_icon_favourite.zlib\" type=\"texture/gim\" id=\"tex_yt_icon_favourite\" compress=\"on\" />\n    <texture origsize=\"2032\" src=\"texture\\tex_vertical_separator.zlib\" type=\"texture/gim\" id=\"tex_vertical_separator\" compress=\"on\" />\n    <texture origsize=\"10960\" src=\"texture\\tex_button_pause.zlib\" type=\"texture/gim\" id=\"tex_button_pause\" compress=\"on\" />\n    <texture origsize=\"10960\" src=\"texture\\tex_button_play.zlib\" type=\"texture/gim\" id=\"tex_button_play\" compress=\"on\" />\n    <texture origsize=\"33248\" src=\"texture\\tex_button_big_repeat.zlib\" type=\"texture/gim\" id=\"tex_button_big_repeat\" compress=\"on\" />\n    <texture origsize=\"5328\" src=\"texture\\tex_button_arrow_left.zlib\" type=\"texture/gim\" id=\"tex_button_arrow_left\" compress=\"on\" />\n    <texture origsize=\"5328\" src=\"texture\\tex_button_arrow_right.zlib\" type=\"texture/gim\" id=\"tex_button_arrow_right\" compress=\"on\" />\n    <texture origsize=\"5072\" src=\"texture\\tex_button_settings.zlib\" type=\"texture/gim\" id=\"tex_button_settings\" compress=\"on\" />\n    <texture src=\"texture\\tex_common_bg.png\" type=\"texture/png\" id=\"tex_common_bg\" />\n    <texture src=\"texture\\tex_fpmenu_icon_youtube.png\" type=\"texture/png\" id=\"tex_fpmenu_icon_youtube\" />\n    <texture src=\"texture\\tex_fpmenu_icon_http.png\" type=\"texture/png\" id=\"tex_fpmenu_icon_http\" />\n    <texture src=\"texture\\tex_fpmenu_icon_ftp.png\" type=\"texture/png\" id=\"tex_fpmenu_icon_ftp\" />\n    <texture src=\"texture\\tex_fpmenu_icon_local.png\" type=\"texture/png\" id=\"tex_fpmenu_icon_local\" />\n    <texture src=\"texture\\tex_fpmenu_icon_hvdb.png\" type=\"texture/png\" id=\"tex_fpmenu_icon_hvdb\" />\n    <texture src=\"texture\\tex_file_icon_video.png\" type=\"texture/png\" id=\"tex_file_icon_video\" />\n    <texture src=\"texture\\tex_file_icon_folder.png\" type=\"texture/png\" id=\"tex_file_icon_folder\" />\n    <texture src=\"texture\\tex_file_icon_playlist.png\" type=\"texture/png\" id=\"tex_file_icon_playlist\" />\n    <texture origsize=\"25728\" src=\"texture\\tex_file_icon_music.zlib\" type=\"texture/gim\" id=\"tex_file_icon_music\" compress=\"on\" />\n    <texture src=\"texture\\tex_file_icon_unsupported.png\" type=\"texture/png\" id=\"tex_file_icon_unsupported\" />\n    <texture src=\"texture\\tex_black.dds\" type=\"texture/dds\" id=\"tex_black\" />\n    <texture src=\"texture\\tex_button_expand.png\" type=\"texture/png\" id=\"tex_button_expand\" />\n    <texture src=\"texture\\tex_yt_icon_live_now.png\" type=\"texture/png\" id=\"tex_yt_icon_live_now\" />\n    <texture src=\"texture\\tex_yt_icon_fav_for_player.png\" type=\"texture/png\" id=\"tex_yt_icon_favourite_for_player\" />\n    <texture src=\"texture\\tex_yt_icon_fav_for_player_glow.png\" type=\"texture/png\" id=\"tex_yt_icon_favourite_for_player_glow\" />\n  </texturetable>\n  \n  <filetable>\n    <file src=\"file\\netstream_settings.xml\" type=\"application/xml\" id=\"file_netstream_settings\" />\n  </filetable>\n  \n</resource>"
  },
  {
    "path": "NetStream/gen_headers.bat",
    "content": "@echo off\nSET PLUGIN=netstream\nSET HASHGEN=%SCE_PSP2_SDK_DIR%/host_tools/build/rco/bin/psp2pafhashgen.exe\n\n\"%HASHGEN%\" -i \"RES_RCO\\%PLUGIN%_plugin.xml\" -o \"include\\%PLUGIN%_plugin.h\"\n\"%HASHGEN%\" -i \"RES_RCO\\file\\%PLUGIN%_settings.xml\" -o \"include\\%PLUGIN%_settings.h\"\n\"%HASHGEN%\" -i \"RES_RCO\\locale\\%PLUGIN%_locale_en.xml\" -o \"include\\%PLUGIN%_locale.h\""
  },
  {
    "path": "NetStream/gen_rco.bat",
    "content": "@echo off\nSET PLUGIN=netstream\nSET COMPILER=%SCE_PSP2_SDK_DIR%/host_tools/build/rco/bin/acdc.exe\nSET TMP=RES_RCO/RES_RCO_TMP\n\n@RD /S /Q \"%TMP%\"\nmkdir \"%TMP%\"\n\nfor %%f in (RES_RCO/locale/*.xml) do (\n\n\"%COMPILER%\" -c -i \"RES_RCO/locale/%%f\" -s \"%SCE_PSP2_SDK_DIR%/host_tools/build/rco/def/rcs.cxmldef\" -o \"%TMP%/%%f.rcs\"\n\n)\n\n\"%COMPILER%\" -c -i \"RES_RCO/%PLUGIN%_plugin.xml\" -s \"%SCE_PSP2_SDK_DIR%/host_tools/build/rco/def/rco.cxmldef\" -o \"CONTENTS/%PLUGIN%_plugin.rco\" -r \"CONTENTS/%PLUGIN%_plugin.rcd\""
  },
  {
    "path": "NetStream/include/browsers/ftp_server_browser.h",
    "content": "#ifndef _FTP_SERVER_BROWSER_H_\n#define _FTP_SERVER_BROWSER_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <psp2_compat/curl/curl.h>\n\n#include \"browsers/generic_server_browser.h\"\n\nusing namespace paf;\n\nclass FtpServerBrowser : public GenericServerBrowser\n{\npublic:\n\n\tFtpServerBrowser(const char *host, const char *port, const char *user, const char *password);\n\n\t~FtpServerBrowser();\n\n\tbool Probe();\n\n\tbool IsAtRoot(string *current);\n\n\tbool IsAtRoot();\n\n\tvoid SetPath(const char *ref);\n\n\tstring GetPath();\n\n\tvoid GetInfoForPlayer(string const& in, string& url, GenericPlayer::Option **opt);\n\n\tvector<FtpServerBrowser::Entry *> *GoTo(const char *ref, int32_t *result);\n\nprivate:\n\n\tstatic size_t DownloadCore(char *buffer, size_t size, size_t nitems, void *userdata);\n\n\tCURLU *m_url;\n\tCURL *m_curl;\n\tstring m_root;\n\tchar *m_buffer;\n\tuint32_t m_posInBuf;\n\tint32_t m_useNlst;\n};\n\n#endif"
  },
  {
    "path": "NetStream/include/browsers/generic_server_browser.h",
    "content": "#ifndef _GENERIC_SERVER_BROWSER_H_\n#define _GENERIC_SERVER_BROWSER_H_\n\n#include <kernel.h>\n#include <paf.h>\n\nusing namespace paf;\n\nclass GenericServerBrowser\n{\npublic:\n\n\tclass Entry\n\t{\n\tpublic:\n\n\t\tenum Type\n\t\t{\n\t\t\tType_UnsupportedFile,\n\t\t\tType_SupportedFile,\n\t\t\tType_PlaylistFile,\n\t\t\tType_Folder\n\t\t};\n\n\t\tstring ref;\n\t\tstring displayName;\n\t\tuint32_t type;\n\t};\n\n\tGenericServerBrowser()\n\t{\n\n\t}\n\n\tvirtual ~GenericServerBrowser()\n\t{\n\n\t}\n\n\tvirtual bool Probe() = 0;\n\n\tvirtual bool IsAtRoot(string *current) = 0;\n\n\tvirtual bool IsAtRoot() = 0;\n\n\tvirtual void SetPath(const char *ref) = 0;\n\n\tvirtual string GetPath() = 0;\n\n\tvirtual void GetInfoForPlayer(string const& in, string& url, GenericPlayer::Option **opt) = 0;\n\n\tvirtual vector<GenericServerBrowser::Entry *> *GoTo(const char *ref, int32_t *result) = 0;\n};\n\n#endif"
  },
  {
    "path": "NetStream/include/browsers/http_server_browser.h",
    "content": "#ifndef _HTTP_SERVER_BROWSER_H_\n#define _HTTP_SERVER_BROWSER_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <psp2_compat/curl/curl.h>\n\n#include \"browsers/generic_server_browser.h\"\n\nusing namespace paf;\n\nclass HttpServerBrowser : public GenericServerBrowser\n{\npublic:\n\n\tHttpServerBrowser(const char *host, const char *port, const char *user, const char *password);\n\n\t~HttpServerBrowser();\n\n\tbool Probe();\n\n\tbool IsAtRoot(string *current);\n\n\tbool IsAtRoot();\n\n\tvoid SetPath(const char *ref);\n\n\tstring GetPath();\n\n\tvoid GetInfoForPlayer(string const& in, string& url, GenericPlayer::Option **opt);\n\n\tvector<HttpServerBrowser::Entry *> *GoTo(const char *ref, int32_t *result);\n\nprivate:\n\n\tstatic size_t DownloadCore(char *buffer, size_t size, size_t nitems, void *userdata);\n\n\tCURLU *m_url;\n\tCURL *m_curl;\n\tstring m_root;\n\tchar *m_buffer;\n\tuint32_t m_posInBuf;\n};\n\n#endif"
  },
  {
    "path": "NetStream/include/browsers/hvdb_tracks_browser.h",
    "content": "#ifndef _HVDB_TRACKS_BROWSER_H_\n#define _HVDB_TRACKS_BROWSER_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <psp2_compat/curl/curl.h>\n\n#include \"browsers/generic_server_browser.h\"\n\nusing namespace paf;\n\nclass HvdbTracksBrowser : public GenericServerBrowser\n{\npublic:\n\n\tHvdbTracksBrowser(const char *workId, const char *workBannerUrl);\n\n\t~HvdbTracksBrowser();\n\n\tbool Probe();\n\n\tbool IsAtRoot(string *current);\n\n\tbool IsAtRoot();\n\n\tvoid SetPath(const char *ref);\n\n\tstring GetPath();\n\n\tvoid GetInfoForPlayer(string const& in, string& url, GenericPlayer::Option **opt);\n\n\tvector<HvdbTracksBrowser::Entry *> *GoTo(const char *ref, int32_t *result);\n\nprivate:\n\n\tvoid ParseRefString(const char *str, HVDBItem **item, uint32_t *idx);\n\n\tHVDBItem *GetItemAt(HVDBItem *firstItem, uint32_t idx);\n\n\tstring m_path;\n\tstring m_currentDataName;\n\tstring m_workId;\n\tstring m_bannerUrl;\n\tvoid *m_hvdbCtx;\n\tGenericPlayer::Option *m_option;\n};\n\n#endif"
  },
  {
    "path": "NetStream/include/browsers/local_server_browser.h",
    "content": "#ifndef _LOCAL_SERVER_BROWSER_H_\n#define _LOCAL_SERVER_BROWSER_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <psp2_compat/curl/curl.h>\n\n#include \"browsers/generic_server_browser.h\"\n\nusing namespace paf;\n\nclass LocalServerBrowser : public GenericServerBrowser\n{\npublic:\n\n\tstatic bool DefaultFsSort(const LocalServerBrowser::Entry* a, const LocalServerBrowser::Entry* b);\n\n\tLocalServerBrowser();\n\n\t~LocalServerBrowser();\n\n\tbool Probe();\n\n\tbool IsAtRoot(string *current);\n\n\tbool IsAtRoot();\n\n\tvoid SetPath(const char *ref);\n\n\tstring GetPath();\n\n\tvoid GetInfoForPlayer(string const& in, string& url, GenericPlayer::Option **opt);\n\n\tvector<LocalServerBrowser::Entry *> *GoTo(const char *ref, int32_t *result);\n\nprivate:\n\n\tstring m_path;\n};\n\n#endif"
  },
  {
    "path": "NetStream/include/common.h",
    "content": "#ifndef _COMMON_H_\n#define _COMMON_H_\n\n#include <paf.h>\n\n#include \"netstream_plugin.h\"\n#include \"netstream_settings.h\"\n#include \"netstream_locale.h\"\n\n#include \"menus/menu_settings.h\"\n\n#define USER_AGENT \"Mozilla/5.0 (PlayStation Vita 3.74) AppleWebKit/537.73 (KHTML, like Gecko) Silk/3.2\"\n\n#define NP_TUS_FAV_LOG_SLOT\t\t(2)\n#define NP_TUS_HIST_LOG_SLOT\t(1)\n\nusing namespace paf;\n\nextern Plugin *g_appPlugin;\n\nextern intrusive_ptr<graph::Surface> g_texCheckMark;\nextern intrusive_ptr<graph::Surface> g_texTransparent;\n\n#endif\n"
  },
  {
    "path": "NetStream/include/debug.h",
    "content": "#ifndef _DEBUG_H_\n#define _DEBUG_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#ifdef _DEBUG\n\n//#define DEBUG_MEM_HEAP\n//#define DEBUG_SURFACE_HEAP\n//#define DEBUG_JOB_QUEUE\n//#define DEBUG_EXTRA_TTY\n\nvoid InitDebug();\nvoid SetCurrentDebugParam(paf::Plugin *plugin, paf::ui::Scene *page);\nvoid SetPageDebugMode(paf::Plugin *plugin, paf::IDParam const& id, paf::Plugin::PageDebugMode mode, bool on);\n\n#endif\n\n#endif\n"
  },
  {
    "path": "NetStream/include/dialog.h",
    "content": "#ifndef _DIALOG_H_\n#define _DIALOG_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <common_gui_dialog.h>\n\nusing namespace paf;\n\nnamespace dialog\n{\n\tenum\n\t{\n\t\tDialogEvent = (ui::Handler::CB_STATE + 0x40000),\n\t};\n\n\tenum ButtonCode\n\t{\n\t\tButtonCode_X = 1,\n\t\tButtonCode_Ok,\n\t\tButtonCode_Cancel,\n\t\tButtonCode_Yes,\n\t\tButtonCode_No,\n\t\tButtonCode_Button1 = ButtonCode_Yes,\n\t\tButtonCode_Button2 = ButtonCode_No,\n\t\tButtonCode_Button3 = ButtonCode_Cancel\n\t};\n\n\tvoid OpenPleaseWait(Plugin *workPlugin, const wchar_t *titleText, const wchar_t *messageText, bool withCancel = false);\n\n\tvoid OpenYesNo(Plugin *workPlugin, const wchar_t *titleText, const wchar_t *messageTextL);\n\n\tvoid OpenOk(Plugin *workPlugin, const wchar_t *titleText, const wchar_t *messageText);\n\n\tvoid OpenError(Plugin *workPlugin, int32_t errorCode, const wchar_t *messageText = NULL);\n\n\tvoid OpenTwoButton(\n\t\tPlugin *workPlugin,\n\t\tconst wchar_t *titleText,\n\t\tconst wchar_t *messageText,\n\t\tuint32_t button1TextHashref,\n\t\tuint32_t button2TextHashref);\n\n\tvoid OpenThreeButton(\n\t\tPlugin *workPlugin,\n\t\tconst wchar_t *titleText,\n\t\tconst wchar_t *messageText,\n\t\tuint32_t button1TextHashref,\n\t\tuint32_t button2TextHashref,\n\t\tuint32_t button3TextHashref);\n\n\tui::ListView *OpenListView(\n\t\tPlugin *workPlugin,\n\t\tconst wchar_t *titleText);\n\n\tui::ScrollView *OpenScrollView(\n\t\tPlugin *workPlugin,\n\t\tconst wchar_t *titleText);\n\n\tvoid Close();\n\n\tvoid WaitEnd();\n\n\tbool IsActive();\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/include/downloader.h",
    "content": "#ifndef _ELEVENMPV_DOWNLOADER_H_\n#define _ELEVENMPV_DOWNLOADER_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <ipmi.h>\n#include <download_service.h>\n\nusing namespace paf;\n\nclass Downloader\n{\npublic:\n\n\tenum\n\t{\n\t\tDownloaderEvent = (ui::Handler::CB_STATE + 0x60000),\n\t};\n\n\tDownloader();\n\n\t~Downloader();\n\n\tint32_t Enqueue(Plugin *workPlugin, const char *url, const char *name);\n\n\tint32_t EnqueueAsync(Plugin *workPlugin, const char *url, const char *name);\n\nprivate:\n\n\tclass AsyncEnqueue : public job::JobItem\n\t{\n\tpublic:\n\n\t\tAsyncEnqueue(Plugin *workPlugin, Downloader *downloader, const char *url, const char *name) :\n\t\tjob::JobItem(\"Downloader::AsyncEnqueue\", NULL), m_plugin(workPlugin), m_downloader(downloader), m_url8(url), m_name8(name)\n\t\t{\n\n\t\t}\n\n\t\t~AsyncEnqueue() {}\n\n\t\tint32_t Run()\n\t\t{\n\t\t\tDownloader *pdownloader = (Downloader *)m_downloader;\n\t\t\tpdownloader->Enqueue(m_plugin, m_url8.c_str(), m_name8.c_str());\n\n\t\t\treturn SCE_PAF_OK;\n\t\t}\n\n\t\tvoid Finish(int32_t result) {}\n\n\tprivate:\n\n\t\tstring m_url8;\n\t\tstring m_name8;\n\t\tvoid *m_downloader;\n\t\tPlugin *m_plugin;\n\t};\n\n\tsce::Download dw;\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/include/event.h",
    "content": "#ifndef _EVENT_UTIL_H_\n#define _EVENT_UTIL_H_\n\n#include <kernel.h>\n#include <paf.h>\n\nusing namespace paf;\n\nnamespace event\n{\n\tvoid BroadcastGlobalEvent(Plugin *workPlugin, uint32_t type, int32_t d0 = 0, int32_t d1 = 0, int32_t d2 = 0, int32_t d3 = 0);\n};\n\n\n#endif\n"
  },
  {
    "path": "NetStream/include/ftpparse.h",
    "content": "#ifndef FTPPARSE_H\n#define FTPPARSE_H\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/*\nftpparse(&fp,buf,len) tries to parse one line of LIST output.\n\nThe line is an array of len characters stored in buf.\nIt should not include the terminating CR LF; so buf[len] is typically CR.\n\nIf ftpparse() can't find a filename, it returns 0.\n\nIf ftpparse() can find a filename, it fills in fp and returns 1.\nfp is a struct ftpparse, defined below.\nThe name is an array of fp.namelen characters stored in fp.name;\nfp.name points somewhere within buf.\n*/\n\nstruct ftpparse {\n  char *name; /* not necessarily 0-terminated */\n  int namelen;\n  int flagtrycwd; /* 0 if cwd is definitely pointless, 1 otherwise */\n  int flagtryretr; /* 0 if retr is definitely pointless, 1 otherwise */\n  int sizetype;\n  long size; /* number of octets */\n  int mtimetype;\n  time_t mtime; /* modification time */\n  int idtype;\n  char *id; /* not necessarily 0-terminated */\n  int idlen;\n} ;\n\n#define FTPPARSE_SIZE_UNKNOWN 0\n#define FTPPARSE_SIZE_BINARY 1 /* size is the number of octets in TYPE I */\n#define FTPPARSE_SIZE_ASCII 2 /* size is the number of octets in TYPE A */\n\n#define FTPPARSE_MTIME_UNKNOWN 0\n#define FTPPARSE_MTIME_LOCAL 1 /* time is correct */\n#define FTPPARSE_MTIME_REMOTEMINUTE 2 /* time zone and secs are unknown */\n#define FTPPARSE_MTIME_REMOTEDAY 3 /* time zone and time of day are unknown */\n/*\nWhen a time zone is unknown, it is assumed to be GMT. You may want\nto use localtime() for LOCAL times, along with an indication that the\ntime is correct in the local time zone, and gmtime() for REMOTE* times.\n*/\n\n#define FTPPARSE_ID_UNKNOWN 0\n#define FTPPARSE_ID_FULL 1 /* unique identifier for files on this FTP server */\n\nint ftpparse(struct ftpparse *,char *,int);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "NetStream/include/hvdb_utils.h",
    "content": "#ifndef _HVDBUTILS_H_\n#define _HVDBUTILS_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <ini_file_processor.h>\n\n#include \"yt_utils.h\"\n#include \"downloader.h\"\n\nusing namespace paf;\n\nnamespace hvdbutils\n{\n\tvoid Init();\n\n\tvoid Term();\n\n\tvoid Flush();\n\n\tint32_t EnqueueDownload(const char *url, const char *name);\n\n\tint32_t EnqueueDownloadAsync(const char *url, const char *name);\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/include/main.h",
    "content": "#ifndef _MAIN_H_\n#define _MAIN_H_\n\n#include <kernel.h>\n#include <paf.h>\n\nusing namespace paf;\n\nnamespace menu {\n\tnamespace main {\n\t\tclass NetcheckJob : public job::JobItem\n\t\t{\n\t\tpublic:\n\n\t\t\tenum Type\n\t\t\t{\n\t\t\t\tType_Initial,\n\t\t\t\tType_NpOnly\n\t\t\t};\n\n\t\t\tNetcheckJob(Type type) : job::JobItem(\"NS::NetcheckJob\", NULL), m_type(type)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~NetcheckJob() {}\n\n\t\t\tint32_t Run();\n\n\t\t\tvoid Finish(int32_t result) {}\n\n\t\tprivate:\n\n\t\t\tvoid OnDialogUserCancelEvent(int32_t type);\n\n\t\t\tType m_type;\n\t\t};\n\n\t\tint32_t OnNpDialogComplete(void *data);\n\t}\n}\n\n\n#endif\n"
  },
  {
    "path": "NetStream/include/menus/menu_first.h",
    "content": "#ifndef _MENU_FIRST_H_\n#define _MENU_FIRST_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"menu_generic.h\"\n\nusing namespace paf;\n\nnamespace menu {\n\n\tclass First : public GenericMenu\n\t{\n\tpublic:\n\n\t\tclass ListViewFactory : public ui::listview::ItemFactory\n\t\t{\n\t\tpublic:\n\n\t\t\tListViewFactory(menu::First *parent) : m_parent(parent)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~ListViewFactory()\n\t\t\t{\n\n\t\t\t}\n\n\t\t\tui::ListItem* Create(CreateParam& param)\n\t\t\t{\n\t\t\t\treturn m_parent->CreateListItem(param);\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tmenu::First *m_parent;\n\t\t};\n\n\t\tFirst();\n\n\t\t~First() override;\n\n\t\tui::ListItem* CreateListItem(ui::listview::ItemFactory::CreateParam& param);\n\n\t\tvoid OnListButton(ui::Widget *self);\n\n\t\tvoid SetOfflineMode();\n\n\t\tMenuType GetMenuType() override\n\t\t{\n\t\t\treturn MenuType_First;\n\t\t}\n\n\t\tconst uint32_t *GetSupportedSettingsItems(int32_t *count) override\n\t\t{\n\t\t\t*count = 0;\n\t\t\treturn nullptr;\n\t\t}\n\n\tprivate:\n\n\t\tbool m_showHvdb;\n\t\tui::ListView *m_rootList;\n\t};\n}\n\n#endif\n"
  },
  {
    "path": "NetStream/include/menus/menu_ftp.h",
    "content": "#ifndef _MENU_FTP_H_\n#define _MENU_FTP_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"dialog.h\"\n#include \"menu_server.h\"\n#include \"browsers/ftp_server_browser.h\"\n#include \"menus/menu_player_simple.h\"\n\nusing namespace paf;\n\nnamespace menu {\n\tclass Ftp : public GenericServerMenu\n\t{\n\tpublic:\n\n\t\tFtp()\n\t\t{\n\t\t\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\n\t\t\tchar host[256];\n\t\t\tchar port[32];\n\t\t\tchar user[256];\n\t\t\tchar password[256];\n\n\t\t\tsettings->GetString(\"ftp_host\", host, sizeof(host), \"\");\n\t\t\tsettings->GetString(\"ftp_port\", port, sizeof(port), \"\");\n\t\t\tsettings->GetString(\"ftp_user\", user, sizeof(user), \"\");\n\t\t\tsettings->GetString(\"ftp_password\", password, sizeof(password), \"\");\n\n\t\t\tm_browser = new FtpServerBrowser(host, port, user, password);\n\t\t}\n\n\t\tMenuType GetMenuType() override\n\t\t{\n\t\t\treturn MenuType_Ftp;\n\t\t}\n\n\t\tconst uint32_t *GetSupportedSettingsItems(int32_t *count) override\n\t\t{\n\t\t\t*count = sizeof(k_settingsIdList) / sizeof(char*);\n\t\t\treturn k_settingsIdList;\n\t\t}\n\n\tprivate:\n\n\t\tconst uint32_t k_settingsIdList[1] = {\n\t\t\tftp_setting\n\t\t};\n\t};\n}\n\n#endif"
  },
  {
    "path": "NetStream/include/menus/menu_generic.h",
    "content": "#ifndef _MENU_GENERIC_H_\n#define _MENU_GENERIC_H_\n\n#include <kernel.h>\n#include <paf.h>\n\nusing namespace paf;\n\nnamespace menu {\n\n\tenum MenuType\n\t{\n\t\tMenuType_First,\t\t\t// Initial menu that is displayed after application boot\n\t\tMenuType_Http,\t\t\t// HTTP server menu\n\t\tMenuType_Ftp,\t\t\t// FTP server menu\n\t\tMenuType_Local,\t\t\t// Local file browser menu\n\t\tMenuType_Youtube,\t\t// YouTube menu\n\t\tMenuType_Hvdb,\t\t\t// HVDB menu\n\t\tMenuType_PlayerSimple,\t// Simple Player menu (simple fullscreen player)\n\t\tMenuType_PlayerYouTube,\t// YouTube Player menu (description/comments etc.),\n\t\tMenuType_HvdbTracks\t\t// HVDB tracks browser menu\n\t};\n\n\t/**\n\t * Opens settings menu\n\t *\n\t * @param[in] type - PAF event type\n\t * @param[in] self - PAF widget event issuer\n\t * @param[in] e - PAF event object\n\t * @param[in] userdata - Event userdata\n\t */\n\tvoid SettingsButtonCbFun(int32_t type, ui::Handler *self, ui::Event *e, void *userdata);\n\n\t/**\n\t * Parameters that will be used for creating/opening the menu\n\t */\n\tclass MenuOpenParam : public Plugin::PageOpenParam\n\t{\n\tpublic:\n\n\t\t/**\n\t\t * @param[in] useFadeIn - when true, menu fades in\n\t\t * @param[in] fadeinTimeMs - fadein time in milliseconds\n\t\t * @param[in] effectType - PAF transition effect, one of paf::Plugin::TransitionType, can be used in combination with fadein\n\t\t * @param[in] openFlags - PAF environment option flags, see paf::ui::EnvironmentParam\n\t\t * @param[in] priority - PAF menu priority (rendering order)\n\t\t */\n\t\tMenuOpenParam(\n\t\t\tbool useFadeIn = false,\n\t\t\tfloat fadeinTimeMs = 200.0f,\n\t\t\tPlugin::TransitionType effectType = Plugin::TransitionType_None,\n\t\t\tuint32_t openFlags = 0,\n\t\t\tint32_t priority = -1) :\n\t\t\tm_envOpt(nullptr)\n\t\t{\n\t\t\tfade = useFadeIn;\n\t\t\tfade_time_ms = fadeinTimeMs;\n\t\t\ttransition_type = effectType;\n\t\t\toverwrite_draw_priority = priority;\n\n\t\t\tif (openFlags != 0)\n\t\t\t{\n\t\t\t\tif ((openFlags & ui::EnvironmentParam::RESOLUTION_HD_HALF) == ui::EnvironmentParam::RESOLUTION_HD_HALF\n\t\t\t\t\t|| (openFlags & ui::EnvironmentParam::RESOLUTION_HD_FULL) == ui::EnvironmentParam::RESOLUTION_HD_FULL)\n\t\t\t\t{\n\t\t\t\t\tif (SCE_PAF_IS_DOLCE)\n\t\t\t\t\t{\n\t\t\t\t\t\tm_envOpt = new ui::EnvironmentParam(openFlags);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tm_envOpt = new ui::EnvironmentParam(openFlags);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tenv_param = m_envOpt;\n\t\t\tgraphics_flag = 0x80;\n\t\t}\n\n\t\t~MenuOpenParam()\n\t\t{\n\t\t\tdelete m_envOpt;\n\t\t}\n\n\tprivate:\n\n\t\tui::EnvironmentParam *m_envOpt;\t// PAF environment parameters object\n\t};\n\n\t/**\n\t * Parameters that will be used for closing the menu\n\t */\n\tclass MenuCloseParam : public Plugin::PageCloseParam\n\t{\n\tpublic:\n\n\t\t/**\n\t\t * @param[in] useFadeOut - when true, menu fades out\n\t\t * @param[in] fadeoutTimeMs - fadeout time in milliseconds\n\t\t * @param[in] effectType - PAF transition effect, one of paf::Plugin::TransitionType, can be used in combination with fadeout\n\t\t */\n\t\tMenuCloseParam(\n\t\t\tbool useFadeOut = false,\n\t\t\tfloat fadeoutTimeMs = 200.0f,\n\t\t\tPlugin::TransitionType effectType = Plugin::TransitionType_None)\n\t\t{\n\t\t\tfade = useFadeOut;\n\t\t\tfade_time_ms = fadeoutTimeMs;\n\t\t\ttransition_type = effectType;\n\t\t}\n\n\t\t~MenuCloseParam()\n\t\t{\n\n\t\t}\n\t};\n\n\t/**\n\t * Generic application menu. All other menus must inherit from this class\n\t */\n\tclass GenericMenu\n\t{\n\tpublic:\n\n\t\t/**\n\t\t * @param[in] name - Menu template name. Must match name used for the template in the plugin XML\n\t\t * @param[in] oparam - Menu open parameters\n\t\t * @param[in] cparam - Menu close parameters\n\t\t */\n\t\tGenericMenu(const char *, MenuOpenParam const& oparam, MenuCloseParam const& cparam);\n\n\t\tvirtual ~GenericMenu();\n\n\t\t/**\n\t\t * Activates the menu, enabling rendering and input for it\n\t\t */\n\t\tvirtual void Activate();\n\n\t\t/**\n\t\t * Deactivates the menu, disabling rendering and input for it\n\t\t *\n\t\t * @param[in] withDelay - When set to true, deactivation will be delayed by 200 milliseconds\n\t\t */\n\t\tvirtual void Deactivate(bool withDelay = false);\n\n\t\t/**\n\t\t * Disables user input for all menu elements\n\t\t */\n\t\tvirtual void DisableInput();\n\n\t\t/**\n\t\t * Enables user input for all menu elements\n\t\t */\n\t\tvirtual void EnableInput();\n\n\t\t/**\n\t\t * Get menu type\n\t\t *\n\t\t * @return menu type\n\t\t */\n\t\tvirtual MenuType GetMenuType() = 0;\n\n\t\t/**\n\t\t * Get supported settings menu items.\n\t\t *\n\t\t * @param[out] count - Number of items in the hash array\n\t\t *\n\t\t * @return pointer to the array of hashes of the names of supported settings items\n\t\t */\n\t\tvirtual const uint32_t *GetSupportedSettingsItems(int32_t *count) = 0;\n\n\t\t/**\n\t\t * Get menu root widget\n\t\t *\n\t\t * @return menu root scene widget\n\t\t */\n\t\tui::Scene *GetRoot() const;\n\n\tprotected:\n\n\t\tui::Scene *m_root;\t\t\t\t// Menu root scene widget\n\n\tprivate:\n\n\t\tMenuCloseParam m_closeParam;\t// Close parameters\n\t};\n\n\t/**\n\t * Initializes menu system\n\t */\n\tvoid InitMenuSystem();\n\n\t/**\n\t * Terminates menu system\n\t */\n\tvoid TermMenuSystem();\n\n\t/**\n\t * Get total count of currently opened menus\n\t *\n\t * @return count of currently opened menus\n\t */\n\tuint32_t GetMenuCount();\n\n\t/**\n\t * Get top menu\n\t *\n\t * @return pointer to the Menu object at the top of the menu stack\n\t */\n\tmenu::GenericMenu *GetTopMenu();\n\n\t/**\n\t * Get menu from the menu stack of currently opened menus\n\t *\n\t * @param[in] idx - Index of the menu in the menu stack\n\t *\n\t * @return pointer to the Menu object, or NULL if idx is invalid\n\t */\n\tmenu::GenericMenu *GetMenuAt(uint32_t idx);\n\n\t/**\n\t * Deactivate all opened menus, up to the margin.\n\t * Menus are deactivated starting from the top of the menu stack, with endMargin number\n\t * of menus remaining active at the bottom of the stack\n\t *\n\t * @param[in] endMargin - indicates how many menus from the bottom of the menu stack should be left active\n\t */\n\tvoid DeactivateAll(uint32_t endMargin = 0);\n\n\t/**\n\t * Activate all opened menus\n\t */\n\tvoid ActivateAll();\n}\n\n\n#endif"
  },
  {
    "path": "NetStream/include/menus/menu_http.h",
    "content": "#ifndef _MENU_HTTP_H_\n#define _MENU_HTTP_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"dialog.h\"\n#include \"menu_server.h\"\n#include \"browsers/http_server_browser.h\"\n\nusing namespace paf;\n\nnamespace menu {\n\tclass Http : public GenericServerMenu\n\t{\n\tpublic:\n\n\t\tHttp()\n\t\t{\n\t\t\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\n\t\t\tchar host[256];\n\t\t\tchar port[32];\n\t\t\tchar user[256];\n\t\t\tchar password[256];\n\n\t\t\tsettings->GetString(\"http_host\", host, sizeof(host), \"\");\n\t\t\tsettings->GetString(\"http_port\", port, sizeof(port), \"\");\n\t\t\tsettings->GetString(\"http_user\", user, sizeof(user), \"\");\n\t\t\tsettings->GetString(\"http_password\", password, sizeof(password), \"\");\n\n\t\t\tm_browser = new HttpServerBrowser(host, port, user, password);\n\t\t}\n\n\t\tMenuType GetMenuType() override\n\t\t{\n\t\t\treturn MenuType_Http;\n\t\t}\n\n\t\tconst uint32_t *GetSupportedSettingsItems(int32_t *count) override\n\t\t{\n\t\t\t*count = sizeof(k_settingsIdList) / sizeof(char*);\n\t\t\treturn k_settingsIdList;\n\t\t}\n\n\tprivate:\n\n\t\tconst uint32_t k_settingsIdList[1] = {\n\t\t\thttp_setting\n\t\t};\n\t};\n}\n\n#endif"
  },
  {
    "path": "NetStream/include/menus/menu_hvdb.h",
    "content": "#ifndef _MENU_HVDB_H_\n#define _MENU_HVDB_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"dialog.h\"\n#include \"tex_pool.h\"\n#include \"hvdb.h\"\n#include \"menu_generic.h\"\n\nusing namespace paf;\n\nnamespace menu {\n\tclass HVDB : public GenericMenu\n\t{\n\tpublic:\n\n\t\tclass Submenu\n\t\t{\n\t\tpublic:\n\n\t\t\tenum SubmenuType\n\t\t\t{\n\t\t\t\tSubmenuType_Favourites = 0x947652c2\n\t\t\t};\n\n\t\t\tSubmenu(HVDB *parentObj);\n\n\t\t\tvirtual ~Submenu();\n\n\t\t\tvirtual void ReleaseCurrentPage();\n\n\t\t\tvirtual void GoToNextPage() = 0;\n\n\t\t\tvirtual void GoToPrevPage() = 0;\n\n\t\t\tvirtual void GoToBasePageForSync() = 0;\n\n\t\t\tvirtual SubmenuType GetType() = 0;\n\n\t\t\tui::ListItem* CreateListItem(ui::listview::ItemFactory::CreateParam& param);\n\n\t\t\tclass ListViewCb : public ui::listview::ItemFactory\n\t\t\t{\n\t\t\tpublic:\n\n\t\t\t\tListViewCb(Submenu *parent) : m_parent(parent)\n\t\t\t\t{\n\n\t\t\t\t}\n\n\t\t\t\t~ListViewCb()\n\t\t\t\t{\n\n\t\t\t\t}\n\n\t\t\t\tui::ListItem *Create(CreateParam& param)\n\t\t\t\t{\n\t\t\t\t\treturn m_parent->CreateListItem(param);\n\t\t\t\t}\n\n\t\t\t\tvoid Start(StartParam& param)\n\t\t\t\t{\n\t\t\t\t\tparam.list_item->Show(common::transition::Type_Popup1);\n\t\t\t\t}\n\n\t\t\tprivate:\n\n\t\t\t\tSubmenu *m_parent;\n\t\t\t};\n\n\t\t\tclass Item\n\t\t\t{\n\t\t\tpublic:\n\n\t\t\t\tItem()\n\t\t\t\t{\n\n\t\t\t\t}\n\n\t\t\t\twstring name;\n\t\t\t\twstring stat;\n\t\t\t\tstring workId;\n\t\t\t\tstring bannerUrl;\n\t\t\t\tIDParam texId;\n\t\t\t\tTexPool *texPool;\n\t\t\t};\n\n\t\tprotected:\n\n\t\t\tHVDB *m_baseParent;\n\t\t\tui::Widget *m_submenuRoot;\n\t\t\tui::ListView *m_list;\n\t\t\tbool m_interrupted;\n\t\t\tbool m_allJobsComplete;\n\t\t\tvector<Item> m_results;\n\t\t\tuint32_t m_currentPage;\n\n\t\tprivate:\n\n\t\t\tstatic void OnTexPoolAdd(int32_t type, ui::Handler *self, ui::Event *e, void *userdata);\n\n\t\t\tvoid OnListButton(ui::Widget *wdg);\n\t\t};\n\n\t\tclass FavouriteSubmenu : public Submenu\n\t\t{\n\t\tpublic:\n\n\t\t\tclass FavouriteJob : public job::JobItem\n\t\t\t{\n\t\t\tpublic:\n\n\t\t\t\tFavouriteJob(FavouriteSubmenu *parent) : job::JobItem(\"HVDB::FavouriteJob\", NULL), m_parent(parent)\n\t\t\t\t{\n\n\t\t\t\t}\n\n\t\t\t\t~FavouriteJob() {}\n\n\t\t\t\tint32_t Run()\n\t\t\t\t{\n\t\t\t\t\tm_parent->ParseFavourite();\n\n\t\t\t\t\treturn SCE_PAF_OK;\n\t\t\t\t}\n\n\t\t\t\tvoid Finish(int32_t result) {}\n\n\t\t\tprivate:\n\n\t\t\t\tFavouriteSubmenu *m_parent;\n\t\t\t};\n\n\t\t\tFavouriteSubmenu(HVDB *parentObj);\n\n\t\t\t~FavouriteSubmenu();\n\n\t\t\tvoid ParseFavourite();\n\n\t\t\tvoid GoToNextPage();\n\n\t\t\tvoid GoToPrevPage();\n\n\t\t\tvoid GoToBasePageForSync();\n\n\t\t\tSubmenuType GetType()\n\t\t\t{\n\t\t\t\treturn SubmenuType_Favourites;\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tHVDBPaginationInfo m_pgi;\n\t\t};\n\n\t\tHVDB();\n\n\t\t~HVDB()  override;\n\n\t\tvoid SwitchSubmenu(Submenu::SubmenuType type);\n\n\t\tvoid Refresh();\n\n\t\tMenuType GetMenuType() override\n\t\t{\n\t\t\treturn MenuType_Hvdb;\n\t\t}\n\n\t\tconst uint32_t *GetSupportedSettingsItems(int32_t *count) override\n\t\t{\n\t\t\t*count = sizeof(k_settingsIdList) / sizeof(char*);\n\t\t\treturn k_settingsIdList;\n\t\t}\n\n\tprivate:\n\n\t\tvoid OnBackButton();\n\t\tvoid OnSubmenuButton(ui::Widget *wdg);\n\t\tvoid OnSettingsButton();\n\t\tvoid OnOptionMenuEvent(int32_t type, int32_t subtype);\n\n\t\tbool AuthMe();\n\n\t\tui::Widget *m_browserRoot;\n\t\tui::BusyIndicator *m_loaderIndicator;\n\t\tui::Text *m_topText;\n\t\tSubmenu *m_currentSubmenu;\n\t\tint32_t m_dialogIdx;\n\t\tTexPool *m_texPool;\n\n\t\tconst uint32_t k_settingsIdList[3] = {\n\t\t\thvdb_account_setting,\n\t\t\thvdb_search_setting,\n\t\t\thvdb_player_setting\n\t\t};\n\t};\n\n}\n\n#endif\n"
  },
  {
    "path": "NetStream/include/menus/menu_hvdb_tracks.h",
    "content": "#ifndef _MENU_HVDB_TRACKS_H_\n#define _MENU_HVDB_TRACKS_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"dialog.h\"\n#include \"menu_server.h\"\n#include \"browsers/hvdb_tracks_browser.h\"\n\nusing namespace paf;\n\nnamespace menu {\n\tclass HvdbTracks : public GenericServerMenu\n\t{\n\tpublic:\n\n\t\tHvdbTracks(const char *workId, const char *bannerUrl)\n\t\t{\n\t\t\tm_browser = new HvdbTracksBrowser(workId, bannerUrl);\n\t\t}\n\n\t\tMenuType GetMenuType() override\n\t\t{\n\t\t\treturn MenuType_HvdbTracks;\n\t\t}\n\n\t\tconst uint32_t *GetSupportedSettingsItems(int32_t *count) override\n\t\t{\n\t\t\t*count = sizeof(k_settingsIdList) / sizeof(char*);\n\t\t\treturn k_settingsIdList;\n\t\t}\n\n\tprivate:\n\n\t\tconst uint32_t k_settingsIdList[3] = {\n\t\t\thvdb_account_setting,\n\t\t\thvdb_search_setting,\n\t\t\thvdb_player_setting\n\t\t};\n\t};\n}\n\n#endif"
  },
  {
    "path": "NetStream/include/menus/menu_local.h",
    "content": "#ifndef _MENU_LOCAL_H_\n#define _MENU_LOCAL_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"dialog.h\"\n#include \"menu_server.h\"\n#include \"browsers/local_server_browser.h\"\n\nusing namespace paf;\n\nnamespace menu {\n\tclass Local : public GenericServerMenu\n\t{\n\tpublic:\n\n\t\tLocal()\n\t\t{\n\t\t\tm_browser = new LocalServerBrowser();\n\t\t}\n\n\t\tMenuType GetMenuType() override\n\t\t{\n\t\t\treturn MenuType_Local;\n\t\t}\n\n\t\tconst uint32_t *GetSupportedSettingsItems(int32_t *count) override\n\t\t{\n\t\t\t*count = sizeof(k_settingsIdList) / sizeof(char*);\n\t\t\treturn k_settingsIdList;\n\t\t}\n\n\tprivate:\n\n\t\tconst uint32_t k_settingsIdList[1] = {\n\t\t\tlocal_setting\n\t\t};\n\t};\n}\n\n#endif"
  },
  {
    "path": "NetStream/include/menus/menu_player_simple.h",
    "content": "#ifndef _MENU_PLAYER_SIMPLE_H_\n#define _MENU_PLAYER_SIMPLE_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"players/player_generic.h\"\n#include \"subs/subs_generic.h\"\n#include \"menu_generic.h\"\n#include \"menu_youtube.h\"\n\nusing namespace paf;\n\nnamespace menu {\n\tclass PlayerSimple : public GenericMenu\n\t{\n\tpublic:\n\n\t\tenum\n\t\t{\n\t\t\tPlayerSimpleEvent = (ui::Handler::CB_STATE + 0x10000),\n\t\t};\n\n\t\tenum PlayerEvent\n\t\t{\n\t\t\tPlayerEvent_InitFail,\n\t\t\tPlayerEvent_InitOk,\n\t\t\tPlayerEvent_Back\n\t\t};\n\n\t\tenum AccJumpState\n\t\t{\n\t\t\tAccJumpState_None,\n\t\t\tAccJumpState_Accumulate,\n\t\t\tAccJumpState_Perform\n\t\t};\n\n\t\tenum SettingsOverride\n\t\t{\n\t\t\tSettingsOverride_None,\n\t\t\tSettingsOverride_YouTube\n\t\t};\n\n\t\tclass PadListener : public inputdevice::InputListener\n\t\t{\n\t\tpublic:\n\n\t\t\tPadListener(PlayerSimple *parent) : InputListener(inputdevice::DEVICE_TYPE_PAD), m_parent(parent)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\tvoid OnUpdate(inputdevice::Data *data)\n\t\t\t{\n\t\t\t\tm_parent->OnPadUpdate(data);\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tPlayerSimple *m_parent;\n\t\t};\n\n\t\ttypedef void(*PlayerSimpleCallback)(PlayerSimple *player, void *pUserArg);\n\n\t\tPlayerSimple(const char *url, GenericPlayer::Option *opt = NULL, GenericSubtitles::Option *sopt = NULL);\n\n\t\t~PlayerSimple() override;\n\n\t\tGenericPlayer *GetPlayer();\n\n\t\tvoid SetScale(float scale);\n\n\t\tfloat GetScale();\n\n\t\tvoid SetPosition(float x, float y);\n\n\t\tvoid SetSettingsOverride(SettingsOverride override);\n\n\t\tMenuType GetMenuType() override\n\t\t{\n\t\t\treturn MenuType_PlayerSimple;\n\t\t}\n\n\t\tconst uint32_t *GetSupportedSettingsItems(int32_t *count) override\n\t\t{\n\t\t\tswitch (m_settingsOverride)\n\t\t\t{\n\t\t\tcase SettingsOverride_None:\n\t\t\t\t*count = 0;\n\t\t\t\treturn nullptr;\n\t\t\tcase SettingsOverride_YouTube:\n\t\t\t\t*count = sizeof(k_settingsIdListYoutubeOverride) / sizeof(char*);\n\t\t\t\treturn k_settingsIdListYoutubeOverride;\n\t\t\t}\n\n\t\t\treturn nullptr;\n\t\t}\n\n\tprivate:\n\n\t\tstatic int32_t PowerCallback(SceUID notifyId, int32_t notifyCount, int32_t notifyArg, void *pCommon);\n\t\tstatic void UpdateTask(void *pArgBlock);\n\t\tvoid OnVideoPlaneTouch();\n\t\tvoid OnProgressBarStateChange(int32_t type);\n\t\tvoid OnBackButton();\n\t\tvoid OnPlayButton();\n\t\tvoid OnWholeRepeatButton();\n\t\tvoid OnPowerCallback(int32_t notifyArg);\n\t\tvoid OnGenericPlayerStateChange(int32_t state);\n\t\tvoid OnUpdate();\n\t\tvoid OnPadUpdate(inputdevice::Data *data);\n\n\t\tui::Widget *m_videoPlane;\n\t\tui::BusyIndicator *m_loadIndicator;\n\t\tui::Widget *m_leftAccText;\n\t\tui::Widget *m_rightAccText;\n\t\tui::Widget *m_statPlane;\n\t\tui::Widget *m_backButton;\n\t\tui::Widget *m_wholeRepeatButton;\n\t\tui::Text *m_elapsedTimeText;\n\t\tui::Text *m_subsMainText;\n\t\tui::Text *m_subsEdgeText[4];\n\t\tui::ProgressBarTouch *m_progressBar;\n\t\tui::Widget *m_progressPlane;\n\t\tui::Widget *m_playButton;\n\t\tuint32_t m_oldCurrTime;\n\t\tbool m_progressPlaneShown;\n\t\tuint32_t m_progressPlaneShownTime;\n\t\tbool m_isSeeking;\n\t\tbool m_isLS;\n\t\tuint32_t m_oldButtons;\n\t\tGenericPlayer::PlayerState m_oldState;\n\t\tint32_t m_accJumpTime;\n\t\tuint32_t m_accStartTime;\n\t\tAccJumpState m_accJumpState;\n\t\tfloat m_currentScale;\n\t\tSettingsOverride m_settingsOverride;\n\t\tSceUID m_pwCbId;\n\t\tcommon::SharedPtr<inputdevice::InputListener> m_padListener;\n\t\tGenericSubtitles::SystemSettings m_subSettings;\n\t\tmath::v2 m_subsBaseCharSize;\n\t\tvector<uint32_t> m_subIndices;\n\t\tvector<uint32_t> m_oldSubIndices;\n\t\tGenericPlayer *m_player;\n\t\tGenericSubtitles *m_subtitles;\n\n\t\tconst uint32_t k_settingsIdListYoutubeOverride[4] = {\n\t\t\tyoutube_search_setting,\n\t\t\tyoutube_comment_setting,\n\t\t\tyoutube_quality_setting,\n\t\t\tyoutube_player_setting\n\t\t};\n\t};\n}\n\n#endif\n"
  },
  {
    "path": "NetStream/include/menus/menu_player_youtube.h",
    "content": "#ifndef _MENU_PLAYER_YOUTUBE_H_\n#define _MENU_PLAYER_YOUTUBE_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"dialog.h\"\n#include \"ftube.h\"\n#include \"menu_generic.h\"\n#include \"menus/menu_player_simple.h\"\n\nusing namespace paf;\n\n#define LIVE_COMMENT_NUM\t\t6\n#define LIVE_COMMENT_MAGIC\t\t0x16865ddb\n#define SELECT_QUALITY_MAGIC\t0x3e9f36f4\n\n#define USE_LIVE_COMMENT_HASHING\n\nnamespace menu {\n\n\tclass PlayerYoutube : public GenericMenu\n\t{\n\tpublic:\n\n\t\tenum CompanelMode\n\t\t{\n\t\t\tCompanelMode_None,\n\t\t\tCompanelMode_Description,\n\t\t\tCompanelMode_Comment\n\t\t};\n\n\t\tclass LoadJob : public job::JobItem\n\t\t{\n\t\tpublic:\n\n\t\t\tLoadJob(PlayerYoutube *parent) : job::JobItem(\"YouTube::LoadJob\", NULL), m_parent(parent)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~LoadJob() {}\n\n\t\t\tint32_t Run()\n\t\t\t{\n\t\t\t\tm_parent->Load();\n\n\t\t\t\treturn SCE_PAF_OK;\n\t\t\t}\n\n\t\t\tvoid Finish(int32_t result) {}\n\n\t\tprivate:\n\n\t\t\tPlayerYoutube *m_parent;\n\t\t};\n\n\t\tclass CommentItem\n\t\t{\n\t\tpublic:\n\n\t\t\twstring author;\n\t\t\twstring content;\n\t\t\twstring date;\n\t\t\twstring voteCount;\n\t\t\tbool likedByOwner;\n\t\t\tstring replyContinuation;\n\t\t};\n\n\t\tclass LiveCommentListViewCb : public ui::listview::ItemFactory\n\t\t{\n\t\tpublic:\n\n\t\t\tLiveCommentListViewCb(menu::PlayerYoutube *parent) : m_parent(parent)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~LiveCommentListViewCb()\n\t\t\t{\n\n\t\t\t}\n\n\t\t\tui::ListItem* Create(CreateParam& param)\n\t\t\t{\n\t\t\t\treturn m_parent->CreateLiveCommentListItem(param);\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tmenu::PlayerYoutube *m_parent;\n\t\t};\n\n\t\tclass CommentListViewCb : public ui::listview::ItemFactory\n\t\t{\n\t\tpublic:\n\n\t\t\tCommentListViewCb(menu::PlayerYoutube *parent) : m_parent(parent)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~CommentListViewCb()\n\t\t\t{\n\n\t\t\t}\n\n\t\t\tui::ListItem* Create(CreateParam& param)\n\t\t\t{\n\t\t\t\treturn m_parent->CreateCommentListItem(param);\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tPlayerYoutube *m_parent;\n\t\t};\n\n\t\tclass SelectQualityDialogListViewCb : public ui::listview::ItemFactory\n\t\t{\n\t\tpublic:\n\n\t\t\tSelectQualityDialogListViewCb(menu::PlayerYoutube *parent) : m_parent(parent)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~SelectQualityDialogListViewCb()\n\t\t\t{\n\n\t\t\t}\n\n\t\t\tui::ListItem* Create(CreateParam& param)\n\t\t\t{\n\t\t\t\treturn m_parent->CreateSelectQualityListItem(param);\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tmenu::PlayerYoutube *m_parent;\n\t\t};\n\n\t\tclass LiveCommentParseThread : public thread::Thread\n\t\t{\n\t\tpublic:\n\n\t\t\tLiveCommentParseThread(PlayerYoutube *parent) : thread::Thread(SCE_KERNEL_DEFAULT_PRIORITY_USER + 20, SCE_KERNEL_64KiB, \"YouTube::CommentParseThread\", NULL), m_parent(parent)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\tvoid EntryFunction()\n\t\t\t{\n\t\t\t\tm_parent->ParseLiveComments(this);\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tPlayerYoutube *m_parent;\n\t\t};\n\n\t\tclass CommentParseJob : public job::JobItem\n\t\t{\n\t\tpublic:\n\n\t\t\tCommentParseJob(PlayerYoutube *parent) : job::JobItem(\"YouTube::CommentParseJob\", NULL), m_parent(parent)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~CommentParseJob() {}\n\n\t\t\tint32_t Run()\n\t\t\t{\n\t\t\t\tm_parent->ParseComments();\n\n\t\t\t\treturn SCE_PAF_OK;\n\t\t\t}\n\n\t\t\tvoid Finish(int32_t result) {}\n\n\t\tprivate:\n\n\t\t\tPlayerYoutube *m_parent;\n\t\t};\n\n\t\tPlayerYoutube(const char *id, bool isFavourite);\n\n\t\t~PlayerYoutube() override;\n\n\t\tMenuType GetMenuType() override\n\t\t{\n\t\t\treturn MenuType_PlayerYouTube;\n\t\t}\n\n\t\tconst uint32_t *GetSupportedSettingsItems(int32_t *count) override\n\t\t{\n\t\t\t*count = sizeof(k_settingsIdList) / sizeof(char*);\n\t\t\treturn k_settingsIdList;\n\t\t}\n\n\tprivate:\n\n\t\tstatic void LoadSecondStageTask(void *pArgBlock);\n\t\tvoid OnLoadSecondStage();\n\t\tvoid OnDwAddComplete(int32_t result);\n\t\tvoid OnBackButton();\n\t\tvoid OnSettingsButton();\n\t\tvoid OnExpandButton();\n\t\tvoid OnVideoSettingsButton();\n\t\tvoid OnSelectQualityButton(ui::Widget *wdg);\n\t\tvoid OnFavButton();\n\t\tvoid OnCommentButton();\n\t\tvoid OnDescButton();\n\t\tvoid OnCommentBodyButton(ui::Widget *wdg);\n\t\tvoid OnPlayerEvent(int32_t type);\n\t\tvoid OnOptionMenuEvent(int32_t type, int32_t subtype);\n\t\tvoid OnSettingsEvent(int32_t type);\n\n\t\tvoid Load();\n\t\tvoid ParseComments();\n\t\tui::ListItem *CreateLiveCommentListItem(ui::listview::ItemFactory::CreateParam& param);\n\t\tui::ListItem *CreateCommentListItem(ui::listview::ItemFactory::CreateParam& param);\n\t\tvoid ParseLiveComments(thread::Thread *thrd);\n\n\t\tui::ListItem *CreateSelectQualityListItem(ui::listview::ItemFactory::CreateParam& param);\n\n\t\tui::Text *m_title;\n\t\tui::Text *m_stat0;\n\t\tui::Text *m_stat1;\n\t\tui::Text *m_stat2;\n\t\tui::Button *m_expandButton;\n\t\tui::Button *m_videoSettingsButton;\n\t\tui::Button *m_favButton;\n\t\tui::Widget *m_companelBase;\n\t\tui::Widget *m_commentButton;\n\t\tui::Widget *m_descButton;\n\t\tui::ListView *m_companelRoot;\n\t\tmenu::PlayerSimple *m_player;\n\t\tstring m_videoLink;\n\t\tstring m_videoLinkForDw;\n\t\tstring m_audioLink;\n\t\tstring m_videoId;\n\t\tbool m_isLive;\n\t\tbool m_isFav;\n\t\tstring m_description;\n\t\tstring m_commentCont;\n\t\tvector<CommentItem> m_commentItems;\n\t\tLiveCommentParseThread *m_liveCommentThread;\n\t\tGenericPlayer::Option *m_option;\n\n\t\tconst uint32_t k_settingsIdList[5] = {\n\t\t\tyoutube_search_setting,\n\t\t\tyoutube_comment_setting,\n\t\t\tyoutube_quality_setting,\n\t\t\tyoutube_player_setting,\n\t\t\tcloud_sync_setting\n\t\t};\n\t};\n}\n\n#endif\n"
  },
  {
    "path": "NetStream/include/menus/menu_server.h",
    "content": "#ifndef _MENU_SERVER_H_\n#define _MENU_SERVER_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"dialog.h\"\n#include \"menu_generic.h\"\n#include \"browsers/generic_server_browser.h\"\n#include \"menus/menu_player_simple.h\"\n\nusing namespace paf;\n\nnamespace menu {\n\tclass GenericServerMenu : public GenericMenu\n\t{\n\tpublic:\n\n\t\tclass ListViewCb : public ui::listview::ItemFactory\n\t\t{\n\t\tpublic:\n\n\t\t\tListViewCb(GenericServerMenu *parent) : m_parent(parent)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~ListViewCb()\n\t\t\t{\n\n\t\t\t}\n\n\t\t\tui::ListItem *Create(CreateParam& param)\n\t\t\t{\n\t\t\t\treturn m_parent->CreateListItem(param);\n\t\t\t}\n\n\t\t\tvoid Start(StartParam& param)\n\t\t\t{\n\t\t\t\tparam.list_item->Show(common::transition::Type_Popup1);\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tGenericServerMenu *m_parent;\n\t\t};\n\n\t\tclass GoToJob : public job::JobItem\n\t\t{\n\t\tpublic:\n\n\t\t\tGoToJob(GenericServerMenu *parent) : job::JobItem(\"Server::GoToJob\", NULL), m_parent(parent)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~GoToJob() {}\n\n\t\t\tint32_t Run()\n\t\t\t{\n\t\t\t\tm_parent->GoTo(m_targetRef);\n\n\t\t\t\treturn SCE_PAF_OK;\n\t\t\t}\n\n\t\t\tvoid Finish(int32_t result) {}\n\n\t\t\tvoid SetRef(const string& ref)\n\t\t\t{\n\t\t\t\tm_targetRef = ref;\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tGenericServerMenu *m_parent;\n\t\t\tstring m_targetRef;\n\t\t};\n\n\t\tclass BrowserPage\n\t\t{\n\t\tpublic:\n\n\t\t\tBrowserPage() : m_isLoaded(false)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~BrowserPage()\n\t\t\t{\n\n\t\t\t}\n\n\t\t\tvector<GenericServerBrowser::Entry *> *m_itemList;\n\t\t\tui::ListView *m_list;\n\t\t\tbool m_isLoaded;\n\t\t};\n\n\t\tGenericServerMenu();\n\n\t\t~GenericServerMenu() override;\n\n\t\tui::ListItem* CreateListItem(ui::listview::ItemFactory::CreateParam& param);\n\n\t\tvoid GoTo(const string& ref);\n\n\t\tbool PushBrowserPage(string *ref);\n\n\t\tbool PopBrowserPage();\n\n\tprotected:\n\n\t\tGenericServerBrowser *m_browser;\n\n\tprivate:\n\n\t\tvoid OnBackButton();\n\t\tvoid OnListButton(ui::Widget *wdg);\n\t\tvoid OnSettingsButton();\n\t\tvoid OnPlayerEvent(int32_t type);\n\t\tvoid OnOptionMenuEvent(int32_t type);\n\t\tvoid OnConnectionFailedDialogEvent();\n\t\tvoid OnPlayerCreateTimeout(GenericServerBrowser::Entry *entry);\n\n\t\tui::Widget *m_browserRoot;\n\t\tui::BusyIndicator *m_loaderIndicator;\n\t\tui::Text *m_topText;\n\t\tvector<BrowserPage *> m_pageList;\n\t\tmenu::GenericMenu *m_player;\n\t\tbool m_firstBoot;\n\t\tbool m_playerFailed;\n\t};\n}\n\n#endif"
  },
  {
    "path": "NetStream/include/menus/menu_settings.h",
    "content": "#ifndef _MENU_SETTINGS_H_\n#define _MENU_SETTINGS_H_\n\n#include <paf.h>\n#include <app_settings.h>\n\n#include \"menus/menu_generic.h\"\n\nusing namespace paf;\n\nnamespace menu {\n\tclass Settings\n\t{\n\tpublic:\n\n\t\tenum\n\t\t{\n\t\t\tSettingsEvent = (ui::Handler::CB_STATE + 0x30000),\n\t\t};\n\n\t\tenum SettingsEvent\n\t\t{\n\t\t\tSettingsEvent_Close,\n\t\t\tSettingsEvent_ValueChange\n\t\t};\n\n\t\tSettings();\n\n\t\t~Settings();\n\n\t\tstatic Settings *GetInstance();\n\n\t\tstatic sce::AppSettings *GetAppSetInstance();\n\n\t\tstatic void Init();\n\n\tprivate:\n\n\t\tstatic void CBOnStartPageTransition(const char *elementId, int32_t type);\n\n\t\tstatic void CBOnPageActivate(const char *elementId, int32_t type);\n\n\t\tstatic void CBOnPageDeactivate(const char *elementId, int32_t type);\n\n\t\tstatic int32_t CBOnCheckVisible(const char *elementId, bool *pIsVisible);\n\n\t\tstatic int32_t CBOnPreCreate(const char *elementId, sce::AppSettings::Element *element);\n\n\t\tstatic int32_t CBOnPostCreate(const char *elementId, paf::ui::Widget *widget);\n\n\t\tstatic int32_t CBOnPress(const char *elementId, const char *newValue);\n\n\t\tstatic int32_t CBOnPress2(const char *elementId, const char *newValue);\n\n\t\tstatic void CBOnTerm(int32_t result);\n\n\t\tstatic wchar_t *CBOnGetString(const char *elementId);\n\n\t\tstatic int32_t CBOnGetSurface(graph::Surface **surf, const char *elementId);\n\t};\n}\n\n#endif\n"
  },
  {
    "path": "NetStream/include/menus/menu_youtube.h",
    "content": "#ifndef _MENU_YOUTUBE_H_\n#define _MENU_YOUTUBE_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"dialog.h\"\n#include \"tex_pool.h\"\n#include \"ftube.h\"\n#include \"menu_generic.h\"\n\nusing namespace paf;\n\nnamespace menu {\n\tclass YouTube : public GenericMenu\n\t{\n\tpublic:\n\n\t\tclass Submenu\n\t\t{\n\t\tpublic:\n\n\t\t\tenum SubmenuType\n\t\t\t{\n\t\t\t\tSubmenuType_Search = 0xbe840a1f,\n\t\t\t\tSubmenuType_History = 0x2bc652ba,\n\t\t\t\tSubmenuType_Favourites = 0x947652c2\n\t\t\t};\n\n\t\t\tSubmenu(YouTube *parentObj);\n\n\t\t\tvirtual ~Submenu();\n\n\t\t\tvirtual void ReleaseCurrentPage();\n\n\t\t\tvirtual void GoToNextPage() = 0;\n\n\t\t\tvirtual void GoToPrevPage() = 0;\n\n\t\t\tvirtual void GoToBasePageForSync() = 0;\n\n\t\t\tvirtual SubmenuType GetType() = 0;\n\n\t\t\tui::ListItem* CreateListItem(ui::listview::ItemFactory::CreateParam& param);\n\n\t\t\tclass ListViewCb : public ui::listview::ItemFactory\n\t\t\t{\n\t\t\tpublic:\n\n\t\t\t\tListViewCb(Submenu *parent) : m_parent(parent)\n\t\t\t\t{\n\n\t\t\t\t}\n\n\t\t\t\t~ListViewCb()\n\t\t\t\t{\n\n\t\t\t\t}\n\n\t\t\t\tui::ListItem *Create(CreateParam& param)\n\t\t\t\t{\n\t\t\t\t\treturn m_parent->CreateListItem(param);\n\t\t\t\t}\n\n\t\t\t\tvoid Start(StartParam& param)\n\t\t\t\t{\n\t\t\t\t\tparam.list_item->Show(common::transition::Type_Popup1);\n\t\t\t\t}\n\n\t\t\tprivate:\n\n\t\t\t\tSubmenu *m_parent;\n\t\t\t};\n\n\t\t\tclass Item\n\t\t\t{\n\t\t\tpublic:\n\n\t\t\t\tItem()\n\t\t\t\t{\n\n\t\t\t\t}\n\n\t\t\t\tFTItemType type;\n\t\t\t\twstring name;\n\t\t\t\twstring time;\n\t\t\t\twstring stat;\n\t\t\t\tstring videoId;\n\t\t\t\tIDParam texId;\n\t\t\t\tTexPool *texPool;\n\t\t\t};\n\n\t\tprotected:\n\n\t\t\tYouTube *m_baseParent;\n\t\t\tui::Widget *m_submenuRoot;\n\t\t\tui::ListView *m_list;\n\t\t\tbool m_interrupted;\n\t\t\tbool m_allJobsComplete;\n\t\t\tvector<Item> m_results;\n\t\t\tuint32_t m_currentPage;\n\n\t\tprivate:\n\n\t\t\tstatic void OnTexPoolAdd(int32_t type, ui::Handler *self, ui::Event *e, void *userdata);\n\n\t\t\tvoid OnListButton(ui::Widget *wdg);\n\t\t};\n\n\t\tclass SearchSubmenu : public Submenu\n\t\t{\n\t\tpublic:\n\n\t\t\tclass SearchJob : public job::JobItem\n\t\t\t{\n\t\t\tpublic:\n\n\t\t\t\tSearchJob(SearchSubmenu *parent) : job::JobItem(\"YouTube::SearchJob\", NULL), m_parent(parent)\n\t\t\t\t{\n\n\t\t\t\t}\n\n\t\t\t\t~SearchJob() {}\n\n\t\t\t\tint32_t Run()\n\t\t\t\t{\n\t\t\t\t\tm_parent->Search();\n\n\t\t\t\t\treturn SCE_PAF_OK;\n\t\t\t\t}\n\n\t\t\t\tvoid Finish(int32_t result) {}\n\n\t\t\tprivate:\n\n\t\t\t\tSearchSubmenu *m_parent;\n\t\t\t};\n\n\t\t\tSearchSubmenu(YouTube *parentObj);\n\n\t\t\t~SearchSubmenu();\n\n\t\t\tvoid Search();\n\n\t\t\tvoid GoToNextPage();\n\n\t\t\tvoid GoToPrevPage();\n\n\t\t\tvoid GoToBasePageForSync();\n\n\t\t\tSubmenuType GetType()\n\t\t\t{\n\t\t\t\treturn SubmenuType_Search;\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tvoid OnSearchButton();\n\n\t\t\tui::TextBox *m_searchBox;\n\t\t\tui::Widget *m_searchButton;\n\t\t\tstring m_request;\n\t\t\tmap<uint32_t, string> m_continuations;\n\t\t};\n\n\t\tclass HistorySubmenu : public Submenu\n\t\t{\n\t\tpublic:\n\n\t\t\tclass HistoryJob : public job::JobItem\n\t\t\t{\n\t\t\tpublic:\n\n\t\t\t\tHistoryJob(HistorySubmenu *parent) : job::JobItem(\"YouTube::HistoryJob\", NULL), m_parent(parent)\n\t\t\t\t{\n\n\t\t\t\t}\n\n\t\t\t\t~HistoryJob() {}\n\n\t\t\t\tint32_t Run()\n\t\t\t\t{\n\t\t\t\t\tm_parent->Parse();\n\n\t\t\t\t\treturn SCE_PAF_OK;\n\t\t\t\t}\n\n\t\t\t\tvoid Finish(int32_t result) {}\n\n\t\t\tprivate:\n\n\t\t\t\tHistorySubmenu *m_parent;\n\t\t\t};\n\n\t\t\tHistorySubmenu(YouTube *parentObj);\n\n\t\t\t~HistorySubmenu();\n\n\t\t\tvoid Parse();\n\n\t\t\tvoid GoToNextPage();\n\n\t\t\tvoid GoToPrevPage();\n\n\t\t\tvoid GoToBasePageForSync();\n\n\t\t\tSubmenuType GetType()\n\t\t\t{\n\t\t\t\treturn SubmenuType_History;\n\t\t\t}\n\t\t};\n\n\t\tclass FavouriteSubmenu : public Submenu\n\t\t{\n\t\tpublic:\n\n\t\t\tclass FavouriteJob : public job::JobItem\n\t\t\t{\n\t\t\tpublic:\n\n\t\t\t\tFavouriteJob(FavouriteSubmenu *parent) : job::JobItem(\"YouTube::FavouriteJob\", NULL), m_parent(parent)\n\t\t\t\t{\n\n\t\t\t\t}\n\n\t\t\t\t~FavouriteJob() {}\n\n\t\t\t\tint32_t Run()\n\t\t\t\t{\n\t\t\t\t\tm_parent->Parse();\n\n\t\t\t\t\treturn SCE_PAF_OK;\n\t\t\t\t}\n\n\t\t\t\tvoid Finish(int32_t result) {}\n\n\t\t\tprivate:\n\n\t\t\t\tFavouriteSubmenu *m_parent;\n\t\t\t};\n\n\t\t\tFavouriteSubmenu(YouTube *parentObj);\n\n\t\t\t~FavouriteSubmenu();\n\n\t\t\tvoid Parse();\n\n\t\t\tvoid GoToNextPage();\n\n\t\t\tvoid GoToPrevPage();\n\n\t\t\tvoid GoToBasePageForSync();\n\n\t\t\tSubmenuType GetType()\n\t\t\t{\n\t\t\t\treturn SubmenuType_Favourites;\n\t\t\t}\n\n\t\tprivate:\n\n\t\t\tvoid OnSearchButton();\n\n\t\t\tui::TextBox *m_searchBox;\n\t\t\tui::Widget *m_searchButton;\n\t\t\tstring m_request;\n\t\t};\n\n\t\tclass LogClearJob : public job::JobItem\n\t\t{\n\t\tpublic:\n\n\t\t\tenum Type\n\t\t\t{\n\t\t\t\tType_Fav,\n\t\t\t\tType_Hist\n\t\t\t};\n\n\t\t\tLogClearJob(Type type, Submenu *submenu) : job::JobItem(\"YouTube::LogClearJob\", NULL), m_type(type), m_submenu(submenu)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~LogClearJob() {}\n\n\t\t\tint32_t Run();\n\n\t\t\tvoid Finish(int32_t result) {}\n\n\t\tprivate:\n\n\t\t\tType m_type;\n\t\t\tSubmenu *m_submenu;\n\t\t};\n\n\t\tclass CloudJob : public job::JobItem\n\t\t{\n\t\tpublic:\n\n\t\t\tenum Type\n\t\t\t{\n\t\t\t\tType_Upload,\n\t\t\t\tType_Download\n\t\t\t};\n\n\t\t\tCloudJob(Type type, Submenu *submenu) : job::JobItem(\"YouTube::CloudJob\", NULL), m_type(type), m_submenu(submenu)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~CloudJob() {}\n\n\t\t\tint32_t Run();\n\n\t\t\tvoid Finish(int32_t result) {}\n\n\t\tprivate:\n\n\t\t\tType m_type;\n\t\t\tSubmenu *m_submenu;\n\t\t};\n\n\t\tYouTube();\n\n\t\t~YouTube()  override;\n\n\t\tvoid SwitchSubmenu(Submenu::SubmenuType type);\n\n\t\tMenuType GetMenuType() override\n\t\t{\n\t\t\treturn MenuType_Youtube;\n\t\t}\n\n\t\tconst uint32_t *GetSupportedSettingsItems(int32_t *count) override\n\t\t{\n\t\t\t*count = sizeof(k_settingsIdList) / sizeof(char*);\n\t\t\treturn k_settingsIdList;\n\t\t}\n\n\tprivate:\n\n\t\tvoid OnBackButton();\n\t\tvoid OnSubmenuButton(ui::Widget *wdg);\n\t\tvoid OnSettingsButton();\n\t\tvoid OnOptionMenuEvent(int32_t type, int32_t subtype);\n\t\tvoid OnDialogEvent(int32_t type);\n\t\tvoid OnSettingsEvent(int32_t type);\n\n\t\tui::Widget *m_browserRoot;\n\t\tui::BusyIndicator *m_loaderIndicator;\n\t\tui::Text *m_topText;\n\t\tui::Box *m_btMenu;\n\t\tui::Widget *m_searchBt;\n\t\tui::Widget *m_histBt;\n\t\tui::Widget *m_favBt;\n\t\tSubmenu *m_currentSubmenu;\n\t\tint32_t m_dialogIdx;\n\t\tTexPool *m_texPool;\n\n\t\tconst uint32_t k_settingsIdList[5] = {\n\t\t\tyoutube_search_setting,\n\t\t\tyoutube_comment_setting,\n\t\t\tyoutube_quality_setting,\n\t\t\tyoutube_player_setting,\n\t\t\tcloud_sync_setting\n\t\t};\n\t};\n\n}\n\n#endif\n"
  },
  {
    "path": "NetStream/include/netstream_locale.h",
    "content": "#ifndef _netstream_locale_H_\n#define _netstream_locale_H_\n\n//\n//This file was generated automatically by psp2pafhshgen.exe\n//\n\n#define msg_title_menu_first (0xcae20590)\n#define msg_fpmenu_item_0 (0xab1aa619)\n#define msg_fpmenu_item_1 (0xc308121f)\n#define msg_fpmenu_item_2 (0x45965a3d)\n#define msg_fpmenu_item_3 (0xa8fb98bc)\n#define msg_fpmenu_item_4 (0x5c491dfd)\n#define msg_youtube_history (0xa8a29762)\n#define msg_youtube_description (0x336514d8)\n#define msg_youtube_comment_more (0xa3ada054)\n#define msg_youtube_comment_detail (0x057bb502)\n#define msg_youtube_comment_reply (0x996ef6f5)\n#define msg_youtube_comment_like_count (0xc4d65d6e)\n#define msg_next_page (0x8adf20f8)\n#define msg_previous_page (0xede8bfcb)\n#define msg_settings (0xed3441bf)\n#define msg_settings_http (0x6c5673f2)\n#define msg_settings_ftp (0x704624b0)\n#define msg_settings_account (0x9c86b550)\n#define msg_settings_local (0xd9a4496d)\n#define msg_settings_search (0x58e3fab6)\n#define msg_settings_comment (0x126adfcc)\n#define msg_settings_quality (0xe8b7b3e1)\n#define msg_settings_player (0xc522e457)\n#define msg_settings_cloud_sync (0xd17de6c8)\n#define msg_settings_verinfo (0x32a4c75a)\n#define msg_http_host (0xdcb23ff1)\n#define msg_http_port (0xc7f3641b)\n#define msg_http_user (0x4af03db0)\n#define msg_http_password (0x1df489af)\n#define msg_ftp_host (0x3bfcdb72)\n#define msg_ftp_port (0xa27211e8)\n#define msg_ftp_user (0x91940499)\n#define msg_ftp_password (0x8b0f92bb)\n#define msg_ftp_nlst (0xc8025a39)\n#define msg_ftp_nlst_hint (0x8bac33a4)\n#define msg_hvdb_host (0xda01ba30)\n#define msg_hvdb_user (0xe167be34)\n#define msg_hvdb_password (0x30dea278)\n#define msg_local_playlist_prefix (0x4278708e)\n#define msg_local_sort_name (0xd5e8c8fa)\n#define msg_local_sort_type (0x02c5dfcb)\n#define msg_option_local_sort_name_0 (0x6ae3e929)\n#define msg_option_local_sort_name_1 (0x27cace63)\n#define msg_option_local_sort_type_0 (0x07755294)\n#define msg_option_local_sort_type_1 (0xa20432c9)\n#define msg_youtube_quality_vod_video (0x1908a662)\n#define msg_youtube_quality_vod_audio (0x972a9228)\n#define msg_youtube_quality_live (0xf9526359)\n#define msg_youtube_search_region (0x0b103c0e)\n#define msg_youtube_search_sort (0x656f44a5)\n#define msg_youtube_search_date (0xcf93868a)\n#define msg_youtube_search_dur (0xcfaf8812)\n#define msg_youtube_search_feature (0xa8de0f20)\n#define msg_youtube_search_proxy (0x4c529b77)\n#define msg_youtube_comment_sort (0xfd6ca373)\n#define msg_option_search_region_0 (0xb56add1e)\n#define msg_option_search_sort_0 (0x522b5f02)\n#define msg_option_search_sort_1 (0xecde5937)\n#define msg_option_search_sort_2 (0xa41c4c57)\n#define msg_option_search_sort_3 (0x2dc7bf9f)\n#define msg_option_search_date_0 (0x9dc2d0cd)\n#define msg_option_search_date_1 (0x7972fabe)\n#define msg_option_search_date_2 (0x8b497f22)\n#define msg_option_search_date_3 (0xe22a82a1)\n#define msg_option_search_date_4 (0x9a7b465f)\n#define msg_option_search_date_5 (0xe7a24a6b)\n#define msg_option_search_dur_0 (0xc39e8c4f)\n#define msg_option_search_dur_1 (0xc44c1c25)\n#define msg_option_search_dur_2 (0x8cf1273f)\n#define msg_option_search_dur_3 (0x6b7af5cc)\n#define msg_option_search_feature_0 (0x4f23fcae)\n#define msg_option_search_feature_1 (0xd4ecbd56)\n#define msg_option_comment_sort_0 (0x0715b7f3)\n#define msg_option_comment_sort_1 (0x59115ba0)\n#define msg_option_youtube_quality_vod_video_0 (0x8e8f98b5)\n#define msg_option_youtube_quality_vod_video_1 (0xb30ef49b)\n#define msg_option_youtube_quality_vod_video_2 (0x5165af0b)\n#define msg_option_youtube_quality_vod_video_3 (0x7d4ae9f0)\n#define msg_option_youtube_quality_vod_video_4 (0x6c8ddd13)\n#define msg_option_youtube_quality_vod_video_5 (0xae9e2192)\n#define msg_option_youtube_quality_live_0 (0xee0ba354)\n#define msg_option_youtube_quality_live_1 (0x858f1e17)\n#define msg_option_youtube_quality_live_2 (0x6f2108e2)\n#define msg_option_youtube_quality_live_3 (0x789efe84)\n#define msg_option_youtube_quality_live_4 (0xe2994c58)\n#define msg_hvdb_search_sort (0xfa7c8d91)\n#define msg_hvdb_search_sort_type (0x9b0bd3ed)\n#define msg_hvdb_search_filter (0x31ded7e7)\n#define msg_option_hvdb_search_sort_0 (0x93cdc1e6)\n#define msg_option_hvdb_search_sort_1 (0xec171b82)\n#define msg_option_hvdb_search_sort_type_0 (0xccfe3a39)\n#define msg_option_hvdb_search_sort_type_1 (0x8e2eed08)\n#define msg_option_hvdb_search_sort_type_2 (0x40b00c6a)\n#define msg_option_hvdb_search_sort_type_3 (0x787efc0e)\n#define msg_option_hvdb_search_sort_type_4 (0x39eecc63)\n#define msg_option_hvdb_search_sort_type_5 (0x3f9339c8)\n#define msg_option_hvdb_search_sort_type_6 (0xcbcb9f9d)\n#define msg_option_hvdb_search_sort_type_7 (0xcad39666)\n#define msg_option_hvdb_search_sort_type_8 (0xde388b81)\n#define msg_option_hvdb_search_filter_0 (0x68f52ed4)\n#define msg_option_hvdb_search_filter_1 (0xbac48c12)\n#define msg_option_hvdb_search_filter_2 (0x4fc34921)\n#define msg_option_hvdb_search_filter_3 (0xaa3e0f0c)\n#define msg_option_hvdb_search_filter_4 (0x0f26631d)\n#define msg_option_hvdb_search_filter_5 (0x9f0969d9)\n#define msg_toggle_hvdb_banner (0x0e69d985)\n#define msg_toggle_cloud_sync (0xe3434564)\n#define msg_toggle_cloud_sync_auto (0x2144bf5c)\n#define msg_cloud_sync_hint (0x650bd57f)\n#define msg_toggle_youtube_min (0x9236786a)\n#define msg_settings_hvdb_refresh (0xa20c0934)\n#define msg_settings_youtube_cloud_upload (0x5fe6009c)\n#define msg_settings_youtube_cloud_download (0xb35e246e)\n#define msg_settings_youtube_clean_history (0xce0c7a4d)\n#define msg_settings_youtube_clean_fav (0x0342b229)\n#define msg_settings_youtube_clean_history_confirm (0xd3225a4e)\n#define msg_settings_youtube_clean_fav_confirm (0x68a1ba57)\n#define msg_settings_youtube_download (0x8449e69c)\n#define msg_settings_youtube_download_audio (0x99364cad)\n#define msg_settings_youtube_download_begin (0x5ed1d900)\n#define msg_quality_select_dialog_title (0x6307ab56)\n#define msg_error_psn_connection (0x56f0c03c)\n#endif"
  },
  {
    "path": "NetStream/include/netstream_plugin.h",
    "content": "#ifndef _netstream_plugin_H_\n#define _netstream_plugin_H_\n\n//\n//This file was generated automatically by psp2pafhshgen.exe\n//\n\n#define netstream_plugin (0xb2fabc6f)\n#define page_first (0xe63e6133)\n#define plane_base_bg_page_first (0x94c4a1ca)\n#define template_ref_top_title_bar_page_first (0x3f9ee201)\n#define template_ref_list_view_page_first (0xc4d69f4c)\n#define page_server_generic (0x4bcbf5f5)\n#define plane_base_bg_page_server_generic (0x7e8e5c95)\n#define template_ref_top_title_bar_page_server_generic (0x9f4f703a)\n#define plane_browser_root_page_server_generic (0xbe3c359a)\n#define busyindicator_loader_page_server_generic (0x124a7a79)\n#define button_back_page_server_generic (0xa4f7d1fe)\n#define button_settings_page_server_generic (0x0efde917)\n#define page_youtube (0xd9d437d7)\n#define plane_base_bg_page_youtube (0x86efefd3)\n#define template_ref_top_title_bar_page_youtube (0xa1049fc2)\n#define plane_browser_root_page_youtube (0x149aa632)\n#define busyindicator_loader_page_youtube (0x8c1b7fd7)\n#define plane_bottommenu_page_youtube (0x67720528)\n#define box_bottommenu_page_youtube (0xc88bf810)\n#define button_yt_btmenu_search (0xbe840a1f)\n#define button_yt_btmenu_history (0x2bc652ba)\n#define yt_plane_bottommenu_sep1 (0xd2144aee)\n#define button_yt_btmenu_favourite (0x947652c2)\n#define yt_plane_bottommenu_sep2 (0x019d2b63)\n#define button_back_page_youtube (0xaf2e605e)\n#define button_settings_page_youtube (0x72ea9465)\n#define page_hvdb (0x46781da9)\n#define plane_base_bg_page_hvdb (0x5221a311)\n#define template_ref_top_title_bar_page_hvdb (0x90950173)\n#define plane_browser_root_page_hvdb (0xec2b4bf1)\n#define busyindicator_loader_page_hvdb (0x5d1f04ac)\n#define button_back_page_hvdb (0x49aa414e)\n#define button_settings_page_hvdb (0x6e9c0546)\n#define page_youtube_player (0xce0eb512)\n#define plane_base_bg_page_youtube_player (0x14efbee7)\n#define plane_root_page_youtube_player (0x9794cec3)\n#define text_video_title (0x440b44a9)\n#define plane_video_dummy (0xd6acc553)\n#define text_video_stat_0 (0x04004a27)\n#define text_video_stat_1 (0xdeb2242c)\n#define text_video_stat_2 (0x9e5efcb0)\n#define button_youtube_fav (0xfe64fd07)\n#define button_youtube_expand (0x5935ac0d)\n#define button_youtube_settings (0xfd489044)\n#define plane_youtube_live_now (0xa4e3ca2a)\n#define plane_youtube_companel_base (0x62c325b5)\n#define plane_youtube_companel_frame (0x9795d2cc)\n#define plane_youtube_companel_fill (0x1780cda8)\n#define button_yt_companel_description (0x6a78b2b9)\n#define button_yt_companel_comment (0x629df833)\n#define button_back_page_youtube_player (0x0aaea8c4)\n#define button_settings_page_youtube_player (0xa823085e)\n#define plane_youtube_loader (0x87680fe5)\n#define busyindicator_youtube_loader (0xcb3165bc)\n#define page_player_simple (0xf185100a)\n#define plane_video_page_player_simple (0x79d84d3d)\n#define landscape (0x0a2f2cd9)\n#define full_hd (0x4dbf9bdc)\n#define text_video_page_player_subs_edge_0 (0xf011e6a6)\n#define text_video_page_player_subs_edge_1 (0x5dcd2072)\n#define text_video_page_player_subs_edge_2 (0xc0000861)\n#define text_video_page_player_subs_edge_3 (0x8061d9eb)\n#define text_video_page_player_subs_main (0x0dc433eb)\n#define busyindicator_video_page_player_simple (0xb6f59ab8)\n#define text_video_page_player_simple_acc_left (0x9b2f5135)\n#define text_video_page_player_simple_acc_right (0xe77b3c6f)\n#define button_video_page_control_trigger (0x0996c400)\n#define button_video_page_whole_repeat (0xa6a71a6b)\n#define plane_statindicator (0xf1b32eba)\n#define plane_video_control_panel_bg (0x3c3c2c43)\n#define progressbar_touch_video_control_panel (0x2e5febc7)\n#define text_video_control_panel_progressbar_label_elapsed (0x64c584eb)\n#define text_video_control_panel_progressbar_label_total (0xd4315474)\n#define button_video_control_panel_playpause (0xddeb183f)\n#define button_back_page_player_simple (0x0a0a4f24)\n#define style_button_option_single (0x667e5d41)\n#define plane_obj1 (0xf239aa56)\n#define label_obj1 (0xbde6cef8)\n#define plane_obj2 (0xa246c545)\n#define style_button_option_top (0xf808f140)\n#define style_button_option_bottom (0xa4f80dc0)\n#define style_button_option_middle (0x29d701c3)\n#define style_text_option_menu_ruler (0x9d28f73d)\n#define text_obj1 (0xa56e4ba2)\n#define style_plane_black (0xaaa827ae)\n#define style_busyindicator_big (0x44a21a77)\n#define style_text_top_title_bar (0x1bc003d9)\n#define style_list_view_generic (0xfad63dd9)\n#define style_list_view_item_generic (0x885879e0)\n#define style_image_button_list_button (0xe6cd9335)\n#define plane_obj3 (0xddbbc1de)\n#define style_plane_video_page_control_bg (0x762eff8c)\n#define style_text_video_control_panel_progressbar_label_green (0x3eb7c2ac)\n#define style_text_video_control_panel_progressbar_label_white (0xa273dd12)\n#define style_video_control_panel_progressbar (0x31bc66a3)\n#define plane_obj6 (0xa5ea3dd2)\n#define plane_obj7 (0x07e9a874)\n#define plane_obj8 (0xda8566da)\n#define plane_obj4 (0x1c4fbcb6)\n#define plane_obj9 (0x39d33475)\n#define plane_obj5 (0x7c500a37)\n#define style_button_video_control_panel (0xe0c4c74b)\n#define style_button_video_big_repeat (0x3e151589)\n#define style_text_video_control_panel_acc_left (0xf9313764)\n#define style_text_video_control_panel_acc_right (0xb234f959)\n#define style_list_view_hvdb (0xf0d6bf00)\n#define style_image_button_list_button_hvdb (0xacb012c0)\n#define style_image_button_list_button_hvdb_aligned (0xb1433214)\n#define style_text_list_button_hvdb_subtext (0xdbdbf648)\n#define style_list_view_youtube (0xd50417b3)\n#define style_button_yt_search (0x3dc1bb84)\n#define style_button_yt_history (0x623942ea)\n#define style_button_yt_favourite (0x437141f6)\n#define style_text_box_top_youtube_search (0x38cc6c7c)\n#define style_button_yt_top_search (0xc93ad05d)\n#define style_image_button_list_button_youtube (0x24f20afe)\n#define style_image_button_list_button_youtube_aligned (0xc9fe737b)\n#define style_text_list_button_youtube_time (0x409c87af)\n#define style_text_list_button_youtube_subtext (0x92697e0c)\n#define style_text_youtube_video_title (0x52460631)\n#define style_text_youtube_video_stat (0xd461b912)\n#define style_text_youtube_video_stat_right_align (0xa9e17ed6)\n#define style_text_youtube_companel (0x38fa4408)\n#define style_button_yt_expand (0x578c3485)\n#define style_button_yt_settings (0x4c5eda08)\n#define style_button_yt_fav (0x3465f513)\n#define style_plane_youtube_loader (0xbbff71eb)\n#define style_button_yt_companel (0x9ec395e5)\n#define style_list_view_companel (0x386ff929)\n#define style_scroll_view_companel (0xfc80bbc0)\n#define style_button_yt_comment (0x41c21f50)\n#define style_button_yt_quality_select (0xb111e15d)\n#define template_option_menu_base (0xed36b1c7)\n#define button_option_menu_close (0x655c6a32)\n#define plane_option_menu_base (0x4446ff86)\n#define text_option_menu_ruler (0xc9cdb2cc)\n#define box_option_menu (0xae3d8acd)\n#define template_option_menu_button_single (0x9227a229)\n#define button_option_menu_single (0x242a5612)\n#define template_option_menu_button_top (0x9e7aa431)\n#define button_option_menu_top (0x1f350609)\n#define template_option_menu_button_bottom (0xeaf5dc69)\n#define button_option_menu_bottom (0xe034ff9c)\n#define template_option_menu_button_middle (0x429cab34)\n#define button_option_menu_middle (0xbbc3bf22)\n#define template_top_title_bar (0xdb521164)\n#define plane_top (0x8be92f90)\n#define box_top (0xd461521e)\n#define text_top (0xfab814ca)\n#define plane_top_separator (0x939510d6)\n#define template_list_item_generic (0x929d094f)\n#define list_item_generic (0xce92de48)\n#define image_button_list_item (0xefeb27e8)\n#define template_list_view_generic (0xaf8dc058)\n#define list_view_generic (0xa176265a)\n#define template_list_view_hvdb_fav (0x5bd1ad61)\n#define plane_list_view_hvdb_fav_root (0xf5b571f4)\n#define list_view_hvdb (0xb6455f38)\n#define template_list_item_hvdb (0xb17d6cbb)\n#define list_item_hvdb (0x5f236960)\n#define image_button_list_item_hvdb (0xc16c2ffd)\n#define text_list_item_hvdb_time (0xe9ff1a73)\n#define text_list_item_hvdb_subtext (0x46b06861)\n#define template_list_item_hvdb_aligned (0xea9a41ee)\n#define list_item_hvdb_aligned (0xe88d0f7f)\n#define image_button_list_item_hvdb_aligned (0xf206e7d6)\n#define template_list_view_youtube_search (0xfc5c5e23)\n#define plane_list_view_youtube_search_root (0x698023d4)\n#define plane_top_youtube_search (0x98cff0fe)\n#define text_box_top_youtube_search (0xb85026a0)\n#define button_top_youtube_search (0x8bb93ec5)\n#define list_view_youtube (0x141e4129)\n#define template_list_view_youtube_history (0xf3ccbdab)\n#define plane_list_view_youtube_history_root (0x65e38415)\n#define template_list_view_youtube_fav (0x07f60af5)\n#define plane_list_view_youtube_fav_root (0x4ee965e7)\n#define plane_top_youtube_fav (0x8951635e)\n#define template_list_item_youtube (0x8e21b0cb)\n#define list_item_youtube (0xbb459f1c)\n#define image_button_list_item_youtube (0x4af481a3)\n#define text_list_item_youtube_time (0x94781539)\n#define text_list_item_youtube_subtext (0xbf47692e)\n#define template_list_item_youtube_aligned (0xf3990ecd)\n#define list_item_youtube_aligned (0x1df53fb2)\n#define image_button_list_item_youtube_aligned (0x0ad60347)\n#define template_list_view_youtube_companel (0x8fde7ef3)\n#define list_view_youtube_companel (0xf935cf50)\n#define template_scroll_view_youtube_companel (0x8824b2e2)\n#define scroll_view_youtube_companel (0x2af8c40c)\n#define text_youtube_companel (0x0d53901a)\n#define template_list_item_youtube_quality_select (0x4c0e8661)\n#define list_item_youtube_quality_select (0x482b1df9)\n#define button_yt_quality_select_item (0x398a71ea)\n#define template_list_item_youtube_comment (0x9439135e)\n#define list_item_youtube_comment (0x82a72645)\n#define button_yt_companel_comment_item (0x160347a5)\n#define template_scroll_item_youtube_comment_detail (0x18ae4e45)\n#define text_youtube_comment_detail (0x64dd9d5e)\n#define plane_comment_detail_separator (0x5376d048)\n#define text_youtube_comment_detail_body (0x7ab6ee5d)\n#define ja (0x84572ef2)\n#define en (0x094b0fe0)\n#define fr (0xb858a87c)\n#define es (0x09cd68a2)\n#define de (0x600ccd1b)\n#define it (0x6c5522ca)\n#define nl (0x595477bd)\n#define pt (0xbc811258)\n#define ru (0x67b8b1c4)\n#define ko (0x65a7da8f)\n#define fi (0x6b163fa3)\n#define sv (0x0a6190df)\n#define da (0xcdd4f874)\n#define no (0xfd128635)\n#define pl (0xf437cb07)\n#define tr (0xd9e83874)\n#define tex_yt_icon_search (0x9d4271de)\n#define tex_yt_icon_history (0xd7b56e3a)\n#define tex_yt_icon_favourite (0x007f29c1)\n#define tex_vertical_separator (0x497731c5)\n#define tex_button_pause (0x15a38e2c)\n#define tex_button_play (0xe662c1b8)\n#define tex_button_big_repeat (0x1c7a4609)\n#define tex_button_arrow_left (0x9c71909e)\n#define tex_button_arrow_right (0xd9857177)\n#define tex_button_settings (0x75dcaa15)\n#define tex_common_bg (0xa935e111)\n#define tex_fpmenu_icon_youtube (0xa84eb1aa)\n#define tex_fpmenu_icon_http (0x9a91af5d)\n#define tex_fpmenu_icon_ftp (0xa8d8a98c)\n#define tex_fpmenu_icon_local (0x01add48c)\n#define tex_fpmenu_icon_hvdb (0x850881d2)\n#define tex_file_icon_video (0x5aa46fb7)\n#define tex_file_icon_folder (0xdeab6c16)\n#define tex_file_icon_playlist (0xfb08ccb2)\n#define tex_file_icon_music (0xdd85e31c)\n#define tex_file_icon_unsupported (0x289b9013)\n#define tex_black (0x974eadf7)\n#define tex_button_expand (0xff3d36d8)\n#define tex_yt_icon_live_now (0x96343816)\n#define tex_yt_icon_favourite_for_player (0xf11b796d)\n#define tex_yt_icon_favourite_for_player_glow (0xbdb0e87f)\n#define file_netstream_settings (0x66adfd8d)\n#endif"
  },
  {
    "path": "NetStream/include/netstream_settings.h",
    "content": "#ifndef _netstream_settings_H_\n#define _netstream_settings_H_\n\n//\n//This file was generated automatically by psp2pafhshgen.exe\n//\n\n#define ns_setting (0x9ae4442b)\n#define http_setting (0x823282d5)\n#define http_host (0xbe7aa61b)\n#define http_port (0x4d5195ab)\n#define http_user (0x74bca4c7)\n#define http_password (0x1cc16d21)\n#define ftp_setting (0x72e40d3f)\n#define ftp_host (0xe1a509f3)\n#define ftp_port (0xef7b3626)\n#define ftp_user (0x89e77ea8)\n#define ftp_password (0x571003fe)\n#define ftp_nlst (0xd6f1d921)\n#define hvdb_account_setting (0x53adb9eb)\n#define hvdb_host (0x92199baf)\n#define hvdb_user (0x48230999)\n#define hvdb_password (0x24f1face)\n#define hvdb_search_setting (0x647436d9)\n#define list_hvdb_search_sort (0x4b1ffc49)\n#define list_hvdb_search_sort_00 (0xe48be6b0)\n#define list_hvdb_search_sort_01 (0xf456ace6)\n#define list_hvdb_search_sort_type (0x0d052e0a)\n#define list_hvdb_search_sort_type_00 (0xac31e72a)\n#define list_hvdb_search_sort_type_01 (0x599cece6)\n#define list_hvdb_search_sort_type_02 (0x2b00d21e)\n#define list_hvdb_search_sort_type_03 (0xbcc70780)\n#define list_hvdb_search_sort_type_04 (0x8c223f0b)\n#define list_hvdb_search_sort_type_05 (0x780c2ccc)\n#define list_hvdb_search_sort_type_06 (0xce32a1ca)\n#define list_hvdb_search_sort_type_07 (0xe3b428a8)\n#define list_hvdb_search_sort_type_08 (0x2e867622)\n#define list_hvdb_search_filter (0xfff9f55b)\n#define list_hvdb_search_filter_00 (0xff601f56)\n#define list_hvdb_search_filter_01 (0x14923727)\n#define list_hvdb_search_filter_02 (0xa208d4a8)\n#define list_hvdb_search_filter_03 (0x74b344f7)\n#define list_hvdb_search_filter_04 (0x4ada3bb1)\n#define list_hvdb_search_filter_05 (0x75f5ea81)\n#define hvdb_player_setting (0x7085ec8e)\n#define toggle_hvdb_banner (0x2f9d4916)\n#define local_setting (0x988ec70c)\n#define local_playlist_prefix (0xa088d09c)\n#define list_local_sort_name (0xf7bca884)\n#define list_local_sort_name_00 (0x8b449a7a)\n#define list_local_sort_name_01 (0xa0340593)\n#define list_local_sort_type (0x6e2b969f)\n#define list_local_sort_type_00 (0x8cca7adf)\n#define list_local_sort_type_01 (0x996d8e98)\n#define youtube_search_setting (0x47942f14)\n#define list_youtube_search_region (0x274ee177)\n#define list_youtube_search_region_00 (0xd5304921)\n#define list_youtube_search_sort (0xcf6d2a1c)\n#define list_youtube_search_sort_00 (0x43d23f6c)\n#define list_youtube_search_sort_01 (0xa6ae18f3)\n#define list_youtube_search_sort_02 (0x331188e8)\n#define list_youtube_search_sort_03 (0x0842641b)\n#define list_youtube_search_date (0xcdcb47c1)\n#define list_youtube_search_date_00 (0xe8d5f4d5)\n#define list_youtube_search_date_01 (0x98d22213)\n#define list_youtube_search_date_02 (0x98f72046)\n#define list_youtube_search_date_03 (0x154a251e)\n#define list_youtube_search_date_04 (0xf19b986e)\n#define list_youtube_search_date_05 (0x8f0eac16)\n#define list_youtube_search_dur (0x46241320)\n#define list_youtube_search_dur_00 (0x7eb02561)\n#define list_youtube_search_dur_01 (0x71920c7a)\n#define list_youtube_search_dur_02 (0xdc2a6509)\n#define list_youtube_search_dur_03 (0xf394dc0f)\n#define list_youtube_search_feature (0x1f3fe3e7)\n#define list_youtube_search_feature_00 (0xef4ef491)\n#define list_youtube_search_feature_01 (0x4a955857)\n#define text_field_youtube_search_proxy (0x76a42f88)\n#define youtube_comment_setting (0x83fbebce)\n#define list_youtube_comment_sort (0xec9209f7)\n#define llist_youtube_comment_sort_00 (0x4993c0b5)\n#define llist_youtube_comment_sort_01 (0x197955f2)\n#define youtube_quality_setting (0x962064f3)\n#define list_youtube_quality_vod_video (0x7a1e6972)\n#define list_youtube_quality_vod_video_00 (0xa56d44d5)\n#define list_youtube_quality_vod_video_01 (0x0c8bb609)\n#define list_youtube_quality_vod_video_02 (0xdc83cbc1)\n#define list_youtube_quality_vod_video_03 (0x51f96b07)\n#define list_youtube_quality_vod_video_04 (0x9c60d0ee)\n#define list_youtube_quality_vod_video_05 (0xfc7571be)\n#define list_youtube_quality_live (0x5e89b800)\n#define list_youtube_quality_live_00 (0x6eeed69e)\n#define list_youtube_quality_live_01 (0xf914faac)\n#define list_youtube_quality_live_02 (0x49637007)\n#define list_youtube_quality_live_03 (0xf4b1f21a)\n#define list_youtube_quality_live_04 (0x5c407879)\n#define youtube_player_setting (0xb7539596)\n#define toggle_youtube_min (0x32513d0c)\n#define cloud_sync_setting (0xfb02b78a)\n#define toggle_cloud_sync (0x2c7de826)\n#define toggle_cloud_sync_auto (0x59fcfe5e)\n#define verinfo_setting (0x45eb30eb)\n#define label_verinfo (0x804ff666)\n#endif"
  },
  {
    "path": "NetStream/include/np_utils.h",
    "content": "#ifndef _NP_UTILS_H_\n#define _NP_UTILS_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <np.h>\n\nusing namespace paf;\n\nnamespace nputils\n{\n\tclass TUS\n\t{\n\tpublic:\n\n\t\tTUS();\n\n\t\t~TUS();\n\n\t\tint32_t Init();\n\n\t\tint32_t Term();\n\n\t\tint32_t UploadFile(uint32_t slot, const char *path);\n\n\t\tint32_t DownloadFile(uint32_t slot, const char *path);\n\n\t\tint32_t UploadString(uint32_t slot, const string& data);\n\n\t\tint32_t DownloadString(uint32_t slot, string& data);\n\n\t\tint32_t GetDataStatus(uint32_t slot, SceNpTusDataStatus *status);\n\n\t\tint32_t DeleteData(uint32_t slot);\n\n\t\tint32_t DeleteData(const vector<uint32_t> *slots);\n\n\tprivate:\n\n\t\tSceNpId m_npid;\n\t\tint32_t m_ctx;\n\t};\n\n\tint32_t PreInit(thread::SyncCall::Function onComplete);\n\n\tint32_t Init(const char *tag = NULL, bool needTUS = false, const vector<uint32_t> *usedTUSSlots = NULL);\n\n\tint32_t Term();\n\n\tbool IsAllGreen();\n\n\tTUS *GetTUS();\n\n\tint32_t NetDialogInit(void *data);\n\n\tvoid NetDialogCheck(void *data);\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/include/option_menu.h",
    "content": "#ifndef _OPTION_MENU_H_\n#define _OPTION_MENU_H_\n\n#include <kernel.h>\n#include <paf.h>\n\nusing namespace paf;\n\n#define OPTION_MENU_BUTTON_MAGIC 0xa5448baf\n\nclass OptionMenu\n{\npublic:\n\n\tenum\n\t{\n\t\tOptionMenuEvent = (ui::Handler::CB_STATE + 0x50000),\n\t};\n\n\tenum OptionMenuEvent\n\t{\n\t\tOptionMenuEvent_Button,\n\t\tOptionMenuEvent_Close\n\t};\n\n\tclass Button\n\t{\n\tpublic:\n\n\t\twstring label;\n\t};\n\n\tOptionMenu(Plugin *workPlugin, ui::Widget *root, vector<Button> *buttons);\n\n\t~OptionMenu();\n\nprivate:\n\n\tstatic void OnSizeAdjust(int32_t type, ui::Handler *self, ui::Event *e, void *userdata);\n\tvoid OnButton(ui::Widget *wdg);\n\n\tPlugin *m_plugin;\n\tui::Scene *m_rootScene;\n\tui::Widget *m_parentRoot;\n\tui::Widget *m_optPlaneRoot;\n\tuint32_t m_buttonCount;\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/include/players/player_av.h",
    "content": "#ifndef _AV_PLAYER_H_\n#define _AV_PLAYER_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <sceavplayer_webmaf.h>\n#include <psp2_compat/curl/curl.h>\n\n#include \"common.h\"\n#include \"players/player_generic.h\"\n#include <paf_file_ext.h>\n\nusing namespace paf;\n\nclass AVPlayer : public GenericPlayer\n{\npublic:\n\n\tclass Option : public GenericPlayer::Option\n\t{\n\tpublic:\n\n\t\tOption()\n\t\t{\n\t\t\tplayerType = PlayerType_AV;\n\t\t}\n\t};\n\n\tclass BootJob : public job::JobItem\n\t{\n\tpublic:\n\n\t\tBootJob(AVPlayer *parent) : job::JobItem(\"AVPlayer::BootJob\", NULL), m_parent(parent)\n\t\t{\n\n\t\t}\n\n\t\t~BootJob() {}\n\n\t\tint32_t Run()\n\t\t{\n\t\t\tm_parent->OnBootJob();\n\t\t\treturn SCE_PAF_OK;\n\t\t}\n\n\t\tvoid Finish(int32_t result) {}\n\n\tprivate:\n\n\t\tAVPlayer *m_parent;\n\t};\n\n\tAVPlayer(ui::Widget *targetPlane, const char *url, Option *opt);\n\n\t~AVPlayer();\n\n\tvoid InitAsync();\n\n\tvoid Term();\n\n\tInitState GetInitState();\n\n\tuint32_t GetTotalTimeMs();\n\n\tuint32_t GetCurrentTimeMs();\n\n\tbool JumpToTimeMs(uint32_t time);\n\n\tvoid SwitchPlaybackState();\n\n\tbool IsPaused();\n\n\tPlayerState GetState();\n\n\tvoid SetPowerSaving(bool enable);\n\n\tuint32_t GetVideoRepresentationNum();\n\n\tuint32_t GetAudioRepresentationNum();\n\n\tvoid GetActiveRepresentationsInfo(StreamInfo::RepresentationInfo *info);\n\n\tstatic void PreInit();\n\n\tstatic SupportType IsSupported(const char *path);\n\n\tstatic const char *GetVersion();\n\nprivate:\n\n\tenum SeekState\n\t{\n\t\tSeekState_Ok,\n\t\tSeekState_Waiting,\n\t\tSeekState_Failed\n\t};\n\n\tclass SmoothStreaming\n\t{\n\tpublic:\n\n\t\tSmoothStreaming();\n\t\t~SmoothStreaming();\n\n\t\tstatic void GetLiveReplacement(SceAvPlayerHttpReplacement *repl);\n\t\tstatic void GetVODReplacement(SceAvPlayerFileReplacement *repl);\n\n\tprivate:\n\n\t\tstatic size_t CurlDownload(char *buffer, size_t size, size_t nitems, void *userdata);\n\n\t\tint64_t LivePostImpl(char *url, bool continuation,\n\t\t\tSceAvPlayerHTTPHeader *headers, uint8_t numHeaders, uint8_t *body, uint32_t len,\n\t\t\tuint8_t *buf, uint32_t bufLen, bool *completed);\n\t\tint64_t LiveGetImpl(char *url, bool continuation, uint64_t rangeStart, uint64_t rangeEnd, uint8_t *buf, uint32_t bufLen, bool *completed);\n\t\tint32_t GetLastStatusImpl();\n\t\tint64_t GetFileSizeImpl();\n\n\t\tint32_t VodOpenFileImpl(const char *argFilename);\n\t\tint32_t VodCloseFileImpl();\n\t\tint32_t VodReadOffsetFileImpl(uint8_t *argBuffer, uint64_t argPosition, uint32_t argLength);\n\t\tuint64_t VodSizeFileImpl();\n\n\t\tstatic SmoothStreaming *s_vodObjStorage;\n\n\t\tCURL *m_curl;\n\t\tint32_t m_lastError;\n\t\tbool m_hasRange;\n\t\tbool m_downloadDone;\n\t\tuint32_t m_total;\n\t\tuint32_t m_readSz;\n\t\tuint64_t m_rangeStart;\n\t\tuint64_t m_rangeEnd;\n\t\tuint8_t *m_tmpBuf;\n\t\tcommon::SharedPtr<File> m_vod;\n\t\tcommon::SharedPtr<Buffer> m_vodBuf;\n\t\tPredictiveFile *m_prVod;\n\t};\n\n\tclass AVAudioThread : public thread::Thread\n\t{\n\tpublic:\n\n\t\tAVAudioThread(AVPlayer *parent, SceAvPlayerHandle core, Option *option) :\n\t\t\tthread::Thread(SCE_KERNEL_DEFAULT_PRIORITY_USER - 10, SCE_KERNEL_16KiB, \"AVAudioThread\", option)\n\t\t{\n\t\t\tm_parent = parent;\n\t\t\tm_playerCore = core;\n\t\t}\n\n\t\tvoid EntryFunction();\n\n\tprivate:\n\n\t\tAVPlayer *m_parent;\n\t\tSceAvPlayerHandle m_playerCore;\n\t};\n\n\tstatic void SurfaceUpdateTask(void *pArgBlock);\n\n\tstatic void *PlayerAllocate(void *jumpback, uint32_t alignment, uint32_t size);\n\n\tstatic void PlayerDeallocate(void *jumpback, void *pMemory);\n\n\tstatic void *PlayerAllocateTexture(void *jumpback, uint32_t alignment, uint32_t size);\n\n\tstatic void PlayerDeallocateTexture(void *jumpback, void *pMemory);\n\n\tstatic void PlayerChangeStateCb(void *instance, int32_t argEventId, int32_t argSourceId, void *argEventData);\n\n\tvoid OnSurfaceUpdate();\n\tvoid OnBootJob();\n\tvoid OnPlayerWarning(const char *format, _Va_list ap);\n\n\tvoid SetState(int32_t argEventId);\n\n\tvoid SetInitState(InitState state);\n\n\tvoid ParseStreamInfo();\n\n\tSceAvPlayerHandle m_playerCore;\n\tOption m_opt;\n\tstring m_basePath;\n\tvector<uint32_t> m_curSubIdx;\n\tvector<uint32_t> m_prevSubIdx;\n\tSceAvPlayerVideo m_lastVideoDetails;\n\tSceAvPlayerAudio m_lastAudioDetails;\n\tint32_t m_currentVideoStreamId;\n\tint32_t m_currentAudioStreamId;\n\tAVAudioThread *m_audioThread;\n\tPlayerState m_currentState;\n\tint64_t m_jumpTimeMs;\n\tpaf::map<uint64_t, intrusive_ptr<graph::Surface>> m_drawSurf;\n\tuint32_t m_duration;\n\tSeekState m_lastSeekState;\n\tbool m_ssStream;\n};\n\n#endif"
  },
  {
    "path": "NetStream/include/players/player_beav.h",
    "content": "#ifndef _BEAV_PLAYER_H_\n#define _BEAV_PLAYER_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <scebeavplayer.h>\n#include <taihen.h>\n\n#include \"common.h\"\n#include \"players/player_generic.h\"\n#include <paf_file_ext.h>\n\nusing namespace paf;\n\n#define BEAV_SURFACE_COUNT\t\t\t2\n#define BEAV_VIDEO_BUFFER_COUNT\t\t4\n#define BEAV_VIDEO_BUFFER_WIDTH\t\t1280\n#define BEAV_VIDEO_BUFFER_HEIGHT\t720\n#define BEAV_DECODE_BUFFER_SIZE\t\t(BEAV_VIDEO_BUFFER_WIDTH * BEAV_VIDEO_BUFFER_HEIGHT * 4 * BEAV_VIDEO_BUFFER_COUNT)\n#define BEAV_USER_AGENT\t\t\t\tUSER_AGENT\t\t\n\nclass BEAVPlayer : public GenericPlayer\n{\npublic:\n\n\tclass Option : public GenericPlayer::Option\n\t{\n\tpublic:\n\n\t\tenum Resolution : int32_t\n\t\t{\n\t\t\tResolution_144p,\n\t\t\tResolution_240p,\n\t\t\tResolution_360p,\n\t\t\tResolution_480p,\n\t\t\tResolution_720p\n\t\t};\n\n\t\tOption()\n\t\t{\n\t\t\tplayerType = PlayerType_BEAV;\n\t\t\tdefaultRes = Resolution_480p;\n\t\t}\n\n\t\tvoid Copy(Option &dst)\n\t\t{\n\t\t\tdst = *this;\n\t\t}\n\n\t\tResolution defaultRes;\n\t};\n\n\tclass LibLSInterface\n\t{\n\tpublic:\n\n\t\tstatic void Init();\n\t\tstatic void Term();\n\n\t\tstatic void GetReplacement(SceBeavCorePlayerLsInputPluginInterface *repl);\n\n\tprivate:\n\n\t\tLibLSInterface();\n\t\t~LibLSInterface();\n\n\t\tstatic size_t DownloadCore(char *buffer, size_t size, size_t nitems, void *userdata);\n\t\tstatic LSInputResult ConvertError(int err);\n\n\t\tLSInputResult Open(char *pcURI, uint64_t uOffset, uint32_t uTimeOutMSecs);\n\t\tLSInputResult GetSize(uint64_t *pSize);\n\t\tLSInputResult Read(void *pBuffer, uint32_t uSize, uint32_t uTimeOutMSecs, uint32_t *pReadSize);\n\t\tLSInputResult Abort();\n\t\tLSInputResult GetLastError(uint32_t *pNativeError);\n\n\t\tstatic CURL *s_fileCurl;\n\t\tstatic CURL *s_plCurl;\n\t\tstatic thread::RMutex s_plMtx;\n\t\tstatic thread::RMutex s_fileMtx;\n\n\t\tvoid *m_curl;\n\t\tint64_t m_readPos;\n\t\tvoid *m_buf;\n\t\tuint32_t m_pos;\n\t\tint32_t m_lastError;\n\t};\n\n\tclass BootJob : public job::JobItem\n\t{\n\tpublic:\n\n\t\tBootJob(BEAVPlayer *parent) : job::JobItem(\"BEAVPlayer::BootJob\", NULL), m_parent(parent)\n\t\t{\n\n\t\t}\n\n\t\t~BootJob() {}\n\n\t\tint32_t Run()\n\t\t{\n\t\t\tm_parent->OnBootJob();\n\t\t\treturn SCE_PAF_OK;\n\t\t}\n\n\t\tvoid Finish(int32_t result) {}\n\n\tprivate:\n\n\t\tBEAVPlayer *m_parent;\n\t};\n\n\tBEAVPlayer(ui::Widget *targetPlane, const char *url, Option *opt);\n\n\t~BEAVPlayer();\n\n\tvoid InitAsync();\n\n\tvoid Term();\n\n\tInitState GetInitState();\n\n\tuint32_t GetTotalTimeMs();\n\n\tuint32_t GetCurrentTimeMs();\n\n\tbool JumpToTimeMs(uint32_t time);\n\n\tvoid SwitchPlaybackState();\n\n\tbool IsPaused();\n\n\tPlayerState GetState();\n\n\tvoid SetPowerSaving(bool enable);\n\n\tuint32_t GetVideoRepresentationNum();\n\n\tuint32_t GetAudioRepresentationNum();\n\n\tvoid GetVideoRepresentationInfo(GenericRepresentationInfo *info, uint32_t idx);\n\n\tvoid SelectVideoRepresentation(uint32_t idx);\n\n\tvoid GetActiveRepresentationsInfo(StreamInfo::RepresentationInfo *info);\n\n\tstatic void PreInit();\n\n\tstatic SupportType IsSupported(const char *path);\n\n\tstatic const char *GetVersion();\n\nprivate:\n\n\tclass BEAVAudioThread : public thread::Thread\n\t{\n\tpublic:\n\n\t\tBEAVAudioThread(BEAVPlayer *parent, SceBeavCorePlayerHandle core, Option *option) :\n\t\t\tthread::Thread(SCE_KERNEL_HIGHEST_PRIORITY_USER + 1, SCE_KERNEL_16KiB, \"BEAVAudioThread\", option)\n\t\t{\n\t\t\tm_parent = parent;\n\t\t\tm_playerCore = core;\n\t\t}\n\n\t\tvoid EntryFunction();\n\n\tprivate:\n\n\t\tBEAVPlayer *m_parent;\n\t\tSceBeavCorePlayerHandle m_playerCore;\n\t};\n\n\tstatic void SurfaceUpdateTask(void *pArgBlock);\n\n\tstatic uint32_t GetFreeHeapSize();\n\n\tstatic LSResult LsErrorHandler(LSResult error, LSSession *session, LSStreamlist *streamlist, LSStreamfile *streamfile, void *userdata);\n\n\tstatic LSResult LsStatusHandler(LSStatus status, LSSession *session, LSStreamlist *streamlist, LSStreamfile *streamfile, void *userdata);\n\n\tstatic LSResult LsInitGlobalsHook(LSLibraryInitParams *params);\n\n\tvoid OnSurfaceUpdate();\n\tvoid OnBootJob();\n\n\tvoid SetInitState(InitState state);\n\n\tvoid ParseStreamInfo(LSStreamlist *streamlist, uint32_t scount);\n\n\tstatic SceBeavCorePlayerLibLSInterface s_liblsInterface;\n\tstatic tai_hook_ref_t s_liblsInitHookRef;\n\n\tSceBeavCorePlayerHandle m_playerCore;\n\tBEAVAudioThread *m_audioThread;\n\tvoid *m_decodeBuffer;\n\tLSStreamlist *m_currentLsStreamlist;\n\tOption m_opt;\n\tuint32_t m_lastVideoWidth;\n\tuint32_t m_lastVideoHeight;\n\tuint32_t m_lastAudioChannelCount;\n\tuint32_t m_lastAudioSampleRate;\n\tbool m_bootEarlyExit;\n\tpaf::map<uint64_t, intrusive_ptr<graph::Surface>> m_drawSurf;\n};\n\n#endif"
  },
  {
    "path": "NetStream/include/players/player_fmod.h",
    "content": "#ifndef _FMOD_PLAYER_H_\n#define _FMOD_PLAYER_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <fmod/fmod.hpp>\n\n#include \"common.h\"\n#include \"players/player_generic.h\"\n\nusing namespace paf;\n\nclass FMODPlayer : public GenericPlayer\n{\npublic:\n\n\tclass Option : public GenericPlayer::Option\n\t{\n\tpublic:\n\n\t\tOption()\n\t\t{\n\t\t\tplayerType = PlayerType_FMOD;\n\t\t}\n\t};\n\n\tclass BootJob : public job::JobItem\n\t{\n\tpublic:\n\n\t\tBootJob(FMODPlayer *parent) : job::JobItem(\"FMODPlayer::BootJob\", NULL), m_parent(parent)\n\t\t{\n\n\t\t}\n\n\t\t~BootJob() {}\n\n\t\tint32_t Run()\n\t\t{\n\t\t\tm_parent->OnBootJob();\n\t\t\treturn SCE_PAF_OK;\n\t\t}\n\n\t\tvoid Finish(int32_t result) {}\n\n\tprivate:\n\n\t\tFMODPlayer *m_parent;\n\t};\n\n\tFMODPlayer(ui::Widget *targetPlane, const char *url, Option *opt);\n\n\t~FMODPlayer();\n\n\tvoid InitAsync();\n\n\tvoid Term();\n\n\tInitState GetInitState();\n\n\tuint32_t GetTotalTimeMs();\n\n\tuint32_t GetCurrentTimeMs();\n\n\tbool JumpToTimeMs(uint32_t time);\n\n\tvoid SwitchPlaybackState();\n\n\tbool IsPaused();\n\n\tPlayerState GetState();\n\n\tvoid SetPowerSaving(bool enable);\n\n\tuint32_t GetAudioRepresentationNum();\n\n\tstatic void PreInit();\n\n\tstatic SupportType IsSupported(const char *path);\n\n\tstatic const char *GetVersion();\n\nprivate:\n\n\tclass HybridInterface\n\t{\n\tpublic:\n\n\t\tstatic FMOD_RESULT Open(const char *name, unsigned int *filesize, void **handle, void *userdata);\n\t\tstatic FMOD_RESULT Close(void *handle, void *userdata);\n\t\tstatic FMOD_RESULT Read(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread, void *userdata);\n\t\tstatic FMOD_RESULT Seek(void *handle, unsigned int pos, void *userdata);\n\t};\n\n\tstatic void UpdateTask(void *pArgBlock);\n\n\tvoid OnBootJob();\n\n\tvoid SetInitState(InitState state);\n\n\tstatic FMOD::System *s_system;\n\tstatic FMOD::ChannelGroup *s_chg;\n\n\tFMOD::Sound *m_snd;\n\tFMOD::Channel *m_ch;\n\tOption m_opt;\n};\n\n#endif"
  },
  {
    "path": "NetStream/include/players/player_generic.h",
    "content": "#ifndef _GENERIC_PLAYER_H_\n#define _GENERIC_PLAYER_H_\n\n#include <kernel.h>\n#include <paf.h>\n\nusing namespace paf;\n\nclass GenericPlayer\n{\npublic:\n\n\tenum\n\t{\n\t\tGenericPlayerChangeState = (ui::Handler::CB_STATE + 0x20000),\t// Event base for all Players\n\t};\n\n\tenum SupportType\n\t{\n\t\tSupportType_NotSupported,\t\t// File is definetely not supported\n\t\tSupportType_Supported,\t\t\t// File is supported\n\t\tSupportType_MaybeSupported\t\t// File support cannot be determined\n\t};\n\n\tenum InitState\n\t{\n\t\tInitState_NotInit,\t\t\t\t// Initial Player state after constructing\n\t\tInitState_InProgress,\t\t\t// Initialization is in progress\n\t\tInitState_InitOk,\t\t\t\t// Initialization has been successfull\n\t\tInitState_InitFail\t\t\t\t// Initialization failed\n\t};\n\n\tenum PlayerState\n\t{\n\t\tPlayerState_Stop = 0x00,\t\t// Player is stopped\n\t\tPlayerState_Ready = 0x01,\t\t// Player is ready to start playback\n\t\tPlayerState_Play = 0x02,\t\t// Player is playing\n\t\tPlayerState_Pause = 0x03,\t\t// Player is paused\n\t\tPlayerState_Buffering = 0x04,\t// Player is buffering\n\t\tPlayerState_Eof = 0x23\t\t\t// Player has reached end of the stream\n\t};\n\n\tenum PlayerType\n\t{\n\t\tPlayerType_Auto,\t\t\t\t// Player type is not determined, use auto detection\n\t\tPlayerType_BEAV,\t\t\t\t// SceBEAVCorePlayer\n\t\tPlayerType_AV,\t\t\t\t\t// WebMAF SceAvPlayer\n\t\tPlayerType_FMOD\t\t\t\t\t// FMOD\n\t};\n\n\tenum StreamType\n\t{\n\t\tStreamType_Video,\t\t\t\t// Video stream\n\t\tStreamType_Audio\t\t\t\t// Audio stream\n\t};\n\n\t/**\n\t * Generic representation info, needed for UI purposes\n\t */\n\tclass GenericRepresentationInfo\n\t{\n\tpublic:\n\n\t\tGenericRepresentationInfo()\n\t\t{\n\t\t\ttype = StreamType_Video;\n\t\t\tcurrentlySelected = false;\n\t\t\tenabled = true;\n\t\t}\n\n\t\tStreamType type;\t\t\t// Base stream type for this representation\n\t\twstring string;\t\t\t\t// Representation name string, e.g. \"1280x720\"\n\t\tbool currentlySelected;\t\t// Representation is currently selected for the baser stream\n\t\tbool enabled;\t\t\t\t// Representation is enabled within the Player and can be selected\n\t};\n\n\t/**\n\t * AV stream information\n\t */\n\tclass StreamInfo\n\t{\n\tpublic:\n\n\t\t/**\n\t\t * AV stream representation information\n\t\t */\n\t\tclass RepresentationInfo\n\t\t{\n\t\tpublic:\n\n\t\t\tRepresentationInfo()\n\t\t\t{\n\t\t\t\tbitrate = 0;\n\t\t\t\twidth = 0;\n\t\t\t\theight = 0;\n\t\t\t\tch = 0;\n\t\t\t\tsrate = 0;\n\t\t\t}\n\n\t\t\tuint32_t bitrate;\t// Bitrate in kbps\t\n\t\t\tuint32_t width;\t\t// Width in pixels\n\t\t\tuint32_t height;\t// Height in pixels\n\t\t\tuint16_t ch;\t\t// Number of audio channels\n\t\t\tuint32_t srate;\t\t// Audio sampling rate in Hz\n\t\t};\n\n\t\tStreamType type;\t\t\t\t\t\t\t// Stream type\n\t\tvector<RepresentationInfo> representation;\t// Representations available for the current stream\n\t};\n\n\t/**\n\t * Optional structure that contains Player options passed during creation of the object\n\t */\n\tclass Option\n\t{\n\tpublic:\n\n\t\tOption()\n\t\t{\n\t\t\tplayerType = PlayerType_Auto;\n\t\t}\n\n\t\tvoid CommonCopy(Option& dst)\n\t\t{\n\t\t\tdst = *this;\n\t\t}\n\n\t\tPlayerType playerType;\t// This Player type. Must be set to the appropriate player type\n\t\tstring auxStreamUrl;\t// Aux stream url. Depends on the player type\n\t};\n\n\t/**\n\t * Creates player instance. This method shouldn't do any long term blocking processing, move it to InitAsync().\n\t */\n\tGenericPlayer() : m_target(NULL), m_initState(InitState_NotInit), m_powerSaving(false)\n\t{\n\n\t}\n\n\t/**\n\t * Destructs player instance.\n\t */\n\tvirtual ~GenericPlayer()\n\t{\n\n\t}\n\n\t/**\n\t * Initializes player asynchronously to the main framework thread.\n\t */\n\tvirtual void InitAsync() = 0;\n\n\t/**\n\t * Terminates player.\n\t */\n\tvirtual void Term() = 0;\n\n\t/**\n\t * Gets current state of the init process started with InitAsync().\n\t *\n\t * @return Current init process status.\n\t */\n\tvirtual InitState GetInitState() = 0;\n\n\t/**\n\t * Gets total duration of the media in milliseconds if available, 0 otherwise (ex. if live).\n\t *\n\t * @return Total duration of the media in milliseconds if available, 0 otherwise (ex. if live).\n\t */\n\tvirtual uint32_t GetTotalTimeMs() = 0;\n\n\t/**\n\t * Gets current timestamp of the media in milliseconds if available, 0 otherwise (ex. if live).\n\t *\n\t * @return Current timestamp of the media in milliseconds if available, 0 otherwise (ex. if live).\n\t */\n\tvirtual uint32_t GetCurrentTimeMs() = 0;\n\n\t/**\n\t * Jumps to the timestamp, if possible.\n\t *\n\t * @param[in] time - Jump destination time in milliseconds.\n\t *\n\t * @return true if jump was executed, false otherwise (ex. if live).\n\t */\n\tvirtual bool JumpToTimeMs(uint32_t time) = 0;\n\n\t/**\n\t * Switches playback state from play to pause in cycle.\n\t */\n\tvirtual void SwitchPlaybackState() = 0;\n\n\t/**\n\t * Check if player is paused.\n\t *\n\t * @return true if paused, false otherwise.\n\t */\n\tvirtual bool IsPaused() = 0;\n\n\t/**\n\t * Gets current state of the player.\n\t *\n\t * @return Current state of the player.\n\t */\n\tvirtual PlayerState GetState() = 0;\n\n\t/**\n\t * Sets power saving mode. The call to this function indicates that player should enable all power saving features available to it.\n\t * In power saving mode player must output audio, but may not output video.\n\t *\n\t * @param[in] enable - True if power saving mode should be enabled.\n\t */\n\tvirtual void SetPowerSaving(bool enable) = 0;\n\n\t/**\n\t * Gets total amount of the video representations in the current media. If representation selection feature for video is not available,\n\t * this method must return 1. If player doen't support video playback, this method must return 0\n\t *\n\t * @return Total amount of the video representations in the current media.\n\t */\n\tvirtual uint32_t GetVideoRepresentationNum()\n\t{\n\t\treturn 0;\n\t}\n\n\t/**\n\t * Gets total amount of the audio representations in the current media. If representation selection feature for audio is not available,\n\t * this method must return 1. If player doen't support audio playback, this method must return 0\n\t *\n\t * @return Total amount of the audio representations in the current media.\n\t */\n\tvirtual uint32_t GetAudioRepresentationNum()\n\t{\n\t\treturn 0;\n\t}\n\n\t/**\n\t * Gets basic video representation info. May be left unimplemented if player doesn't support video representation selection or video playback.\n\t *\n\t * @param[in] info - Basic representation info.\n\t * @param[in] idx - Index of the target representation, max is GetVideoRepresentationNum() - 1.\n\t */\n\tvirtual void GetVideoRepresentationInfo(GenericRepresentationInfo *info, uint32_t idx)\n\t{\n\n\t}\n\n\t/**\n\t * Gets basic audio representation info. May be left unimplemented if player doesn't support audio representation selection or audio playback.\n\t *\n\t * @param[in] info - Basic representation info.\n\t * @param[in] idx - Index of the target representation, max is GetAudioRepresentationNum() - 1.\n\t */\n\tvirtual void GetAudioRepresentationInfo(GenericRepresentationInfo *info, uint32_t idx)\n\t{\n\n\t}\n\n\t/**\n\t * Select video representation. May be left unimplemented if player doesn't support video representation selection or video playback.\n\t *\n\t * @param[in] idx - Index of the target representation, max is GetVideoRepresentationNum() - 1.\n\t */\n\tvirtual void SelectVideoRepresentation(uint32_t idx)\n\t{\n\n\t}\n\n\t/**\n\t * Select audio representation. May be left unimplemented if player doesn't support audio representation selection or audio playback.\n\t *\n\t * @param[in] idx - Index of the target representation, max is GetAudioRepresentationNum() - 1.\n\t */\n\tvirtual void SelectAudioRepresentation(uint32_t idx)\n\t{\n\n\t}\n\n\t/**\n\t * Gets technical information about currently selected video and audio representations.\n\t *\n\t * @param[in] info - Representation info.\n\t */\n\tvirtual void GetActiveRepresentationsInfo(StreamInfo::RepresentationInfo *info)\n\t{\n\n\t}\n\nprotected:\n\n\tui::Widget *m_target;\t\t\t// Widget used for video rendering\n\tstring m_path;\t\t\t\t\t// Target stream path\n\tInitState m_initState;\t\t\t// Current initialization state\n\tvector<StreamInfo> m_streams;\t// AV stream information\n\tbool m_powerSaving;\t\t\t\t// Indicates if power saving is enabled, see SetPowerSaving()\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/include/subs/subs_generic.h",
    "content": "#ifndef _GENERIC_SUBS_H_\n#define _GENERIC_SUBS_H_\n\n#include <kernel.h>\n#include <paf.h>\n\nusing namespace paf;\n\nclass GenericSubtitles\n{\npublic:\n\n\tenum SubtitlesType\n\t{\n\t\tSubtitlesType_Auto,\t\t\t\t// Subtitles type is not determined, use auto detection\n\t\tSubtitlesType_SRT,\t\t\t\t// SubRip\n\t};\n\n\tenum SupportType\n\t{\n\t\tSupportType_NotSupported,\t\t// File is definetely not supported\n\t\tSupportType_Supported\t\t\t// File is supported\n\t};\n\n\tclass SubtitleEntry\n\t{\n\tpublic:\n\n\t\tSubtitleEntry()\n\t\t{\n\t\t\tcolor = math::v4::_0000();\n\t\t\tposition = math::v4::_0000();\n\t\t\tstartTime = 0;\n\t\t\tendTime = 0;\n\t\t\tcharSizeScale = 1.0f;\n\t\t\tanchorX = ui::Widget::ANCHOR_CENTER;\n\t\t\tanchorY = ui::Widget::ANCHOR_CENTER;\n\t\t\talignX = ui::Widget::ALIGN_NONE;\n\t\t\talignY = ui::Widget::ALIGN_NONE;\n\t\t}\n\n\t\twstring string;\t\t\t// Text string\n\t\tuint64_t startTime;\t\t// Start time in ms\n\t\tuint64_t endTime;\t\t// End time in ms\n\t\tfloat charSizeScale;\t// Additional scaling for the base character size\n\t\tmath::v4 color;\n\t\tuint32_t colorPacked;\n\t\tmath::v4 position;\n\t\tuint32_t anchorX;\n\t\tuint32_t anchorY;\n\t\tuint32_t alignX;\n\t\tuint32_t alignY;\n\t};\n\n\t/**\n\t * Optional structure that contains Subtitles options passed during creation of the object\n\t */\n\tclass Option\n\t{\n\tpublic:\n\n\t\tOption()\n\t\t{\n\t\t\tsubtitlesType = SubtitlesType_Auto;\n\t\t}\n\n\t\tSubtitlesType subtitlesType;\t// This Subtitles type. Must be set to the appropriate subtitles type\n\t};\n\n\tclass SystemSettings\n\t{\n\tpublic:\n\n\t\tSystemSettings()\n\t\t{\n\t\t\tenable = false;\n\t\t\tsize = 0;\n\t\t\tedge = 0;\n\t\t\tfontType = 0;\n\t\t}\n\n\t\tint32_t enable;\n\t\tint32_t size;\n\t\tint32_t edge;\n\t\tint32_t fontType;\n\t};\n\n\tstatic void GetSystemSettings(SystemSettings& settings);\n\n\t/**\n\t * Creates subtitles instance\n\t */\n\tGenericSubtitles();\n\n\t/**\n\t * Destructs subtitles instance\n\t */\n\tvirtual ~GenericSubtitles();\n\n\t/**\n\t * Initializes subtitles asynchronously to the main framework thread\n\t */\n\tvirtual void InitAsync() = 0;\n\n\tvoid GetActiveSubtitleIndices(vector<uint32_t>& result, uint64_t currentTimeMs);\n\n\tvector<SubtitleEntry> const& GetSubtitlieEntries();\n\nprotected:\n\n\tstring m_path;\t\t\t\t\t\t// Subtitles file path\n\tvector<SubtitleEntry> m_entries;\t// Actual subtitle entries\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/include/subs/subs_srt.h",
    "content": "#ifndef _SRT_SUBS_H_\n#define _SRT_SUBS_H_\n\n#include <kernel.h>\n#include <paf.h>\n\n#include \"subs/subs_generic.h\"\n\nusing namespace paf;\n\nclass SRTSubtitles : public GenericSubtitles\n{\npublic:\n\n\tclass Option : public GenericSubtitles::Option\n\t{\n\tpublic:\n\n\t\tOption()\n\t\t{\n\t\t\tsubtitlesType = SubtitlesType_SRT;\n\t\t}\n\n\t\tSubtitlesType subtitlesType;\n\t};\n\n\tSRTSubtitles(const char *videoPath, Option *opt);\n\n\t~SRTSubtitles() override;\n\n\tvoid InitAsync() override;\n\n\tstatic SupportType IsSupported(const char *videoPath);\n\nprivate:\n\n\tenum SrtPosition\n\t{\n\t\tSRT_POSITION_BOTTOM_DEFAULT,\n\t\tSRT_POSITION_BOTTOM_LEFT,\n\t\tSRT_POSITION_BOTTOM_CENTER,\n\t\tSRT_POSITION_BOTTOM_RIGHT,\n\t\tSRT_POSITION_MIDDLE_LEFT,\n\t\tSRT_POSITION_MIDDLE_CENTER,\n\t\tSRT_POSITION_MIDDLE_RIGHT,\n\t\tSRT_POSITION_TOP_LEFT,\n\t\tSRT_POSITION_TOP_CENTER,\n\t\tSRT_POSITION_TOP_RIGHT\n\t};\n\n\tclass BootJob : public job::JobItem\n\t{\n\tpublic:\n\n\t\tBootJob(SRTSubtitles *parent) : job::JobItem(\"SRTSubtitles::BootJob\", NULL), m_parent(parent)\n\t\t{\n\n\t\t}\n\n\t\t~BootJob() {}\n\n\t\tint32_t Run()\n\t\t{\n\t\t\tm_parent->OnBootJob();\n\t\t\treturn SCE_PAF_OK;\n\t\t}\n\n\t\tvoid Finish(int32_t result) {}\n\n\tprivate:\n\n\t\tSRTSubtitles *m_parent;\n\t};\n\n\tclass SrtMemFile\n\t{\n\tpublic:\n\n\t\tSrtMemFile(common::SharedPtr<File> file)\n\t\t{\n\t\t\tm_pos = 0;\n\t\t\tm_size = file->GetFileSize();\n\t\t\tm_mem = new char[m_size];\n\t\t\tif (!m_mem)\n\t\t\t{\n\t\t\t\tm_size = 0;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfile->Read(m_mem, m_size);\n\t\t}\n\n\t\t~SrtMemFile()\n\t\t{\n\t\t\tdelete m_mem;\n\t\t}\n\n\t\tint32_t Fgetc()\n\t\t{\n\t\t\tif (m_pos >= m_size)\n\t\t\t{\n\t\t\t\treturn EOF;\n\t\t\t}\n\n\t\t\tint32_t ret = static_cast<int32_t>(m_mem[m_pos]);\n\t\t\tm_pos++;\n\n\t\t\treturn ret;\n\t\t}\n\n\t\tchar *Fgets(char *s, int32_t n)\n\t\t{\n\t\t\tint32_t i = 0;\n\t\t\tint32_t c = 0;\n\t\t\tif (n <= 0) return s;\n\t\t\tfor (i = 0; i < n - 1; i++)\n\t\t\t{\n\t\t\t\tc = Fgetc();\n\t\t\t\tif (c == EOF)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\ts[i] = c;\n\t\t\t\tif (c == '\\n')\n\t\t\t\t{\n\t\t\t\t\t++i;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (c == EOF)\n\t\t\t{\n\t\t\t\tif (i != 0)  s[i] = '\\0';\n\t\t\t\treturn NULL;\n\t\t\t}\n\t\t\ts[i] = '\\0';\n\t\t\treturn s;\n\t\t}\n\n\tprivate:\n\n\t\tchar *m_mem;\n\t\tuint32_t m_size;\n\t\tuint32_t m_pos;\n\t\tchar m_dummy;\n\t};\n\n\tvoid OnBootJob();\n\n\tvoid ParseSrt(common::SharedPtr<File> file);\n\n\tstatic uint64_t GetMilliseconds(const char *time);\n\n\tstatic int32_t GetSize(const char *dialog);\n\n\tstatic uint32_t GetColor(const char *dialog);\n\n\tstatic SrtPosition GetPosition(const char *dialog);\n\n\tstatic char *CleanSrtDialog(char *dialog);\n\n\tstatic math::v4 ConvertColor(uint32_t color);\n\n\tstatic const char *s_srtDelim;\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/include/tex_pool.h",
    "content": "#ifndef _TEX_POOL_H_\n#define _TEX_POOL_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <paf_file_ext.h>\n\n#include \"event.h\"\n\nusing namespace paf;\n\nclass TexPool\n{\npublic:\n\n\ttypedef void(*OnAddAsyncComplete)(uint32_t hash, bool result, void *pArgBlock);\n\n\tTexPool(Plugin *_cbPlugin = NULL, bool useDefaultQueue = false);\n\n\t~TexPool();\n\n\tvoid DestroyAsync();\n\n\tintrusive_ptr<graph::Surface> Get(IDParam const& id);\n\n\tbool Add(Plugin *plugin, IDParam const& id, bool allowReplace = false);\n\tbool Add(IDParam const& id, uint8_t *buffer, size_t bufferSize, bool allowReplace = false);\n\tbool Add(IDParam const& id, const char *path, bool allowReplace = false);\n\tbool Add(IDParam const& id, intrusive_ptr<graph::Surface>& surf, bool allowReplace = false);\n\n\tbool AddAsync(IDParam const& id, uint8_t *buffer, size_t bufferSize, bool allowReplace = false);\n\tbool AddAsync(IDParam const& id, const char *path, bool allowReplace = false);\n\n\tvoid Remove(IDParam const& id);\n\tvoid RemoveAll();\n\n\tbool Exist(IDParam const& id);\n\n\tvoid AddAsyncWaitComplete();\n\tint32_t AddAsyncActiveNum();\n\tvoid AddAsyncCancelPending();\n\n\tuint32_t GetSize();\n\n\tinline void SetShare(CurlFile::Share *sh)\n\t{\n\t\tm_share = sh;\n\t}\n\n\tinline bool IsAlive()\n\t{\n\t\treturn m_alive;\n\t}\n\n\tinline void SetAlive(bool value)\n\t{\n\t\tm_alive = value;\n\t}\n\nprivate:\n\n\tclass AddAsyncJob : public job::JobItem\n\t{\n\tpublic:\n\n\t\tAddAsyncJob(TexPool *parent, uint32_t hash, uint8_t *buf, size_t bufSize) :\n\t\t\tjob::JobItem(\"TexPool::AddAsyncJob\", NULL), m_parent(parent), m_hash(hash), m_buf(buf), m_bufSize(bufSize)\n\t\t{\n\n\t\t}\n\n\t\tAddAsyncJob(TexPool *parent, uint32_t hash, const string& path) :\n\t\t\tjob::JobItem(\"TexPool::AddAsyncJob\", NULL), m_parent(parent), m_hash(hash), m_buf(NULL), m_path(path)\n\t\t{\n\n\t\t}\n\n\t\t~AddAsyncJob()\n\t\t{\n\n\t\t}\n\n\t\tint32_t Run()\n\t\t{\n\t\t\tbool result = false;\n\n\t\t\tif (m_buf)\n\t\t\t{\n\t\t\t\tresult = m_parent->Add(m_hash, m_buf, m_bufSize, true);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tresult = m_parent->Add(m_hash, m_path.c_str(), true);\n\t\t\t}\n\n\t\t\tif (result && m_parent->IsAlive() && m_parent->m_cbPlugin)\n\t\t\t{\n\t\t\t\tevent::BroadcastGlobalEvent(m_parent->m_cbPlugin, ui::Handler::CB_STATE_READY_CACHEIMAGE, m_hash);\n\t\t\t}\n\n\t\t\treturn SCE_PAF_OK;\n\t\t}\n\n\t\tvoid Finish(int32_t result)\n\t\t{\n\n\t\t}\n\n\tprivate:\n\n\t\tTexPool *m_parent;\n\t\tuint8_t *m_buf;\n\t\tsize_t m_bufSize;\n\t\tuint32_t m_hash;\n\t\tstring m_path;\n\t};\n\n\tclass DestroyJob : public job::JobItem\n\t{\n\tpublic:\n\n\t\tDestroyJob(TexPool *parent) : job::JobItem(\"TexPool::DestroyJob\", NULL), m_parent(parent)\n\t\t{\n\n\t\t}\n\n\t\t~DestroyJob()\n\t\t{\n\n\t\t}\n\n\t\tint32_t Run()\n\t\t{\n\t\t\tdelete m_parent;\n\n\t\t\treturn SCE_PAF_OK;\n\t\t}\n\n\t\tvoid Finish(int32_t result)\n\t\t{\n\n\t\t}\n\n\tprivate:\n\n\t\tTexPool *m_parent;\n\t};\n\n\tvoid RemoveForReplace(IDParam const& id);\n\n\tbool AddHttp(IDParam const& id, const char *path);\n\n\tbool AddLocal(IDParam const& id, const char *path);\n\n\tmap<uint32_t, intrusive_ptr<graph::Surface>> m_stor;\n\tCurlFile::Share *m_share;\n\tthread::RMutex *m_storMtx;\n\tjob::JobQueue *m_addAsyncQueue;\n\tbool m_alive;\n\tPlugin *m_cbPlugin;\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/include/tw_utils.h",
    "content": "#ifndef _TWUTILS_H_\n#define _TWUTILS_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <ini_file_processor.h>\n\nusing namespace paf;\n\nnamespace twutils\n{\n\tclass Log\n\t{\n\tpublic:\n\n\t\tclass AddAsyncJob : public job::JobItem\n\t\t{\n\t\tpublic:\n\n\t\t\tAddAsyncJob(Log *parent, const char *data) : job::JobItem(\"twutils::AddAsyncJob\", NULL), m_parent(parent), m_data(data)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~AddAsyncJob() {}\n\n\t\t\tint32_t Run();\n\n\t\t\tvoid Finish(int32_t result) {}\n\n\t\tprivate:\n\n\t\t\tLog *m_parent;\n\t\t\tstring m_data;\n\t\t};\n\n\t\tLog()\n\t\t{\n\n\t\t}\n\n\t\tvirtual ~Log()\n\t\t{\n\t\t\tm_ini->flush();\n\t\t\tm_ini->close();\n\t\t\tdelete m_ini;\n\t\t}\n\n\t\tvirtual int32_t GetNext(char *data);\n\n\t\tvirtual int32_t Get(const char *data);\n\n\t\tvirtual void Reset();\n\n\t\tvirtual void Add(const char *data);\n\n\t\tvirtual void AddAsync(const char *data);\n\n\t\tvirtual void Remove(const char *data);\n\n\t\tvirtual void Flush();\n\n\t\tvirtual int32_t GetSize();\n\n\tprotected:\n\n\t\tsce::Ini::IniFileProcessor *m_ini;\n\t};\n\n\tclass HistLog : public Log\n\t{\n\tpublic:\n\n\t\tHistLog();\n\n\t\tstatic void Clean();\n\n\t\tstatic const uint32_t k_maxHistItems = 20;\n\t};\n\n\tclass FavLog : public Log\n\t{\n\tpublic:\n\n\t\tFavLog();\n\n\t\tstatic void Clean();\n\t};\n\n\tvoid Init();\n\n\tvoid Term();\n\n\tvoid Flush();\n\n\tHistLog *GetHistLog();\n\n\tFavLog *GetFavLog();\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/include/utils.h",
    "content": "#ifndef _UTILS_H_\n#define _UTILS_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <paf_file_ext.h>\n\n#include \"menus/menu_generic.h\"\n#include \"players/player_generic.h\"\n\nusing namespace paf;\n\n#define ROUND_UP(x, a)\t(((x) + ((a) - 1)) & ~((a) - 1))\n#define ROUND_DOWN(x, a) ((x) & ~((a) - 1))\n#define IS_ALIGNED(x, a) (((x) & ((a) - 1)) == 0)\n\nnamespace utils\n{\n\tenum PowerTick\n\t{\n\t\tPowerTick_None,\n\t\tPowerTick_All,\n\t\tPowerTick_Suspend\n\t};\n\n\tvoid Init();\n\n\tuint32_t GetHash(const char *name);\n\n\twchar_t *GetStringWithNum(const char *name, uint32_t num);\n\n\tvoid SetPowerTickTask(PowerTick mode);\n\n\tvoid ConvertSecondsToString(string& string, uint64_t seconds, bool needSeparator);\n\n\tvoid Lock(uint32_t flag);\n\n\tvoid Unlock(uint32_t flag);\n\n\tvoid Wait(uint32_t flag);\n\n\tvoid SetDisplayResolution(uint32_t resolution);\n\n\tjob::JobQueue *GetJobQueue();\n\n\tCurlFile::Share *GetShare();\n\n\tuint32_t SafememGetSettingsSize();\n\n\tvoid SafememWrite(string const& str, uint32_t offset = 0);\n\n\tstring SafememRead(uint32_t offset = 0);\n\n\tbool IsTaihenLoaded();\n\n\ttypedef void(*TimeoutFunc)(void *userdata1, void *userdata2);\n\n\tclass TimeoutListener : public TimerListener\n\t{\n\tpublic:\n\n\t\tTimeoutListener(Timer *t, TimeoutFunc _func) : TimerListener(t, NULL), m_func(_func)\n\t\t{\n\n\t\t}\n\n\t\tvoid OnFinish(void *data1, void *data2)\n\t\t{\n\t\t\tif (m_func)\n\t\t\t{\n\t\t\t\tm_func(data1, data2);\n\t\t\t}\n\t\t\tTimerListenerList::DefaultList()->Unregister(this);\n\t\t\tdelete this;\n\t\t}\n\n\tprivate:\n\n\t\tTimeoutFunc m_func;\n\t};\n\n\ttypedef TimeoutListener* TimeoutID;\n\n\tTimeoutID SetTimeout(TimeoutFunc func, float timeoutMs, void *userdata1 = NULL, void *userdata2 = NULL);\n\n\tvoid ClearTimeout(TimeoutID id);\n\n\tclass CurlDownloadContext\n\t{\n\tpublic:\n\n\t\tCurlDownloadContext()\n\t\t{\n\t\t\tm_buf = NULL;\n\t\t\tm_pos = 0;\n\t\t}\n\n\t\t~CurlDownloadContext() {};\n\n\t\tvoid *m_buf;\n\t\tuint32_t m_pos;\n\t};\n\n\tvoid SetGlobalProxy(const char *proxy);\n\n\tconst char *GetGlobalProxy();\n\n\tbool DoGETRequest(const char *curl, void **ppRespBuf, size_t *pRespBufSize, const char **ppHeaders, uint32_t headerNum,\n\t\tint32_t *pRespCode, void*(*liballoc)(size_t), void(*libdealloc)(void *), void*(*librealloc)(void *, size_t));\n\n\tbool DoPOSTRequest(const char *curl, void *pBuf, size_t bufSize, const char **ppHeaders, uint32_t headerNum, void **ppRespBuf,\n\t\tsize_t *pRespBufSize, int32_t *pRespCode, void*(*liballoc)(size_t), void(*libdealloc)(void *), void*(*librealloc)(void *, size_t));\n\n\tvoid SetRequestShare(CURLSH *share);\n\n\tvoid ResolutionToQualityString(wstring& res, uint32_t width, uint32_t height, bool selected = false);\n\n\tvoid AudioParamsToQualityString(wstring& res, uint32_t ch, uint32_t srate, bool selected = false);\n\n\tbool IsVideoSupported(uint32_t width, uint32_t height);\n\n\tbool IsAudioSupported(uint32_t ch, uint32_t srate);\n\n\tbool IsLocalPath(const char *path);\n\n\tmenu::GenericMenu *CreatePlayer(string const& url);\n\n\tGenericPlayer::SupportType GetContentSupportType(const char *path);\n};\n\n\n#endif\n"
  },
  {
    "path": "NetStream/include/yt_utils.h",
    "content": "#ifndef _YTUTILS_H_\n#define _YTUTILS_H_\n\n#include <kernel.h>\n#include <paf.h>\n#include <ini_file_processor.h>\n\n#include \"downloader.h\"\n#include \"ftube.h\"\n\nusing namespace paf;\n\nnamespace ytutils\n{\n\tclass Log\n\t{\n\tpublic:\n\n\t\tclass AddAsyncJob : public job::JobItem\n\t\t{\n\t\tpublic:\n\n\t\t\tAddAsyncJob(Log *parent, const char *data) : job::JobItem(\"ytutils::AddAsyncJob\", NULL), m_parent(parent), m_data(data)\n\t\t\t{\n\n\t\t\t}\n\n\t\t\t~AddAsyncJob() {}\n\n\t\t\tint32_t Run();\n\n\t\t\tvoid Finish(int32_t result) {}\n\n\t\tprivate:\n\n\t\t\tLog *m_parent;\n\t\t\tstring m_data;\n\t\t};\n\n\t\tLog(uint32_t tus = UINT_MAX) : m_tus(tus)\n\t\t{\n\n\t\t}\n\n\t\tvirtual ~Log()\n\t\t{\n\t\t\tm_ini->flush();\n\t\t\tm_ini->close();\n\t\t\tdelete m_ini;\n\t\t}\n\n\t\tvirtual int32_t GetNext(char *data);\n\n\t\tvirtual int32_t Get(const char *data);\n\n\t\tvirtual void Reset();\n\n\t\tvirtual void Add(const char *data);\n\n\t\tvirtual void AddAsync(const char *data);\n\n\t\tvirtual void Remove(const char *data);\n\n\t\tvirtual void Flush();\n\n\t\tvirtual int32_t GetSize();\n\n\t\tvirtual int32_t UpdateFromTUS();\n\n\t\tvirtual int32_t UploadToTUS();\n\n\tprotected:\n\n\t\tsce::Ini::IniFileProcessor *m_ini;\n\t\tuint32_t m_tus;\n\t};\n\n\tclass HistLog : public Log\n\t{\n\tpublic:\n\n\t\tHistLog(uint32_t tus = UINT_MAX);\n\n\t\tvirtual int32_t UpdateFromTUS();\n\n\t\tvirtual int32_t UploadToTUS();\n\n\t\tstatic void Clean();\n\n\t\tstatic const uint32_t k_maxHistItems = 20;\n\t};\n\n\tclass FavLog : public Log\n\t{\n\tpublic:\n\n\t\tFavLog(uint32_t tus = UINT_MAX);\n\n\t\tvirtual int32_t UpdateFromTUS();\n\n\t\tvirtual int32_t UploadToTUS();\n\n\t\tstatic void Clean();\n\t};\n\n\tvoid Init(uint32_t histTUS = UINT_MAX, uint32_t favTUS = UINT_MAX);\n\n\tvoid Term();\n\n\tvoid Flush();\n\n\tHistLog *GetHistLog();\n\n\tFavLog *GetFavLog();\n\n\tint32_t EnqueueDownload(const char *url, const char *name);\n\n\tint32_t EnqueueDownloadAsync(const char *url, const char *name);\n\n\tCURLSH *GetShare();\n\n\tvoid FormatViews(wstring& res, uint32_t views, bool add = false);\n};\n\n#endif\n"
  },
  {
    "path": "NetStream/libs/include/fmodngpext.h",
    "content": "#ifndef _FMODNGPEXT_H_\n#define _FMODNGPEXT_H_\n\n#include <fmod/fmod.h>\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\ntypedef struct FMOD_NGPEXT_PARAM\n{\n\tunsigned int at9prio;\n\tunsigned int at3prio;\n\tunsigned int opusprio;\n\tunsigned int aacprio;\n\tunsigned int webmprio;\n} FMOD_NGPEXT_PARAM;\n\nFMOD_RESULT F_API FMOD_NGP_System_Init(FMOD_SYSTEM *system, FMOD_NGPEXT_PARAM *param);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "NetStream/libs/include/ftube.h",
    "content": "#pragma once\n\n#include <stdint.h>\n#include <stddef.h>\n\n#if defined(_LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#ifdef FT_BUILD\n#define FT_EXPORT __declspec(dllexport)\n#else\n#define FT_EXPORT\n#endif\n\n#define FT_OK\t\t\t(0)\n#define FT_EBADF\t\t(0x80010009)\n#define FT_ENOMEM\t\t(0x8001000C)\n#define FT_EFAULT\t\t(0x8001000E)\n#define FT_EINVAL\t\t(0x80010016)\n#define FT_EUNSUP\t\t(0x80010030)\n#define FT_EALREADY\t\t(0x80010078)\n#define FT_EFORMAT\t\t(0x8001002F)\n\ntypedef void*(*FTAllocator)(size_t size);\n\ntypedef void(*FTDeallocator)(void *ptr);\n\ntypedef void*(*FTReallocator)(void *ptr, size_t size);\n\ntypedef bool(*FTGetter)(const char *url, void **ppBuf, size_t *pBufSize, const char **ppHeaders, uint32_t headerNum,\n\tint32_t *pRespCode, FTAllocator ftalloc, FTDeallocator ftdealloc, FTReallocator ftrealloc);\n\ntypedef bool(*FTPoster)(const char *url, void *pBuf, size_t bufSize, const char **ppHeaders, uint32_t headerNum, void **ppRespBuf,\n\tsize_t *pRespBufSize, int32_t *pRespCode, FTAllocator ftalloc, FTDeallocator ftdealloc, FTReallocator ftrealloc);\n\ntypedef enum FTItemType\n{\n\tFT_ITEM_TYPE_VIDEO,\n\tFT_ITEM_TYPE_PLAYLIST,\n\tFT_ITEM_TYPE_CHANNEL,\n\tFT_ITEM_TYPE_COMMENT,\n\tFT_ITEM_TYPE_ALL,\n\n\tFT_ITEM_TYPE_MAX\n} FTItemType;\n\ntypedef enum FTSort\n{\n\tFT_SORT_RELEVANCE,\n\tFT_SORT_RATING,\n\tFT_SORT_DATE,\n\tFT_SORT_VIEW_COUNT,\n\n\tFT_SORT_MAX\n} FTSort;\n\ntypedef enum FTDate\n{\n\tFT_DATE_HOUR,\n\tFT_DATE_TODAY,\n\tFT_DATE_WEEK,\n\tFT_DATE_MONTH,\n\tFT_DATE_YEAR,\n\tFT_DATE_ALL,\n\n\tFT_DATE_MAX\n} FTDate;\n\ntypedef enum FTFeature\n{\n\tFT_FEATURE_LIVE,\n\tFT_FEATURE_NONE,\n\n\tFT_FEATURE_MAX\n} FTFeature;\n\ntypedef enum FTDuration\n{\n\tFT_DURATION_SHORT,\n\tFT_DURATION_MEDIUM,\n\tFT_DURATION_LONG,\n\tFT_DURATION_ALL,\n\n\tFT_DURATION_MAX\n} FTDuration;\n\ntypedef enum FTVODVideoQuality\n{\n\tFT_VIDEO_VOD_QUALITY_NONE = 0,\n\tFT_VIDEO_VOD_QUALITY_144P = 1,\n\tFT_VIDEO_VOD_QUALITY_240P = 2,\n\tFT_VIDEO_VOD_QUALITY_360P = 4,\n\tFT_VIDEO_VOD_QUALITY_480P = 8,\n\tFT_VIDEO_VOD_QUALITY_720P = 16,\n\tFT_VIDEO_VOD_QUALITY_ALL = 0xFFFFFFFF\n} FTVODQuality;\n\ntypedef enum FTVODAudioQuality\n{\n\tFT_AUDIO_VOD_QUALITY_NONE = 0,\n\tFT_AUDIO_VOD_QUALITY_LOW = 1,\n\tFT_AUDIO_VOD_QUALITY_MEDIUM = 2,\n\tFT_AUDIO_VOD_QUALITY_ALL = 0xFFFFFFFF\n} FTVODAudioQuality;\n\ntypedef enum FTRegion\n{\n\tFT_REGION_EN_US,\n\n\tFT_REGION_MAX\n} FTRegion;\n\ntypedef enum FTCommentSort\n{\n\tFT_COMMENT_SORT_TOP,\n\tFT_COMMENT_SORT_NEW,\n\n\tFT_COMMENT_SORT_MAX\n} FTCommentSort;\n\ntypedef struct FTItemVideo\n{\n\tconst char *title;\n\tconst char *id;\n\tconst char *author;\n\tconst char *authorId;\n\tconst char *published; // Only with ftParseSearch\n\tconst char *thmbUrl;\n\tconst char *thmbUrlHq;\n\tuint32_t lengthSec;\n\tbool isLive;\n\tbool isShort;\n\n\t// Only with ftParseVideo\n\tconst char *dashManifest;\n\tconst char *audioOnlyUrl;\n\tconst char *compositeVideoUrl;\n\tuint32_t videoRepCount;\n\tuint32_t audioRepCount;\n\tconst char *description;\n\tuint32_t viewCount;\n\tconst char *dashManifestUrl;\n\tconst char *hlsManifestUrl;\n} FTItemVideo;\n\ntypedef struct FTItemPlaylist\n{\n\tconst char *title;\n\tconst char *id;\n\tconst char *author;\n\tconst char *authorId;\n\tconst char *published;\n\tconst char *thmbUrl;\n\tconst char *thmbUrlHq;\n\tuint32_t videoCount;\n} FTItemPlaylist;\n\ntypedef struct FTItemChannel\n{\n\tconst char *author;\n\tconst char *authorId;\n\tconst char *thmbUrl;\n\tconst char *subCount;\n} FTItemChannel;\n\ntypedef struct FTItemComment\n{\n\tchar reserved[sizeof(char *) + sizeof(uint32_t)];\n\tconst char *author;\n\tconst char *authorId;\n\tconst char *published;\n\tconst char *thmbUrl;\n\tconst char *content;\n\tconst char *voteCount;\n\tuint32_t replyCount;\n\tbool isOwner;\n\tbool likedByOwner;\n\tconst char *replyContinuation;\n} FTItemComment;\n\ntypedef struct FTItem\n{\n\tFTItemType type;\n\tunion\n\t{\n\t\tFTItemVideo *videoItem;\n\t\tFTItemPlaylist *playlistItem;\n\t\tFTItemChannel *channelItem;\n\t\tFTItemComment *commentItem;\n\t};\n\tFTItem *next;\n} FTItem;\n\nFT_EXPORT int32_t ftSetRegion(FTRegion region);\n\nFT_EXPORT int32_t ftInit(FTAllocator allocator, FTDeallocator deallocator, FTReallocator reallocator, FTGetter getter, FTPoster poster);\n\nFT_EXPORT int32_t ftTerm();\n\nFT_EXPORT int32_t ftParseSearch(void **ppContext, const char *request, const char *continuation, FTItemType type, FTSort sort, FTDate date, FTFeature feature, FTDuration dur, FTItem **firstItem, const char **continuationToken);\n\nFT_EXPORT int32_t ftParseVideo(void **ppContext, const char *videoId, uint32_t videoQuality, uint32_t audioQuality, FTItem **item);\n\nFT_EXPORT int32_t ftParseComments(void **ppContext, const char *videoId, const char *continuation, FTCommentSort sort, FTItem **item, const char **continuationToken);\n\nFT_EXPORT int32_t ftParseLiveComments(void **ppContext, const char *videoId, uint32_t maxNum, FTItem **firstItem);\n\nFT_EXPORT int32_t ftCleanup(void *pContext);\n\n#if defined(_LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus)\n}\n#endif"
  },
  {
    "path": "NetStream/libs/include/hvdb.h",
    "content": "#pragma once\n\n#include <stdint.h>\n#include <stddef.h>\n\n#if defined(_LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#ifdef HVDB_BUILD\n#define HVDB_EXPORT __declspec(dllexport)\n#else\n#define HVDB_EXPORT\n#endif\n\n#define HVDB_OK\t\t\t(0)\n#define HVDB_EPERM\t\t(0x80010001)\n#define HVDB_EBADF\t\t(0x80010009)\n#define HVDB_ENOMEM\t\t(0x8001000C)\n#define HVDB_EFAULT\t\t(0x8001000E)\n#define HVDB_EINVAL\t\t(0x80010016)\n#define HVDB_EUNSUP\t\t(0x80010030)\n#define HVDB_EALREADY\t(0x80010078)\n#define HVDB_EFORMAT\t(0x8001002F)\n\ntypedef void*(*HVDBAllocator)(size_t size);\ntypedef void(*HVDBDeallocator)(void *ptr);\ntypedef void*(*HVDBReallocator)(void *ptr, size_t size);\n\ntypedef bool(*HVDBGetter)(const char *url, void **ppBuf, size_t *pBufSize, const char **ppHeaders, uint32_t headerNum,\n\tint32_t *pRespCode, HVDBAllocator ftalloc, HVDBDeallocator ftdealloc, HVDBReallocator ftrealloc);\n\ntypedef bool(*HVDBPoster)(const char *url, void *pBuf, size_t bufSize, const char **ppHeaders, uint32_t headerNum, void **ppRespBuf,\n\tsize_t *pRespBufSize, int32_t *pRespCode, HVDBAllocator ftalloc, HVDBDeallocator ftdealloc, HVDBReallocator ftrealloc);\n\ntypedef enum HVDBItemType\n{\n\tHVDB_ITEM_TYPE_WORK,\n\tHVDB_ITEM_TYPE_DATA,\n\n\tHVDB_ITEM_TYPE_MAX\n} HVDBItemType;\n\ntypedef enum HVDBDataType\n{\n\tHVDB_DATA_TYPE_FOLDER,\n\tHVDB_DATA_TYPE_MEDIA,\n\n\tHVDB_DATA_TYPE_MAX\n} HVDBDataType;\n\ntypedef enum HVDBSort\n{\n\tHVDB_SORT_ASCENDING,\n\tHVDB_SORT_DESCENDING,\n\n\tHVDB_SORT_MAX\n} HVDBSort;\n\ntypedef enum HVDBOrder\n{\n\tHVDB_ORDER_CREATE_DATE,\n\tHVDB_ORDER_RELEASE,\n\tHVDB_ORDER_DL_COUNT,\n\tHVDB_ORDER_PRICE,\n\tHVDB_ORDER_RATE_AVERAGE,\n\tHVDB_ORDER_REVIEW_COUNT,\n\tHVDB_ORDER_ID,\n\tHVDB_ORDER_NSFW,\n\tHVDB_ORDER_UPDATED_AT,\n\n\tHVDB_ORDER_MAX\n} HVDBOrder;\n\ntypedef enum HVDBFilter\n{\n\tHVDB_FILTER_MARKED,\n\tHVDB_FILTER_LISTENING,\n\tHVDB_FILTER_LISTENED,\n\tHVDB_FILTER_REPLAY,\n\tHVDB_FILTER_POSTPONED,\n\tHVDB_FILTER_ALL,\n\n\tHVDB_FILTER_MAX\n} HVDBFilter;\n\ntypedef struct HVDBItemWork\n{\n\tconst char *title;\n\tchar id[16];\n\tchar circleId[16];\n\tconst char *circle;\n\tconst char *published;\n\tfloat rating;\n\tuint32_t rateCount;\n\tuint32_t dlCount;\n\tconst char *thmbUrl;\n\tconst char *bannerUrl;\n\tbool isNsfw;\n} HVDBItemWork;\n\ntypedef struct HVDBItemData\n{\n\tuint64_t reserved; // sizeof(ArduinoJson::JsonVariantConst)\n\tHVDBDataType type;\n\tconst char *title;\n\tconst char *url;\n} HVDBItemData;\n\ntypedef struct HVDBItem\n{\n\tHVDBItemType type;\n\tunion\n\t{\n\t\tHVDBItemWork *workItem;\n\t\tHVDBItemData *dataItem;\n\t};\n\tHVDBItem *next;\n} HVDBItem;\n\ntypedef struct HVDBPaginationInfo\n{\n\tuint32_t currentPage;\n\tuint32_t worksPerPage;\n\tuint32_t worksTotal;\n} HVDBPaginationInfo;\n\nHVDB_EXPORT int32_t hvdbInit(HVDBAllocator allocator, HVDBDeallocator deallocator, HVDBReallocator reallocator, HVDBGetter getter, HVDBPoster poster);\n\nHVDB_EXPORT int32_t hvdbSetInstance(const char *instance);\n\nHVDB_EXPORT int32_t hvdbTerm();\n\nHVDB_EXPORT int32_t hvdbParseWork(void **ppContext, const char *audioId, HVDBItem **item);\n\nHVDB_EXPORT int32_t hvdbParseData(void **ppContext, const char *audioId, HVDBItem **item);\n\nHVDB_EXPORT int32_t hvdbParseDataFolder(void *pContext, HVDBItemData *folder, HVDBItem **item);\n\nHVDB_EXPORT int32_t hvdbParseFavourites(void **ppContext, uint32_t page, HVDBSort sort, HVDBOrder order, HVDBFilter filter, HVDBPaginationInfo *pagination, HVDBItem **item);\n\nHVDB_EXPORT int32_t hvdbLogin(const char *name, const char *password);\n\nHVDB_EXPORT int32_t hvdbIsLoggedIn();\n\nHVDB_EXPORT int32_t hvdbCleanup(void *pContext);\n\n#if defined(_LANGUAGE_C_PLUS_PLUS)||defined(__cplusplus)||defined(c_plusplus)\n}\n#endif"
  },
  {
    "path": "NetStream/libs/include/lootkit.h",
    "content": "#pragma once\n\n#include <kernel.h>\n\nSCE_CDECL_BEGIN\n\n#ifdef LOOTKIT_BUILD\n#define LTK_EXPORT __declspec(dllexport)\n#else\n#define LTK_EXPORT\n#endif\n\ntypedef enum LtkItemType\n{\n\tLTK_ITEM_TYPE_CATEGORY,\n\tLTK_ITEM_TYPE_CHANNEL,\n\n\tINV_ITEM_TYPE_MAX\n} LtkItemType;\n\ntypedef enum LtkSearchType\n{\n\tLTK_SEARCH_TYPE_CATEGORY,\n\tLTK_SEARCH_TYPE_CHANNEL,\n\n\tLTK_SEARCH_TYPE_MAX\n} LtkSearchType;\n\ntypedef enum LtkHlsQuality\n{\n\tLTK_HLS_QUALITY_160P,\n\tLTK_HLS_QUALITY_360P,\n\tLTK_HLS_QUALITY_480P,\n\tLTK_HLS_QUALITY_720P,\n\n\tLTK_HLS_QUALITY_MAX\n} InvHlsQuality;\n\ntypedef enum LtkSearchDirection\n{\n\tLTK_SEARCH_DIR_AFTER,\n\tLTK_SEARCH_DIR_BEFORE,\n\n\tLTK_SEARCH_DIR_MAX\n} LtkSearchDirection;\n\ntypedef enum LtkVideoType\n{\n\tLTK_VIDEO_TYPE_VOD,\n\tLTK_VIDEO_TYPE_HIGHLIGHT,\n\tLTK_VIDEO_TYPE_UPLOAD,\n\tLTK_VIDEO_TYPE_ALL,\n\n\tLTK_VIDEO_TYPE_MAX\n} LtkVideoType;\n\ntypedef struct LtkItemCategory\n{\n\tconst char *id;\n\tconst char *name;\n\tconst char *thmbUrl;\n\tconst char *pagination;\n} LtkItemCategory;\n\ntypedef struct LtkItemChannel\n{\n\tconst char *id;\n\tconst char *login;\n\tconst char *name;\n\tconst char *title;\n\tconst char *categoryName;\n\tconst char *thmbUrl;\n\tconst char *startedAt;\n\tSceBool isLive;\n\tconst char *pagination;\n} LtkItemChannel;\n\ntypedef struct LtkItemVideo\n{\n\tScePVoid reserved;\n\tLtkVideoType type;\n\tconst char *id;\n\tconst char *title;\n\tconst char *description;\n\tconst char *duration;\n\tconst char *date;\n\tconst char *thmbUrl;\n\tconst char *pagination;\n} LtkItemVideo;\n\ntypedef struct LtkItem\n{\n\tScePVoid reserved;\n\tLtkItemType type;\n\tunion\n\t{\n\t\tLtkItemCategory *categoryItem;\n\t\tLtkItemChannel *channelItem;\n\t};\n} LtkItem;\n\ntypedef ScePVoid(*LtkAllocator)(size_t size);\n\ntypedef SceVoid(*LtkDeallocator)(ScePVoid ptr);\n\ntypedef SceBool(*LtkDownloader)(const char *url, ScePVoid *ppBuf, SceSize *pBufSize, ScePVoid postData, SceSize postDataSize);\n\nLTK_EXPORT SceInt32 ltkInit(LtkAllocator allocator, LtkDeallocator deallocator, const char *lootUrl);\n\nLTK_EXPORT SceInt32 ltkTerm();\n\nLTK_EXPORT SceInt32 ltkParseSearch(const char *request, const char *pagination, LtkSearchType type, LtkSearchDirection dir, LtkItem **firstItem);\n\nLTK_EXPORT SceInt32 ltkParseVideo(LtkItemChannel *item, LtkVideoType type, const char *pagination, LtkSearchDirection dir, LtkItemVideo **videos);\n\nLTK_EXPORT SceInt32 ltkGetHlsUrl(LtkItemChannel *item, LtkHlsQuality quality, char *hlsUrl, SceInt32 sizeOfUrl);\n\nLTK_EXPORT SceInt32 ltkGetVideoUrl(LtkItemVideo *item, LtkHlsQuality quality, char *videoUrl, SceInt32 sizeOfUrl);\n\nLTK_EXPORT SceInt32 ltkCleanupSearch(LtkItem *items);\n\nLTK_EXPORT SceInt32 ltkCleanupVideo(LtkItemVideo *items);\n\nSCE_CDECL_END\n"
  },
  {
    "path": "NetStream/libs/include/sceavplayer_webmaf.h",
    "content": "﻿#ifndef _SCE_AVPLAYER_SCEAVPLAYER_WEBMAF_H\n#define _SCE_AVPLAYER_SCEAVPLAYER_WEBMAF_H\n\n#include <stdarg.h>\n#include <stdint.h>\n#include <sceavplayer.h>\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#define SCE_AV_PLAYER_PCM_BUFFER_SIZE 2048\n\n#define SCE_AVPLAYER_STATE_EOS 0x6\n\ntypedef enum SceAvPlayerRepresentationType {\n\tSCE_AVPLAYER_REPRESENTATION_UNKNOWN,\t\t///< An unknown stream type.\n\tSCE_AVPLAYER_REPRESENTATION_VIDEO,\t\t\t///< The video stream type.\n\tSCE_AVPLAYER_REPRESENTATION_AUDIO,\t\t\t///< The audio stream type.\n\tSCE_AVPLAYER_REPRESENTATION_TIMEDTEXT\t\t///< The timed text stream type.\n} SceAvPlayerRepresentationType;\n\ntypedef enum SceAvPlayerEventsEx {\n\tSCE_AVPLAYER_STATE_NO_DATA = 0x06,\n\tSCE_AVPLAYER_DRM_ERROR = 0x40,\n\tSCE_AVPLAYER_OUTPUT_PROTECTION = 0x50,\n\tSCE_AVPLAYER_TIMED_TEXT_DELIVERY_EX = 0x60,\n\tSCE_AVPLAYER_ACTIVATION_REQUIRED = 0x70\n} SceAvPlayerEventsEx;\n\ntypedef enum NMLogLevel {\n\tNM_LOG_LEVEL_NONE = 0,\n\tNM_LOG_LEVEL_INFO = 1,\n\tNM_LOG_LEVEL_WARNINGS = 2,\n\tNM_LOG_LEVEL_ALL = 3\n} NMLogLevel;\n\ntypedef enum SceAvPlayerUrlType {\n\tSceAvPlayer_LAUrl = 0,\n\tSceAvPlayer_CustomData = 1,\n\tSceAvPlayer_KeyUrl = 2,\n\tSceAvPlayer_ManifestUrl = 99\n} SceAvPlayerUrlType;\n\ntypedef enum SceAvPlayerSourceType {\n\tSceAvPlayerSource_Unknown = 0,\n\tSceAvPlayerSource_File = 1,\n\tSceAvPlayerSource_SmoothStreaming = 2,\n\tSceAvPlayerSource_DashMp4 = 4,\n\tSceAvPlayerSource_DashTS = 6,\n\tSceAvPlayerSource_HLS = 8,\n\tSceAvPlayerSource_FileTS = 9\n} SceAvPlayerSourceType;\n\ntypedef void *SceAvPlayerHttpInstance;\n\ntypedef void*(*SceAvPlayerHTTPAllocate)(void *, uint32_t, uint32_t);\n\ntypedef void(*SceAvPlayerHTTPDeallocate)(void *, void *);\n\ntypedef int32_t(*SceAvPlayerHttpRedirectCb)(char *, void *);\n\ntypedef struct SceAvPlayerHTTPCtx {\n\tuint32_t httpCtxId;\n\tuint32_t sslCtxId;\n} SceAvPlayerHTTPCtx;\n\ntypedef struct SceAvPlayerHTTPHeader {\n\tchar * name;\n\tchar * value;\n} SceAvPlayerHTTPHeader;\n\ntypedef struct SceAvPlayerHTTPSData {\n\tchar * ptr;\n\tsize_t size;\n} SceAvPlayerHTTPSData;\n\ntypedef struct SceAvPlayerHttpReplacement {\n\tint32_t(*init)(SceAvPlayerHttpInstance *instancePP, void *objPtr, SceAvPlayerHTTPAllocate alloc,\n\t\tSceAvPlayerHTTPDeallocate dealloc, char *userAgent, SceAvPlayerHTTPCtx *httpCtxId);\n\tint32_t(*deInit)(SceAvPlayerHttpInstance *instancePP);\n\tint32_t(*setRedirectCb)(SceAvPlayerHttpInstance instanceP, SceAvPlayerHttpRedirectCb *redirectCb, void *object);\n\tint64_t(*post)(SceAvPlayerHttpInstance instanceP, char *url, bool continuation,\n\t\tSceAvPlayerHTTPHeader *headers, uint8_t numHeaders, uint8_t *body, uint32_t len,\n\t\tuint8_t *buf, uint32_t bufLen, bool *completed);\n\tint64_t(*get)(SceAvPlayerHttpInstance instanceP, char *url, bool continuation,\n\t\tuint64_t rangeStart, uint64_t rangeEnd, uint8_t *buf, uint32_t bufLen, bool *completed);\n\tint32_t(*setCert)(SceAvPlayerHttpInstance instanceP, SceAvPlayerHTTPSData *cert, SceAvPlayerHTTPSData *privKey);\n\tint32_t(*setRecvTimeout)(SceAvPlayerHttpInstance instanceP, int64_t usec);\n\tint32_t(*getLastStatus)(SceAvPlayerHttpInstance instanceP);\n} SceAvPlayerHttpReplacement;\n\ntypedef struct SceAvPlayerPostInitDataNew {\n\tuint32_t demuxVideoBufferSize;\n\tuint8_t _reserved[0x40];\n\tSceAvPlayerHttpReplacement httpReplacement;\n\tSceAvPlayerHTTPCtx httpCtx;\n\tuint8_t reserved[0x14];\n} SceAvPlayerPostInitDataNew;\n\ntypedef struct SceAvPlayerURICommon {\n\tchar *name;\n\tuint32_t length;\n} SceAvPlayerURICommon;\n\ntypedef struct SceAvPlayerURISimpleQuery {\n\tSceAvPlayerURICommon userName;\n\tSceAvPlayerURICommon password;\n\tSceAvPlayerURICommon query;\n\tSceAvPlayerURICommon fragment;\n} SceAvPlayerURISimpleQuery;\n\ntypedef struct SceAvPlayerURISimpleDetails {\n\tSceAvPlayerURICommon uri;\n\tSceAvPlayerURISimpleQuery details;\n\tSceAvPlayerSourceType sourceType;\n} SceAvPlayerURISimpleDetails;\n\ntypedef struct SceAvPlayerStreamOptions {\n\tuint8_t reserved[4];\n\tbool allowWMAPro;\n} SceAvPlayerStreamOptions;\n\ntypedef union SceAvPlayerSourceDetails {\n\tstruct SceAvPlayerURISimpleDetails UriDetails;\n\tuint8_t reserved[128];\n} SceAvPlayerSourceDetails;\n\ntypedef struct SceAvPlayerPostInitDataEx {\n\tuint32_t unk_00;\n\tuint32_t unk_04;\n\tuint32_t demuxSharedHeapSize;\n\tuint32_t demuxVideoBufferSize;\n\tuint32_t demuxAudioBufferSize;\n\tuint32_t streamingContainerBufferSize;\n\tuint32_t unk_18;\n} SceAvPlayerPostInitDataEx;\n\ntypedef union SceAvPlayerRepresentationDetails {\n\tSceAvPlayerAudio audio;\n\tSceAvPlayerVideo video;\n\tSceAvPlayerTimedText subs;\n} SceAvPlayerRepresentationDetails;\n\ntypedef struct SceAvPlayerRepresentationInfo {\n\tuint32_t bitrate;\n\tSceAvPlayerRepresentationType type;\n\tuint8_t reserved[16];\n\tSceAvPlayerRepresentationDetails details;\n} SceAvPlayerRepresentationInfo;\n\ntypedef struct SceAvPlayerAudioEx {\n\tuint16_t channelCount;\n\tuint8_t reserved[2];\n\tuint32_t sampleRate;\n\tuint32_t size;\n\tuint8_t languageCode[4];\n\tuint8_t reserved1[64];\n} SceAvPlayerAudioEx;\n\ntypedef struct SceAvPlayerVideoEx {\n\tuint32_t width;\n\tuint32_t height;\n\tfloat aspectRatio;\n\tuint8_t languageCode[4];\n\tuint32_t framerate;\n\tuint32_t cropLeftOffset;\n\tuint32_t cropRightOffset;\n\tuint32_t cropTopOffset;\n\tuint32_t cropBottomOffset;\n\tuint16_t cropLeftPixels;\n\tuint16_t cropRightPixels;\n\tuint16_t cropTopPixels;\n\tuint16_t cropBottomPixels;\n\tuint32_t pitch;\n\tuint8_t reserved[32];\n} SceAvPlayerVideoEx;\n\ntypedef struct SceAvPlayerTimedTextEx {\n\tuint8_t languageCode[4];\n\tuint8_t reserved[12];\n\tuint8_t reserved1[64];\n} SceAvPlayerTimedTextEx;\n\ntypedef union SceAvPlayerStreamDetailsEx {\n\tSceAvPlayerAudioEx audio;\n\tSceAvPlayerVideoEx video;\n\tSceAvPlayerTimedTextEx subs;\n\tuint8_t reserved[80];\n} SceAvPlayerStreamDetailsEx;\n\ntypedef struct SceAvPlayerFrameInfoEx {\n\tvoid * pData;\n\tuint8_t reserved[4];\n\tuint64_t timeStamp;\n\tSceAvPlayerStreamDetailsEx details;\n} SceAvPlayerFrameInfoEx;\n\ntypedef int32_t SceAvPlayerLogger(void *userData, const char *format, _Va_list ap);\n\nint32_t sceAvPlayerGetVersionInfo(char *versionInfo, uint32_t bufferLen, uint32_t *versionInfoLen);\n\nint32_t sceAvPlayerSetLogger(SceAvPlayerLogger f, void *userData);\n\nint32_t sceAvPlayerOsalPrintf(char *format);\n\nint32_t sceAvPlayerOsalPrintf2(char *format);\n\nint32_t sceAvPlayerAddSourceEx(SceAvPlayerHandle h, SceAvPlayerUrlType UrlType, SceAvPlayerSourceDetails *pUrlExtras);\n\nSceAvPlayerFileReplacement NETMediaInit(uint8_t *pNetBuffer, size_t buffsz, int32_t sslCtxId, int32_t httpCtxId, SceAvPlayerMemAllocator *pMemAllocator, NMLogLevel logLevel);\n\nvoid NETMediaDeInit(void *arg, SceAvPlayerMemAllocator *pMemAllocator);\n\nint32_t sceAvPlayerSetAvailableBW(SceAvPlayerHandle h, uint32_t argBW);\n\nint32_t sceAvPlayerGetAvailableBW(SceAvPlayerHandle h, uint32_t *argpBW);\n\nint32_t sceAvPlayerGetStreamBitrate(SceAvPlayerHandle h, uint32_t argStreamID, uint32_t *argpBitrate);\n\nint32_t sceAvPlayerEnableRepresentation(SceAvPlayerHandle h, uint32_t argStreamID, uint32_t representationID);\n\nint32_t sceAvPlayerGetRepresentationInfo(SceAvPlayerHandle h, uint32_t argStreamID, uint32_t representationID, SceAvPlayerRepresentationInfo *argInfo);\n\nint32_t sceAvPlayerDisableRepresentation(SceAvPlayerHandle h, uint32_t argStreamID, uint32_t representationID);\n\nint32_t sceAvPlayerRepresentationCount(SceAvPlayerHandle h, uint32_t argStreamID);\n\nint32_t sceAvPlayerGetStreamSetBitrate(SceAvPlayerHandle h, uint32_t argStreamID, uint32_t *argpBitrate);\n\nint32_t sceAvPlayerRepresentationIsEnabled(SceAvPlayerHandle h, uint32_t argStreamID, uint32_t representationID, bool *enabled);\n\nint32_t sceAvPlayerChangeStream(SceAvPlayerHandle h, uint32_t argStreamID, uint32_t argTargetStreamID);\n\nint32_t sceAvPlayerEnableStreamEx(SceAvPlayerHandle h, uint32_t argStreamID, SceAvPlayerStreamOptions *argOpt);\n\nint32_t sceAvPlayerPostInitEx(SceAvPlayerHandle h, SceAvPlayerPostInitDataEx *pPostInit);\n\nint32_t sceAvPlayerGetVideoDataEx(SceAvPlayerHandle h, SceAvPlayerFrameInfoEx *argFrameInfo);\n\n//int32_t sceAvPlayerGetStreamInfoEx(SceAvPlayerHandle h);\n\n//int32_t sceAvPlayerGetAudioDataEx(SceAvPlayerHandle h);\n\n//int32_t SceAvPlayer_07CBDB80(SceAvPlayerHandle h);\n//int32_t SceAvPlayer_3534430F(SceAvPlayerHandle h);\n//int32_t SceAvPlayer_3F125760(SceAvPlayerHandle h);\n//int32_t SceAvPlayer_62EE177D(SceAvPlayerHandle h);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\t/* _SCE_AVPLAYER_SCEAVPLAYER_WEBMAF_H */\n\n"
  },
  {
    "path": "NetStream/package.conf",
    "content": "Content_ID = HB0000-GRVA00024_00-NETSTREAM0000000\nK_licensee = 0\nDRMType = Local\nContentType = PSP2GD\nPackageVersion = 01.00\nPublishingTools = 0x23100000\nPFSseed = 0\nPFSBuilder = 0"
  },
  {
    "path": "NetStream/param.sfx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n<paramsfo>\n\t<param key=\"APP_VER\">03.35</param>\n\t<param key=\"ATTRIBUTE\">33408</param>\n\t<param key=\"ATTRIBUTE_MINOR\">16</param>\n\t<param key=\"ATTRIBUTE2\">0</param>\n\t<param key=\"CATEGORY\">gdc</param>\n\t<param key=\"CONTENT_ID\">HB0000-GRVA00024_00-NETSTREAM0000000</param>\n\t<param key=\"GC_RO_SIZE\">0</param>\n\t<param key=\"GC_RW_SIZE\">0</param>\n\t<param key=\"PARENTAL_LEVEL\">1</param>\n\t<param key=\"PSP2_DISP_VER\">03.600</param>\n\t<param key=\"PSP2_SYSTEM_VER\">56623104</param>\n\t<param key=\"REGION_DENY\">0</param>\n\t<param key=\"SAVEDATA_MAX_SIZE\">1048576</param>\n\t<param key=\"STITLE\">NetStream</param>\n\t<param key=\"TITLE\">NetStream</param>\n\t<param key=\"TITLE_ID\">GRVA00024</param>\n\t<param key=\"VERSION\">01.00</param>\n</paramsfo>"
  },
  {
    "path": "NetStream/source/browsers/ftp_server_browser.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <libdbg.h>\n#include <psp2_compat/curl/curl.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"ftpparse.h\"\n#include \"players/player_av.h\"\n#include \"players/player_beav.h\"\n#include \"browsers/ftp_server_browser.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[FTPBrowser]\"\n\nusing namespace paf;\n\nFtpServerBrowser::FtpServerBrowser(const char *host, const char *port, const char *user, const char *password)\n{\n\tm_useNlst = 0;\n\tm_url = curl_url();\n\n\tSCE_DBG_LOG_INFO(\"[FtpServerBrowser] %s : %s : %s : %s\\n\", host, port, user, password);\n\n\tif (host)\n\t\tcurl_url_set(m_url, CURLUPART_URL, host, 0);\n\tif (port)\n\t\tcurl_url_set(m_url, CURLUPART_PORT, port, 0);\n\tif (user)\n\t\tcurl_url_set(m_url, CURLUPART_USER, user, 0);\n\tif (password)\n\t\tcurl_url_set(m_url, CURLUPART_PASSWORD, password, 0);\n\n\tm_curl = curl_easy_init();\n\n\tchar *addr;\n\tif (!curl_url_get(m_url, CURLUPART_URL, &addr, 0))\n\t{\n\t\tm_root = addr;\n\t\tcurl_easy_setopt(m_curl, CURLOPT_URL, addr);\n\t\tcurl_free(addr);\n\t}\n\n\tcurl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, 0L);\n\tcurl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 0L);\n\tcurl_easy_setopt(m_curl, CURLOPT_CONNECTTIMEOUT, 5L);\n\tcurl_easy_setopt(m_curl, CURLOPT_TIMEOUT, 15L);\n\tcurl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, 1L);\n\tcurl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, DownloadCore);\n\tcurl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this);\n\tif (utils::GetGlobalProxy())\n\t{\n\t\tcurl_easy_setopt(m_curl, CURLOPT_PROXY, utils::GetGlobalProxy());\n\t}\n\tmenu::Settings::GetAppSetInstance()->GetInt(\"ftp_nlst\", &m_useNlst, 0);\n\tif (m_useNlst)\n\t{\n\t\tcurl_easy_setopt(m_curl, CURLOPT_DIRLISTONLY, 1L);\n\t}\n}\n\nFtpServerBrowser::~FtpServerBrowser()\n{\n\tcurl_url_cleanup(m_url);\n\tcurl_easy_cleanup(m_curl);\n}\n\nbool FtpServerBrowser::Probe()\n{\n\tcurl_easy_setopt(m_curl, CURLOPT_NOBODY, 1L);\n\n\tCURLcode ret = curl_easy_perform(m_curl);\n\tcurl_easy_setopt(m_curl, CURLOPT_NOBODY, 0L);\n\tcurl_easy_setopt(m_curl, CURLOPT_HTTPGET, 1L);\n\n\tif (ret != CURLE_OK)\n\t{\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nbool FtpServerBrowser::IsAtRoot(string *current)\n{\n\treturn (m_root == *current);\n}\n\nbool FtpServerBrowser::IsAtRoot()\n{\n\treturn (m_root == GetPath());\n}\n\nstring FtpServerBrowser::GetPath()\n{\n\tstring ret;\n\tchar *path;\n\tcurl_url_get(m_url, CURLUPART_URL, &path, 0);\n\tif (path)\n\t{\n\t\tchar *decoded = curl_easy_unescape(m_curl, path, 0, NULL);\n\t\tret = decoded;\n\t\tcurl_free(decoded);\n\t\tcurl_free(path);\n\t}\n\n\treturn ret;\n}\n\nvoid FtpServerBrowser::GetInfoForPlayer(string const& in, string& url, GenericPlayer::Option **opt)\n{\n\turl = \"http://\";\n\tCURLU *turl = curl_url_dup(m_url);\n\tcurl_url_set(turl, CURLUPART_URL, in.c_str(), 0);\n\tchar *result;\n\tcurl_url_get(turl, CURLUPART_URL, &result, 0);\n\turl += result;\n\tcurl_free(result);\n\tcurl_url_cleanup(turl);\n\t*opt = NULL;\n}\n\nvoid FtpServerBrowser::SetPath(const char *ref)\n{\n\tif (ref)\n\t{\n\t\tchar *encoded = curl_easy_escape(m_curl, ref, 0);\n\t\tchar *current;\n\t\tcurl_url_get(m_url, CURLUPART_URL, &current, 0);\n\t\tstring full = current;\n\t\tfull += encoded;\n\t\tfull += \"/\";\n\t\tcurl_url_set(m_url, CURLUPART_URL, full.c_str(), 0);\n\t\tcurl_free(encoded);\n\t\tcurl_free(current);\n\t}\n}\n\nvector<FtpServerBrowser::Entry *> *FtpServerBrowser::GoTo(const char *ref, int32_t *result)\n{\n\tvector<FtpServerBrowser::Entry *> *ret = new vector<FtpServerBrowser::Entry *>;\n\tCURLcode cret;\n\n\tSetPath(ref);\n\n\tchar *addr;\n\tcurl_url_get(m_url, CURLUPART_URL, &addr, 0);\n\tSCE_DBG_LOG_INFO(\"[GoTo] Attempt to open %s\\n\", addr);\n\tcurl_easy_setopt(m_curl, CURLOPT_URL, addr);\n\tcurl_free(addr);\n\n\tm_buffer = NULL;\n\tm_posInBuf = 0;\n\n\tcret = curl_easy_perform(m_curl);\n\tif (cret != CURLE_OK)\n\t{\n\t\t*result = cret;\n\t\treturn ret;\n\t}\n\n\tif (m_buffer && m_posInBuf > 2)\n\t{\n\t\tm_buffer[m_posInBuf - 1] = 0;\n\n\t\tchar *tok = sce_paf_strtok(m_buffer, \"\\n\");\n\t\twhile (tok != NULL) {\n\t\t\tif (!m_useNlst)\n\t\t\t{\n\t\t\t\tstruct ftpparse ftpe;\n\t\t\t\tint fret = ftpparse(&ftpe, tok, sce_paf_strlen(tok));\n\t\t\t\tif (fret == 1)\n\t\t\t\t{\n\t\t\t\t\ttok = ftpe.name;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\ttok = \"\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tGenericPlayer::SupportType supportType = utils::GetContentSupportType(tok);\n\n\t\t\tif (supportType != BEAVPlayer::SupportType_NotSupported)\n\t\t\t{\n\t\t\t\tchar *decoded = curl_easy_unescape(m_curl, tok, 0, NULL);\n\t\t\t\tFtpServerBrowser::Entry *entry = new FtpServerBrowser::Entry();\n\t\t\t\tentry->ref = decoded;\n\t\t\t\tentry->type = FtpServerBrowser::Entry::Type_UnsupportedFile;\n\t\t\t\tcurl_free(decoded);\n\n\t\t\t\tif (supportType == BEAVPlayer::SupportType_MaybeSupported)\n\t\t\t\t{\n\t\t\t\t\tentry->type = FtpServerBrowser::Entry::Type_Folder;\n\t\t\t\t}\n\t\t\t\telse if (supportType == BEAVPlayer::SupportType_Supported)\n\t\t\t\t{\n\t\t\t\t\tentry->type = FtpServerBrowser::Entry::Type_SupportedFile;\n\t\t\t\t}\n\n\t\t\t\tret->push_back(entry);\n\t\t\t}\n\t\t\ttok = sce_paf_strtok(NULL, \"\\n\");\n\t\t}\n\n\t\t*result = SCE_OK;\n\t}\n\telse\n\t{\n\t\t*result = SCE_ERROR_ERRNO_ENOENT;\n\t}\n\n\tif (m_buffer)\n\t\tsce_paf_free(m_buffer);\n\n\treturn ret;\n}\n\nsize_t FtpServerBrowser::DownloadCore(char *buffer, size_t size, size_t nitems, void *userdata)\n{\n\tFtpServerBrowser *obj = static_cast<FtpServerBrowser *>(userdata);\n\tsize_t toCopy = size * nitems;\n\n\tif (toCopy != 0)\n\t{\n\t\tobj->m_buffer = static_cast<char *>(sce_paf_realloc(obj->m_buffer, obj->m_posInBuf + toCopy));\n\t\tsce_paf_memcpy(obj->m_buffer + obj->m_posInBuf, buffer, toCopy);\n\t\tobj->m_posInBuf += toCopy;\n\t\treturn toCopy;\n\t}\n\n\treturn 0;\n}"
  },
  {
    "path": "NetStream/source/browsers/http_server_browser.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <libdbg.h>\n#include <psp2_compat/curl/curl.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"players/player_av.h\"\n#include \"players/player_beav.h\"\n#include \"players/player_fmod.h\"\n#include \"browsers/http_server_browser.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[HTTPBrowser]\"\n\nusing namespace paf;\n\nHttpServerBrowser::HttpServerBrowser(const char *host, const char *port, const char *user, const char *password)\n{\n\tm_url = curl_url();\n\n\tSCE_DBG_LOG_INFO(\"[HttpServerBrowser] %s : %s : %s : %s\\n\", host, port, user, password);\n\n\tif (host)\n\t\tcurl_url_set(m_url, CURLUPART_URL, host, 0);\n\tif (port)\n\t\tcurl_url_set(m_url, CURLUPART_PORT, port, 0);\n\tif (user)\n\t\tcurl_url_set(m_url, CURLUPART_USER, user, 0);\n\tif (password)\n\t\tcurl_url_set(m_url, CURLUPART_PASSWORD, password, 0);\n\n\tm_curl = curl_easy_init();\n\n\tchar *addr;\n\tif (!curl_url_get(m_url, CURLUPART_URL, &addr, 0))\n\t{\n\t\tm_root = addr;\n\t\tcurl_easy_setopt(m_curl, CURLOPT_URL, addr);\n\t\tcurl_free(addr);\n\t}\n\n\tcurl_easy_setopt(m_curl, CURLOPT_USERAGENT, USER_AGENT);\n\tcurl_easy_setopt(m_curl, CURLOPT_ACCEPT_ENCODING, NULL);\n\tcurl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, 0L);\n\tcurl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 0L);\n\tcurl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1L);\n\tcurl_easy_setopt(m_curl, CURLOPT_TCP_KEEPALIVE, 1L);\n\tcurl_easy_setopt(m_curl, CURLOPT_CONNECTTIMEOUT, 5L);\n\tcurl_easy_setopt(m_curl, CURLOPT_TIMEOUT, 15L);\n\tcurl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, 1L);\n\tcurl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, DownloadCore);\n\tcurl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this);\n\tcurl_easy_setopt(m_curl, CURLOPT_HTTPGET, 1L);\n\tif (utils::GetGlobalProxy())\n\t{\n\t\tcurl_easy_setopt(m_curl, CURLOPT_PROXY, utils::GetGlobalProxy());\n\t}\n}\n\nHttpServerBrowser::~HttpServerBrowser()\n{\n\tcurl_url_cleanup(m_url);\n\tcurl_easy_cleanup(m_curl);\n}\n\nbool HttpServerBrowser::Probe()\n{\n\tcurl_easy_setopt(m_curl, CURLOPT_NOBODY, 1L);\n\n\tCURLcode ret = curl_easy_perform(m_curl);\n\tcurl_easy_setopt(m_curl, CURLOPT_NOBODY, 0L);\n\tcurl_easy_setopt(m_curl, CURLOPT_HTTPGET, 1L);\n\n\tif (ret != CURLE_OK)\n\t{\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nbool HttpServerBrowser::IsAtRoot(string *current)\n{\n\treturn (m_root == *current);\n}\n\nbool HttpServerBrowser::IsAtRoot()\n{\n\treturn (m_root == GetPath());\n}\n\nstring HttpServerBrowser::GetPath()\n{\n\tstring ret;\n\tchar *path;\n\tcurl_url_get(m_url, CURLUPART_URL, &path, 0);\n\tif (path)\n\t{\n\t\tchar *decoded = curl_easy_unescape(m_curl, path, 0, NULL);\n\t\tret = decoded;\n\t\tcurl_free(decoded);\n\t\tcurl_free(path);\n\t}\n\n\treturn ret;\n}\n\nvoid HttpServerBrowser::GetInfoForPlayer(string const& in, string& url, GenericPlayer::Option **opt)\n{\n\tCURLU *turl = curl_url_dup(m_url);\n\tcurl_url_set(turl, CURLUPART_URL, in.c_str(), 0);\n\tchar *result;\n\tcurl_url_get(turl, CURLUPART_URL, &result, 0);\n\turl = result;\n\tcurl_free(result);\n\tcurl_url_cleanup(turl);\n\t*opt = NULL;\n}\n\nvoid HttpServerBrowser::SetPath(const char *ref)\n{\n\tif (ref)\n\t{\n\t\tchar *encoded = curl_easy_escape(m_curl, ref, 0);\n\t\tchar *current;\n\t\tcurl_url_get(m_url, CURLUPART_URL, &current, 0);\n\t\tstring full = current;\n\t\tfull += encoded;\n\t\tfull += \"/\";\n\t\tcurl_url_set(m_url, CURLUPART_URL, full.c_str(), 0);\n\t\tcurl_free(encoded);\n\t\tcurl_free(current);\n\t}\n}\n\nvector<HttpServerBrowser::Entry *> *HttpServerBrowser::GoTo(const char *ref, int32_t *result)\n{\n\tvector<HttpServerBrowser::Entry *> *ret = new vector<HttpServerBrowser::Entry *>;\n\tCURLcode cret;\n\n\tSetPath(ref);\n\n\tchar *addr;\n\tcurl_url_get(m_url, CURLUPART_URL, &addr, 0);\n\tSCE_DBG_LOG_INFO(\"[GoTo] Attempt to open %s\\n\", addr);\n\tcurl_easy_setopt(m_curl, CURLOPT_URL, addr);\n\tcurl_free(addr);\n\n\tm_buffer = NULL;\n\tm_posInBuf = 0;\n\n\tcret = curl_easy_perform(m_curl);\n\tif (cret != CURLE_OK)\n\t{\n\t\t*result = cret;\n\t\treturn ret;\n\t}\n\n\tif (m_buffer && m_posInBuf > 2)\n\t{\n\t\tm_buffer[m_posInBuf - 1] = 0;\n\n\t\tchar *href = NULL;\n\t\tchar *refEnd = m_buffer;\n\t\twhile (1)\n\t\t{\n\t\t\thref = sce_paf_strstr(refEnd + 1, \"<a href=\\\"\");\n\t\t\tif (!href)\n\t\t\t\tbreak;\n\t\t\thref += 9;\n\n\t\t\trefEnd = sce_paf_strstr(href, \"\\\">\");\n\t\t\t*refEnd = 0;\n\n\t\t\tGenericPlayer::SupportType supportType = utils::GetContentSupportType(href);\n\n\t\t\tif (supportType != GenericPlayer::SupportType_NotSupported)\n\t\t\t{\n\t\t\t\tchar *decoded = curl_easy_unescape(m_curl, href, 0, NULL);\n\t\t\t\tHttpServerBrowser::Entry *entry = new HttpServerBrowser::Entry();\n\t\t\t\tentry->ref = decoded;\n\t\t\t\tentry->type = HttpServerBrowser::Entry::Type_UnsupportedFile;\n\t\t\t\tcurl_free(decoded);\n\n\t\t\t\tif (supportType == GenericPlayer::SupportType_MaybeSupported)\n\t\t\t\t{\n\t\t\t\t\tentry->type = HttpServerBrowser::Entry::Type_Folder;\n\t\t\t\t}\n\t\t\t\telse if (supportType == GenericPlayer::SupportType_Supported)\n\t\t\t\t{\n\t\t\t\t\tentry->type = HttpServerBrowser::Entry::Type_SupportedFile;\n\t\t\t\t}\n\n\t\t\t\tret->push_back(entry);\n\t\t\t}\n\t\t}\n\n\t\t*result = SCE_OK;\n\t}\n\telse\n\t{\n\t\t*result = SCE_ERROR_ERRNO_ENOENT;\n\t}\n\n\tif (m_buffer)\n\t\tsce_paf_free(m_buffer);\n\n\treturn ret;\n}\n\nsize_t HttpServerBrowser::DownloadCore(char *buffer, size_t size, size_t nitems, void *userdata)\n{\n\tHttpServerBrowser *obj = static_cast<HttpServerBrowser *>(userdata);\n\tsize_t toCopy = size * nitems;\n\n\tif (toCopy != 0)\n\t{\n\t\tobj->m_buffer = static_cast<char *>(sce_paf_realloc(obj->m_buffer, obj->m_posInBuf + toCopy));\n\t\tsce_paf_memcpy(obj->m_buffer + obj->m_posInBuf, buffer, toCopy);\n\t\tobj->m_posInBuf += toCopy;\n\t\treturn toCopy;\n\t}\n\n\treturn 0;\n}"
  },
  {
    "path": "NetStream/source/browsers/hvdb_tracks_browser.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <libdbg.h>\n#include <psp2_compat/curl/curl.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"hvdb.h\"\n#include \"players/player_av.h\"\n#include \"players/player_beav.h\"\n#include \"players/player_fmod.h\"\n#include \"browsers/hvdb_tracks_browser.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[HvdbTracksBrowser]\"\n\nusing namespace paf;\n\nHvdbTracksBrowser::HvdbTracksBrowser(const char *workId, const char *workBannerUrl)\n{\n\tm_workId = workId;\n\tm_bannerUrl = workBannerUrl;\n\tm_hvdbCtx = NULL;\n\tm_option = NULL;\n}\n\nHvdbTracksBrowser::~HvdbTracksBrowser()\n{\n\thvdbCleanup(m_hvdbCtx);\n\n\tif (m_option)\n\t{\n\t\tdelete m_option;\n\t}\n}\n\nbool HvdbTracksBrowser::Probe()\n{\n\treturn true;\n}\n\nbool HvdbTracksBrowser::IsAtRoot(string *current)\n{\n\treturn current->empty();\n}\n\nbool HvdbTracksBrowser::IsAtRoot()\n{\n\treturn m_path.empty();\n}\n\nstring HvdbTracksBrowser::GetPath()\n{\n\treturn m_path;\n}\n\nvoid HvdbTracksBrowser::GetInfoForPlayer(string const& in, string& url, GenericPlayer::Option **opt)\n{\n\tHVDBItem *rootItem = NULL;\n\tuint32_t idx = 0;\n\tParseRefString(in.c_str(), &rootItem, &idx);\n\tif (!rootItem)\n\t{\n\t\treturn;\n\t}\n\n\trootItem = GetItemAt(rootItem, idx);\n\turl = rootItem->dataItem->url;\n\n\tif (m_option)\n\t{\n\t\tdelete m_option;\n\t\tm_option = NULL;\n\t}\n\n\tint32_t showBanner;\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetInt(\"hvdb_show_banner\", &showBanner, 0);\n\tif (showBanner)\n\t{\n\t\tGenericPlayer::Option *popt = new GenericPlayer::Option();\n\t\tpopt->auxStreamUrl = m_bannerUrl;\n\t\tm_option = popt;\n\t}\n\n\t*opt = m_option;\n\n\tsceClibPrintf(\"get formatted url: %s\\n\", url.c_str());\n}\n\nvoid HvdbTracksBrowser::SetPath(const char *ref)\n{\n\tif (ref)\n\t{\n\t\tif (!sce_paf_strcmp(ref, \"..\"))\n\t\t{\n\t\t\tchar *tmp = static_cast<char *>(sce_paf_malloc(m_path.length() + 1));\n\t\t\tsce_paf_strcpy(tmp, m_path.c_str());\n\t\t\tchar *sptr = sce_paf_strrchr(tmp, '/');\n\t\t\tif (!sptr)\n\t\t\t{\n\t\t\t\tm_path.clear();\n\t\t\t\tsce_paf_free(tmp);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t*sptr = 0;\n\t\t\tsptr = sce_paf_strrchr(tmp, '/');\n\t\t\tif (!sptr)\n\t\t\t{\n\t\t\t\tm_path.clear();\n\t\t\t\tsce_paf_free(tmp);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsptr += 1;\n\t\t\t*sptr = 0;\n\t\t\tm_path = tmp;\n\t\t\tsce_paf_free(tmp);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_path += m_currentDataName + \"/\";\n\t\t}\n\t}\n\telse\n\t{\n\t\tm_path.clear();\n\t}\n}\n\nvector<HvdbTracksBrowser::Entry *> *HvdbTracksBrowser::GoTo(const char *ref, int32_t *result)\n{\n\tint32_t fret;\n\tHVDBItem *hvdbItem = NULL;\n\tHVDBItem *hvdbBaseItem = NULL;\n\tvector<HvdbTracksBrowser::Entry *> *ret = new vector<HvdbTracksBrowser::Entry *>;\n\n\tSCE_DBG_LOG_INFO(\"[GoTo] Attempt to open %s\", m_path.c_str());\n\n\tif (ref)\n\t{\n\t\tHVDBItem *rootItem = NULL;\n\t\tuint32_t idx = 0;\n\t\tParseRefString(ref, &rootItem, &idx);\n\t\tif (!rootItem)\n\t\t{\n\t\t\t*result = SCE_ERROR_ERRNO_ENOENT;\n\t\t\tgoto error_return;\n\t\t}\n\n\t\trootItem = GetItemAt(rootItem, idx);\n\t\tm_currentDataName = rootItem->dataItem->title;\n\n\t\tfret = hvdbParseDataFolder(m_hvdbCtx, rootItem->dataItem, &hvdbItem);\n\t}\n\telse\n\t{\n\t\tif (m_hvdbCtx)\n\t\t{\n\t\t\thvdbCleanup(m_hvdbCtx);\n\t\t\tm_hvdbCtx = NULL;\n\t\t}\n\n\t\tm_currentDataName.clear();\n\n\t\tfret = hvdbParseData(&m_hvdbCtx, m_workId.c_str(), &hvdbItem);\n\t}\n\n\tSetPath(ref);\n\n\tif (fret <= 0)\n\t{\n\t\tif (fret == 0)\n\t\t{\n\t\t\tfret = SCE_ERROR_ERRNO_ENOENT;\n\t\t}\n\t\t*result = fret;\n\t\tgoto error_return;\n\t}\n\n\thvdbBaseItem = hvdbItem;\n\n\tfor (int i = 0; i < fret; i++)\n\t{\n\t\tif (hvdbItem->dataItem->type == HVDB_DATA_TYPE_FOLDER)\n\t\t{\n\t\t\tHvdbTracksBrowser::Entry *entry = new HvdbTracksBrowser::Entry();\n\t\t\tentry->ref = common::ToString(reinterpret_cast<uint32_t>(hvdbBaseItem)) + \"_\" + common::ToString(i) + \"/\";\n\t\t\tentry->displayName = hvdbItem->dataItem->title;\n\t\t\tentry->type = HvdbTracksBrowser::Entry::Type_Folder;\n\t\t\tret->push_back(entry);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tGenericPlayer::SupportType supportType = utils::GetContentSupportType(hvdbItem->dataItem->url);\n\t\t\tif (supportType == GenericPlayer::SupportType_Supported)\n\t\t\t{\n\t\t\t\tHvdbTracksBrowser::Entry *entry = new HvdbTracksBrowser::Entry();\n\t\t\t\tentry->ref = common::ToString(reinterpret_cast<uint32_t>(hvdbBaseItem)) + \"_\" + common::ToString(i) + \"/\";\n\t\t\t\tentry->displayName = hvdbItem->dataItem->title;\n\t\t\t\tentry->type = HvdbTracksBrowser::Entry::Type_SupportedFile;\n\t\t\t\tret->push_back(entry);\n\t\t\t}\n\t\t}\n\n\t\thvdbItem = hvdbItem->next;\n\t}\n\n\t*result = SCE_OK;\n\nerror_return:\n\n\treturn ret;\n}\n\nvoid HvdbTracksBrowser::ParseRefString(const char *str, HVDBItem **item, uint32_t *idx)\n{\n\tif (!str)\n\t{\n\t\treturn;\n\t}\n\n\tconst char *last = NULL;\n\tconst char *p = str;\n\tfor (; *p; ++p)\n\t{\n\t\tif (((*p >= '0' && *p <= '9') || *p == '_') && (p == str || *(p - 1) == '/'))\n\t\t{\n\t\t\tlast = p;\n\t\t}\n\t}\n\n\tif (last)\n\t{\n\t\tchar *end = NULL;\n\t\t*item = reinterpret_cast<HVDBItem *>(sce_paf_strtoul(last, &end, 10));\n\t\tif (end)\n\t\t{\n\t\t\t*idx = sce_paf_strtoul(end + 1, NULL, 10);\n\t\t}\n\t}\n}\n\nHVDBItem *HvdbTracksBrowser::GetItemAt(HVDBItem *firstItem, uint32_t idx)\n{\n\tuint32_t i = 0;\n\tHVDBItem *item = firstItem;\n\tdo\n\t{\n\t\tif (i == idx)\n\t\t{\n\t\t\treturn item;\n\t\t}\n\t\titem = item->next;\n\t\ti++;\n\t} while (item);\n\n\treturn NULL;\n}"
  },
  {
    "path": "NetStream/source/browsers/local_server_browser.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <libdbg.h>\n#include <psp2_compat/curl/curl.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"players/player_av.h\"\n#include \"players/player_beav.h\"\n#include \"players/player_fmod.h\"\n#include \"browsers/local_server_browser.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[LocalBrowser]\"\n\nusing namespace paf;\n\nconst char *k_supportedRoots[] = {\n\t\t\"ux0:\",\n\t\t\"uma0:\"\n};\n\nLocalServerBrowser::LocalServerBrowser()\n{\n\t\n}\n\nLocalServerBrowser::~LocalServerBrowser()\n{\n\n}\n\nbool LocalServerBrowser::Probe()\n{\n\treturn true;\n}\n\nbool LocalServerBrowser::IsAtRoot(string *current)\n{\n\treturn current->empty();\n}\n\nbool LocalServerBrowser::IsAtRoot()\n{\n\treturn m_path.empty();\n}\n\nstring LocalServerBrowser::GetPath()\n{\n\treturn m_path;\n}\n\nvoid LocalServerBrowser::GetInfoForPlayer(string const& in, string& url, GenericPlayer::Option **opt)\n{\n\tstring fullPath = m_path + in;\n\n\tif (!utils::IsLocalPath(in.c_str()))\n\t{\n\t\turl = in;\n\t}\n\telse\n\t{\n\t\turl = fullPath;\n\t}\n\t*opt = NULL;\n}\n\nvoid LocalServerBrowser::SetPath(const char *ref)\n{\n\tif (ref)\n\t{\n\t\tif (!sce_paf_strcmp(ref, \"..\"))\n\t\t{\n\t\t\tchar *tmp = static_cast<char *>(sce_paf_malloc(m_path.length() + 1));\n\t\t\tsce_paf_strcpy(tmp, m_path.c_str());\n\t\t\tchar *sptr = sce_paf_strrchr(tmp, '/');\n\t\t\tif (!sptr)\n\t\t\t{\n\t\t\t\tm_path.clear();\n\t\t\t\tsce_paf_free(tmp);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t*sptr = 0;\n\t\t\tsptr = sce_paf_strrchr(tmp, '/');\n\t\t\tif (!sptr)\n\t\t\t{\n\t\t\t\tsptr = sce_paf_strchr(tmp, ':');\n\t\t\t}\n\t\t\tsptr += 1;\n\t\t\t*sptr = 0;\n\t\t\tm_path = tmp;\n\t\t\tsce_paf_free(tmp);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_path += ref;\n\t\t}\n\t}\n\telse\n\t{\n\t\tm_path.clear();\n\t}\n}\n\nbool LocalServerBrowser::DefaultFsSort(const LocalServerBrowser::Entry *a, const LocalServerBrowser::Entry *b)\n{\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\n\tint32_t nameSort = 0;\n\tint32_t typeSort = 0;\n\tbool isFolderA = a->type == LocalServerBrowser::Entry::Type_Folder;\n\tbool isFolderB = b->type == LocalServerBrowser::Entry::Type_Folder;\n\tsettings->GetInt(\"local_sort_name\", (int32_t *)&nameSort, 0);\n\tsettings->GetInt(\"local_sort_type\", (int32_t *)&typeSort, 0);\n\n\tswitch (typeSort)\n\t{\n\tcase 0:\n\t\tif (isFolderA && !isFolderB)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\telse if (!isFolderA && isFolderB)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\tbreak;\n\tcase 1:\n\t\tif (isFolderA && !isFolderB)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\telse if (!isFolderA && isFolderB)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\tbreak;\n\t}\n\n\tint32_t ret = sce_paf_strcasecmp(a->ref.c_str(), b->ref.c_str());\n\n\tswitch (nameSort)\n\t{\n\tcase 0:\n\t\tif (ret <= 0)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn false;\n\t\t}\n\tcase 1:\n\t\tif (ret <= 0)\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\nvector<LocalServerBrowser::Entry *> *LocalServerBrowser::GoTo(const char *ref, int32_t *result)\n{\n\tchar prefix[256];\n\tvector<LocalServerBrowser::Entry *> *ret = new vector<LocalServerBrowser::Entry *>;\n\tmenu::Settings::GetAppSetInstance()->GetString(\"local_playlist_prefix\", prefix, sizeof(prefix), \"\");\n\n\tSetPath(ref);\n\n\tSCE_DBG_LOG_INFO(\"[GoTo] Attempt to open %s\\n\", m_path.c_str());\n\n\tif (ref)\n\t{\n\t\tif (sce_paf_strstr(ref, \".m3u8\"))\n\t\t{\n\t\t\tcommon::SharedPtr<LocalFile> fres;\n\t\t\tint32_t res = -1;\n\t\t\tsize_t fsz = 0;\n\t\t\tchar *fbuf = NULL;\n\t\t\tchar *begin = NULL;\n\t\t\tchar *end = NULL;\n\n\t\t\tfres = LocalFile::Open(GetPath().c_str(), File::RDONLY, 0, &res);\n\t\t\tif (res < 0)\n\t\t\t{\n\t\t\t\t*result = res;\n\t\t\t\tgoto error_return;\n\t\t\t}\n\n\t\t\tfsz = fres->GetFileSize();\n\t\t\tfbuf = (char *)sce_paf_malloc(fsz + 1);\n\t\t\tif (!fbuf)\n\t\t\t{\n\t\t\t\t*result = SCE_ERROR_ERRNO_ENOMEM;\n\t\t\t\tfres.reset();\n\t\t\t\tgoto error_return;\n\t\t\t}\n\n\t\t\tfbuf[fsz] = 0;\n\t\t\tfres->Read(fbuf, fsz);\n\t\t\tfres->Close();\n\t\t\tfres.reset();\n\n\t\t\tbegin = sce_paf_strtok(fbuf, \"#\");\n\t\t\twhile (begin)\n\t\t\t{\n\t\t\t\tbegin = sce_paf_strchr(begin, '\\n');\n\t\t\t\tif (begin && sce_paf_strlen(begin) > 3)\n\t\t\t\t{\n\t\t\t\t\tbegin++;\n\t\t\t\t\tif (*begin == '#')\n\t\t\t\t\t{\n\t\t\t\t\t\tbegin = sce_paf_strtok(NULL, \"#\");\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tend = sce_paf_strchr(begin, '\\r');\n\t\t\t\t\tif (end)\n\t\t\t\t\t{\n\t\t\t\t\t\t*end = 0;\n\t\t\t\t\t}\n\t\t\t\t\tend = sce_paf_strchr(begin, '\\n');\n\t\t\t\t\tif (end)\n\t\t\t\t\t{\n\t\t\t\t\t\t*end = 0;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!sce_paf_strncmp(begin, \"http\", 4))\n\t\t\t\t\t{\n\t\t\t\t\t\tLocalServerBrowser::Entry *entry = new LocalServerBrowser::Entry();\n\t\t\t\t\t\tentry->ref = begin;\n\t\t\t\t\t\tentry->type = LocalServerBrowser::Entry::Type_SupportedFile;\n\t\t\t\t\t\tret->push_back(entry);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tLocalServerBrowser::Entry *entry = new LocalServerBrowser::Entry();\n\t\t\t\t\t\tentry->ref = prefix;\n\t\t\t\t\t\tentry->ref += begin;\n\t\t\t\t\t\tentry->type = LocalServerBrowser::Entry::Type_SupportedFile;\n\t\t\t\t\t\tret->push_back(entry);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tbegin = sce_paf_strtok(NULL, \"#\");\n\t\t\t}\n\n\t\t\tsce_paf_free(fbuf);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tDir dir;\n\t\t\tDirEnt dentry;\n\n\t\t\tif (dir.Open(m_path.c_str()) >= 0)\n\t\t\t{\n\t\t\t\twhile (dir.Read(&dentry) >= 0)\n\t\t\t\t{\n\t\t\t\t\tGenericPlayer::SupportType supportType = utils::GetContentSupportType(dentry.name.c_str());\n\n\t\t\t\t\tif (supportType != GenericPlayer::SupportType_NotSupported)\n\t\t\t\t\t{\n\t\t\t\t\t\tLocalServerBrowser::Entry *entry = new LocalServerBrowser::Entry();\n\t\t\t\t\t\tentry->ref = dentry.name.c_str();\n\t\t\t\t\t\tentry->type = LocalServerBrowser::Entry::Type_UnsupportedFile;\n\n\t\t\t\t\t\tif (supportType == GenericPlayer::SupportType_MaybeSupported)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tentry->ref += \"/\";\n\t\t\t\t\t\t\tentry->type = LocalServerBrowser::Entry::Type_Folder;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (supportType == GenericPlayer::SupportType_Supported)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (sce_paf_strstr(entry->ref.c_str(), \".m3u8\"))\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tentry->ref += \"/\";\n\t\t\t\t\t\t\t\tentry->type = LocalServerBrowser::Entry::Type_PlaylistFile;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tentry->type = LocalServerBrowser::Entry::Type_SupportedFile;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tret->push_back(entry);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tdir.Close();\n\n\t\t\t\t*result = SCE_OK;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t*result = SCE_ERROR_ERRNO_ENOENT;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tfor (int i = 0; i < sizeof(k_supportedRoots) / sizeof(char *); i++)\n\t\t{\n\t\t\tif (LocalFile::Exists(k_supportedRoots[i]))\n\t\t\t{\n\t\t\t\tLocalServerBrowser::Entry *entry = new LocalServerBrowser::Entry();\n\t\t\t\tentry->ref = k_supportedRoots[i];\n\t\t\t\tentry->type = LocalServerBrowser::Entry::Type_Folder;\n\t\t\t\tret->push_back(entry);\n\t\t\t}\n\t\t}\n\n\t\t*result = SCE_OK;\n\t}\n\n\tpaf::sort(ret->begin(), ret->end(), DefaultFsSort);\n\nerror_return:\n\n\treturn ret;\n}"
  },
  {
    "path": "NetStream/source/debug.cpp",
    "content": "#ifdef _DEBUG\n\n#include <kernel.h>\n#include <libdbg.h>\n#include <paf.h>\n#include <libdbg.h>\n\n#include \"common.h\"\n#include \"debug.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[DEBUG]\"\n\nstatic int32_t s_oldMemSize = 0;\nstatic int32_t s_oldGraphMemSize = 0;\nstatic uint32_t s_iter = 0;\n\nstatic ui::Scene *s_currentPage = NULL;\nstatic Plugin *s_currentPlugin = NULL;\nstatic ui::Text *s_debugText = NULL;\n\nclass PadListener : public inputdevice::InputListener\n{\npublic:\n\n\tPadListener() : InputListener(inputdevice::DEVICE_TYPE_PAD)\n\t{\n\n\t}\n\n\tvoid OnUpdate(inputdevice::Data *data)\n\t{\n#define PRESSED(x) ((data->m_pad_data->paddata & x) && !(data->m_pad_data_pre->paddata & x))\n\t\tif (PRESSED(inputdevice::pad::Data::PAD_SELECT) && s_currentPlugin && s_currentPage)\n\t\t{\n\t\t\tif (s_currentPage->GetDebugMode() != ui::Scene::DEBUG_OFF)\n\t\t\t{\n\t\t\t\tSetPageDebugMode(s_currentPlugin, s_currentPage->GetName(), Plugin::PageDebugMode_PageVisualEdit, false);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tSetPageDebugMode(s_currentPlugin, s_currentPage->GetName(), Plugin::PageDebugMode_PageVisualEdit, true);\n\t\t\t}\n\t\t}\n#undef PRESSED\n\t}\n};\n\nvoid DebugFocusCB(ui::Widget* pre, ui::Widget* curr, void *data)\n{\n\tif (pre)\n\t{\n\t\twchar_t buf[256];\n\t\tmath::v4 pos;\n\t\tmath::v4 *size;\n\t\tmath::v4 off;\n\t\tpos = pre->GetPos(0, NULL, off);\n\t\tsize = pre->GetSize(0);\n\t\tIDParam name = pre->GetName();\n\t\tif (!name.GetID().empty())\n\t\t{\n\t\t\twstring nstr;\n\t\t\tcommon::Utf8ToUtf16(name.GetID(), &nstr);\n\t\t\tsce_paf_swprintf(buf, 256, L\"%s\\nx: %.2f\\ny: %.2f\\nwidth: %.2f\\nheight: %.2f\", nstr.c_str(), pos.x().f(), pos.y().f(), size->x().f(), size->y().f());\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsce_paf_swprintf(buf, 256, L\"0x%08X\\nx: %.2f\\ny: %.2f\\nwidth: %.2f\\nheight: %.2f\", name.GetIDHash(), pos.x().f(), pos.y().f(), size->x().f(), size->y().f());\n\t\t}\n\t\ts_debugText->SetString(buf);\n\t}\n}\n\nvoid LeakTestTask(void *pUserData)\n{\n\tint32_t sz = 0;\n\tint32_t delta = 0;\n\tstring str;\n\n#ifdef DEBUG_MEM_HEAP\n\tmemory::HeapAllocator *glAlloc = static_cast<memory::HeapAllocator *>(GetGlobalHeapAllocator());\n\tsz = glAlloc->GetFreeSize();\n\n\tstr.clear();\n\tstr = common::FormatBytesize(sz, 0);\n\tSCE_DBG_LOG_INFO(\"[NS_DEBUG] Free heap memory: %s\", str.c_str());\n\n\tdelta = s_oldMemSize - sz;\n\tdelta = -delta;\n\tif (delta) {\n\t\tSCE_DBG_LOG_INFO(\"[NS_DEBUG] Memory delta: %d bytes\", delta);\n\t}\n\ts_oldMemSize = sz;\n#endif\n\n#ifdef DEBUG_SURFACE_HEAP\n\n\tsz = gutil::GetDefaultSurfacePool()->GetFreeSize();\n\n\tstr.clear();\n\tstr = common::FormatBytesize(sz, 0);\n\tSCE_DBG_LOG_INFO(\"[NS_DEBUG] Free graphics pool: %s\", str.c_str());\n\n\tdelta = s_oldGraphMemSize - sz;\n\tdelta = -delta;\n\tif (delta) {\n\t\tSCE_DBG_LOG_INFO(\"[NS_DEBUG] Graphics pool delta: %d bytes\", delta);\n\t}\n\ts_oldGraphMemSize = sz;\n#endif\n}\n\nvoid JobQueueTestTask(void *pUserData)\n{\n\n}\n\nvoid InitDebug()\n{\n\tsceDbgSetMinimumLogLevel(SCE_DBG_LOG_LEVEL_INFO);\n\n#ifdef DEBUG_EXTRA_TTY\n\tSCE_PAF_AUTO_TEST_SET_EXTRA_TTY(sceIoOpen(\"tty0:\", SCE_O_WRONLY, 0));\n\tSCE_PAF_AUTO_TEST_DUMP(\"\\n\\n-----PAF EXTRA TTY DEBUG MODE ON-----\\n\\n\");\n#endif\n\n\tcommon::MainThreadCallList::Register(LeakTestTask, NULL);\n#ifdef DEBUG_JOB_QUEUE\n\tcommon::MainThreadCallList::Register(JobQueueTestTask, NULL);\n#endif\n\n\tcommon::SharedPtr<inputdevice::InputListener> listener(new PadListener());\n\tinputdevice::AddInputListener(listener);\n}\n\nvoid SetCurrentDebugParam(paf::Plugin *plugin, paf::ui::Scene *page)\n{\n\ts_currentPlugin = plugin;\n\ts_currentPage = page;\n}\n\nvoid SetPageDebugMode(paf::Plugin *plugin, paf::IDParam const& id, paf::Plugin::PageDebugMode mode, bool on)\n{\n\tplugin->SetPageDebugMode(id, mode, on);\n\n\tif (on && (mode == paf::Plugin::PageDebugMode::PageDebugMode_PageVisual || mode == paf::Plugin::PageDebugMode::PageDebugMode_PageVisualEdit))\n\t{\n\t\tui::Scene *page = static_cast<ui::Scene *>(plugin->GetNodeEntity_Widget(id));\n\t\tpage->SetDebugFocusCB(DebugFocusCB);\n\n\t\ts_debugText = (ui::Text *)plugin->CreateWidget(page->GetDebugCube(), \"text\", \"debug_text\", \"_common_style_text_copy_dialog_desc\");\n\t\ts_debugText->SetPos(0.0f, 0.0f, 0.0f);\n\t\ts_debugText->SetAlign(ui::Widget::ALIGN_MINUS, ui::Widget::ALIGN_PLUS, ui::Widget::ALIGN_NONE, NULL);\n\t\ts_debugText->SetAnchor(ui::Widget::ANCHOR_LEFT, ui::Widget::ANCHOR_TOP, ui::Widget::ANCHOR_CENTER, NULL);\n\t\ts_debugText->SetAdjust(ui::Widget::ADJUST_CONTENT, ui::Widget::ADJUST_CONTENT, ui::Widget::ADJUST_CONTENT);\n\t\ts_debugText->SetStyleAttribute(graph::TextStyleAttribute::TextStyleAttribute_BackColor, 0, 0, { 0.0f, 0.0f, 0.0f, 1.0f });\n\t\ts_debugText->EnableDebugFocus(false);\n\t}\n}\n\n/*\nuint32_t oldButtons = 0;\nui::Widget *widg = NULL;\n\nvoid DirectInputCallback(input::GamePad::GamePadData *pData)\n{\n\tVector4 opos = widg->GetPosition();\n\n\tif (pData->buttons & SCE_PAF_CTRL_UP)\n\t{\n\t\topos.y += 1;\n\t}\n\telse if (pData->buttons & SCE_PAF_CTRL_DOWN)\n\t{\n\t\topos.y -= 1;\n\t}\n\telse if (pData->buttons & SCE_PAF_CTRL_RIGHT)\n\t{\n\t\topos.x += 1;\n\t}\n\telse if (pData->buttons & SCE_PAF_CTRL_LEFT)\n\t{\n\t\topos.x -= 1;\n\t}\n\telse if ((pData->buttons & SCE_PAF_CTRL_CROSS) && !(oldButtons & SCE_PAF_CTRL_CROSS))\n\t{\n\t\tsceClibPrintf(\"\\nx: %f\\ny: %f\\n\", opos.x, opos.y);\n\t}\n\n\twidg->SetPosition(&opos);\n\n\toldButtons = pData->buttons;\n}\n*/\n\n#endif"
  },
  {
    "path": "NetStream/source/dialog.cpp",
    "content": "#include <kernel.h>\n#include <libdbg.h>\n#include <paf.h>\n#include <common_gui_dialog.h>\n\n#include \"common.h\"\n#include \"event.h\"\n#include \"dialog.h\"\n\n#define CURRENT_DIALOG_NONE -1\n\nusing namespace paf;\nusing namespace sce;\n\nstatic int32_t s_currentDialog = CURRENT_DIALOG_NONE;\nstatic Plugin *s_currentPlugin = NULL;\n\nstatic uint32_t s_twoButtonContTable[12];\nstatic uint32_t s_threeButtonContTable[16];\n\nnamespace dialog {\n\tvoid CommonGuiEventHandler(int32_t instanceSlot, CommonGuiDialog::DIALOG_CB buttonCode, void *pUserArg)\n\t{\n\t\tCommonGuiDialog::Dialog::Close(instanceSlot);\n\t\ts_currentDialog = CURRENT_DIALOG_NONE;\n\t\tevent::BroadcastGlobalEvent(s_currentPlugin, DialogEvent, buttonCode);\n\t\ts_currentPlugin = NULL;\n\t}\n}\n\nvoid dialog::OpenPleaseWait(Plugin *workPlugin, const wchar_t *titleText, const wchar_t *messageText, bool withCancel)\n{\n\tif (s_currentDialog != CURRENT_DIALOG_NONE)\n\t\treturn;\n\n\tbool isMainThread = thread::ThreadIDCache::Check();\n\n\tpaf::wstring title = titleText;\n\tpaf::wstring message = messageText;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\n\tif (withCancel)\n\t\ts_currentDialog = CommonGuiDialog::Dialog::Show(workPlugin, &title, &message, &CommonGuiDialog::Param::s_dialogCancelBusy, CommonGuiEventHandler, NULL);\n\telse\n\t\ts_currentDialog = CommonGuiDialog::Dialog::Show(workPlugin, &title, &message, &CommonGuiDialog::Param::s_dialogTextSmallBusy, CommonGuiEventHandler, NULL);\n\n\ts_currentPlugin = workPlugin;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n}\n\nvoid dialog::OpenYesNo(Plugin *workPlugin, const wchar_t *titleText, const wchar_t *messageText)\n{\n\tif (s_currentDialog != CURRENT_DIALOG_NONE)\n\t\treturn;\n\n\tbool isMainThread = thread::ThreadIDCache::Check();\n\n\tpaf::wstring title = titleText;\n\tpaf::wstring message = messageText;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\n\ts_currentDialog = CommonGuiDialog::Dialog::Show(workPlugin, &title, &message, &CommonGuiDialog::Param::s_dialogYesNo, CommonGuiEventHandler, NULL);\n\ts_currentPlugin = workPlugin;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n}\n\nvoid dialog::OpenOk(Plugin *workPlugin, const wchar_t *titleText, const wchar_t *messageText)\n{\n\tif (s_currentDialog != CURRENT_DIALOG_NONE)\n\t\treturn;\n\n\tbool isMainThread = thread::ThreadIDCache::Check();\n\n\tpaf::wstring title = titleText;\n\tpaf::wstring message = messageText;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\n\ts_currentDialog = CommonGuiDialog::Dialog::Show(workPlugin, &title, &message, &CommonGuiDialog::Param::s_dialogOk, CommonGuiEventHandler, NULL);\n\ts_currentPlugin = workPlugin;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n}\n\nvoid dialog::OpenError(Plugin *workPlugin, int32_t errorCode, const wchar_t *messageText)\n{\n\tif (s_currentDialog != CURRENT_DIALOG_NONE)\n\t\treturn;\n\n\tbool isMainThread = thread::ThreadIDCache::Check();\n\n\tCommonGuiDialog::ErrorDialog dialog;\n\n\tauto cb = new CommonGuiDialog::EventCBListener(CommonGuiEventHandler, NULL);\n\n\tdialog.work_plugin = workPlugin;\n\tdialog.error = errorCode;\n\tdialog.listener = cb;\n\tif (messageText)\n\t\tdialog.message = messageText;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\n\ts_currentDialog = dialog.Show();\n\ts_currentPlugin = workPlugin;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n}\n\nvoid dialog::OpenThreeButton(\n\tPlugin *workPlugin,\n\tconst wchar_t *titleText,\n\tconst wchar_t *messageText,\n\tuint32_t button1TextHashref,\n\tuint32_t button2TextHashref,\n\tuint32_t button3TextHashref)\n{\n\tif (s_currentDialog != CURRENT_DIALOG_NONE)\n\t\treturn;\n\n\tbool isMainThread = thread::ThreadIDCache::Check();\n\n\tCommonGuiDialog::Param dparam;\n\n\tdparam = CommonGuiDialog::Param::s_dialogYesNoCancel;\n\tsce_paf_memcpy(s_threeButtonContTable, CommonGuiDialog::Param::s_dialogYesNoCancel.contents_list, sizeof(s_threeButtonContTable));\n\ts_threeButtonContTable[1] = button1TextHashref;\n\ts_threeButtonContTable[5] = button2TextHashref;\n\ts_threeButtonContTable[9] = button3TextHashref;\n\ts_threeButtonContTable[7] = 0x20413274;\n\ts_threeButtonContTable[11] = 0x20413274;\n\tdparam.contents_list = (CommonGuiDialog::ContentsHashTable *)s_threeButtonContTable;\n\n\tpaf::wstring title = titleText;\n\tpaf::wstring message = messageText;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\n\ts_currentDialog = CommonGuiDialog::Dialog::Show(workPlugin, &title, &message, &dparam, CommonGuiEventHandler, NULL);\n\ts_currentPlugin = workPlugin;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n}\n\nvoid dialog::OpenTwoButton(\n\tPlugin *workPlugin,\n\tconst wchar_t *titleText,\n\tconst wchar_t *messageText,\n\tuint32_t button1TextHashref,\n\tuint32_t button2TextHashref)\n{\n\tif (s_currentDialog != CURRENT_DIALOG_NONE)\n\t\treturn;\n\n\tbool isMainThread = thread::ThreadIDCache::Check();\n\n\tCommonGuiDialog::Param dparam;\n\n\tdparam = CommonGuiDialog::Param::s_dialogYesNo;\n\tsce_paf_memcpy(s_twoButtonContTable, CommonGuiDialog::Param::s_dialogYesNo.contents_list, sizeof(s_twoButtonContTable));\n\ts_twoButtonContTable[1] = button2TextHashref;\n\ts_twoButtonContTable[5] = button1TextHashref;\n\ts_twoButtonContTable[3] = 0x20413274;\n\tdparam.contents_list = (CommonGuiDialog::ContentsHashTable *)s_twoButtonContTable;\n\n\tpaf::wstring title = titleText;\n\tpaf::wstring message = messageText;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\n\ts_currentDialog = CommonGuiDialog::Dialog::Show(workPlugin, &title, &message, &dparam, CommonGuiEventHandler, NULL);\n\ts_currentPlugin = workPlugin;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n}\n\nui::ListView *dialog::OpenListView(\n\tPlugin *workPlugin,\n\tconst wchar_t *titleText)\n{\n\tif (s_currentDialog != CURRENT_DIALOG_NONE)\n\t\treturn NULL;\n\n\tbool isMainThread = thread::ThreadIDCache::Check();\n\n\tpaf::wstring title = titleText;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\n\ts_currentDialog = CommonGuiDialog::Dialog::Show(workPlugin, &title, NULL, &CommonGuiDialog::Param::s_dialogXLView, CommonGuiEventHandler, NULL);\n\tui::Widget *ret = CommonGuiDialog::Dialog::GetWidget(s_currentDialog, CommonGuiDialog::REGISTER_ID_LIST_VIEW);\n\ts_currentPlugin = workPlugin;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\treturn (ui::ListView *)ret;\n}\n\nui::ScrollView *dialog::OpenScrollView(\n\tPlugin *workPlugin,\n\tconst wchar_t *titleText)\n{\n\tif (s_currentDialog != CURRENT_DIALOG_NONE)\n\t\treturn NULL;\n\n\tbool isMainThread = thread::ThreadIDCache::Check();\n\n\tpaf::wstring title = titleText;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\n\ts_currentDialog = CommonGuiDialog::Dialog::Show(workPlugin, &title, NULL, &CommonGuiDialog::Param::s_dialogXView, CommonGuiEventHandler, NULL);\n\tui::Widget *ret = CommonGuiDialog::Dialog::GetWidget(s_currentDialog, CommonGuiDialog::REGISTER_ID_SCROLL_VIEW);\n\ts_currentPlugin = workPlugin;\n\n\tif (!isMainThread)\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\treturn (ui::ScrollView *)ret;\n}\n\nvoid dialog::Close()\n{\n\tif (s_currentDialog == CURRENT_DIALOG_NONE)\n\t\treturn;\n\n\tCommonGuiDialog::Dialog::Close(s_currentDialog);\n\ts_currentDialog = CURRENT_DIALOG_NONE;\n\ts_currentPlugin = NULL;\n}\n\nvoid dialog::WaitEnd()\n{\n\tif (s_currentDialog == CURRENT_DIALOG_NONE)\n\t\treturn;\n\n\twhile (s_currentDialog != CURRENT_DIALOG_NONE) {\n\t\tthread::Sleep(100);\n\t}\n}\n\nbool dialog::IsActive()\n{\n\tif (s_currentDialog == CURRENT_DIALOG_NONE)\n\t\treturn false;\n\n\treturn true;\n}"
  },
  {
    "path": "NetStream/source/downloader.cpp",
    "content": "#include <kernel.h>\n#include <libsysmodule.h>\n#include <paf.h>\n#include <ipmi.h>\n#include <download_service.h>\n\n#include \"downloader.h\"\n#include \"event.h\"\n\nusing namespace paf;\n\nDownloader::Downloader()\n{\n\tIPMI::Client::Config conf;\n\tIPMI::Client *client;\n\tuint32_t clMemSize;\n\tint32_t ret;\n\n\tsce_paf_memset(&dw, 0, sizeof(sce::Download));\n\tsce_paf_memset(&conf, 0, sizeof(IPMI::Client::Config));\n\n\tsce_paf_strncpy(reinterpret_cast<char *>(conf.serviceName), \"SceDownload\", sizeof(conf.serviceName));\n\tconf.pipeBudgetType = IPMI::BudgetType_Default;\n\tconf.numResponses = 1;\n\tconf.requestQueueSize = 0x1E00;\n\tconf.receptionQueueSize = 0x1E00;\n\tconf.numAsyncResponses = 1;\n\tconf.requestQueueAddsize1 = 0xF00;\n\tconf.requestQueueAddsize2 = 0xF00;\n\tconf.numEventFlags = 1;\n\tconf.msgQueueSize = 0;\n\tconf.serverPID = SCE_UID_INVALID_UID;\n\n\tclMemSize = conf.estimateClientMemorySize();\n\tdw.clientMem = sce_paf_malloc(clMemSize);\n\tdw.bufMem = sce_paf_malloc(SCE_KERNEL_4KiB);\n\n\tIPMI::Client::create(&client, &conf, &dw, dw.clientMem);\n\n\tdw.client = client;\n\n\tsce::Download::ConnectionOpt connOpt;\n\tsce_paf_memset(&connOpt, 0, sizeof(sce::Download::ConnectionOpt));\n\tconnOpt.budgetType = conf.pipeBudgetType;\n\n\tint ret2 = client->connect(&connOpt, sizeof(sce::Download::ConnectionOpt), &ret);\n\n\tdw.unk_00 = SCE_UID_INVALID_UID;\n\tdw.unk_04 = SCE_UID_INVALID_UID;\n\tdw.unk_08 = SCE_UID_INVALID_UID;\n}\n\nDownloader::~Downloader()\n{\n\tdw.client->disconnect();\n\tdw.client->destroy();\n\tsce_paf_free(dw.clientMem);\n\tsce_paf_free(dw.bufMem);\n}\n\nint32_t Downloader::Enqueue(Plugin *workPlugin, const char *url, const char *name)\n{\n\tIPMI::DataInfo dtInfo[3];\n\tIPMI::BufferInfo bfInfo[1];\n\tint32_t ret = SCE_OK;\n\tint32_t ret2 = SCE_OK;\n\tint32_t dwRes = 0;\n\n\tsce::Download::GetHeaderInfoParam hparam;\n\tsce::Download::AuthParam aparam;\n\tsce::Download::DownloadParam dparam;\n\tsce::Download::HeaderInfo minfo;\n\tsce_paf_memset(&hparam, 0, sizeof(sce::Download::GetHeaderInfoParam));\n\tsce_paf_memset(&aparam, 0, sizeof(sce::Download::AuthParam));\n\tsce_paf_memset(&dparam, 0, sizeof(sce::Download::DownloadParam));\n\tsce_paf_memset(&minfo, 0, sizeof(sce::Download::HeaderInfo));\n\n\thparam.contentType = sce::Download::ContentType_Multimedia;\n\thparam.resolveTimeout = 5000;\n\thparam.resolveRetry = 2;\n\thparam.connectTimeout = 3000;\n\thparam.sendTimeout = 0;\n\thparam.recvTimeout = 3000;\n\tsce_paf_strcpy((char *)hparam.url, url);\n\n\tdtInfo[0].data = &hparam;\n\tdtInfo[0].dataSize = sizeof(sce::Download::GetHeaderInfoParam);\n\tdtInfo[1].data = &aparam;\n\tdtInfo[1].dataSize = sizeof(sce::Download::AuthParam);\n\n\tbfInfo[0].data = &minfo;\n\tbfInfo[0].dataSize = sizeof(sce::Download::HeaderInfo);\n\n\tret = dw.client->invokeSyncMethod(sce::Download::Method_GetHeaderInfo, dtInfo, 2, &ret2, bfInfo, 1);\n\tif (ret != SCE_OK)\n\t\tgoto end;\n\telse if (ret2 != SCE_OK)\n\t{\n\t\tret = ret2;\n\t\tgoto end;\n\t}\n\n\tsce_paf_memset(&minfo.name, 0, sizeof(minfo.name));\n\tsce_paf_strcpy(reinterpret_cast<char *>(minfo.name), name);\n\n\tdparam.bgdlLocation = 1;\n\tsce_paf_strcpy(reinterpret_cast<char *>(dparam.url), url);\n\n\tdtInfo[0].data = &dparam;\n\tdtInfo[0].dataSize = sizeof(sce::Download::DownloadParam);\n\tdtInfo[1].data = &aparam;\n\tdtInfo[1].dataSize = sizeof(sce::Download::AuthParam);\n\tdtInfo[2].data = &minfo;\n\tdtInfo[2].dataSize = sizeof(sce::Download::HeaderInfo);\n\n\tbfInfo[0].data = &dwRes;\n\tbfInfo[0].dataSize = sizeof(int32_t);\n\n\tret2 = SCE_OK;\n\tret = dw.client->invokeSyncMethod(sce::Download::Method_Download, dtInfo, 3, &ret2, bfInfo, 1);\n\tif (ret2 != SCE_OK)\n\t{\n\t\t//invalid filename?\n\t\tsce_paf_memset(&minfo.name, 0, sizeof(minfo.name));\n\t\tchar *ext = sce_paf_strrchr(name, '.');\n\t\tsce_paf_snprintf(reinterpret_cast<char *>(minfo.name), sizeof(minfo.name), \"DefaultFilename_%u%s\", sceKernelGetProcessTimeLow(), ext);\n\n\t\tret2 = SCE_OK;\n\t\tret = dw.client->invokeSyncMethod(sce::Download::Method_Download, dtInfo, 3, &ret2, bfInfo, 1);\n\t\tif (ret2 != SCE_OK)\n\t\t{\n\t\t\tret = ret2;\n\t\t\tgoto end;\n\t\t}\n\t}\n\nend:\n\n\tevent::BroadcastGlobalEvent(workPlugin, DownloaderEvent, ret);\n\n\treturn ret;\n}\n\nint32_t Downloader::EnqueueAsync(Plugin *workPlugin, const char *url, const char *name)\n{\n\tAsyncEnqueue *dwJob = new AsyncEnqueue(workPlugin, this, url, name);\n\tcommon::SharedPtr<job::JobItem> itemParam(dwJob);\n\n\treturn job::JobQueue::DefaultQueue()->Enqueue(itemParam);\n}"
  },
  {
    "path": "NetStream/source/event.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n\n#include \"event.h\"\n\nstatic void PostEventRecursive(ui::Widget *target, int32_t type, ui::Event *ev)\n{\n\tfor (int i = 0; i < target->GetChildrenNum(); i++)\n\t{\n\t\tui::Widget *subtarget = target->GetChild(i);\n\t\tif (subtarget)\n\t\t{\n\t\t\tPostEventRecursive(subtarget, type, ev);\n\t\t}\n\t}\n\ttarget->DoEvent(type, ev);\n}\n\nvoid event::BroadcastGlobalEvent(Plugin *workPlugin, uint32_t type, int32_t d0, int32_t d1, int32_t d2, int32_t d3)\n{\n\tui::Event ev(ui::EV_COMMAND, ui::Event::MODE_DISPATCH, ui::Event::ROUTE_FORWARD, 0, d0, d1, d2, d3);\n\tresource::ResourceObj *res = workPlugin->GetResource();\n\tif (res)\n\t{\n\t\tcxml::Element el = res->GetTableElement(resource::TableType_Page);\n\t\tel = el.GetFirstChild();\n\t\twhile (el == true)\n\t\t{\n\t\t\tuint32_t pageId = 0;\n\t\t\tcxml::util::GetIDHash(el, \"id\", &pageId);\n\t\t\tui::Widget *target = workPlugin->PageRoot(pageId);\n\t\t\tif (target)\n\t\t\t{\n\t\t\t\tPostEventRecursive(target, type, &ev);\n\t\t\t}\n\t\t\tel = el.GetNextSibling();\n\t\t}\n\t}\n}"
  },
  {
    "path": "NetStream/source/ftpparse.c",
    "content": "/* ftpparse.c, ftpparse.h: library for parsing FTP LIST responses\n20001223\nD. J. Bernstein, djb@cr.yp.to\nhttp://cr.yp.to/ftpparse.html\n\nCommercial use is fine, if you let me know what programs you're using this in.\n\nCurrently covered formats:\nEPLF.\nUNIX ls, with or without gid.\nMicrosoft FTP Service.\nWindows NT FTP Server.\nVMS.\nWFTPD.\nNetPresenz (Mac).\nNetWare.\nMSDOS.\n\nDefinitely not covered: \nLong VMS filenames, with information split across two lines.\nNCSA Telnet FTP server. Has LIST = NLST (and bad NLST for directories).\n*/\n\n#include <kernel.h>\n#include <time.h>\n#include \"ftpparse.h\"\n\nextern int sceKernelLibcGmtime_r(const time_t *timer, struct tm *buf);\nextern time_t sceKernelLibcTime(time_t *tod);\n\nstatic long totai(long year,long month,long mday)\n{\n  long result;\n  if (month >= 2) month -= 2;\n  else { month += 10; --year; }\n  result = (mday - 1) * 10 + 5 + 306 * month;\n  result /= 10;\n  if (result == 365) { year -= 3; result = 1460; }\n  else result += 365 * (year % 4);\n  year /= 4;\n  result += 1461 * (year % 25);\n  year /= 25;\n  if (result == 36524) { year -= 3; result = 146096; }\n  else { result += 36524 * (year % 4); }\n  year /= 4;\n  result += 146097 * (year - 5);\n  result += 11017;\n  return result * 86400;\n}\n\nstatic int flagneedbase = 1;\nstatic time_t base; /* time() value on this OS at the beginning of 1970 TAI */\nstatic long now; /* current time */\nstatic int flagneedcurrentyear = 1;\nstatic long currentyear; /* approximation to current year */\n\nstruct tm *libc_gmtime(const time_t *ptimer)\n{\n\tint *tls = (int *)sceKernelGetTLSAddr(0xca);\n\tint local_3c[9];\n\tsceKernelLibcGmtime_r(ptimer, (struct tm *)local_3c);\n\tif (tls != 0) {\n\t\t*tls = local_3c[0];\n\t\ttls[1] = local_3c[1];\n\t\ttls[2] = local_3c[2];\n\t\ttls[3] = local_3c[3];\n\t\ttls[4] = local_3c[4];\n\t\tif (0x76b < local_3c[5]) {\n\t\t\tlocal_3c[5] = local_3c[5] + -0x76c;\n\t\t}\n\t\ttls[5] = local_3c[5];\n\t\ttls[6] = local_3c[6];\n\t\ttls[7] = local_3c[7];\n\t\ttls[8] = local_3c[8];\n\t}\n\n\treturn (struct tm *)tls;\n}\n\nstatic time_t libc_time(time_t *tod)\n{\n\ttime_t ret;\n\ttime_t todi;\n\n\tret = sceKernelLibcTime(&todi);\n\tif (tod != NULL) {\n\t\t*tod = ret;\n\t}\n\n\treturn ret;\n}\n\nstatic void initbase(void)\n{\n  struct tm *t;\n  if (!flagneedbase) return;\n\n  base = 0;\n  t = libc_gmtime(&base);\n  base = -(totai(t->tm_year + 1900,t->tm_mon,t->tm_mday) + t->tm_hour * 3600 + t->tm_min * 60 + t->tm_sec);\n  /* assumes the right time_t, counting seconds. */\n  /* base may be slightly off if time_t counts non-leap seconds. */\n  flagneedbase = 0;\n}\n\nstatic void initnow(void)\n{\n  long day;\n  long year;\n\n  initbase();\n  now = libc_time((time_t *) 0) - base;\n\n  if (flagneedcurrentyear) {\n\tday = now / 86400;\n\tif ((now % 86400) < 0) --day;\n\tday -= 11017;\n\tyear = 5 + day / 146097;\n\tday = day % 146097;\n\tif (day < 0) { day += 146097; --year; }\n\tyear *= 4;\n\tif (day == 146096) { year += 3; day = 36524; }\n\telse { year += day / 36524; day %= 36524; }\n\tyear *= 25;\n\tyear += day / 1461;\n\tday %= 1461;\n\tyear *= 4;\n\tif (day == 1460) { year += 3; day = 365; }\n\telse { year += day / 365; day %= 365; }\n\tday *= 10;\n\tif ((day + 5) / 306 >= 10) ++year;\n\tcurrentyear = year;\n\tflagneedcurrentyear = 0;\n  }\n}\n\n/* UNIX ls does not show the year for dates in the last six months. */\n/* So we have to guess the year. */\n/* Apparently NetWare uses ``twelve months'' instead of ``six months''; ugh. */\n/* Some versions of ls also fail to show the year for future dates. */\nstatic long guesstai(long month,long mday)\n{\n  long year;\n  long t;\n\n  initnow();\n\n  for (year = currentyear - 1;year < currentyear + 100;++year) {\n\tt = totai(year,month,mday);\n\tif (now - t < 350 * 86400)\n\t  return t;\n  }\n\n  return 0;\n}\n\nstatic int check(char *buf,char *monthname)\n{\n  if ((buf[0] != monthname[0]) && (buf[0] != monthname[0] - 32)) return 0;\n  if ((buf[1] != monthname[1]) && (buf[1] != monthname[1] - 32)) return 0;\n  if ((buf[2] != monthname[2]) && (buf[2] != monthname[2] - 32)) return 0;\n  return 1;\n}\n\nstatic char *months[12] = {\n  \"jan\",\"feb\",\"mar\",\"apr\",\"may\",\"jun\",\"jul\",\"aug\",\"sep\",\"oct\",\"nov\",\"dec\"\n} ;\n\nstatic int getmonth(char *buf,int len)\n{\n  int i;\n  if (len == 3)\n\tfor (i = 0;i < 12;++i)\n\t  if (check(buf,months[i])) return i;\n  return -1;\n}\n\nstatic long getlong(char *buf,int len)\n{\n  long u = 0;\n  while (len-- > 0)\n\tu = u * 10 + (*buf++ - '0');\n  return u;\n}\n\nint ftpparse(struct ftpparse *fp,char *buf,int len)\n{\n  int i;\n  int j;\n  int state;\n  long size;\n  long year;\n  long month;\n  long mday;\n  long hour;\n  long minute;\n\n  fp->name = 0;\n  fp->namelen = 0;\n  fp->flagtrycwd = 0;\n  fp->flagtryretr = 0;\n  fp->sizetype = FTPPARSE_SIZE_UNKNOWN;\n  fp->size = 0;\n  fp->mtimetype = FTPPARSE_MTIME_UNKNOWN;\n  fp->mtime = 0;\n  fp->idtype = FTPPARSE_ID_UNKNOWN;\n  fp->id = 0;\n  fp->idlen = 0;\n\n  if (len < 2) /* an empty name in EPLF, with no info, could be 2 chars */\n\treturn 0;\n\n  switch(*buf) {\n\t/* see http://pobox.com/~djb/proto/eplf.txt */\n\t/* \"+i8388621.29609,m824255902,/,\\tdev\" */\n\t/* \"+i8388621.44468,m839956783,r,s10376,\\tRFCEPLF\" */\n\tcase '+':\n\t  i = 1;\n\t  for (j = 1;j < len;++j) {\n\t\tif (buf[j] == 9) {\n\t\t  fp->name = buf + j + 1;\n\t\t  fp->namelen = len - j - 1;\n\t\t  return 1;\n\t\t}\n\t\tif (buf[j] == ',') {\n\t\t  switch(buf[i]) {\n\t\t\tcase '/':\n\t\t\t  fp->flagtrycwd = 1;\n\t\t\t  break;\n\t\t\tcase 'r':\n\t\t\t  fp->flagtryretr = 1;\n\t\t\t  break;\n\t\t\tcase 's':\n\t\t\t  fp->sizetype = FTPPARSE_SIZE_BINARY;\n\t\t\t  fp->size = getlong(buf + i + 1,j - i - 1);\n\t\t\t  break;\n\t\t\tcase 'm':\n\t\t\t  fp->mtimetype = FTPPARSE_MTIME_LOCAL;\n\t\t\t  initbase();\n\t\t\t  fp->mtime = base + getlong(buf + i + 1,j - i - 1);\n\t\t\t  break;\n\t\t\tcase 'i':\n\t\t\t  fp->idtype = FTPPARSE_ID_FULL;\n\t\t\t  fp->id = buf + i + 1;\n\t\t\t  fp->idlen = j - i - 1;\n\t\t  }\n\t\t  i = j + 1;\n\t\t}\n\t  }\n\t  return 0;\n\t\n\t/* UNIX-style listing, without inum and without blocks */\n\t/* \"-rw-r--r--   1 root     other        531 Jan 29 03:26 README\" */\n\t/* \"dr-xr-xr-x   2 root     other        512 Apr  8  1994 etc\" */\n\t/* \"dr-xr-xr-x   2 root     512 Apr  8  1994 etc\" */\n\t/* \"lrwxrwxrwx   1 root     other          7 Jan 25 00:17 bin -> usr/bin\" */\n\t/* Also produced by Microsoft's FTP servers for Windows: */\n\t/* \"----------   1 owner    group         1803128 Jul 10 10:18 ls-lR.Z\" */\n\t/* \"d---------   1 owner    group               0 May  9 19:45 Softlib\" */\n\t/* Also WFTPD for MSDOS: */\n\t/* \"-rwxrwxrwx   1 noone    nogroup      322 Aug 19  1996 message.ftp\" */\n\t/* Also NetWare: */\n\t/* \"d [R----F--] supervisor            512       Jan 16 18:53    login\" */\n\t/* \"- [R----F--] rhesus             214059       Oct 20 15:27    cx.exe\" */\n\t/* Also NetPresenz for the Mac: */\n\t/* \"-------r--         326  1391972  1392298 Nov 22  1995 MegaPhone.sit\" */\n\t/* \"drwxrwxr-x               folder        2 May 10  1996 network\" */\n\tcase 'b':\n\tcase 'c':\n\tcase 'd':\n\tcase 'l':\n\tcase 'p':\n\tcase 's':\n\tcase '-':\n\n\t  if (*buf == 'd') fp->flagtrycwd = 1;\n\t  if (*buf == '-') fp->flagtryretr = 1;\n\t  if (*buf == 'l') fp->flagtrycwd = fp->flagtryretr = 1;\n\n\t  state = 1;\n\t  i = 0;\n\t  for (j = 1;j < len;++j)\n\t\tif ((buf[j] == ' ') && (buf[j - 1] != ' ')) {\n\t\t  switch(state) {\n\t\t\tcase 1: /* skipping perm */\n\t\t\t  state = 2;\n\t\t\t  break;\n\t\t\tcase 2: /* skipping nlink */\n\t\t\t  state = 3;\n\t\t\t  if ((j - i == 6) && (buf[i] == 'f')) /* for NetPresenz */\n\t\t\t\tstate = 4;\n\t\t\t  break;\n\t\t\tcase 3: /* skipping uid */\n\t\t\t  state = 4;\n\t\t\t  break;\n\t\t\tcase 4: /* getting tentative size */\n\t\t\t  size = getlong(buf + i,j - i);\n\t\t\t  state = 5;\n\t\t\t  break;\n\t\t\tcase 5: /* searching for month, otherwise getting tentative size */\n\t\t\t  month = getmonth(buf + i,j - i);\n\t\t\t  if (month >= 0)\n\t\t\t\tstate = 6;\n\t\t\t  else\n\t\t\t\tsize = getlong(buf + i,j - i);\n\t\t\t  break;\n\t\t\tcase 6: /* have size and month */\n\t\t\t  mday = getlong(buf + i,j - i);\n\t\t\t  state = 7;\n\t\t\t  break;\n\t\t\tcase 7: /* have size, month, mday */\n\t\t\t  if ((j - i == 4) && (buf[i + 1] == ':')) {\n\t\t\t\thour = getlong(buf + i,1);\n\t\t\t\tminute = getlong(buf + i + 2,2);\n\t\t\t\tfp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;\n\t\t\t\tinitbase();\n\t\t\t\tfp->mtime = base + guesstai(month,mday) + hour * 3600 + minute * 60;\n\t\t\t  } else if ((j - i == 5) && (buf[i + 2] == ':')) {\n\t\t\t\thour = getlong(buf + i,2);\n\t\t\t\tminute = getlong(buf + i + 3,2);\n\t\t\t\tfp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;\n\t\t\t\tinitbase();\n\t\t\t\tfp->mtime = base + guesstai(month,mday) + hour * 3600 + minute * 60;\n\t\t\t  }\n\t\t\t  else if (j - i >= 4) {\n\t\t\t\tyear = getlong(buf + i,j - i);\n\t\t\t\tfp->mtimetype = FTPPARSE_MTIME_REMOTEDAY;\n\t\t\t\tinitbase();\n\t\t\t\tfp->mtime = base + totai(year,month,mday);\n\t\t\t  }\n\t\t\t  else\n\t\t\t\treturn 0;\n\t\t\t  fp->name = buf + j + 1;\n\t\t\t  fp->namelen = len - j - 1;\n\t\t\t  state = 8;\n\t\t\t  break;\n\t\t\tcase 8: /* twiddling thumbs */\n\t\t\t  break;\n\t\t  }\n\t\t  i = j + 1;\n\t\t  while ((i < len) && (buf[i] == ' ')) ++i;\n\t\t}\n\n\t  if (state != 8)\n\t\treturn 0;\n\n\t  fp->size = size;\n\t  fp->sizetype = FTPPARSE_SIZE_BINARY;\n\n\t  if (*buf == 'l')\n\t\tfor (i = 0;i + 3 < fp->namelen;++i)\n\t\t  if (fp->name[i] == ' ')\n\t\t\tif (fp->name[i + 1] == '-')\n\t\t\t  if (fp->name[i + 2] == '>')\n\t\t\t\tif (fp->name[i + 3] == ' ') {\n\t\t\t\t  fp->namelen = i;\n\t\t\t\t  break;\n\t\t\t\t}\n\n\t  /* eliminate extra NetWare spaces */\n\t  if ((buf[1] == ' ') || (buf[1] == '['))\n\t\tif (fp->namelen > 3)\n\t\t  if (fp->name[0] == ' ')\n\t\t\tif (fp->name[1] == ' ')\n\t\t\t  if (fp->name[2] == ' ') {\n\t\t\t\tfp->name += 3;\n\t\t\t\tfp->namelen -= 3;\n\t\t\t  }\n\n\t  return 1;\n  }\n\n  /* MultiNet (some spaces removed from examples) */\n  /* \"00README.TXT;1      2 30-DEC-1996 17:44 [SYSTEM] (RWED,RWED,RE,RE)\" */\n  /* \"CORE.DIR;1          1  8-SEP-1996 16:09 [SYSTEM] (RWE,RWE,RE,RE)\" */\n  /* and non-MutliNet VMS: */\n  /* \"CII-MANUAL.TEX;1  213/216  29-JAN-1996 03:33:12  [ANONYMOU,ANONYMOUS]   (RWED,RWED,,)\" */\n  for (i = 0;i < len;++i)\n\tif (buf[i] == ';')\n\t  break;\n  if (i < len) {\n\tfp->name = buf;\n\tfp->namelen = i;\n\tif (i > 4)\n\t  if (buf[i - 4] == '.')\n\t\tif (buf[i - 3] == 'D')\n\t\t  if (buf[i - 2] == 'I')\n\t\t\tif (buf[i - 1] == 'R') {\n\t\t\t  fp->namelen -= 4;\n\t\t\t  fp->flagtrycwd = 1;\n\t\t\t}\n\tif (!fp->flagtrycwd)\n\t  fp->flagtryretr = 1;\n\twhile (buf[i] != ' ') if (++i == len) return 0;\n\twhile (buf[i] == ' ') if (++i == len) return 0;\n\twhile (buf[i] != ' ') if (++i == len) return 0;\n\twhile (buf[i] == ' ') if (++i == len) return 0;\n\tj = i;\n\twhile (buf[j] != '-') if (++j == len) return 0;\n\tmday = getlong(buf + i,j - i);\n\twhile (buf[j] == '-') if (++j == len) return 0;\n\ti = j;\n\twhile (buf[j] != '-') if (++j == len) return 0;\n\tmonth = getmonth(buf + i,j - i);\n\tif (month < 0) return 0;\n\twhile (buf[j] == '-') if (++j == len) return 0;\n\ti = j;\n\twhile (buf[j] != ' ') if (++j == len) return 0;\n\tyear = getlong(buf + i,j - i);\n\twhile (buf[j] == ' ') if (++j == len) return 0;\n\ti = j;\n\twhile (buf[j] != ':') if (++j == len) return 0;\n\thour = getlong(buf + i,j - i);\n\twhile (buf[j] == ':') if (++j == len) return 0;\n\ti = j;\n\twhile ((buf[j] != ':') && (buf[j] != ' ')) if (++j == len) return 0;\n\tminute = getlong(buf + i,j - i);\n\n\tfp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;\n\tinitbase();\n\tfp->mtime = base + totai(year,month,mday) + hour * 3600 + minute * 60;\n\n\treturn 1;\n  }\n\n  /* MSDOS format */\n  /* 04-27-00  09:09PM       <DIR>          licensed */\n  /* 07-18-00  10:16AM       <DIR>          pub */\n  /* 04-14-00  03:47PM                  589 readme.htm */\n  if ((*buf >= '0') && (*buf <= '9')) {\n\ti = 0;\n\tj = 0;\n\twhile (buf[j] != '-') if (++j == len) return 0;\n\tmonth = getlong(buf + i,j - i) - 1;\n\twhile (buf[j] == '-') if (++j == len) return 0;\n\ti = j;\n\twhile (buf[j] != '-') if (++j == len) return 0;\n\tmday = getlong(buf + i,j - i);\n\twhile (buf[j] == '-') if (++j == len) return 0;\n\ti = j;\n\twhile (buf[j] != ' ') if (++j == len) return 0;\n\tyear = getlong(buf + i,j - i);\n\tif (year < 50) year += 2000;\n\tif (year < 1000) year += 1900;\n\twhile (buf[j] == ' ') if (++j == len) return 0;\n\ti = j;\n\twhile (buf[j] != ':') if (++j == len) return 0;\n\thour = getlong(buf + i,j - i);\n\twhile (buf[j] == ':') if (++j == len) return 0;\n\ti = j;\n\twhile ((buf[j] != 'A') && (buf[j] != 'P')) if (++j == len) return 0;\n\tminute = getlong(buf + i,j - i);\n\tif (hour == 12) hour = 0;\n\tif (buf[j] == 'A') if (++j == len) return 0;\n\tif (buf[j] == 'P') { hour += 12; if (++j == len) return 0; }\n\tif (buf[j] == 'M') if (++j == len) return 0;\n\n\twhile (buf[j] == ' ') if (++j == len) return 0;\n\tif (buf[j] == '<') {\n\t  fp->flagtrycwd = 1;\n\t  while (buf[j] != ' ') if (++j == len) return 0;\n\t}\n\telse {\n\t  i = j;\n\t  while (buf[j] != ' ') if (++j == len) return 0;\n\t  fp->size = getlong(buf + i,j - i);\n\t  fp->sizetype = FTPPARSE_SIZE_BINARY;\n\t  fp->flagtryretr = 1;\n\t}\n\twhile (buf[j] == ' ') if (++j == len) return 0;\n\n\tfp->name = buf + j;\n\tfp->namelen = len - j;\n\n\tfp->mtimetype = FTPPARSE_MTIME_REMOTEMINUTE;\n\tinitbase();\n\tfp->mtime = base + totai(year,month,mday) + hour * 3600 + minute * 60;\n\n\treturn 1;\n  }\n\n  /* Some useless lines, safely ignored: */\n  /* \"Total of 11 Files, 10966 Blocks.\" (VMS) */\n  /* \"total 14786\" (UNIX) */\n  /* \"DISK$ANONFTP:[ANONYMOUS]\" (VMS) */\n  /* \"Directory DISK$PCSA:[ANONYM]\" (VMS) */\n\n  return 0;\n}\n"
  },
  {
    "path": "NetStream/source/hvdb_utils.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <psp2_compat/curl/curl.h>\n#include <ini_file_processor.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"hvdb_utils.h\"\n#include \"hvdb.h\"\n\nusing namespace paf;\nusing namespace sce;\n\nvoid hvdbutils::Init()\n{\n\thvdbInit(sce_paf_malloc, sce_paf_free, sce_paf_realloc, utils::DoGETRequest, utils::DoPOSTRequest);\n}\n\nvoid hvdbutils::Flush()\n{\n\n}\n\nvoid hvdbutils::Term()\n{\n\thvdbTerm();\n}\n\nint32_t hvdbutils::EnqueueDownload(const char *url, const char *name)\n{\n\treturn ytutils::EnqueueDownload(url, name);\n}\n\nint32_t hvdbutils::EnqueueDownloadAsync(const char *url, const char *name)\n{\n\treturn ytutils::EnqueueDownloadAsync(url, name);\n}"
  },
  {
    "path": "NetStream/source/main.cpp",
    "content": "#include <appmgr.h>\n#include <kernel.h>\n#include <libsysmodule.h>\n#include <libdbg.h>\n#include <net.h>\n#include <libnetctl.h>\n#include <paf.h>\n#include <power.h>\n#include <taihen.h>\n#include <stdlib.h>\n\n#include \"common.h\"\n#include \"main.h\"\n#include \"debug.h\"\n#include \"dialog.h\"\n#include \"utils.h\"\n#include \"yt_utils.h\"\n#include \"tw_utils.h\"\n#include \"hvdb_utils.h\"\n#include \"np_utils.h\"\n#include \"players/player_beav.h\"\n#include \"players/player_av.h\"\n#include \"players/player_fmod.h\"\n#include \"menus/menu_generic.h\"\n#include \"menus/menu_first.h\"\n\n#include <curl/curl.h>\n\nextern \"C\"\n{\n\tint sceUserMainThreadPriority = SCE_KERNEL_INDIVIDUAL_QUEUE_HIGHEST_PRIORITY + 20;\n\tint sceUserMainThreadCpuAffinityMask = SCE_KERNEL_CPU_MASK_USER_0;\n\n\ttypedef void*(*curl_allocate_np)(unsigned int);\n\ttypedef void(*curl_free_np)(void *);\n\ttypedef void*(*curl_reallocate_np)(void *, unsigned int);\n\n\tint curl_global_memmanager_set_np(curl_allocate_np, curl_free_np, curl_reallocate_np);\n}\n\nusing namespace paf;\n\nPlugin *g_appPlugin;\n\nintrusive_ptr<graph::Surface> g_texCheckMark;\nintrusive_ptr<graph::Surface> g_texTransparent;\n\nint32_t menu::main::OnNpDialogComplete(void *data)\n{\n\tint32_t ret = *(int32_t *)(data);\n\tif (ret >= 0 && nputils::IsAllGreen())\n\t{\n\t\tdialog::OpenPleaseWait(g_appPlugin, NULL, Framework::Instance()->GetCommonString(\"msg_wait\"));\n\n\t\tmenu::main::NetcheckJob *ncJob = new menu::main::NetcheckJob(menu::main::NetcheckJob::Type_NpOnly);\n\t\tcommon::SharedPtr<job::JobItem> itemParam(ncJob);\n\t\tjob::JobQueue::DefaultQueue()->Enqueue(itemParam);\n\t}\n\telse\n\t{\n\t\tdialog::OpenError(g_appPlugin, ret, g_appPlugin->GetString(msg_error_psn_connection));\n\t}\n\n\treturn 0;\n}\n\nint32_t menu::main::NetcheckJob::Run()\n{\n\tint32_t ret = SCE_OK;\n\tint32_t sync = 0;\n\tSceUID shellPid = SCE_UID_INVALID_UID;\n\tbool dialogAborted = false;\n\tchar titleid[12];\n\tSceNetInitParam param;\n\n\tif (m_type == Type_NpOnly)\n\t{\n\t\tvector<uint32_t> tusSlots;\n\t\ttusSlots.push_back(NP_TUS_HIST_LOG_SLOT);\n\t\ttusSlots.push_back(NP_TUS_FAV_LOG_SLOT);\n\n\t\tret = nputils::Init(\"NetStream\", true, &tusSlots);\n\t\tdialog::Close();\n\t\tif (ret < 0)\n\t\t{\n\t\t\tdialog::OpenError(g_appPlugin, ret, g_appPlugin->GetString(msg_error_psn_connection));\n\t\t}\n\n\t\treturn SCE_PAF_OK;\n\t}\n\n\tparam.memory = sce_paf_malloc(SCE_KERNEL_32KiB);\n\tparam.size = SCE_KERNEL_32KiB;\n\tparam.flags = 0;\n\n\tret = sceNetInit(&param);\n\twhile (ret != SCE_OK)\n\t{\n\t\tif (!dialog::IsActive() || dialogAborted)\n\t\t{\n\t\t\tdialog::OpenError(g_appPlugin, SCE_ERROR_ERRNO_ECANCELED, Framework::Instance()->GetCommonString(\"msg_error_network_connection\"));\n\t\t\tdialogAborted = true;\n\t\t\tbreak;\n\t\t}\n\t\tret = sceNetInit(&param);\n\t\tthread::Sleep(100);\n\t}\n\n\tret = sceNetCtlInit();\n\twhile (ret != SCE_OK)\n\t{\n\t\tif (!dialog::IsActive() || dialogAborted)\n\t\t{\n\t\t\tdialog::OpenError(g_appPlugin, SCE_ERROR_ERRNO_ECANCELED, Framework::Instance()->GetCommonString(\"msg_error_network_connection\"));\n\t\t\tdialogAborted = true;\n\t\t\tbreak;\n\t\t}\n\t\tret = sceNetCtlInit();\n\t\tthread::Sleep(100);\n\t}\n\n\tsceNetCtlInetGetState(&ret);\n\twhile (ret != SCE_NET_CTL_STATE_IPOBTAINED)\n\t{\n\t\tif (!dialog::IsActive() || dialogAborted)\n\t\t{\n\t\t\tdialog::OpenError(g_appPlugin, SCE_ERROR_ERRNO_ECANCELED, Framework::Instance()->GetCommonString(\"msg_error_network_connection\"));\n\t\t\tdialogAborted = true;\n\t\t\tbreak;\n\t\t}\n\t\tsceNetCtlInetGetState(&ret);\n\t\tthread::Sleep(100);\n\t}\n\n\tmenu::Settings::Init();\n\n\tif (!dialogAborted)\n\t{\n\t\tytutils::Init(NP_TUS_HIST_LOG_SLOT, NP_TUS_FAV_LOG_SLOT);\n\t\thvdbutils::Init();\n\n\t\tdialog::Close();\n\t}\n\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetInt(\"cloud_sync\", static_cast<int32_t *>(&sync), 0);\n\tif (sync && !dialogAborted)\n\t{\n\t\tnputils::PreInit(OnNpDialogComplete);\n\t}\n\n\tsceAppMgrAppParamGetString(SCE_KERNEL_PROCESS_ID_SELF, 12, titleid, 12);\n\tif (sceAppMgrGetIdByName(&shellPid, \"NPXS19999\") == SCE_OK && utils::IsTaihenLoaded())\n\t{\n\t\tstring pluginPath = common::FormatString(\"ux0:app/%s/module/download_enabler_netstream.suprx\", titleid);\n\t\ttaiLoadStartModuleForPid(shellPid, pluginPath.c_str(), 0, NULL, 0);\n\t}\n\n\tif (dialogAborted)\n\t{\n\t\tmenu::First *fmenu = static_cast<menu::First *>(menu::GetTopMenu());\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t\tfmenu->SetOfflineMode();\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t}\n\n\treturn SCE_PAF_OK;\n}\n\nvoid pluginLoadCB(Plugin *plugin)\n{\n\tif (plugin == NULL)\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[NS_PLUGIN_BASE] Plugin load FAIL!\\n\");\n\t\treturn;\n\t}\n\n\tg_appPlugin = plugin;\n\n\tFramework *fw = Framework::Instance();\n\n\tdialog::OpenPleaseWait(g_appPlugin, NULL, fw->GetCommonString(\"msg_connecting_wait\"), true);\n\n\tmenu::main::NetcheckJob *ncJob = new menu::main::NetcheckJob(menu::main::NetcheckJob::Type_Initial);\n\tcommon::SharedPtr<job::JobItem> itemParam(ncJob);\n\tjob::JobQueue::DefaultQueue()->Enqueue(itemParam);\n\n\tmenu::InitMenuSystem();\n\n\tg_texCheckMark = fw->GetCommonTexture(\"_common_texture_check_mark\");\n\tg_texTransparent = fw->GetCommonTexture(\"_common_texture_transparent\");\n\n\tnew menu::First();\n}\n\nint main()\n{\n\t// PAF framework init\n\tFramework::InitParam fwParam;\n\tFramework::SampleInit(&fwParam);\n\tfwParam.mode = Framework::Mode_Normal;\n\tfwParam.surface_pool_size = SCE_KERNEL_32MiB;\n\tfwParam.text_surface_pool_size = SCE_KERNEL_4MiB;\n\tfwParam.graph_heap_size_on_main_memory = 0;\n\tfwParam.graph_heap_size_on_video_memory = SCE_KERNEL_1MiB;\n\tfwParam.graphics_option = 7;\n\n\tif (SCE_PAF_IS_DOLCE)\n\t{\n\t\tscePowerSetConfigurationMode(SCE_POWER_CONFIGURATION_MODE_C);\n\t\tfwParam.env_param = new ui::EnvironmentParam(ui::EnvironmentParam::RESOLUTION_PSP2);\n\t\tfwParam.screen_width = 1920;\n\t\tfwParam.screen_height = 1088;\n\t\t//fwParam.option |= Framework::FrameworkOption_UseDisplayAreaSettings;\n\t}\n\n\tFramework *fw = new Framework(fwParam);\n\tfw->LoadCommonResourceAsync();\n\n\tutils::SetDisplayResolution(ui::EnvironmentParam::RESOLUTION_PSP2);\n\n#ifdef _DEBUG\n\tsceDbgSetMinimumLogLevel(SCE_DBG_LOG_LEVEL_TRACE);\n\tInitDebug();\n#endif\n\n\tSceAppUtilInitParam init;\n\tSceAppUtilBootParam boot;\n\tsce_paf_memset(&init, 0, sizeof(SceAppUtilInitParam));\n\tsce_paf_memset(&boot, 0, sizeof(SceAppUtilBootParam));\n\tsceAppUtilInit(&init, &boot);\n\n\t// Module init\n\tsceSysmoduleLoadModule(SCE_SYSMODULE_FIBER);\n\tsceSysmoduleLoadModule(SCE_SYSMODULE_NET);\n\tsceSysmoduleLoadModule(SCE_SYSMODULE_NP);\n\tsceSysmoduleLoadModule(SCE_SYSMODULE_NP_TUS);\n\tsceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_BXCE);\n\tsceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_INI_FILE_PROCESSOR);\n\tsceSysmoduleLoadModuleInternal(SCE_SYSMODULE_INTERNAL_COMMON_GUI_DIALOG);\n\tnew Module(\"vs0:sys/external/libfios2.suprx\");\n\tnew Module(\"vs0:sys/external/libc.suprx\");\n\tnew Module(\"app0:module/libcurl.suprx\");\n\tnew Module(\"app0:module/libFourthTube.suprx\");\n\tnew Module(\"app0:module/libLootkit.suprx\");\n\tnew Module(\"app0:module/libhvdb.suprx\");\n\n\tcurl_global_memmanager_set_np(sce_paf_malloc, sce_paf_free, sce_paf_realloc);\n\n\tutils::Init();\n\n\t// Plugin init\n\tPlugin::InitParam pluginParam;\n\tpluginParam.name = \"netstream_plugin\";\n\tpluginParam.resource_file = \"app0:netstream_plugin.rco\";\n\tpluginParam.caller_name = \"__main__\";\n#ifdef _DEBUG\n\tpluginParam.option |= Plugin::Option_ResourceLoadWithDebugSymbol;\n#endif\n\tpluginParam.start_func = pluginLoadCB;\n\n\tPlugin::LoadAsync(pluginParam);\n\n\tAVPlayer::PreInit();\n\tBEAVPlayer::PreInit();\n\tFMODPlayer::PreInit();\n\n\tfw->Run();\n\n\tsceKernelExitProcess(0);\n\n\treturn 0;\n}"
  },
  {
    "path": "NetStream/source/menus/menu_first.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"menus/menu_first.h\"\n#include \"menus/menu_ftp.h\"\n#include \"menus/menu_http.h\"\n#include \"menus/menu_local.h\"\n#include \"menus/menu_hvdb.h\"\n#include \"menus/menu_youtube.h\"\n#include \"menus/menu_settings.h\"\n\n#include <paf_file_ext.h>\n\nusing namespace paf;\n\nstatic bool s_afterBoot = true;\n\nmenu::First::First() : GenericMenu(\"page_first\", MenuOpenParam(true), MenuCloseParam()), m_showHvdb(false)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\n\tif (LocalFile::Exists(\"app0:config.ini\"))\n\t{\n\t\tm_showHvdb = true;\n\t}\n\n\tauto topText = static_cast<ui::Text *>(m_root->FindChild(text_top));\n\twstring title = g_appPlugin->GetString(msg_title_menu_first);\n\ttopText->SetString(title);\n\n\tm_rootList = static_cast<ui::ListView *>(m_root->FindChild(list_view_generic));\n\tm_rootList->SetItemFactory(new ListViewFactory(this));\n\tm_rootList->InsertSegment(0, 1);\n\tm_rootList->SetCellSizeDefault(0, { 960.0f, 80.0f });\n\tm_rootList->SetSegmentLayoutType(0, ui::ListView::LAYOUT_TYPE_LIST);\n\tif (m_showHvdb)\n\t{\n\t\tm_rootList->InsertCell(0, 0, 5);\n\t}\n\telse\n\t{\n\t\tm_rootList->InsertCell(0, 0, 4);\n\t}\n}\n\nmenu::First::~First()\n{\n\tauto listView = static_cast<ui::ListView *>(m_root->FindChild(list_view_generic));\n\tlistView->SetName(static_cast<uint32_t>(0));\n}\n\nui::ListItem* menu::First::CreateListItem(ui::listview::ItemFactory::CreateParam& param)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\tui::ListItem *item = nullptr;\n\tint32_t idx = param.cell_index;\n\tuint32_t texid = 0;\n\n\tif (!param.list_view->GetName().GetIDHash())\n\t{\n\t\treturn new ui::ListItem(param.parent, nullptr);\n\t}\n\n\tif (!m_showHvdb && idx > 0)\n\t{\n\t\tidx++;\n\t}\n\n\tg_appPlugin->TemplateOpen(param.parent, template_list_item_generic, tmpParam);\n\titem = static_cast<ui::ListItem *>(param.parent->GetChild(param.parent->GetChildrenNum() - 1));\n\n\tui::Widget *button = item->FindChild(image_button_list_item);\n\n\twstring name = utils::GetStringWithNum(\"msg_fpmenu_item_\", idx);\n\tbutton->SetString(name);\n\tbutton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::First *>(userdata)->OnListButton(static_cast<ui::Button *>(self));\n\t}, this);\n\n\tswitch (idx)\n\t{\n\tcase 0:\n\t\ttexid = tex_fpmenu_icon_youtube;\n\t\tbreak;\n\tcase 1:\n\t\ttexid = tex_fpmenu_icon_hvdb;\n\t\tbreak;\n\tcase 2:\n\t\ttexid = tex_fpmenu_icon_http;\n\t\tbreak;\n\tcase 3:\n\t\ttexid = tex_fpmenu_icon_ftp;\n\t\tbreak;\n\tcase 4:\n\t\ttexid = tex_fpmenu_icon_local;\n\t\tbreak;\n\t}\n\n\tbutton->SetName(texid);\n\n\tintrusive_ptr<graph::Surface> tex = g_appPlugin->GetTexture(texid);\n\tif (tex.get())\n\t{\n\t\tbutton->SetTexture(tex);\n\t}\n\n\treturn item;\n}\n\nvoid menu::First::OnListButton(ui::Widget *self)\n{\n\tswitch (self->GetName().GetIDHash())\n\t{\n\tcase tex_fpmenu_icon_youtube:\n\t\tmenu::YouTube *ymenu = new menu::YouTube();\n\t\tbreak;\n\tcase tex_fpmenu_icon_hvdb:\n\t\tmenu::HVDB *hvdbmenu = new menu::HVDB();\n\t\tbreak;\n\tcase tex_fpmenu_icon_http:\n\t\tmenu::Http *hmenu = new menu::Http();\n\t\thmenu->PushBrowserPage(NULL);\n\t\tbreak;\n\tcase tex_fpmenu_icon_ftp:\n\t\tmenu::Ftp *fmenu = new menu::Ftp();\n\t\tfmenu->PushBrowserPage(NULL);\n\t\tbreak;\n\tcase tex_fpmenu_icon_local:\n\t\tmenu::Local *lmenu = new menu::Local();\n\t\tif (s_afterBoot)\n\t\t{\n\t\t\tstring ref = utils::SafememRead();\n\t\t\tlmenu->PushBrowserPage(&ref);\n\t\t\ts_afterBoot = false;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tlmenu->PushBrowserPage(NULL);\n\t\t}\n\t\tbreak;\n\t}\n}\n\nvoid menu::First::SetOfflineMode()\n{\n\tif (!m_rootList)\n\t{\n\t\treturn;\n\t}\n\n\tm_rootList->DeleteCell(0, 0, m_rootList->GetCellNum(0) - 1);\n}"
  },
  {
    "path": "NetStream/source/menus/menu_generic.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"debug.h\"\n#include \"menus/menu_generic.h\"\n#include \"menus/menu_settings.h\"\n\nusing namespace paf;\n\nstatic paf::vector<menu::GenericMenu*> s_menuStack;\n\nvoid menu::SettingsButtonCbFun(int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n{\n\tnew menu::Settings();\n}\n\nmenu::GenericMenu::GenericMenu(const char *name, MenuOpenParam const& oparam, MenuCloseParam const& cparam)\n{\n\tif (!name)\n\t{\n\t\treturn;\n\t}\n\n\tm_closeParam = cparam;\n\n\tm_root = g_appPlugin->PageOpen(name, oparam);\n\tm_root->SetName(name);\n\n\tif (!s_menuStack.empty())\n\t{\n\t\ts_menuStack.back()->Deactivate(true);\n\t}\n\n\ts_menuStack.push_back(this);\n\n#ifdef _DEBUG\n\tSetCurrentDebugParam(g_appPlugin, m_root);\n#endif\n}\n\nmenu::GenericMenu::~GenericMenu()\n{\n\ts_menuStack.pop_back();\n\n\tg_appPlugin->PageClose(m_root->GetName(), m_closeParam);\n\n\tif (!s_menuStack.empty())\n\t{\n\t\ts_menuStack.back()->Activate();\n\n#ifdef _DEBUG\n\t\tSetCurrentDebugParam(g_appPlugin, s_menuStack.back()->GetRoot());\n#endif\n\t}\n}\n\nvoid menu::GenericMenu::Deactivate(bool withDelay)\n{\n\tTimer *t = nullptr;\n\tm_root->SetActivate(false);\n\tif (withDelay)\n\t{\n\t\tt = new Timer(200.0f);\n\t}\n\tm_root->Hide(t);\n}\n\nvoid menu::GenericMenu::Activate()\n{\n\tm_root->Show();\n\tm_root->SetActivate(true);\n}\n\nvoid menu::GenericMenu::DisableInput()\n{\n\tm_root->SetActivate(false);\n}\n\nvoid menu::GenericMenu::EnableInput()\n{\n\tm_root->SetActivate(true);\n}\n\nui::Scene *menu::GenericMenu::GetRoot() const\n{\n\treturn m_root;\n}\n\nvoid menu::DeactivateAll(uint32_t endMargin)\n{\n\tfor (int i = 0; i < s_menuStack.size() - endMargin; i++)\n\t{\n\t\ts_menuStack.at(i)->Deactivate();\n\t}\n}\n\nvoid menu::ActivateAll()\n{\n\tfor (auto menu : s_menuStack)\n\t{\n\t\tmenu->Activate();\n\t}\n}\n\nvoid menu::InitMenuSystem()\n{\n\n}\n\nvoid menu::TermMenuSystem()\n{\n\n}\n\nmenu::GenericMenu *menu::GetTopMenu()\n{\n\tif (!s_menuStack.empty())\n\t{\n\t\treturn s_menuStack.back();\n\t}\n\n\treturn nullptr;\n}\n\nuint32_t menu::GetMenuCount()\n{\n\treturn s_menuStack.size();\n}\n\nmenu::GenericMenu *menu::GetMenuAt(uint32_t idx)\n{\n\treturn s_menuStack.at(idx);\n}"
  },
  {
    "path": "NetStream/source/menus/menu_hvdb.cpp",
    "content": "#include <kernel.h>\n#include <appmgr.h>\n#include <stdlib.h>\n#include <string.h>\n#include <libdbg.h>\n#include <paf.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"yt_utils.h\"\n#include \"np_utils.h\"\n#include \"dialog.h\"\n#include \"tex_pool.h\"\n#include \"hvdb.h\"\n#include <paf_file_ext.h>\n#include \"option_menu.h\"\n#include \"menus/menu_generic.h\"\n#include \"menus/menu_hvdb.h\"\n#include \"menus/menu_hvdb_tracks.h\"\n#include \"menus/menu_settings.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[HVDB]\"\n\nusing namespace paf;\n\nmenu::HVDB::Submenu::Submenu(HVDB *parentObj)\n{\n\tm_currentPage = 0;\n\tm_baseParent = parentObj;\n\tm_interrupted = false;\n\tm_allJobsComplete = true;\n}\n\nmenu::HVDB::Submenu::~Submenu()\n{\n\tm_list->SetName(static_cast<uint32_t>(0));\n\tReleaseCurrentPage();\n\tcommon::transition::DoReverse(0.0f, m_submenuRoot, common::transition::Type_FadeinFast, true, false);\n}\n\nvoid menu::HVDB::Submenu::ReleaseCurrentPage()\n{\n\tm_interrupted = true;\n\twhile (!m_allJobsComplete)\n\t{\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t\tthread::Sleep(10);\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t}\n\tm_interrupted = false;\n\n\tif (m_list->GetCellNum(0) > 0)\n\t{\n\t\tm_list->DeleteCell(0, 0, m_list->GetCellNum(0));\n\t}\n\n\tm_baseParent->m_texPool->SetAlive(false);\n\tm_baseParent->m_texPool->AddAsyncCancelPending();\n\tm_baseParent->m_texPool->RemoveAll();\n\tm_baseParent->m_texPool->SetAlive(true);\n\n\tm_results.clear();\n}\n\nvoid menu::HVDB::Submenu::OnListButton(ui::Widget *wdg)\n{\n\tuint32_t totalCount = m_results.size();\n\tuint32_t idhash = wdg->GetName().GetIDHash();\n\n\tif (m_currentPage == 0)\n\t{\n\t\tif (idhash == totalCount)\n\t\t{\n\t\t\tGoToNextPage();\n\t\t\treturn;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (idhash == totalCount)\n\t\t{\n\t\t\tGoToPrevPage();\n\t\t\treturn;\n\t\t}\n\t\telse if (idhash == totalCount + 1)\n\t\t{\n\t\t\tGoToNextPage();\n\t\t\treturn;\n\t\t}\n\t}\n\n\tSubmenu::Item item = m_results.at(idhash);\n\n\tmenu::HvdbTracks *menu = new menu::HvdbTracks(item.workId.c_str(), item.bannerUrl.c_str());\n\tmenu->PushBrowserPage(NULL);\n}\n\nvoid menu::HVDB::Submenu::OnTexPoolAdd(int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n{\n\tItem *workItem = static_cast<Item *>(userdata);\n\tui::Button *button = static_cast<ui::Button *>(self);\n\n\tif (e->GetValue(0) == workItem->texId.GetIDHash())\n\t{\n\t\tbutton->SetTexture(workItem->texPool->Get(workItem->texId));\n\t\tbutton->DeleteEventCallback(ui::Handler::CB_STATE_READY_CACHEIMAGE, OnTexPoolAdd, userdata);\n\t}\n}\n\nui::ListItem *menu::HVDB::Submenu::CreateListItem(ui::listview::ItemFactory::CreateParam& param)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\tui::Widget *item = NULL;\n\tui::Widget *button = NULL;\n\tui::Widget *subText = NULL;\n\twstring text16;\n\twchar_t numPageText[32];\n\n\tif (!param.list_view->GetName().GetIDHash())\n\t{\n\t\treturn new ui::ListItem(param.parent, 0);\n\t}\n\n\tui::Widget *targetRoot = param.parent;\n\tuint32_t totalCount = m_results.size();\n\n\tif (param.cell_index == totalCount || param.cell_index == totalCount + 1)\n\t{\n\t\tg_appPlugin->TemplateOpen(targetRoot, template_list_item_hvdb_aligned, tmpParam);\n\t\titem = targetRoot->GetChild(targetRoot->GetChildrenNum() - 1);\n\t\tbutton = item->FindChild(image_button_list_item_hvdb_aligned);\n\t}\n\telse\n\t{\n\t\tg_appPlugin->TemplateOpen(targetRoot, template_list_item_hvdb, tmpParam);\n\t\titem = targetRoot->GetChild(targetRoot->GetChildrenNum() - 1);\n\t\tbutton = item->FindChild(image_button_list_item_hvdb);\n\t}\n\n\tbutton->SetName(param.cell_index);\n\n\tintrusive_ptr<graph::Surface> tex;\n\n\tif (param.cell_index == totalCount)\n\t{\n\t\tif (m_currentPage == 0)\n\t\t{\n\t\t\ttext16 = g_appPlugin->GetString(msg_next_page);\n\t\t\tsce_paf_swprintf(numPageText, sizeof(numPageText) / 2, L\" (%d)\", m_currentPage + 1 + 1);\n\t\t\ttext16 += numPageText;\n\t\t\tbutton->SetString(text16);\n\t\t\ttex = g_appPlugin->GetTexture(tex_button_arrow_right);\n\t\t\tbutton->SetTexture(tex);\n\t\t\tgoto serviceButton;\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttext16 = g_appPlugin->GetString(msg_previous_page);\n\t\t\tsce_paf_swprintf(numPageText, sizeof(numPageText) / 2, L\" (%d)\", m_currentPage + 1 - 1);\n\t\t\ttext16 += numPageText;\n\t\t\tbutton->SetString(text16);\n\t\t\ttex = g_appPlugin->GetTexture(tex_button_arrow_left);\n\t\t\tbutton->SetTexture(tex);\n\t\t\tgoto serviceButton;\n\t\t}\n\t}\n\telse if (param.cell_index == totalCount + 1)\n\t{\n\t\ttext16 = g_appPlugin->GetString(msg_next_page);\n\t\tsce_paf_swprintf(numPageText, sizeof(numPageText) / 2, L\" (%d)\", m_currentPage + 1 + 1);\n\t\ttext16 += numPageText;\n\t\tbutton->SetString(text16);\n\t\ttex = g_appPlugin->GetTexture(tex_button_arrow_right);\n\t\tbutton->SetTexture(tex);\n\t\tgoto serviceButton;\n\t}\n\n\tItem *workItem = &m_results.at(param.cell_index);\n\tsubText = button->FindChild(text_list_item_hvdb_subtext);\n\tsubText->SetString(workItem->stat);\n\tbutton->SetString(workItem->name);\n\tif (m_baseParent->m_texPool->Exist(workItem->texId))\n\t{\n\t\tbutton->SetTexture(m_baseParent->m_texPool->Get(workItem->texId));\n\t}\n\telse\n\t{\n\t\tworkItem->texPool = m_baseParent->m_texPool;\n\t\tbutton->AddEventCallback(ui::Handler::CB_STATE_READY_CACHEIMAGE, OnTexPoolAdd, workItem);\n\t\tm_baseParent->m_texPool->AddAsync(workItem->texId, workItem->texId.GetID().c_str());\n\t}\n\nserviceButton:\n\n\tbutton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<Submenu *>(userdata)->OnListButton(static_cast<ui::Widget *>(self));\n\t}, this);\n\n\treturn static_cast<ui::ListItem *>(item);\n}\n\nvoid menu::HVDB::FavouriteSubmenu::ParseFavourite()\n{\n\tstring text8;\n\tHVDBItem *hvdbItem = NULL;\n\tvoid *hvdbCtx = NULL;\n\tint32_t ret = -1;\n\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tm_baseParent->m_loaderIndicator->Start();\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\tSCE_DBG_LOG_INFO(\"[Favourite] Begin parse\");\n\n\tHVDBSort sort;\n\tHVDBOrder order;\n\tHVDBFilter filter;\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetInt(\"hvdb_search_sort\", (int32_t *)&sort, 0);\n\tsettings->GetInt(\"hvdb_search_sort_type\", (int32_t *)&order, 0);\n\tsettings->GetInt(\"hvdb_search_filter\", (int32_t *)&filter, 0);\n\n\tret = hvdbParseFavourites(&hvdbCtx, m_currentPage + 1, sort, order, filter, &m_pgi, &hvdbItem);\n\tSCE_DBG_LOG_INFO(\"[Favourite] hvdbParseFavourites(): 0x%08X, current page: %d\", ret, m_currentPage);\n\n\tif (ret <= 0)\n\t{\n\t\tdialog::OpenError(g_appPlugin, ret, Framework::Instance()->GetCommonString(\"msg_error_connect_server_peer\"));\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t\tm_baseParent->m_loaderIndicator->Stop();\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t\tm_allJobsComplete = true;\n\t\treturn;\n\t}\n\n\tm_pgi.currentPage--;\n\n\tdo\n\t{\n\t\tItem item;\n\t\titem.workId = hvdbItem->workItem->id;\n\t\titem.bannerUrl = hvdbItem->workItem->bannerUrl;\n\t\ttext8 = \"\\n\";\n\t\ttext8 += hvdbItem->workItem->title;\n\t\tcommon::Utf8ToUtf16(text8, &item.name);\n\t\titem.texId = hvdbItem->workItem->thmbUrl;\n\t\ttext8 = hvdbItem->workItem->circle;\n\t\ttext8 += \"\\n\";\n\t\ttext8 += hvdbItem->workItem->published;\n\t\tcommon::Utf8ToUtf16(text8, &item.stat);\n\n\t\tm_results.push_back(item);\n\n\t\thvdbItem = hvdbItem->next;\n\t} while (hvdbItem);\n\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tm_baseParent->m_loaderIndicator->Stop();\n\tif (m_currentPage == 0)\n\t{\n\t\tif (m_pgi.worksTotal > m_pgi.worksPerPage)\n\t\t{\n\t\t\tm_list->InsertCell(0, 0, m_results.size() + 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_list->InsertCell(0, 0, m_results.size());\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (ret <= m_pgi.worksPerPage)\n\t\t{\n\t\t\tm_list->InsertCell(0, 0, m_results.size() + 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_list->InsertCell(0, 0, m_results.size() + 2);\n\t\t}\n\t}\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\thvdbCleanup(hvdbCtx);\n\n\tm_allJobsComplete = true;\n}\n\nvoid menu::HVDB::FavouriteSubmenu::GoToNextPage()\n{\n\tReleaseCurrentPage();\n\tm_currentPage++;\n\n\tFavouriteJob *job = new FavouriteJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nvoid menu::HVDB::FavouriteSubmenu::GoToPrevPage()\n{\n\tReleaseCurrentPage();\n\tm_currentPage--;\n\n\tFavouriteJob *job = new FavouriteJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nvoid menu::HVDB::FavouriteSubmenu::GoToBasePageForSync()\n{\n\tReleaseCurrentPage();\n\tm_currentPage = 0;\n\n\tFavouriteJob *job = new FavouriteJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nmenu::HVDB::FavouriteSubmenu::FavouriteSubmenu(HVDB *parentObj) : Submenu(parentObj)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\n\tg_appPlugin->TemplateOpen(m_baseParent->m_browserRoot, template_list_view_hvdb_fav, tmpParam);\n\tm_submenuRoot = m_baseParent->m_browserRoot->FindChild(plane_list_view_hvdb_fav_root);\n\tm_list = static_cast<ui::ListView *>(m_submenuRoot->FindChild(list_view_hvdb));\n\tListViewCb *lwCb = new ListViewCb(this);\n\tm_list->SetItemFactory(lwCb);\n\tm_list->InsertSegment(0, 1);\n\tmath::v4 sz(960.0f, 100.0f);\n\tm_list->SetCellSizeDefault(0, sz);\n\tm_list->SetSegmentLayoutType(0, ui::ListView::LAYOUT_TYPE_LIST);\n\n\tcommon::transition::Do(0.0f, m_submenuRoot, common::transition::Type_FadeinFast, true, false);\n\n\tFavouriteJob *job = new FavouriteJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nmenu::HVDB::FavouriteSubmenu::~FavouriteSubmenu()\n{\n\n}\n\nvoid menu::HVDB::OnSettingsButton()\n{\n\tvector<OptionMenu::Button> buttons;\n\tOptionMenu::Button bt;\n\tbt.label = g_appPlugin->GetString(msg_settings);\n\tbuttons.push_back(bt);\n\tbt.label = g_appPlugin->GetString(msg_settings_hvdb_refresh);\n\tbuttons.push_back(bt);\n\n\tnew OptionMenu(g_appPlugin, m_root, &buttons);\n}\n\nvoid menu::HVDB::OnOptionMenuEvent(int32_t type, int32_t subtype)\n{\n\tif (menu::GetTopMenu()->GetMenuType() != menu::MenuType_Hvdb)\n\t{\n\t\treturn;\n\t}\n\n\tif (type == OptionMenu::OptionMenuEvent_Close)\n\t{\n\t\treturn;\n\t}\n\n\tswitch (subtype)\n\t{\n\tcase 0:\n\t\tmenu::SettingsButtonCbFun(ui::Button::CB_BTN_DECIDE, NULL, 0, NULL);\n\t\tbreak;\n\tcase 1:\n\t\tif (m_currentSubmenu && (m_currentSubmenu->GetType() == Submenu::SubmenuType_Favourites))\n\t\t{\n\t\t\tm_currentSubmenu->GoToBasePageForSync();\n\t\t}\n\t\tbreak;\n\t}\n}\n\nvoid menu::HVDB::OnBackButton()\n{\n\tdelete this;\n}\n\nbool menu::HVDB::AuthMe()\n{\n\tchar user[256];\n\tchar password[256];\n\tint32_t ret = -1;\n\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetString(\"hvdb_user\", user, sizeof(user) - 1, \"\");\n\tsettings->GetString(\"hvdb_password\", password, sizeof(password) - 1, \"\");\n\n\tret = hvdbLogin(user, password);\n\tif (ret != HVDB_OK)\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[AuthMe] hvdbLogin(): 0x%08X\", ret);\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nmenu::HVDB::HVDB() :\n\tGenericMenu(\"page_hvdb\",\n\tMenuOpenParam(false, 200.0f, Plugin::TransitionType_SlideFromBottom),\n\tMenuCloseParam(false, 200.0f, Plugin::TransitionType_SlideFromBottom))\n{\n\tm_currentSubmenu = NULL;\n\n\tutils::SetRequestShare(ytutils::GetShare());\n\n\tm_root->AddEventCallback(OptionMenu::OptionMenuEvent,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<HVDB *>(userdata)->OnOptionMenuEvent(e->GetValue(0), e->GetValue(1));\n\t}, this);\n\n\tui::Widget *settingsButton = m_root->FindChild(button_settings_page_hvdb);\n\tsettingsButton->Show(common::transition::Type_Reset);\n\tsettingsButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<HVDB *>(userdata)->OnSettingsButton();\n\t}, this);\n\n\tui::Widget *backButton = m_root->FindChild(button_back_page_hvdb);\n\tbackButton->Show(common::transition::Type_Reset);\n\tbackButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<HVDB *>(userdata)->OnBackButton();\n\t}, this);\n\n\tm_browserRoot = m_root->FindChild(plane_browser_root_page_hvdb);\n\tm_loaderIndicator = static_cast<ui::BusyIndicator *>(m_root->FindChild(busyindicator_loader_page_hvdb));\n\tm_topText = static_cast<ui::Text *>(m_root->FindChild(text_top));\n\n\tm_texPool = new TexPool(g_appPlugin);\n\tm_texPool->SetShare(utils::GetShare());\n\n\tchar host[256];\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetString(\"hvdb_host\", host, sizeof(host) - 1, \"\");\n\thvdbSetInstance(host);\n\n\tif (!AuthMe())\n\t{\n\t\treturn;\n\t}\n\n\tSwitchSubmenu(Submenu::SubmenuType_Favourites);\n}\n\nmenu::HVDB::~HVDB()\n{\n\tdelete m_currentSubmenu;\n\tm_texPool->DestroyAsync();\n\tutils::SetGlobalProxy(NULL);\n\tutils::SetRequestShare(NULL);\n}\n\nvoid menu::HVDB::SwitchSubmenu(Submenu::SubmenuType type)\n{\n\tif (m_currentSubmenu)\n\t{\n\t\tif (m_currentSubmenu->GetType() == type)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tdelete m_currentSubmenu;\n\t\tm_currentSubmenu = NULL;\n\t}\n\n\tswitch (type)\n\t{\n\tcase Submenu::SubmenuType_Favourites:\n\t\tm_currentSubmenu = new FavouriteSubmenu(this);\n\t\tbreak;\n\t}\n}"
  },
  {
    "path": "NetStream/source/menus/menu_player_simple.cpp",
    "content": "#include <kernel.h>\n#include <power.h>\n#include <paf.h>\n#include <libdbg.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"event.h\"\n#include \"dialog.h\"\n#include \"players/player_beav.h\"\n#include \"players/player_av.h\"\n#include \"players/player_fmod.h\"\n#include \"subs/subs_srt.h\"\n#include \"menus/menu_player_simple.h\"\n#include \"menus/menu_settings.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[PlayerSimple]\"\n\nusing namespace paf;\n\nint32_t menu::PlayerSimple::PowerCallback(SceUID notifyId, int32_t notifyCount, int32_t notifyArg, void *pCommon)\n{\n\treinterpret_cast<PlayerSimple *>(pCommon)->OnPowerCallback(notifyArg);\n\treturn SCE_OK;\n}\n\nvoid menu::PlayerSimple::UpdateTask(void *pArgBlock)\n{\n\treinterpret_cast<PlayerSimple *>(pArgBlock)->OnUpdate();\n}\n\nvoid  menu::PlayerSimple::OnVideoPlaneTouch()\n{\n\tif (m_progressPlaneShown)\n\t{\n\t\tif (!m_isLS)\n\t\t{\n\t\t\tm_progressPlane->Hide(common::transition::Type_SlideFromBottom1);\n\t\t}\n\t\tm_backButton->Hide(common::transition::Type_Reset);\n\t\tsceAppMgrSetInfobarState(SCE_APPMGR_INFOBAR_VISIBILITY_INVISIBLE, SCE_APPMGR_INFOBAR_COLOR_BLACK, SCE_APPMGR_INFOBAR_TRANSPARENCY_TRANSLUCENT);\n\t\tm_progressPlaneShown = false;\n\t}\n\telse\n\t{\n\t\tif (!m_isLS)\n\t\t{\n\t\t\tm_progressPlane->Show(common::transition::Type_SlideFromBottom1);\n\t\t}\n\t\tif (m_currentScale == 1.0f)\n\t\t{\n\t\t\tm_backButton->Show(common::transition::Type_Reset);\n\t\t}\n\t\tm_progressPlaneShownTime = sceKernelGetProcessTimeLow();\n\t\tsceAppMgrSetInfobarState(SCE_APPMGR_INFOBAR_VISIBILITY_VISIBLE, SCE_APPMGR_INFOBAR_COLOR_BLACK, SCE_APPMGR_INFOBAR_TRANSPARENCY_TRANSLUCENT);\n\t\tm_progressPlaneShown = true;\n\t}\n}\n\nvoid menu::PlayerSimple::OnProgressBarStateChange(int32_t type)\n{\n\tif (type == ui::ProgressBarTouch::CB_PROGRESSBAR_DRAG_END)\n\t{\n\t\tuint32_t val = (uint32_t)(m_progressBar->GetValue() / 100.0f * static_cast<float>(m_player->GetTotalTimeMs()));\n\t\tm_player->JumpToTimeMs(val);\n\t\tm_isSeeking = false;\n\t}\n\telse if (type == ui::Handler::CB_TOUCH_MOVE || type == ui::Handler::CB_TOUCH_OUT)\n\t{\n\t\tm_isSeeking = true;\n\t}\n}\n\nvoid menu::PlayerSimple::OnBackButton()\n{\n\tevent::BroadcastGlobalEvent(g_appPlugin, PlayerSimpleEvent, PlayerEvent_Back);\n}\n\nvoid menu::PlayerSimple::OnPlayButton()\n{\n\tuint32_t texid = 0;\n\n\tm_player->SwitchPlaybackState();\n\n\tif (m_player->IsPaused())\n\t{\n\t\ttexid = tex_button_play;\n\t}\n\telse\n\t{\n\t\ttexid = tex_button_pause;\n\t}\n\n\tintrusive_ptr<graph::Surface> tex = g_appPlugin->GetTexture(texid);\n\tif (tex.get())\n\t{\n\t\tm_playButton->SetTexture(tex);\n\t}\n}\n\nvoid menu::PlayerSimple::OnWholeRepeatButton()\n{\n\tm_player->JumpToTimeMs(0);\n\tm_player->SwitchPlaybackState();\n\tm_videoPlane->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f });\n\tm_wholeRepeatButton->Hide(common::transition::Type_FadeinFast);\n}\n\nvoid menu::PlayerSimple::OnPowerCallback(int32_t notifyArg)\n{\n\tif (notifyArg & SCE_POWER_CALLBACKARG_RESERVED_22)\n\t{\n\t\tm_player->SetPowerSaving(true);\n\t}\n\telse if (notifyArg & SCE_POWER_CALLBACKARG_RESERVED_23)\n\t{\n\t\tm_player->SetPowerSaving(false);\n\t}\n}\n\nvoid menu::PlayerSimple::OnGenericPlayerStateChange(int32_t state)\n{\n\tstring text8;\n\twstring text16;\n\n\tif (state == GenericPlayer::InitState_InitOk)\n\t{\n\t\tm_loadIndicator->Stop();\n\n\t\tuint32_t totalTime = m_player->GetTotalTimeMs();\n\t\tui::Widget *totalTimeText = m_root->FindChild(text_video_control_panel_progressbar_label_total);\n\t\tif (totalTime > 0)\n\t\t{\n\t\t\tutils::ConvertSecondsToString(text8, totalTime / 1000, false);\n\t\t\tcommon::Utf8ToUtf16(text8, &text16);\n\t\t\ttotalTimeText->SetString(text16);\n\n\t\t\tauto progressBarCb = [](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t\t\t{\n\t\t\t\treinterpret_cast<menu::PlayerSimple *>(userdata)->OnProgressBarStateChange(type);\n\t\t\t};\n\t\t\tm_progressBar->AddEventCallback(ui::ProgressBarTouch::CB_PROGRESSBAR_DRAG_END, progressBarCb, this);\n\t\t\tm_progressBar->AddEventCallback(ui::Handler::CB_TOUCH_MOVE, progressBarCb, this);\n\t\t\tm_progressBar->AddEventCallback(ui::Handler::CB_TOUCH_OUT, progressBarCb, this);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_isLS = true;\n\t\t}\n\n\t\tinputdevice::AddInputListener(m_padListener);\n\n\t\tui::Widget *videoPlane = m_root->FindChild(button_video_page_control_trigger);\n\t\tvideoPlane->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t\t{\n\t\t\treinterpret_cast<menu::PlayerSimple *>(userdata)->OnVideoPlaneTouch();\n\t\t}, this);\n\n\t\tvideoPlane->SetKeycode(inputdevice::pad::Data::PAD_MENU);\n\n\t\tcommon::MainThreadCallList::Register(UpdateTask, this);\n\n\t\tevent::BroadcastGlobalEvent(g_appPlugin, PlayerSimpleEvent, PlayerEvent_InitOk);\n\t}\n\telse if (state == GenericPlayer::InitState_InitFail)\n\t{\n\t\tevent::BroadcastGlobalEvent(g_appPlugin, PlayerSimpleEvent, PlayerEvent_InitFail);\n\t}\n}\n\nvoid menu::PlayerSimple::OnUpdate()\n{\n\tstring text8;\n\twstring text16;\n\n\tif (!m_isLS)\n\t{\n\t\tif (!m_isSeeking)\n\t\t{\n\t\t\tuint32_t currTimeMs = m_player->GetCurrentTimeMs();\n\t\t\tuint32_t currTime = currTimeMs / 1000;\n\t\t\tif (m_subtitles)\n\t\t\t{\n\t\t\t\tm_subtitles->GetActiveSubtitleIndices(m_subIndices, currTimeMs);\n\t\t\t\tif (m_subIndices != m_oldSubIndices)\n\t\t\t\t{\n\t\t\t\t\tif (!m_subIndices.empty() && m_subIndices.size() > 1)\n\t\t\t\t\t{\n\t\t\t\t\t\tSCE_DBG_LOG_WARNING(\"[OnUpdate] Multiple subtitle entries detected (%u), only the first one will be used\", m_subIndices.size());\n\t\t\t\t\t}\n\t\t\t\t\tvector<GenericSubtitles::SubtitleEntry> const& subsLoc = m_subtitles->GetSubtitlieEntries();\n\t\t\t\t\tif (!m_subIndices.empty())\n\t\t\t\t\t{\n\t\t\t\t\t\tGenericSubtitles::SubtitleEntry const& sub = subsLoc.at(m_subIndices[0]);\n\n\t\t\t\t\t\tmath::v4 edgeColor(0.0f, 0.0f, 0.0f, 1.0f);\n\t\t\t\t\t\tif ((sub.colorPacked & 0x00FFFFFF) < 0x00323232)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tedgeColor.set_x(1.0f);\n\t\t\t\t\t\t\tedgeColor.set_y(1.0f);\n\t\t\t\t\t\t\tedgeColor.set_z(1.0f);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfloat scale = sub.charSizeScale;\n\t\t\t\t\t\tif (SCE_PAF_IS_DOLCE)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tscale *= 2.0f;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tmath::v2 scaledCharSize(m_subsBaseCharSize.x().f() * scale, m_subsBaseCharSize.y().f() * scale);\n\n\t\t\t\t\t\tm_subsMainText->SetAnchor(sub.anchorX, sub.anchorY, ui::Widget::ANCHOR_CENTER, NULL);\n\t\t\t\t\t\tm_subsMainText->SetAlign(sub.alignX, sub.alignY, ui::Widget::ALIGN_NONE, NULL);\n\t\t\t\t\t\tm_subsMainText->SetStyleAttribute(graph::TextStyleAttribute_Point, 0, 0, scaledCharSize);\n\t\t\t\t\t\tm_subsMainText->SetStyleAttribute(graph::TextStyleAttribute_Color, 0, 0, sub.color);\n\t\t\t\t\t\tfor (int i = 0; i < 4; i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_subsEdgeText[i]->SetAnchor(sub.anchorX, sub.anchorY, ui::Widget::ANCHOR_CENTER, NULL);\n\t\t\t\t\t\t\tm_subsEdgeText[i]->SetAlign(sub.alignX, sub.alignY, ui::Widget::ALIGN_NONE, NULL);\n\t\t\t\t\t\t\tm_subsEdgeText[i]->SetStyleAttribute(graph::TextStyleAttribute_Point, 0, 0, scaledCharSize);\n\t\t\t\t\t\t\tm_subsEdgeText[i]->SetStyleAttribute(graph::TextStyleAttribute_Color, 0, 0, edgeColor);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tm_subsMainText->SetPos(sub.position);\n\t\t\t\t\t\tfloat subBaseX = sub.position.x().f();\n\t\t\t\t\t\tfloat subBaseY = sub.position.y().f();\n\t\t\t\t\t\tm_subsEdgeText[0]->SetPos({ subBaseX + 2.0f, subBaseY + 2.0f });\n\t\t\t\t\t\tm_subsEdgeText[1]->SetPos({ subBaseX + 2.0f, subBaseY - 2.0f });\n\t\t\t\t\t\tm_subsEdgeText[2]->SetPos({ subBaseX - 2.0f, subBaseY - 2.0f });\n\t\t\t\t\t\tm_subsEdgeText[3]->SetPos({ subBaseX - 2.0f, subBaseY + 2.0f });\n\n\t\t\t\t\t\tm_subsMainText->SetString(sub.string);\n\n\t\t\t\t\t\tswitch (m_subSettings.edge)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tm_subsEdgeText[2]->SetString(sub.string);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tm_subsEdgeText[1]->SetString(sub.string);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\tfor (int i = 0; i < 4; i++)\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tm_subsEdgeText[i]->SetString(sub.string);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tm_subsEdgeText[1]->SetString(sub.string);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tm_subsMainText->SetString(L\"\");\n\t\t\t\t\t\tfor (int i = 0; i < 4; i++)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tm_subsEdgeText[i]->SetString(L\"\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tm_oldSubIndices = m_subIndices;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (currTime != m_oldCurrTime)\n\t\t\t{\n\t\t\t\tutils::ConvertSecondsToString(text8, currTime, false);\n\t\t\t\tcommon::Utf8ToUtf16(text8, &text16);\n\t\t\t\tm_elapsedTimeText->SetString(text16);\n\t\t\t\tfloat progress = static_cast<float>(currTime) * 100000.0f / static_cast<float>(m_player->GetTotalTimeMs());\n\t\t\t\tm_progressBar->SetValue(progress);\n\t\t\t\tm_oldCurrTime = currTime;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tuint32_t val = static_cast<uint32_t>(m_progressBar->GetValue() / 100000.0f * static_cast<float>(m_player->GetTotalTimeMs()));\n\t\t\tutils::ConvertSecondsToString(text8, val, false);\n\t\t\tcommon::Utf8ToUtf16(text8, &text16);\n\t\t\tm_elapsedTimeText->SetString(text16);\n\t\t}\n\n\t\tif (m_accJumpState == AccJumpState_Perform)\n\t\t{\n\t\t\tm_videoPlane->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f });\n\t\t\ttext16 = L\"\";\n\t\t\tm_leftAccText->SetString(text16);\n\t\t\tm_rightAccText->SetString(text16);\n\t\t\tm_player->JumpToTimeMs(m_player->GetCurrentTimeMs() + m_accJumpTime);\n\t\t\tm_accJumpTime = 0;\n\t\t\tm_accJumpState = AccJumpState_None;\n\t\t}\n\t\telse if (m_accJumpState == AccJumpState_Accumulate)\n\t\t{\n\t\t\tif ((sceKernelGetProcessTimeLow() - m_accStartTime) > 500000)\n\t\t\t{\n\t\t\t\tm_accJumpState = AccJumpState_Perform;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (m_progressPlaneShown)\n\t{\n\t\tif (m_isSeeking || m_player->IsPaused() || m_currentScale != 1.0f)\n\t\t{\n\t\t\tm_progressPlaneShownTime = sceKernelGetProcessTimeLow();\n\t\t}\n\t\telse if ((sceKernelGetProcessTimeLow() - m_progressPlaneShownTime) > 5000000)\n\t\t{\n\t\t\tif (!m_isLS)\n\t\t\t{\n\t\t\t\tm_progressPlane->Hide(common::transition::Type_SlideFromBottom1);\n\t\t\t}\n\t\t\tm_backButton->Hide(common::transition::Type_Reset);\n\t\t\tsceAppMgrSetInfobarState(SCE_APPMGR_INFOBAR_VISIBILITY_INVISIBLE, SCE_APPMGR_INFOBAR_COLOR_BLACK, SCE_APPMGR_INFOBAR_TRANSPARENCY_TRANSLUCENT);\n\t\t\tm_progressPlaneShown = false;\n\t\t}\n\t}\n\n\tGenericPlayer::PlayerState state = m_player->GetState();\n\tif (state != m_oldState)\n\t{\n\t\tswitch (state)\n\t\t{\n\t\tcase GenericPlayer::PlayerState_Eof:\n\t\t\tif (!m_isLS)\n\t\t\t{\n\t\t\t\tm_videoPlane->SetColor({ 0.4f, 0.4f, 0.4f, 1.0f });\n\t\t\t\tm_wholeRepeatButton->Show(common::transition::Type_FadeinFast);\n\t\t\t}\n\t\t\tbreak;\n\t\tcase GenericPlayer::PlayerState_Buffering:\n\t\t\t//m_loadIndicator->Start();\n\t\t\tbreak;\n\t\tcase GenericPlayer::PlayerState_Play:\n\t\t\tif (m_oldState == GenericPlayer::PlayerState_Buffering)\n\t\t\t{\n\t\t\t\t//m_loadIndicator->Stop();\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tm_oldState = state;\n}\n\nvoid menu::PlayerSimple::OnPadUpdate(inputdevice::Data *data)\n{\n#define PRESSED(x) ((data->m_pad_data->paddata & x) && !(data->m_pad_data_pre->paddata & x))\n\n\tif (PRESSED(inputdevice::pad::Data::PAD_ENTER))\n\t{\n\t\tif (m_player->GetState() == GenericPlayer::PlayerState_Eof && !m_isLS)\n\t\t{\n\t\t\tOnWholeRepeatButton();\n\t\t}\n\t\telse\n\t\t{\n\t\t\tOnPlayButton();\n\t\t}\n\t}\n\telse if (PRESSED(inputdevice::pad::Data::PAD_ESCAPE) && !m_progressPlaneShown)\n\t{\n\t\tOnBackButton();\n\t\treturn;\n\t}\n\telse if (((PRESSED(inputdevice::pad::Data::PAD_RIGHT)) ||\n\t\t(PRESSED(inputdevice::pad::Data::PAD_LEFT)) ||\n\t\t(PRESSED(inputdevice::pad::Data::PAD_R)) ||\n\t\t(PRESSED(inputdevice::pad::Data::PAD_L))) &&\n\t\t!m_isLS)\n\t{\n\t\tm_videoPlane->SetColor({0.4f, 0.4f, 0.4f, 1.0f});\n\n\t\tif (PRESSED(inputdevice::pad::Data::PAD_RIGHT))\n\t\t{\n\t\t\tm_accJumpTime += 5000;\n\t\t}\n\t\telse if (PRESSED(inputdevice::pad::Data::PAD_LEFT))\n\t\t{\n\t\t\tm_accJumpTime -= 5000;\n\t\t}\n\t\telse if (PRESSED(inputdevice::pad::Data::PAD_R))\n\t\t{\n\t\t\tm_accJumpTime += static_cast<int32_t>(static_cast<float>(m_player->GetTotalTimeMs()) * 0.05f);\n\t\t}\n\t\telse if (PRESSED(inputdevice::pad::Data::PAD_L))\n\t\t{\n\t\t\tm_accJumpTime -= static_cast<int32_t>(static_cast<float>(m_player->GetTotalTimeMs()) * 0.05f);\n\t\t}\n\n\t\tstring text8;\n\t\twstring text16;\n\t\tutils::ConvertSecondsToString(text8, static_cast<uint32_t>(sce_paf_abs(m_accJumpTime) / 1000), false);\n\t\tcommon::Utf8ToUtf16(text8, &text16);\n\t\tif (m_accJumpTime < 0)\n\t\t{\n\t\t\tm_leftAccText->SetString(text16);\n\t\t}\n\t\telse if (m_accJumpTime > 0)\n\t\t{\n\t\t\tm_rightAccText->SetString(text16);\n\t\t}\n\n\t\tm_accStartTime = sceKernelGetProcessTimeLow();\n\t\tm_accJumpState = AccJumpState_Accumulate;\n\t}\n\telse if (PRESSED(inputdevice::pad::Data::PAD_START))\n\t{\n\t\tscePowerRequestDisplayOff();\n\t}\n\n#undef PRESSED\n}\n\nmenu::PlayerSimple::PlayerSimple(const char *url, GenericPlayer::Option *opt, GenericSubtitles::Option *sopt) :\n\tGenericMenu(\"page_player_simple\",\n\tMenuOpenParam(true, 200.0f, Plugin::TransitionType_None, ui::EnvironmentParam::RESOLUTION_HD_FULL),\n\tMenuCloseParam(true)),\n\tm_oldButtons(0),\n\tm_accJumpTime(0),\n\tm_accStartTime(0),\n\tm_accJumpState(AccJumpState_None),\n\tm_progressPlaneShown(false),\n\tm_isLS(false),\n\tm_isSeeking(false),\n\tm_currentScale(1.0f),\n\tm_settingsOverride(SettingsOverride_None),\n\tm_player(NULL),\n\tm_subtitles(NULL)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\n\tcommon::SharedPtr<inputdevice::InputListener> listener(new PadListener(this));\n\tm_padListener = listener;\n\n\tm_progressBar = (ui::ProgressBarTouch *)m_root->FindChild(progressbar_touch_video_control_panel);\n\tm_elapsedTimeText = (ui::Text *)m_root->FindChild(text_video_control_panel_progressbar_label_elapsed);\n\tm_subsMainText = (ui::Text *)m_root->FindChild(text_video_page_player_subs_main);\n\tm_subsEdgeText[0] = (ui::Text *)m_root->FindChild(text_video_page_player_subs_edge_0);\n\tm_subsEdgeText[1] = (ui::Text *)m_root->FindChild(text_video_page_player_subs_edge_1);\n\tm_subsEdgeText[2] = (ui::Text *)m_root->FindChild(text_video_page_player_subs_edge_2);\n\tm_subsEdgeText[3] = (ui::Text *)m_root->FindChild(text_video_page_player_subs_edge_3);\n\tm_leftAccText = m_root->FindChild(text_video_page_player_simple_acc_left);\n\tm_rightAccText = m_root->FindChild(text_video_page_player_simple_acc_right);\n\tm_statPlane = m_root->FindChild(plane_statindicator);\n\tm_progressPlane = m_root->FindChild(plane_video_control_panel_bg);\n\tm_progressPlane->Hide(common::transition::Type_FadeinFast);\n\n\tGenericSubtitles::GetSystemSettings(m_subSettings);\n\n\tSCE_DBG_LOG_INFO(\"[PlayerSimple] m_subSettings.enable:   %d\", m_subSettings.enable);\n\tSCE_DBG_LOG_INFO(\"[PlayerSimple] m_subSettings.fontType: %d\", m_subSettings.fontType);\n\tSCE_DBG_LOG_INFO(\"[PlayerSimple] m_subSettings.edge:     %d\", m_subSettings.edge);\n\tSCE_DBG_LOG_INFO(\"[PlayerSimple] m_subSettings.size:     %d\", m_subSettings.size);\n\n\tif (m_subSettings.enable)\n\t{\n\t\tint32_t fontId = graph::FontFamily_5;\n\t\tswitch (m_subSettings.fontType)\n\t\t{\n\t\tcase 0:\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tfontId = graph::FontFamily_6;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tfontId = graph::FontFamily_3;\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tfontId = graph::FontFamily_4;\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tfontId = graph::FontFamily_7;\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tfontId = graph::FontFamily_8;\n\t\t\tbreak;\n\t\tcase 6:\n\t\t\tfontId = graph::FontFamily_9;\n\t\t}\n\n\t\tm_subsBaseCharSize.set_x(36.0f);\n\t\tm_subsBaseCharSize.set_y(22.0f);\n\t\tswitch (m_subSettings.size)\n\t\t{\n\t\tcase 1:\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tm_subsBaseCharSize.set_x(25.455843f);\n\t\t\tm_subsBaseCharSize.set_y(15.556349f);\n\t\t\tbreak;\n\t\tcase 0:\n\t\t\tm_subsBaseCharSize.set_x(50.911686f);\n\t\t\tm_subsBaseCharSize.set_y(31.112698f);\n\t\t\tbreak;\n\t\t}\n\n\t\tm_subsMainText->SetStyleAttribute(graph::TextStyleAttribute_Family, 0, 0, fontId);\n\n\t\tfor (int i = 0; i < 4; i++)\n\t\t{\n\t\t\tm_subsEdgeText[i]->SetStyleAttribute(graph::TextStyleAttribute_Family, 0, 0, fontId);\n\t\t}\n\t}\n\n\tm_loadIndicator = (ui::BusyIndicator *)m_root->FindChild(busyindicator_video_page_player_simple);\n\tif (SCE_PAF_IS_DOLCE)\n\t{\n\t\tm_loadIndicator->SetBallSize(32.0f);\n\t}\n\tm_loadIndicator->Start();\n\n\tm_backButton = m_root->FindChild(button_back_page_player_simple);\n\tm_backButton->Hide(common::transition::Type_Reset);\n\tm_backButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerSimple *>(userdata)->OnBackButton();\n\t}, this);\n\n\tm_wholeRepeatButton = m_root->FindChild(button_video_page_whole_repeat);\n\tm_wholeRepeatButton->Hide(common::transition::Type_FadeinFast);\n\tm_wholeRepeatButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerSimple *>(userdata)->OnWholeRepeatButton();\n\t}, this);\n\n\tm_playButton = m_root->FindChild(button_video_control_panel_playpause);\n\tm_playButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerSimple *>(userdata)->OnPlayButton();\n\t}, this);\n\n\tm_videoPlane = m_root->FindChild(plane_video_page_player_simple);\n\n\tm_root->AddEventCallback(GenericPlayer::GenericPlayerChangeState,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerSimple *>(userdata)->OnGenericPlayerStateChange(e->GetValue(0));\n\t}, this);\n\n\tif (!opt)\n\t{\n\t\tif (FMODPlayer::IsSupported(url) == GenericPlayer::SupportType_Supported)\n\t\t{\n\t\t\tm_player = new FMODPlayer(m_videoPlane, url, NULL);\n\t\t}\n\t\telse if (BEAVPlayer::IsSupported(url) == GenericPlayer::SupportType_Supported)\n\t\t{\n\t\t\tm_player = new BEAVPlayer(m_videoPlane, url, NULL);\n\t\t\tm_subSettings.enable = false; // BEAV is currently used only for livestreams, no subs here\n\t\t}\n\t\telse if (AVPlayer::IsSupported(url) == GenericPlayer::SupportType_Supported)\n\t\t{\n\t\t\tm_player = new AVPlayer(m_videoPlane, url, NULL);\n\t\t}\n\t}\n\telse if (opt->playerType == GenericPlayer::PlayerType_Auto)\n\t{\n\t\tif (FMODPlayer::IsSupported(url) == GenericPlayer::SupportType_Supported)\n\t\t{\n\t\t\tm_player = new FMODPlayer(m_videoPlane, url, static_cast<FMODPlayer::Option *>(opt));\n\t\t}\n\t\telse if (BEAVPlayer::IsSupported(url) == GenericPlayer::SupportType_Supported)\n\t\t{\n\t\t\tm_player = new BEAVPlayer(m_videoPlane, url, static_cast<BEAVPlayer::Option *>(opt));\n\t\t\tm_subSettings.enable = false; // BEAV is currently used only for livestreams, no subs here\n\t\t}\n\t\telse if (AVPlayer::IsSupported(url) == GenericPlayer::SupportType_Supported)\n\t\t{\n\t\t\tm_player = new AVPlayer(m_videoPlane, url, static_cast<AVPlayer::Option *>(opt));\n\t\t}\n\t}\n\telse\n\t{\n\t\tswitch (opt->playerType)\n\t\t{\n\t\tcase GenericPlayer::PlayerType_FMOD:\n\t\t\tm_player = new FMODPlayer(m_videoPlane, url, static_cast<FMODPlayer::Option *>(opt));\n\t\t\tbreak;\n\t\tcase GenericPlayer::PlayerType_BEAV:\n\t\t\tm_player = new BEAVPlayer(m_videoPlane, url, static_cast<BEAVPlayer::Option *>(opt));\n\t\t\tm_subSettings.enable = false; // BEAV is currently used only for livestreams, no subs here\n\t\t\tbreak;\n\t\tcase GenericPlayer::PlayerType_AV:\n\t\t\tm_player = new AVPlayer(m_videoPlane, url, static_cast<AVPlayer::Option *>(opt));\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (m_subSettings.enable)\n\t{\n\t\tif (!sopt || sopt->subtitlesType == GenericSubtitles::SubtitlesType_Auto)\n\t\t{\n\t\t\tif (SRTSubtitles::IsSupported(url) == GenericSubtitles::SupportType_Supported)\n\t\t\t{\n\t\t\t\tm_subtitles = new SRTSubtitles(url, NULL);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tswitch (sopt->subtitlesType)\n\t\t\t{\n\t\t\tcase GenericSubtitles::SubtitlesType_SRT:\n\t\t\t\tm_subtitles = new SRTSubtitles(url, static_cast<SRTSubtitles::Option *>(sopt));\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (m_player)\n\t{\n\t\tif (m_subtitles)\n\t\t{\n\t\t\tm_subtitles->InitAsync();\n\t\t}\n\t\tm_player->InitAsync();\n\t}\n\telse\n\t{\n\t\tOnGenericPlayerStateChange(GenericPlayer::InitState_InitFail);\n\t}\n\n\tm_pwCbId = sceKernelCreateCallback(\"PowerCallback\", 0, PowerCallback, this);\n\tscePowerRegisterCallback(m_pwCbId);\n\n\tsceAppMgrSetInfobarState(SCE_APPMGR_INFOBAR_VISIBILITY_INVISIBLE, SCE_APPMGR_INFOBAR_COLOR_BLACK, SCE_APPMGR_INFOBAR_TRANSPARENCY_TRANSLUCENT);\n\tutils::SetPowerTickTask(utils::PowerTick_All);\n\tmenu::GetMenuAt(menu::GetMenuCount() - 2)->Deactivate();\n}\n\nmenu::PlayerSimple::~PlayerSimple()\n{\n\tutils::SetDisplayResolution(ui::EnvironmentParam::RESOLUTION_PSP2);\n\tcommon::MainThreadCallList::Unregister(UpdateTask, this);\n\tscePowerUnregisterCallback(m_pwCbId);\n\tsceKernelDeleteCallback(m_pwCbId);\n\tinputdevice::DelInputListener(m_padListener);\n\tdelete m_subtitles;\n\tdelete m_player;\n\tsceAppMgrSetInfobarState(SCE_APPMGR_INFOBAR_VISIBILITY_VISIBLE, SCE_APPMGR_INFOBAR_COLOR_BLACK, SCE_APPMGR_INFOBAR_TRANSPARENCY_TRANSLUCENT);\n\tutils::SetPowerTickTask(utils::PowerTick_None);\n\tmenu::GetTopMenu()->Activate();\n}\n\nfloat menu::PlayerSimple::GetScale()\n{\n\treturn m_currentScale;\n}\n\nvoid menu::PlayerSimple::SetScale(float scale)\n{\n\tif (m_currentScale == scale || scale > 1.0f || scale < 0.0f)\n\t{\n\t\treturn;\n\t}\n\n\tmath::v4 sz(0.0f);\n\tmath::v4 pos(0.0f);\n\tmath::v2 tsz;\n\tui::Widget *triggerPlane = m_root->FindChild(button_video_page_control_trigger);\n\tauto totalTimeText = static_cast<ui::Text *>(m_root->FindChild(text_video_control_panel_progressbar_label_total));\n\n\tif (SCE_PAF_IS_DOLCE)\n\t{\n\t\tsz.set_x(1920.0f * scale);\n\t\tsz.set_y(1088.0f * scale);\n\t\tm_videoPlane->SetSize(sz);\n\t\tsz.set_x(150.0f * scale);\n\t\tsz.set_y(150.0f * scale);\n\t\tm_loadIndicator->SetSize(sz);\n\t\tm_loadIndicator->SetBallSize(32.0f * scale);\n\t\tsz.set_x(180.0f * scale);\n\t\tsz.set_y(180.0f * scale);\n\t\tm_wholeRepeatButton->SetSize(sz);\n\t\tif (scale == 1.0f)\n\t\t{\n\t\t\tsz.set_x(1700.0f);\n\t\t\tsz.set_y(112.0f);\n\t\t\tm_progressPlane->SetSize(sz);\n\t\t\tpos.set_x(0.0f);\n\t\t\tpos.set_y(56.0f);\n\t\t\tm_progressPlane->SetPos(pos);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsz.set_x(1920.0f * scale);\n\t\t\tsz.set_y(112.0f * scale);\n\t\t\tm_progressPlane->SetSize(sz);\n\t\t\tpos.set_x(0.0f);\n\t\t\tpos.set_y(56.0f * scale);\n\t\t\tm_progressPlane->SetPos(pos);\n\t\t}\n\t\tsz.set_x(1400.0f * scale);\n\t\tsz.set_y(20.0f * scale);\n\t\tm_progressBar->SetSize(sz);\n\t\tsz.set_x(90.0f * scale);\n\t\tsz.set_y(80.0f * scale);\n\t\tm_playButton->SetSize(sz);\n\t\tpos.set_x(30.0f * scale);\n\t\tpos.set_y(0.0f);\n\t\tm_playButton->SetPos(pos);\n\t\tpos.set_x(-20.0f * scale);\n\t\tif (scale != 1.0f)\n\t\t{\n\t\t\tpos.set_x(pos.extract_x() - 20.0f * scale);\n\t\t}\n\t\tpos.set_y(20.0f * scale);\n\t\tm_elapsedTimeText->SetPos(pos);\n\t\tpos.set_y(-pos.extract_y());\n\t\ttotalTimeText->SetPos(pos);\n\t}\n\telse\n\t{\n\t\tsz.set_x(960.0f * scale);\n\t\tsz.set_y(544.0f * scale);\n\t\tm_videoPlane->SetSize(sz);\n\t\tsz.set_x(75.0f * scale);\n\t\tsz.set_y(75.0f * scale);\n\t\tm_loadIndicator->SetSize(sz);\n\t\tm_loadIndicator->SetBallSize(16.0f * scale);\n\t\tsz.set_x(90.0f * scale);\n\t\tsz.set_y(90.0f * scale);\n\t\tm_wholeRepeatButton->SetSize(sz);\n\t\tif (scale == 1.0f)\n\t\t{\n\t\t\tsz.set_x(790.0f);\n\t\t\tsz.set_y(56.0f);\n\t\t\tm_progressPlane->SetSize(sz);\n\t\t\tpos.set_x(0.0f);\n\t\t\tpos.set_y(28.0f);\n\t\t\tm_progressPlane->SetPos(pos);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsz.set_x(960.0f * scale);\n\t\t\tsz.set_y(112.0f * scale);\n\t\t\tm_progressPlane->SetSize(sz);\n\t\t\tpos.set_x(0.0f);\n\t\t\tpos.set_y(56.0f * scale);\n\t\t\tm_progressPlane->SetPos(pos);\n\t\t}\n\t\tsz.set_x(538.0f * scale);\n\t\tsz.set_y(10.0f * scale);\n\t\tm_progressBar->SetSize(sz);\n\t\t/*\n\t\tpos.y = 0.0f;\n\t\tpos.x = 14.0f * scale;\n\t\tprogressBar->SetPosition(&pos);\n\t\t*/\n\t\tsz.set_x(48.0f * scale);\n\t\tsz.set_y(80.0f * scale);\n\t\tm_playButton->SetSize(sz);\n\t\tpos.set_x(32.0f * scale);\n\t\tpos.set_y(0.0f);\n\t\tm_playButton->SetPos(pos);\n\t\tpos.set_x(-20.0f * scale);\n\t\tif (scale != 1.0f)\n\t\t{\n\t\t\tpos.set_x(pos.extract_x() - 20.0f * scale);\n\t\t}\n\t\tif (scale != 1.0f)\n\t\t{\n\t\t\tpos.set_y(20.0f * scale);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpos.set_y(12.0f * scale);\n\t\t}\n\t\tm_elapsedTimeText->SetPos(pos);\n\t\tpos.set_y(-pos.extract_y());\n\t\ttotalTimeText->SetPos(pos);\n\t}\n\n\tif (scale != 1.0f)\n\t{\n\t\ttsz.set_x(16.0f);\n\t}\n\telse\n\t{\n\t\ttsz.set_x(20.0f);\n\t}\n\n\ttsz.set_y(tsz.extract_x());\n\tm_elapsedTimeText->SetStyleAttribute(graph::TextStyleAttribute_Point, 0, 0, tsz);\n\ttotalTimeText->SetStyleAttribute(graph::TextStyleAttribute_Point, 0, 0, tsz);\n\n\tif (scale == 1.0f)\n\t{\n\t\tinputdevice::AddInputListener(m_padListener);\n\t\tsceAppMgrSetInfobarState(SCE_APPMGR_INFOBAR_VISIBILITY_INVISIBLE, SCE_APPMGR_INFOBAR_COLOR_BLACK, SCE_APPMGR_INFOBAR_TRANSPARENCY_TRANSLUCENT);\n\t\tm_backButton->Show(common::transition::Type_Reset);\n\t\ttriggerPlane->Show(common::transition::Type_FadeinFast);\n\t\tmenu::GetMenuAt(menu::GetMenuCount() - 2)->Deactivate();\n\t}\n\telse\n\t{\n\t\tinputdevice::DelInputListener(m_padListener);\n\t\tsceAppMgrSetInfobarState(SCE_APPMGR_INFOBAR_VISIBILITY_VISIBLE, SCE_APPMGR_INFOBAR_COLOR_BLACK, SCE_APPMGR_INFOBAR_TRANSPARENCY_TRANSLUCENT);\n\t\tm_backButton->Hide(common::transition::Type_Reset);\n\t\ttriggerPlane->Hide(common::transition::Type_FadeinFast);\n\t\tif (!m_isLS)\n\t\t{\n\t\t\tm_progressPlane->Show(common::transition::Type_FadeinFast);\n\t\t}\n\t\tm_progressPlaneShown = true;\n\t\tmenu::GetMenuAt(menu::GetMenuCount() - 2)->Activate();\n\t}\n\n\tm_currentScale = scale;\n}\n\nvoid menu::PlayerSimple::SetPosition(float x, float y)\n{\n\tm_videoPlane->SetPos({x, y});\n}\n\nvoid menu::PlayerSimple::SetSettingsOverride(SettingsOverride override)\n{\n\tm_settingsOverride = override;\n}\n\nGenericPlayer *menu::PlayerSimple::GetPlayer()\n{\n\treturn m_player;\n}"
  },
  {
    "path": "NetStream/source/menus/menu_player_youtube.cpp",
    "content": "#include <kernel.h>\n#include <appmgr.h>\n#include <stdlib.h>\n#include <string.h>\n#include <libdbg.h>\n#include <paf.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"yt_utils.h\"\n#include \"dialog.h\"\n#include \"ftube.h\"\n#include <paf_file_ext.h>\n#include \"option_menu.h\"\n#include \"players/player_beav.h\"\n#include \"players/player_av.h\"\n#include \"menus/menu_generic.h\"\n#include \"menus/menu_player_youtube.h\"\n#include \"menus/menu_player_simple.h\"\n#include \"menus/menu_settings.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[PlayerYoutube]\"\n\nusing namespace paf;\n\nvoid menu::PlayerYoutube::LoadSecondStageTask(void *pArgBlock)\n{\n\treinterpret_cast<PlayerYoutube *>(pArgBlock)->OnLoadSecondStage();\n\tcommon::MainThreadCallList::Unregister(LoadSecondStageTask, pArgBlock);\n}\n\nvoid menu::PlayerYoutube::Load()\n{\n\tFTItem *ftItem = NULL;\n\tvoid *ftCtx = NULL;\n\tint32_t ret = 0;\n\tstring text8;\n\twstring text16;\n\n\tm_videoLink = \"\";\n\tm_videoLinkForDw = \"\";\n\tm_audioLink.clear();\n\tif (m_option)\n\t{\n\t\tdelete m_option;\n\t\tm_option = NULL;\n\t}\n\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\n\tint32_t vodVideoQuality;\n\tsettings->GetInt(\"yt_quality_vod_video\", reinterpret_cast<int32_t *>(&vodVideoQuality), 3);\n\n\tSCE_DBG_LOG_INFO(\"[Load] Video id: %s\", m_videoId.c_str());\n\n\tret = ftParseVideo(&ftCtx, m_videoId.c_str(), vodVideoQuality, FT_AUDIO_VOD_QUALITY_MEDIUM, &ftItem);\n\tif (ret == FT_OK)\n\t{\n\t\tif (ftItem->videoItem->id)\n\t\t{\n\t\t\tm_description = ftItem->videoItem->description;\n\n\t\t\tthread::RMutex::MainThreadMutex()->Lock();\n\n\t\t\tOnDescButton();\n\n\t\t\ttext8 = ftItem->videoItem->title;\n\t\t\tcommon::Utf8ToUtf16(text8, &text16);\n\t\t\tm_title->SetString(text16);\n\n\t\t\ttext8 = \"Uploaded by \";\n\t\t\ttext8 += ftItem->videoItem->author;\n\t\t\tcommon::Utf8ToUtf16(text8, &text16);\n\t\t\tm_stat0->SetString(text16);\n\n\t\t\tytutils::FormatViews(text16, ftItem->videoItem->viewCount);\n\t\t\tm_stat1->SetString(text16);\n\n\t\t\t// TODO: do something with m_stat2?\n\t\t\t// text8 = \"ERASE ME\";\n\t\t\t// common::Utf8ToUtf16(text8, &text16);\n\t\t\t// m_stat2->SetString(text16);\n\n\t\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\t\t\tif (ftItem->videoItem->isLive)\n\t\t\t{\n\t\t\t\tSCE_DBG_LOG_INFO(\"[Load] Video is LIVE\");\n\n\t\t\t\tBEAVPlayer::Option *opt = new BEAVPlayer::Option();\n\t\t\t\tsettings->GetInt(\"yt_quality_live\", reinterpret_cast<int32_t *>(&opt->defaultRes), 3);\n\t\t\t\tm_option = opt;\n\n\t\t\t\tm_videoLink = ftItem->videoItem->hlsManifestUrl;\n\t\t\t\tm_isLive = true;\n\n\t\t\t\tui::Widget *livePlane = m_root->FindChild(plane_youtube_live_now);\n\t\t\t\tintrusive_ptr<graph::Surface> liveTex = g_appPlugin->GetTexture(tex_yt_icon_live_now);\n\t\t\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t\t\t\tlivePlane->SetTexture(liveTex);\n\t\t\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tSCE_DBG_LOG_INFO(\"[Load] Video is VOD\");\n\n\t\t\t\tif (ftItem->videoItem->compositeVideoUrl)\n\t\t\t\t{\n\t\t\t\t\tm_videoLinkForDw = ftItem->videoItem->compositeVideoUrl;\n\t\t\t\t}\n\n\t\t\t\tcommon::SharedPtr<LocalFile> lmanifest;\n\t\t\t\tint32_t res = -1;\n\n\t\t\t\tlmanifest = LocalFile::Open(\"savedata0:lmanifest.mpd\", File::WRONLY | File::CREAT | File::TRUNC, File::RWU, &res);\n\t\t\t\tif (res == SCE_OK)\n\t\t\t\t{\n\t\t\t\t\tlmanifest->Write(ftItem->videoItem->dashManifest, sce_paf_strlen(ftItem->videoItem->dashManifest));\n\t\t\t\t\tlmanifest->Close();\n\n\t\t\t\t\tm_videoLink = \"savedata0:lmanifest.mpd\";\n\t\t\t\t\tif (ftItem->videoItem->audioOnlyUrl)\n\t\t\t\t\t{\n\t\t\t\t\t\tm_audioLink = ftItem->videoItem->audioOnlyUrl;\n\t\t\t\t\t}\n\n\t\t\t\t\tSCE_DBG_LOG_INFO(\"[Load] DASH manifest ready at %s\", m_videoLink.c_str());\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tSCE_DBG_LOG_ERROR(\"failed to create manifest at %s: 0x%08X\", m_videoLink.c_str(), res);\n\t\t\t\t\tret = res;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tret = -1;\n\t\t}\n\n\t\tftCleanup(ftCtx);\n\t}\n\telse\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[Load] ftParseVideo(): 0x%08X\", ret);\n\t}\n\n\tcommon::MainThreadCallList::Register(menu::PlayerYoutube::LoadSecondStageTask, this);\n}\n\nui::ListItem *menu::PlayerYoutube::CreateLiveCommentListItem(ui::listview::ItemFactory::CreateParam& param)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\tui::Widget *item = NULL;\n\twstring text16;\n\n\tui::Widget *targetRoot = param.parent;\n\n\tg_appPlugin->TemplateOpen(targetRoot, template_list_item_youtube_comment, tmpParam);\n\titem = targetRoot->GetChild(targetRoot->GetChildrenNum() - 1);\n\n\tui::Widget *button = item->FindChild(button_yt_companel_comment_item);\n\tbutton->SetName(LIVE_COMMENT_MAGIC + param.cell_index);\n\n\treturn static_cast<ui::ListItem *>(item);\n}\n\nui::ListItem *menu::PlayerYoutube::CreateCommentListItem(ui::listview::ItemFactory::CreateParam& param)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\tui::Widget *item = NULL;\n\twstring text16;\n\n\tif (!param.list_view->GetName().GetIDHash())\n\t{\n\t\treturn new ui::ListItem(param.parent, 0);\n\t}\n\n\tui::Widget *targetRoot = param.parent;\n\n\tg_appPlugin->TemplateOpen(targetRoot, template_list_item_youtube_comment, tmpParam);\n\titem = targetRoot->GetChild(targetRoot->GetChildrenNum() - 1);\n\n\tui::Widget *button = item->FindChild(button_yt_companel_comment_item);\n\tbutton->SetName(param.cell_index);\n\n\tbutton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnCommentBodyButton(static_cast<ui::Widget *>(self));\n\t}, this);\n\n\tif (param.cell_index == m_commentItems.size())\n\t{\n\t\ttext16 = g_appPlugin->GetString(msg_youtube_comment_more);\n\t}\n\telse\n\t{\n\t\tCommentItem entry = m_commentItems.at(param.cell_index);\n\t\ttext16 = entry.author + L\"  \" + entry.date + L\"\\n\" + entry.content;\n\n\t\tif (!entry.replyContinuation.empty())\n\t\t{\n\t\t\t//TODO: implement comment replies\n\t\t}\n\t}\n\n\tbutton->SetString(text16);\n\n\treturn static_cast<ui::ListItem *>(item);\n}\n\nvoid menu::PlayerYoutube::ParseLiveComments(thread::Thread *thrd)\n{\n\tui::ListView *list = m_companelRoot;\n\tui::Widget *button = NULL;\n\tFTItem *ftItem;\n\tvoid *ftCtx = NULL;\n\tint32_t commCount = 0;\n#ifdef USE_LIVE_COMMENT_HASHING\n\tuint32_t lastHash = 0;\n#endif\n\tstring text8;\n\twstring text16;\n\twstring tmpText16;\n\n\twhile (!thrd->IsCanceled())\n\t{\n\t\tif (m_player->GetScale() != 1.0f)\n\t\t{\n\t\t\tcommCount = ftParseLiveComments(&ftCtx, m_videoId.c_str(), LIVE_COMMENT_NUM, &ftItem);\n\t\t\tif (commCount <= 0)\n\t\t\t{\n\t\t\t\tthread::Sleep(33);\n\t\t\t\tftCleanup(ftCtx);\n\t\t\t\tif (thrd->IsCanceled())\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n#ifdef USE_LIVE_COMMENT_HASHING\n\t\t\tif (utils::GetHash(ftItem->commentItem->content) == lastHash)\n\t\t\t{\n\t\t\t\tthread::Sleep(33);\n\t\t\t\tftCleanup(ftCtx);\n\t\t\t\tif (thrd->IsCanceled())\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n#endif\n\n\t\t\tuint32_t i = commCount - 1;\n\t\t\tdo\n\t\t\t{\n\t\t\t\ttext8 = ftItem->commentItem->author;\n\t\t\t\tcommon::Utf8ToUtf16(text8, &text16);\n\t\t\t\ttext8 = ftItem->commentItem->content;\n\t\t\t\tcommon::Utf8ToUtf16(text8, &tmpText16);\n\t\t\t\ttext16 += L\"\\n\";\n\t\t\t\ttext16 += tmpText16;\n\n\t\t\t\tbutton = list->FindChild(LIVE_COMMENT_MAGIC + i);\n\t\t\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t\t\t\tbutton->SetString(text16);\n\t\t\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\t\t\t\tftItem = ftItem->next;\n\n#ifdef USE_LIVE_COMMENT_HASHING\n\t\t\t\tif (i == commCount - 1)\n\t\t\t\t{\n\t\t\t\t\tlastHash = utils::GetHash(text8.c_str());\n\t\t\t\t}\n#endif\n\n\t\t\t\ti--;\n\t\t\t} while (ftItem);\n\n\t\t\tftCleanup(ftCtx);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tthread::Sleep(33);\n\t\t\tif (thrd->IsCanceled())\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tthread::Sleep(33);\n\t}\n\n\tthrd->Cancel();\n}\n\nui::ListItem *menu::PlayerYoutube::CreateSelectQualityListItem(ui::listview::ItemFactory::CreateParam& param)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\tui::Widget *item = NULL;\n\twstring text16;\n\n\tui::Widget *targetRoot = param.parent;\n\n\tg_appPlugin->TemplateOpen(targetRoot, template_list_item_youtube_quality_select, tmpParam);\n\titem = targetRoot->GetChild(targetRoot->GetChildrenNum() - 1);\n\n\tui::Button *button = static_cast<ui::Button *>(item->FindChild(button_yt_quality_select_item));\n\tbutton->SetName(SELECT_QUALITY_MAGIC + param.cell_index);\n\n\tGenericPlayer::GenericRepresentationInfo repInfo;\n\tm_player->GetPlayer()->GetVideoRepresentationInfo(&repInfo, param.cell_index);\n\n\tbutton->SetString(repInfo.string);\n\tif (repInfo.currentlySelected || !repInfo.enabled)\n\t{\n\t\tbutton->Disable(false);\n\t}\n\telse\n\t{\n\t\tbutton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t\t{\n\t\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnSelectQualityButton(static_cast<ui::Widget *>(self));\n\t\t}, this);\n\t}\n\n\tSCE_DBG_LOG_INFO(\"[CreateSelectQualityListItem] Created %ls, selected: %u, disabled: %u\", repInfo.string.c_str(), repInfo.currentlySelected, !repInfo.enabled);\n\n\treturn static_cast<ui::ListItem *>(item);\n}\n\nvoid menu::PlayerYoutube::ParseComments()\n{\n\tFTItem *commentItem = NULL;\n\tvoid *ftCtx = NULL;\n\tconst char *commentContTmp = NULL;\n\tFTCommentSort sort;\n\tstring text8;\n\twstring text16;\n\tint32_t ret = 0;\n\tuint32_t addOverhead = 0;\n\tuint32_t oldCommentCount = 0;\n\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetInt(\"yt_comment_sort\", reinterpret_cast<int32_t *>(&sort), 0);\n\n\tif (m_commentCont.empty())\n\t{\n\t\tret = ftParseComments(&ftCtx, m_videoId.c_str(), NULL, sort, &commentItem, &commentContTmp);\n\t}\n\telse\n\t{\n\t\tret = ftParseComments(&ftCtx, m_videoId.c_str(), m_commentCont.c_str(), sort, &commentItem, &commentContTmp);\n\t}\n\n\tif (ret <= 0)\n\t{\n\t\tm_commentCont = \"end\";\n\t\treturn;\n\t}\n\n\toldCommentCount = m_commentItems.size();\n\n\tfor (int i = 0; i < ret; i++)\n\t{\n\t\tCommentItem item;\n\t\ttext8 = commentItem->commentItem->author;\n\t\tcommon::Utf8ToUtf16(text8, &item.author);\n\t\ttext8 = commentItem->commentItem->content;\n\t\tcommon::Utf8ToUtf16(text8, &item.content);\n\t\ttext8 = commentItem->commentItem->published;\n\t\tcommon::Utf8ToUtf16(text8, &item.date);\n\t\ttext8 = commentItem->commentItem->voteCount;\n\t\tcommon::Utf8ToUtf16(text8, &item.voteCount);\n\t\titem.likedByOwner = commentItem->commentItem->likedByOwner;\n\t\tif (commentItem->commentItem->replyContinuation)\n\t\t{\n\t\t\titem.replyContinuation = commentItem->commentItem->replyContinuation;\n\t\t}\n\t\tm_commentItems.push_back(item);\n\t\tcommentItem = commentItem->next;\n\t}\n\n\tif (commentContTmp)\n\t{\n\t\tm_commentCont = commentContTmp;\n\t\taddOverhead = 1;\n\t}\n\telse\n\t{\n\t\tm_commentCont = \"end\";\n\t}\n\n\tui::ListView *list = static_cast<ui::ListView *>(m_companelRoot);\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tlist->InsertCell(0, oldCommentCount, m_commentItems.size() + addOverhead - oldCommentCount);\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\tftCleanup(ftCtx);\n}\n\nvoid menu::PlayerYoutube::OnLoadSecondStage()\n{\n\tm_player = new menu::PlayerSimple(m_videoLink.c_str(), m_option);\n\tm_player->SetPosition(-1920.0f, -1080.0f);\n\tm_root->SetShowAlpha(1.0f);\n\tm_player->SetSettingsOverride(menu::PlayerSimple::SettingsOverride_YouTube);\n}\n\nvoid menu::PlayerYoutube::OnCommentBodyButton(ui::Widget *wdg)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\twstring text16;\n\n\tif (wdg->GetName().GetIDHash() == m_commentItems.size())\n\t{\n\t\tui::ListView *list = static_cast<ui::ListView *>(m_companelRoot);\n\t\tlist->DeleteCell(0, m_commentItems.size(), 1);\n\n\t\tCommentParseJob *job = new CommentParseJob(this);\n\t\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\t\tutils::GetJobQueue()->Enqueue(itemParam);\n\t}\n\telse\n\t{\n\t\tCommentItem entry = m_commentItems.at(wdg->GetName().GetIDHash());\n\n\t\tui::ScrollView *commentView = dialog::OpenScrollView(g_appPlugin, g_appPlugin->GetString(msg_youtube_comment_detail));\n\n\t\tg_appPlugin->TemplateOpen(commentView->FindChild(\"dialog_view_box\"), template_scroll_item_youtube_comment_detail, tmpParam);\n\n\t\tui::Widget *detailText = commentView->FindChild(text_youtube_comment_detail);\n\t\ttext16 = entry.author + L\"\\n\" + entry.date + L\"\\n\";\n\t\ttext16 += entry.voteCount + g_appPlugin->GetString(msg_youtube_comment_like_count);\n\t\tdetailText->SetString(text16);\n\n\t\tui::Widget *bodyText = commentView->FindChild(text_youtube_comment_detail_body);\n\t\ttext16 = entry.content;\n\t\tbodyText->SetString(text16);\n\t}\n}\n\nvoid menu::PlayerYoutube::OnExpandButton()\n{\n\tm_player->SetScale(1.0f);\n\tm_player->SetPosition(0.0f, 0.0f);\n}\n\nvoid menu::PlayerYoutube::OnVideoSettingsButton()\n{\n\tui::ListView *root = dialog::OpenListView(g_appPlugin, g_appPlugin->GetString(msg_quality_select_dialog_title));\n\n\troot->InsertSegment(0, 1);\n\tmath::v4 sz(580.0f, 70.0f);\n\troot->SetCellSizeDefault(0, sz);\n\troot->SetSegmentLayoutType(0, ui::ListView::LAYOUT_TYPE_LIST);\n\n\tSelectQualityDialogListViewCb *lwCb = new SelectQualityDialogListViewCb(this);\n\troot->SetItemFactory(lwCb);\n\troot->InsertCell(0, 0, m_player->GetPlayer()->GetVideoRepresentationNum());\n}\n\nvoid menu::PlayerYoutube::OnSelectQualityButton(ui::Widget *wdg)\n{\n\tuint32_t idx = wdg->GetName().GetIDHash() - SELECT_QUALITY_MAGIC;\n\tSCE_DBG_LOG_INFO(\"[OnSelectQualityButton] Selected quality idx: %u\", idx);\n\tm_player->GetPlayer()->SelectVideoRepresentation(idx);\n\tdialog::Close();\n}\n\nvoid menu::PlayerYoutube::OnFavButton()\n{\n\tuint32_t texid = 0;\n\n\tif (m_isFav)\n\t{\n\t\ttexid = tex_yt_icon_favourite_for_player;\n\t\tytutils::GetFavLog()->Remove(m_videoId.c_str());\n\t\tm_isFav = false;\n\t}\n\telse\n\t{\n\t\ttexid = tex_yt_icon_favourite_for_player_glow;\n\t\tytutils::GetFavLog()->AddAsync(m_videoId.c_str());\n\t\tm_isFav = true;\n\t}\n\n\tintrusive_ptr<graph::Surface> favIcon = g_appPlugin->GetTexture(texid);\n\tif (favIcon.get())\n\t{\n\t\tm_favButton->SetTexture(favIcon);\n\t}\n}\n\nvoid menu::PlayerYoutube::OnCommentButton()\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\n\tif (m_companelRoot)\n\t{\n\t\tif (m_companelRoot->GetName().GetID() == \"comment_root\")\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tcommon::transition::DoReverse(0.0f, m_companelRoot, common::transition::Type_FadeinFast, true, false);\n\t\tm_companelRoot = NULL;\n\t}\n\n\tg_appPlugin->TemplateOpen(m_companelBase, template_list_view_youtube_companel, tmpParam);\n\tm_companelRoot = static_cast<ui::ListView *>(m_companelBase->GetChild(m_companelBase->GetChildrenNum() - 1));\n\tm_companelRoot->Show(common::transition::Type_FadeinFast);\n\tm_companelRoot->SetName(\"comment_root\");\n\n\tui::ListView *list = (ui::ListView *)m_companelRoot;\n\n\tlist->InsertSegment(0, 1);\n\tmath::v4 sz(414.0f, 70.0f);\n\tlist->SetCellSizeDefault(0, sz);\n\tlist->SetSegmentLayoutType(0, ui::ListView::LAYOUT_TYPE_LIST);\n\n\tm_commentItems.clear();\n\n\tif (m_isLive)\n\t{\n\t\tLiveCommentListViewCb *lwCb = new LiveCommentListViewCb(this);\n\t\tlist->SetItemFactory(lwCb);\n\t\tlist->InsertCell(0, 0, LIVE_COMMENT_NUM);\n\n\t\tm_liveCommentThread = new LiveCommentParseThread(this);\n\t\tm_liveCommentThread->Start();\n\t}\n\telse\n\t{\n\t\tCommentListViewCb *lwCb = new CommentListViewCb(this);\n\t\tlist->SetItemFactory(lwCb);\n\n\t\tCommentParseJob *job = new CommentParseJob(this);\n\t\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\t\tutils::GetJobQueue()->Enqueue(itemParam);\n\t}\n}\n\nvoid menu::PlayerYoutube::OnDescButton()\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\twstring text16;\n\n\tif (m_description.length() == 0)\n\t{\n\t\treturn;\n\t}\n\n\tif (m_companelRoot)\n\t{\n\t\tif (m_companelRoot->GetName().GetID() == \"description_root\")\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tif (m_liveCommentThread)\n\t\t{\n\t\t\tm_liveCommentThread->Cancel();\n\t\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t\t\tm_liveCommentThread->Join();\n\t\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t\t\tdelete m_liveCommentThread;\n\t\t\tm_liveCommentThread = NULL;\n\t\t}\n\t\tcommon::transition::DoReverse(0.0f, m_companelRoot, common::transition::Type_FadeinFast, true, false);\n\t\tm_companelRoot = NULL;\n\t}\n\n\tg_appPlugin->TemplateOpen(m_companelBase, template_scroll_view_youtube_companel, tmpParam);\n\tm_companelRoot = static_cast<ui::ListView *>(m_companelBase->GetChild(m_companelBase->GetChildrenNum() - 1));\n\tm_companelRoot->Show(common::transition::Type_FadeinFast);\n\tm_companelRoot->SetName(\"description_root\");\n\n\tui::Widget *descText = m_companelRoot->FindChild(text_youtube_companel);\n\n\tcommon::Utf8ToUtf16(m_description, &text16);\n\ttext16 += L\"\\n\\n\";\n\tdescText->SetString(text16);\n}\n\nvoid menu::PlayerYoutube::OnBackButton()\n{\n\tdelete m_player;\n\tdelete this;\n}\n\nvoid menu::PlayerYoutube::OnDwAddComplete(int32_t result)\n{\n\tdialog::Close();\n\tif (result == SCE_OK)\n\t{\n\t\tdialog::OpenOk(g_appPlugin, NULL, g_appPlugin->GetString(msg_settings_youtube_download_begin));\n\t}\n\telse\n\t{\n\t\tdialog::OpenError(g_appPlugin, result);\n\t}\n}\n\nvoid menu::PlayerYoutube::OnSettingsButton()\n{\n\tvector<OptionMenu::Button> buttons;\n\tOptionMenu::Button bt;\n\tbt.label = g_appPlugin->GetString(msg_settings);\n\tbuttons.push_back(bt);\n\tif (!m_isLive)\n\t{\n\t\tbt.label = g_appPlugin->GetString(msg_settings_youtube_download);\n\t\tbuttons.push_back(bt);\n\t\tif (!m_audioLink.empty())\n\t\t{\n\t\t\tbt.label = g_appPlugin->GetString(msg_settings_youtube_download_audio);\n\t\t\tbuttons.push_back(bt);\n\t\t}\n\t}\n\n\tnew OptionMenu(g_appPlugin, m_root, &buttons);\n}\n\nvoid menu::PlayerYoutube::OnOptionMenuEvent(int32_t type, int32_t subtype)\n{\n\tif (type == OptionMenu::OptionMenuEvent_Close)\n\t{\n\t\treturn;\n\t}\n\n\twstring title16;\n\tstring title8;\n\tint32_t res = SCE_OK;\n\tswitch (subtype)\n\t{\n\tcase 0:\n\t\tmenu::GetMenuAt(menu::GetMenuCount() - 2)->DisableInput();\n\t\tmenu::SettingsButtonCbFun(ui::Button::CB_BTN_DECIDE, NULL, 0, NULL);\n\t\tbreak;\n\tcase 1:\n\t\tm_title->GetString(title16);\n\t\tcommon::Utf16ToUtf8(title16, &title8);\n\t\ttitle8 += \".mp4\";\n\n\t\tres = ytutils::EnqueueDownloadAsync(m_videoLinkForDw.c_str(), title8.c_str());\n\t\tSCE_DBG_LOG_INFO(\"[OnOptionMenuEvent] Enqueue video download: %s\", title8.c_str());\n\t\tif (res == SCE_OK)\n\t\t{\n\t\t\tdialog::OpenPleaseWait(g_appPlugin, NULL, Framework::Instance()->GetCommonString(\"msg_wait\"));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdialog::OpenError(g_appPlugin, res);\n\t\t}\n\t\tbreak;\n\tcase 2:\n\t\tm_title->GetString(title16);\n\t\tcommon::Utf16ToUtf8(title16, &title8);\n\t\ttitle8 += \".webm\";\n\n\t\tres = ytutils::EnqueueDownloadAsync(m_audioLink.c_str(), title8.c_str());\n\t\tSCE_DBG_LOG_INFO(\"[OnOptionMenuEvent] Enqueue audio download: %s\", title8.c_str());\n\t\tif (res == SCE_OK)\n\t\t{\n\t\t\tdialog::OpenPleaseWait(g_appPlugin, NULL, Framework::Instance()->GetCommonString(\"msg_wait\"));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdialog::OpenError(g_appPlugin, res);\n\t\t}\n\t\tbreak;\n\t}\n}\n\nvoid menu::PlayerYoutube::OnPlayerEvent(int32_t type)\n{\n\tSCE_DBG_LOG_INFO(\"[OnPlayerEvent] Event: %d\", type);\n\n\tswitch (type)\n\t{\n\tcase PlayerSimple::PlayerEvent_Back:\n\t\tif (m_player->GetScale() != 1.0f)\n\t\t{\n\t\t\tdelete m_player;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_player->SetScale(0.5f);\n\t\t\tif (SCE_PAF_IS_DOLCE)\n\t\t\t{\n\t\t\t\tm_player->SetPosition(26.0f, -158.0f);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tm_player->SetPosition(13.0f, -79.0f);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\tcase PlayerSimple::PlayerEvent_InitOk:\n\t\tint32_t min = 0;\n\n\t\tui::BusyIndicator *loaderIndicator = static_cast<ui::BusyIndicator *>(m_root->FindChild(busyindicator_youtube_loader));\n\t\tui::Widget *loaderPlane = m_root->FindChild(plane_youtube_loader);\n\n\t\tif (m_player->GetPlayer()->GetVideoRepresentationNum() > 1)\n\t\t{\n\t\t\tm_videoSettingsButton->Show();\n\t\t}\n\n\t\tloaderIndicator->Stop();\n\t\tcommon::transition::DoReverse(0.0f, loaderPlane, common::transition::Type_FadeinFast, true, false);\n\t\tEnableInput();\n\n\t\tmenu::Settings::GetAppSetInstance()->GetInt(\"yt_min\", &min, 0);\n\t\tif (min)\n\t\t{\n\t\t\tm_player->SetScale(0.5f);\n\t\t\tif (SCE_PAF_IS_DOLCE)\n\t\t\t{\n\t\t\t\tm_player->SetPosition(26.0f, -158.0f);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tm_player->SetPosition(13.0f, -79.0f);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_player->SetPosition(0.0f, 0.0f);\n\t\t\tm_root->Hide();\n\t\t}\n\t\tbreak;\n\tcase PlayerSimple::PlayerEvent_InitFail:\n\t\tdelete m_player;\n\t\tm_player = NULL;\n\n\t\t//if (m_lastAttempt)\n\t\t{\n\t\t\t//m_lastAttempt = false;\n\n\t\t\tui::BusyIndicator *loaderIndicator = static_cast<ui::BusyIndicator *>(m_root->FindChild(busyindicator_youtube_loader));\n\t\t\tui::Widget *loaderPlane = m_root->FindChild(plane_youtube_loader);\n\n\t\t\tloaderIndicator->Stop();\n\t\t\tcommon::transition::DoReverse(0.0f, loaderPlane, common::transition::Type_FadeinFast, true, false);\n\t\t\tEnableInput();\n\n\t\t\tm_favButton->Disable(false);\n\t\t\tm_expandButton->Disable(false);\n\t\t\tm_videoSettingsButton->Disable(false);\n\n\t\t\tdialog::OpenError(g_appPlugin, SCE_ERROR_ERRNO_EUNSUP, Framework::Instance()->GetCommonString(\"msg_error_connect_server_peer\"));\n\t\t}\n\t\t//else\n\t\t//{\n\t\t//\tutils::SetDisplayResolution(ui::EnvironmentParam::RESOLUTION_HD_FULL);\n\t\t//\tm_lastAttempt = true;\n\t\t//\tLoadJob *job = new LoadJob(this);\n\t\t//\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\t\t//\tutils::GetJobQueue()->Enqueue(itemParam);\n\t\t//}\n\t\tbreak;\n\t}\n}\n\nvoid menu::PlayerYoutube::OnSettingsEvent(int32_t type)\n{\n\tSCE_DBG_LOG_INFO(\"[OnSettingsEvent] Event: %d\", type);\n\n\tif (type == Settings::SettingsEvent_Close)\n\t{\n\t\tmenu::GetMenuAt(menu::GetMenuCount() - 2)->EnableInput();\n\t}\n\telse if (type == Settings::SettingsEvent_ValueChange)\n\t{\n\t\t\n\t}\n}\n\nmenu::PlayerYoutube::PlayerYoutube(const char *id, bool isFavourite) :\n\tGenericMenu(\"page_youtube_player\",\n\tMenuOpenParam(false, 200.0f, Plugin::TransitionType_SlideFromBottom),\n\tMenuCloseParam(false, 200.0f, Plugin::TransitionType_SlideFromBottom))\n{\n\tm_player = NULL;\n\tm_videoId = id;\n\tm_isLive = false;\n\tm_isFav = isFavourite;\n\tm_companelRoot = NULL;\n\tm_liveCommentThread = NULL;\n\tm_option = NULL;\n\n\tm_root->AddEventCallback(OptionMenu::OptionMenuEvent,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnOptionMenuEvent(e->GetValue(0), e->GetValue(1));\n\t}, this);\n\n\tm_root->AddEventCallback(Settings::SettingsEvent,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnSettingsEvent(e->GetValue(0));\n\t}, this);\n\n\tm_root->AddEventCallback(PlayerSimple::PlayerSimpleEvent,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnPlayerEvent(e->GetValue(0));\n\t}, this);\n\n\tm_root->AddEventCallback(Downloader::DownloaderEvent,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnDwAddComplete(e->GetValue(0));\n\t}, this);\n\n\tui::BusyIndicator *loaderIndicator = static_cast<ui::BusyIndicator *>(m_root->FindChild(busyindicator_youtube_loader));\n\tloaderIndicator->Start();\n\n\tui::Widget *settingsButton = m_root->FindChild(button_settings_page_youtube_player);\n\tsettingsButton->Show(common::transition::Type_Reset);\n\tsettingsButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnSettingsButton();\n\t}, this);\n\n\tui::Widget *backButton = m_root->FindChild(button_back_page_youtube_player);\n\tbackButton->Show(common::transition::Type_Reset);\n\tbackButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnBackButton();\n\t}, this);\n\n\tm_title = static_cast<ui::Text *>(m_root->FindChild(text_video_title));\n\tm_stat0 = static_cast<ui::Text *>(m_root->FindChild(text_video_stat_0));\n\tm_stat1 = static_cast<ui::Text *>(m_root->FindChild(text_video_stat_1));\n\tm_stat2 = static_cast<ui::Text *>(m_root->FindChild(text_video_stat_2));\n\n\tm_expandButton = static_cast<ui::Button *>(m_root->FindChild(button_youtube_expand));\n\tm_expandButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnExpandButton();\n\t}, this);\n\n\tm_videoSettingsButton = static_cast<ui::Button *>(m_root->FindChild(button_youtube_settings));\n\tm_videoSettingsButton->Hide();\n\tm_videoSettingsButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnVideoSettingsButton();\n\t}, this);\n\n\tm_favButton = static_cast<ui::Button *>(m_root->FindChild(button_youtube_fav));\n\tm_favButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnFavButton();\n\t}, this);\n\n\tif (m_isFav)\n\t{\n\t\tintrusive_ptr<graph::Surface> favIcon = g_appPlugin->GetTexture(tex_yt_icon_favourite_for_player_glow);\n\t\tm_favButton->SetTexture(favIcon);\n\t}\n\tm_companelBase = m_root->FindChild(plane_youtube_companel_base);\n\tm_commentButton = m_root->FindChild(button_yt_companel_comment);\n\tm_commentButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnCommentButton();\n\t}, this);\n\n\tm_descButton = m_root->FindChild(button_yt_companel_description);\n\tm_descButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::PlayerYoutube *>(userdata)->OnDescButton();\n\t}, this);\n\n\tDisableInput();\n\n\tLoadJob *job = new LoadJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nmenu::PlayerYoutube::~PlayerYoutube()\n{\n\tif (m_liveCommentThread)\n\t{\n\t\tm_liveCommentThread->Cancel();\n\t\tm_liveCommentThread->Join();\n\t\tdelete m_liveCommentThread;\n\t}\n\n\tif (m_companelRoot)\n\t{\n\t\tm_companelRoot->SetName((uint32_t)0);\n\t}\n\n\tif (m_option)\n\t{\n\t\tdelete m_option;\n\t}\n}"
  },
  {
    "path": "NetStream/source/menus/menu_server.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"dialog.h\"\n#include \"players/player_beav.h\"\n#include \"browsers/generic_server_browser.h\"\n#include \"option_menu.h\"\n#include \"menus/menu_server.h\"\n#include \"menus/menu_settings.h\"\n#include \"menus/menu_player_simple.h\"\n\nusing namespace paf;\n\nvoid menu::GenericServerMenu::OnPlayerEvent(int32_t type)\n{\n\tswitch (type)\n\t{\n\tcase PlayerSimple::PlayerEvent_Back:\n\t\tdelete m_player;\n\t\tbreak;\n\tcase PlayerSimple::PlayerEvent_InitOk:\n\n\t\tbreak;\n\tcase PlayerSimple::PlayerEvent_InitFail:\n\t\tm_playerFailed = true;\n\t\tdialog::OpenError(g_appPlugin, SCE_ERROR_ERRNO_EUNSUP, Framework::Instance()->GetCommonString(\"msg_error_load_file\"));\n\t\tdelete m_player;\n\t\tbreak;\n\t}\n}\n\nvoid menu::GenericServerMenu::OnBackButton()\n{\n\tPopBrowserPage();\n\tif (m_pageList.empty())\n\t{\n\t\tdelete this;\n\t}\n}\n\nvoid menu::GenericServerMenu::OnPlayerCreateTimeout(GenericServerBrowser::Entry *entry)\n{\n\tstring url;\n\tGenericPlayer::Option *opt = NULL;\n\tm_browser->GetInfoForPlayer(entry->ref, url, &opt);\n\tm_player = new menu::PlayerSimple(url.c_str(), opt);\n}\n\nvoid menu::GenericServerMenu::OnListButton(ui::Widget *wdg)\n{\n\tBrowserPage *workPage = m_pageList.back();\n\tGenericServerBrowser::Entry *entry = workPage->m_itemList->at(wdg->GetName().GetIDHash());\n\n\tif (entry->type == GenericServerBrowser::Entry::Type_Folder || entry->type == GenericServerBrowser::Entry::Type_PlaylistFile)\n\t{\n\t\tPushBrowserPage(&entry->ref);\n\t}\n\telse if (entry->type == GenericServerBrowser::Entry::Type_SupportedFile)\n\t{\n\t\tif (SCE_PAF_IS_DOLCE)\n\t\t{\n\t\t\tutils::SetDisplayResolution(ui::EnvironmentParam::RESOLUTION_HD_FULL);\n\t\t\tutils::SetTimeout(\n\t\t\t[](void *userdata1, void *userdata2)\n\t\t\t{\n\t\t\t\treinterpret_cast<menu::GenericServerMenu *>(userdata1)->OnPlayerCreateTimeout(reinterpret_cast<GenericServerBrowser::Entry *>(userdata2));\n\t\t\t}, 10.0f, this, entry);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tOnPlayerCreateTimeout(entry);\n\t\t}\n\t}\n}\n\nvoid menu::GenericServerMenu::OnSettingsButton()\n{\n\tvector<OptionMenu::Button> buttons;\n\tOptionMenu::Button bt;\n\tbt.label = g_appPlugin->GetString(msg_settings);\n\tbuttons.push_back(bt);\n\n\tnew OptionMenu(g_appPlugin, m_root, &buttons);\n}\n\nvoid menu::GenericServerMenu::OnOptionMenuEvent(int32_t type)\n{\n\tif (type == OptionMenu::OptionMenuEvent_Close)\n\t{\n\t\treturn;\n\t}\n\n\tmenu::SettingsButtonCbFun(ui::Button::CB_BTN_DECIDE, NULL, 0, NULL);\n}\n\nui::ListItem *menu::GenericServerMenu::CreateListItem(ui::listview::ItemFactory::CreateParam& param)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\tui::Widget *item = NULL;\n\twstring text16;\n\n\tif (!param.list_view->GetName().GetIDHash())\n\t{\n\t\treturn new ui::ListItem(param.parent, 0);\n\t}\n\n\tBrowserPage *workPage = m_pageList.back();\n\n\tGenericServerBrowser::Entry *entry = workPage->m_itemList->at(param.cell_index);\n\tui::Widget *targetRoot = param.parent;\n\n\tg_appPlugin->TemplateOpen(targetRoot, template_list_item_generic, tmpParam);\n\titem = targetRoot->GetChild(targetRoot->GetChildrenNum() - 1);\n\n\tui::Widget *button = item->FindChild(image_button_list_item);\n\tbutton->SetName(param.cell_index);\n\n\tif (entry->displayName.empty())\n\t{\n\t\tcommon::Utf8ToUtf16(entry->ref, &text16);\n\t}\n\telse\n\t{\n\t\tcommon::Utf8ToUtf16(entry->displayName, &text16);\n\t}\n\tbutton->SetString(text16);\n\tbutton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::GenericServerMenu *>(userdata)->OnListButton(static_cast<ui::Widget *>(self));\n\t}, this);\n\n\tuint32_t texid = 0;\n\tswitch (entry->type)\n\t{\n\tdefault:\n\tcase GenericServerBrowser::Entry::Type_UnsupportedFile:\n\t\ttexid = tex_file_icon_unsupported;\n\t\tbreak;\n\tcase GenericServerBrowser::Entry::Type_SupportedFile:\n\t\ttexid = tex_file_icon_video;\n\t\tbreak;\n\tcase GenericServerBrowser::Entry::Type_Folder:\n\t\ttexid = tex_file_icon_folder;\n\t\tbreak;\n\tcase GenericServerBrowser::Entry::Type_PlaylistFile:\n\t\ttexid = tex_file_icon_playlist;\n\t\tbreak;\n\t}\n\n\tintrusive_ptr<graph::Surface> tex = g_appPlugin->GetTexture(texid);\n\tif (tex.get())\n\t{\n\t\tbutton->SetTexture(tex);\n\t}\n\n\treturn static_cast<ui::ListItem *>(item);\n}\n\nvoid menu::GenericServerMenu::OnConnectionFailedDialogEvent()\n{\n\tif (m_playerFailed)\n\t{\n\t\tm_playerFailed = false;\n\t\treturn;\n\t}\n\n\tPopBrowserPage();\n\tmenu::SettingsButtonCbFun(ui::Button::CB_BTN_DECIDE, NULL, 0, NULL);\n\tif (m_pageList.empty())\n\t{\n\t\tdelete this;\n\t}\n\tmenu::GenericMenu *topMenu = menu::GetTopMenu();\n\tif (topMenu)\n\t{\n\t\ttopMenu->DisableInput();\n\t}\n}\n\nvoid menu::GenericServerMenu::GoTo(const string& ref)\n{\n\tint32_t ret = SCE_OK;\n\tstring currentPath;\n\twstring text16;\n\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tm_loaderIndicator->Start();\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\tBrowserPage *workPage = m_pageList.back();\n\n\tif (ref.length() == 0)\n\t{\n\t\tworkPage->m_itemList = m_browser->GoTo(NULL, &ret);\n\t}\n\telse\n\t{\n\t\tworkPage->m_itemList = m_browser->GoTo(ref.c_str(), &ret);\n\t}\n\tif (ret != SCE_OK)\n\t{\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t\tm_loaderIndicator->Stop();\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t\tworkPage->m_isLoaded = true;\n\t\tdialog::OpenError(g_appPlugin, ret, Framework::Instance()->GetCommonString(\"msg_error_connect_server_peer\"));\n\t\treturn;\n\t}\n\tif (m_firstBoot)\n\t{\n\t\tui::Widget *backButton = m_root->FindChild(button_back_page_server_generic);\n\t\tui::Widget *settingsButton = m_root->FindChild(button_settings_page_server_generic);\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t\tbackButton->Show(common::transition::Type_Reset);\n\t\tsettingsButton->Show(common::transition::Type_Reset);\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t\tm_firstBoot = false;\n\t}\n\n\tcurrentPath = m_browser->GetPath();\n\tif (GetMenuType() == MenuType_Local)\n\t{\n\t\tutils::SafememWrite(currentPath);\n\t}\n\tcommon::Utf8ToUtf16(currentPath, &text16);\n\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tm_loaderIndicator->Stop();\n\tworkPage->m_list->InsertCell(0, 0, workPage->m_itemList->size());\n\tm_topText->SetString(text16);\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\tworkPage->m_isLoaded = true;\n}\n\nmenu::GenericServerMenu::GenericServerMenu() :\n\tGenericMenu(\"page_server_generic\",\n\tMenuOpenParam(false, 200.0f, Plugin::TransitionType_SlideFromBottom),\n\tMenuCloseParam(false, 200.0f, Plugin::TransitionType_SlideFromBottom))\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\tm_firstBoot = true;\n\tm_playerFailed = false;\n\n\tm_root->AddEventCallback(dialog::DialogEvent,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::GenericServerMenu *>(userdata)->OnConnectionFailedDialogEvent();\n\t}, this);\n\n\tm_root->AddEventCallback(OptionMenu::OptionMenuEvent,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::GenericServerMenu *>(userdata)->OnOptionMenuEvent(e->GetValue(0));\n\t}, this);\n\n\tm_root->AddEventCallback(PlayerSimple::PlayerSimpleEvent,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::GenericServerMenu *>(userdata)->OnPlayerEvent(e->GetValue(0));\n\t}, this);\n\n\tui::Widget *settingsButton = m_root->FindChild(button_settings_page_server_generic);\n\tsettingsButton->Hide(common::transition::Type_Reset);\n\tsettingsButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::GenericServerMenu *>(userdata)->OnSettingsButton();\n\t}, this);\n\n\tui::Widget *backButton = m_root->FindChild(button_back_page_server_generic);\n\tbackButton->Hide(common::transition::Type_Reset);\n\tbackButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<menu::GenericServerMenu *>(userdata)->OnBackButton();\n\t}, this);\n\n\tm_browserRoot = m_root->FindChild(plane_browser_root_page_server_generic);\n\tm_loaderIndicator = static_cast<ui::BusyIndicator *>(m_root->FindChild(busyindicator_loader_page_server_generic));\n\tm_topText = static_cast<ui::Text *>(m_root->FindChild(text_top));\n}\n\nmenu::GenericServerMenu::~GenericServerMenu()\n{\n\twhile (PopBrowserPage())\n\t{\n\n\t}\n\n\tdelete m_browser;\n}\n\nbool menu::GenericServerMenu::PushBrowserPage(string *ref)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\n\tBrowserPage *page = new BrowserPage();\n\n\tg_appPlugin->TemplateOpen(m_browserRoot, template_list_view_generic, tmpParam);\n\tpage->m_list = static_cast<ui::ListView *>(m_browserRoot->GetChild(m_browserRoot->GetChildrenNum() - 1));\n\tListViewCb *lwCb = new ListViewCb(this);\n\tpage->m_list->SetItemFactory(lwCb);\n\tpage->m_list->InsertSegment(0, 1);\n\tmath::v4 sz(960.0f, 80.0f);\n\tpage->m_list->SetCellSizeDefault(0, sz);\n\tpage->m_list->SetSegmentLayoutType(0, ui::ListView::LAYOUT_TYPE_LIST);\n\n\tBrowserPage *wp;\n\tif (!m_pageList.empty()) {\n\t\tif (m_pageList.size() > 1) {\n\t\t\twp = m_pageList.rbegin()[1];\n\t\t\twp->m_list->Hide(common::transition::Type_Reset);\n\t\t\twp->m_list->SetTransitionComplete(false);\n\t\t}\n\t\twp = m_pageList.back();\n\t\twp->m_list->Show(common::transition::Type_3D_SlideToBack1);\n\t\twp->m_list->SetTransitionComplete(false);\n\t}\n\n\tm_pageList.push_back(page);\n\n\tGoToJob *job = new GoToJob(this);\n\tif (ref)\n\t{\n\t\tjob->SetRef(*ref);\n\t}\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tutils::GetJobQueue()->Enqueue(itemParam);\n\n\treturn true;\n}\n\nbool menu::GenericServerMenu::PopBrowserPage()\n{\n\tBrowserPage *pageToPop;\n\tbool isLastPage = false;\n\n\tif (m_pageList.empty())\n\t{\n\t\treturn false;\n\t}\n\telse if (m_pageList.size() == 1)\n\t{\n\t\tisLastPage = true;\n\t}\n\n\tpageToPop = m_pageList.back();\n\twhile (!pageToPop->m_isLoaded)\n\t{\n\t\tthread::Sleep(10);\n\t}\n\n\tpageToPop->m_list->SetName(static_cast<uint32_t>(0));\n\n\tif (!isLastPage)\n\t{\n\t\tcommon::transition::DoReverse(-100.0f, pageToPop->m_list, common::transition::Type_3D_SlideFromFront, true, false);\n\t}\n\n\tfor (int i = 0; i < pageToPop->m_itemList->size(); i++)\n\t{\n\t\tdelete pageToPop->m_itemList->at(i);\n\t}\n\n\tdelete pageToPop->m_itemList;\n\tdelete pageToPop;\n\tm_pageList.pop_back();\n\n\tif (!isLastPage)\n\t{\n\t\tBrowserPage *wp;\n\t\tif (!m_pageList.empty()) {\n\t\t\twp = m_pageList.back();\n\t\t\twp->m_list->Hide(common::transition::Type_3D_SlideToBack1);\n\t\t\twp->m_list->Show(common::transition::Type_Reset);\n\t\t\twp->m_list->SetTransitionComplete(false);\n\t\t\tif (m_pageList.size() > 1) {\n\t\t\t\twp = m_pageList.rbegin()[1];\n\t\t\t\twp->m_list->Show(common::transition::Type_Reset);\n\t\t\t\twp->m_list->SetTransitionComplete(false);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!isLastPage)\n\t{\n\t\tm_browser->SetPath(\"..\");\n\t\tstring currentPath = m_browser->GetPath();\n\t\twstring text16;\n\t\tcommon::Utf8ToUtf16(currentPath, &text16);\n\t\tm_topText->SetString(text16);\n\t}\n\n\treturn true;\n}"
  },
  {
    "path": "NetStream/source/menus/menu_settings.cpp",
    "content": "#include <kernel.h>\n#include <appmgr.h>\n#include <stdlib.h>\n#include <string.h>\n#include <paf.h>\n#include <audioout.h>\n#include <shellaudio.h>\n#include <libsysmodule.h>\n#include <libdbg.h>\n#include <bxce.h>\n#include <app_settings.h>\n#include <ini_file_processor.h>\n\n#include \"common.h\"\n#include \"menus/menu_settings.h\"\n#include \"menus/menu_generic.h\"\n#include \"players/player_fmod.h\"\n#include \"players/player_av.h\"\n#include \"players/player_beav.h\"\n#include \"utils.h\"\n#include \"event.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[Settings]\"\n\n#define WIDE2(x) L##x\n#define WIDE(x) WIDE2(x)\n\nusing namespace paf;\nusing namespace sce;\n\nconst int32_t k_settingsVersion = 23;\n\nstatic sce::AppSettings *s_appSet = NULL;\nstatic menu::Settings *s_instance = NULL;\nstatic wchar_t *s_verinfo = NULL;\n\nvoid menu::Settings::Init()\n{\n\tint32_t ret;\n\tsize_t fsize = 0;\n\tconst char *fmime = NULL;\n\tPlugin::InitParam pluginParam;\n\tAppSettings::InitParam sparam;\n\n\tpluginParam.name = \"app_settings_plugin\";\n\tpluginParam.resource_file = \"vs0:vsh/common/app_settings_plugin.rco\";\n\tpluginParam.module_file = \"vs0:vsh/common/app_settings.suprx\";\n\tpluginParam.caller_name = \"__main__\";\n\tpluginParam.set_param_func = AppSettings::PluginSetParamCB;\n\tpluginParam.init_func = AppSettings::PluginInitCB;\n\tpluginParam.start_func = AppSettings::PluginStartCB;\n\tpluginParam.stop_func = AppSettings::PluginStopCB;\n\tpluginParam.exit_func = AppSettings::PluginExitCB;\n\tpluginParam.draw_priority = 0x96;\n\n\tPlugin::LoadSync(pluginParam);\n\n\tsparam.xml_file = g_appPlugin->GetResource()->GetFile(file_netstream_settings, &fsize, &fmime);\n\tsparam.alloc_cb = sce_paf_malloc;\n\tsparam.free_cb = sce_paf_free;\n\tsparam.realloc_cb = sce_paf_realloc;\n\tsparam.safemem_offset = 0;\n\tsparam.safemem_size = utils::SafememGetSettingsSize();\n\n\tsce::AppSettings::GetInstance(sparam, &s_appSet);\n\n\tret = -1;\n\ts_appSet->GetInt(\"settings_version\", &ret, 0);\n\tif (ret != k_settingsVersion) {\n\t\tret = s_appSet->Initialize();\n\t\ts_appSet->SetInt(\"settings_version\", k_settingsVersion);\n\t}\n\n\tstring verinfo8;\n\twstring *verinfo16 = new wstring();\n\n\tcurl_version_info_data *curlInfo = curl_version_info(CURLVERSION_NOW);\n\n#ifdef _DEBUG\n\tverinfo8 = \"DEBUG \";\n#else\n\tverinfo8 = \"RELEASE \";\n#endif\n\tverinfo8 += __DATE__;\n\tverinfo8 += \" v 3.35\";\n\tverinfo8 += \"\\n\\nComponents:\\n\\n\";\n\tverinfo8 += \"libcurl: \";\n\tverinfo8 += curlInfo->version;\n\t/*\n\tverinfo8 += \"\\nAVPlayer: \";\n\tverinfo8 += AVPlayer::GetVersion();\n\tverinfo8 += \"\\nBEAVPlayer: \";\n\tverinfo8 += BEAVPlayer::GetVersion();\n\tverinfo8 += \"\\nFMOD: \";\n\tverinfo8 += FMODPlayer::GetVersion();\n\t*/\n\tcommon::Utf8ToUtf16(verinfo8, verinfo16);\n\ts_verinfo = verinfo16->c_str();\n}\n\nmenu::Settings::~Settings()\n{\n\tmenu::GenericMenu *topMenu = menu::GetTopMenu();\n\tif (topMenu) {\n\t\ttopMenu->Activate();\n\t}\n\n\tevent::BroadcastGlobalEvent(g_appPlugin, SettingsEvent, SettingsEvent_Close);\n\n\ts_instance = NULL;\n}\n\nmenu::Settings::Settings()\n{\n\tif (s_instance)\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[Settings] Attempt to create second singleton instance\\n\");\n\t\treturn;\n\t}\n\n\tmenu::GenericMenu *topMenu = menu::GetTopMenu();\n\tif (topMenu)\n\t{\n\t\ttopMenu->DisableInput();\n\t}\n\n\tAppSettings::InterfaceCallbacks ifCb;\n\n\tifCb.onStartPageTransitionCb = CBOnStartPageTransition;\n\tifCb.onPageActivateCb = CBOnPageActivate;\n\tifCb.onPageDeactivateCb = CBOnPageDeactivate;\n\tifCb.onCheckVisible = CBOnCheckVisible;\n\tifCb.onPreCreateCb = CBOnPreCreate;\n\tifCb.onPostCreateCb = CBOnPostCreate;\n\tifCb.onPressCb = CBOnPress;\n\tifCb.onPressCb2 = CBOnPress2;\n\tifCb.onTermCb = CBOnTerm;\n\tifCb.onGetStringCb = CBOnGetString;\n\tifCb.onGetSurfaceCb = CBOnGetSurface;\n\n\tPlugin *appSetPlug = paf::Plugin::Find(\"app_settings_plugin\");\n\tconst AppSettings::Interface *appSetIf = static_cast<const sce::AppSettings::Interface *>(appSetPlug->GetInterface(1));\n\tappSetIf->Show(&ifCb);\n\n\ts_instance = this;\n}\n\nvoid menu::Settings::CBOnStartPageTransition(const char *elementId, int32_t type)\n{\n\n}\n\nvoid menu::Settings::CBOnPageActivate(const char *elementId, int32_t type)\n{\n\n}\n\nvoid menu::Settings::CBOnPageDeactivate(const char *elementId, int32_t type)\n{\n\n}\n\nint32_t menu::Settings::CBOnCheckVisible(const char *elementId, bool *pIsVisible)\n{\n\t*pIsVisible = false;\n\n\tif (sce_paf_strstr(elementId, \"_setting\"))\n\t{\n\t\tif (!sce_paf_strcmp(elementId, \"verinfo_setting\"))\n\t\t{\n\t\t\t*pIsVisible = true;\n\t\t\treturn SCE_OK;\n\t\t}\n\n\t\tint32_t supportedItemsCount = 0;\n\t\tuint32_t elementHash = utils::GetHash(elementId);\n\t\tconst uint32_t *supportedItems = menu::GetTopMenu()->GetSupportedSettingsItems(&supportedItemsCount);\n\n\t\tfor (int i = 0; i < supportedItemsCount; i++)\n\t\t{\n\t\t\tif (supportedItems[i] == elementHash)\n\t\t\t{\n\t\t\t\t*pIsVisible = true;\n\t\t\t\treturn SCE_OK;\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\t*pIsVisible = true;\n\t}\n\n\treturn SCE_OK;\n}\n\nint32_t menu::Settings::CBOnPreCreate(const char *elementId, sce::AppSettings::Element *element)\n{\n\treturn SCE_OK;\n}\n\nint32_t menu::Settings::CBOnPostCreate(const char *elementId, paf::ui::Widget *widget)\n{\n\treturn SCE_OK;\n}\n\nint32_t menu::Settings::CBOnPress(const char *elementId, const char *newValue)\n{\n\tint32_t ret = SCE_OK;\n\tIDParam elem(elementId);\n\tIDParam val(newValue);\n\n\tevent::BroadcastGlobalEvent(g_appPlugin, SettingsEvent, SettingsEvent_ValueChange, elem.GetIDHash(), val.GetIDHash(), newValue[0] - '0');\n\n\treturn ret;\n}\n\nint32_t menu::Settings::CBOnPress2(const char *elementId, const char *newValue)\n{\n\treturn SCE_OK;\n}\n\nvoid menu::Settings::CBOnTerm(int32_t result)\n{\n\tdelete s_instance;\n}\n\nwchar_t *menu::Settings::CBOnGetString(const char *elementId)\n{\n\twchar_t *res = g_appPlugin->GetString(elementId);\n\n\tif (res[0] == 0)\n\t{\n\t\tif (!sce_paf_strcmp(elementId, \"msg_verinfo\"))\n\t\t{\n\t\t\treturn s_verinfo;\n\t\t}\n\t}\n\n\treturn res;\n}\n\nint32_t menu::Settings::CBOnGetSurface(graph::Surface **surf, const char *elementId)\n{\n\treturn SCE_OK;\n}\n\nmenu::Settings *menu::Settings::GetInstance()\n{\n\treturn s_instance;\n}\n\nAppSettings *menu::Settings::GetAppSetInstance()\n{\n\treturn s_appSet;\n}"
  },
  {
    "path": "NetStream/source/menus/menu_youtube.cpp",
    "content": "#include <kernel.h>\n#include <appmgr.h>\n#include <stdlib.h>\n#include <string.h>\n#include <libdbg.h>\n#include <paf.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"yt_utils.h\"\n#include \"np_utils.h\"\n#include \"dialog.h\"\n#include \"tex_pool.h\"\n#include \"ftube.h\"\n#include <paf_file_ext.h>\n#include \"option_menu.h\"\n#include \"menus/menu_generic.h\"\n#include \"menus/menu_youtube.h\"\n#include \"menus/menu_player_youtube.h\"\n#include \"menus/menu_settings.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[YouTube]\"\n\nusing namespace paf;\n\nmenu::YouTube::Submenu::Submenu(YouTube *parentObj)\n{\n\tm_currentPage = 0;\n\tm_baseParent = parentObj;\n\tm_interrupted = false;\n\tm_allJobsComplete = true;\n}\n\nmenu::YouTube::Submenu::~Submenu()\n{\n\tm_list->SetName(static_cast<uint32_t>(0));\n\tReleaseCurrentPage();\n\tcommon::transition::DoReverse(0.0f, m_submenuRoot, common::transition::Type_FadeinFast, true, false);\n}\n\nvoid menu::YouTube::Submenu::ReleaseCurrentPage()\n{\n\tm_interrupted = true;\n\twhile (!m_allJobsComplete)\n\t{\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t\tthread::Sleep(10);\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t}\n\tm_interrupted = false;\n\n\tif (m_list->GetCellNum(0) > 0)\n\t{\n\t\tm_list->DeleteCell(0, 0, m_list->GetCellNum(0));\n\t}\n\n\tm_baseParent->m_texPool->SetAlive(false);\n\tm_baseParent->m_texPool->AddAsyncCancelPending();\n\tm_baseParent->m_texPool->RemoveAll();\n\tm_baseParent->m_texPool->SetAlive(true);\n\n\tm_results.clear();\n}\n\nvoid menu::YouTube::Submenu::OnListButton(ui::Widget *wdg)\n{\n\tuint32_t totalCount = m_results.size();\n\tuint32_t idhash = wdg->GetName().GetIDHash();\n\n\tif (m_currentPage == 0)\n\t{\n\t\tif (idhash == totalCount)\n\t\t{\n\t\t\tGoToNextPage();\n\t\t\treturn;\n\t\t}\n\t}\n\telse\n\t{\n\t\tif (idhash == totalCount)\n\t\t{\n\t\t\tGoToPrevPage();\n\t\t\treturn;\n\t\t}\n\t\telse if (idhash == totalCount + 1)\n\t\t{\n\t\t\tGoToNextPage();\n\t\t\treturn;\n\t\t}\n\t}\n\n\tSubmenu::Item item = m_results.at(idhash);\n\n\tswitch (item.type)\n\t{\n\tcase FT_ITEM_TYPE_VIDEO:\n\t\tytutils::GetHistLog()->AddAsync(item.videoId.c_str());\n\t\tutils::SetDisplayResolution(ui::EnvironmentParam::RESOLUTION_HD_FULL);\n\t\tnew menu::PlayerYoutube(item.videoId.c_str(), GetType() == Submenu::SubmenuType_Favourites);\n\t\tbreak;\n\t}\n}\n\nvoid menu::YouTube::Submenu::OnTexPoolAdd(int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n{\n\tItem *workItem = static_cast<Item *>(userdata);\n\tui::Button *button = static_cast<ui::Button *>(self);\n\n\tif (e->GetValue(0) == workItem->texId.GetIDHash())\n\t{\n\t\tbutton->SetTexture(workItem->texPool->Get(workItem->texId));\n\t\tbutton->DeleteEventCallback(ui::Handler::CB_STATE_READY_CACHEIMAGE, OnTexPoolAdd, userdata);\n\t}\n}\n\nui::ListItem *menu::YouTube::Submenu::CreateListItem(ui::listview::ItemFactory::CreateParam& param)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\tui::Widget *item = NULL;\n\tui::Widget *button = NULL;\n\tui::Text *timeText = NULL;\n\tui::Widget *subText = NULL;\n\twstring text16;\n\twchar_t numPageText[32];\n\n\tif (!param.list_view->GetName().GetIDHash())\n\t{\n\t\treturn new ui::ListItem(param.parent, 0);\n\t}\n\n\tui::Widget *targetRoot = param.parent;\n\tuint32_t totalCount = m_results.size();\n\n\tif (param.cell_index == totalCount || param.cell_index == totalCount + 1)\n\t{\n\t\tg_appPlugin->TemplateOpen(targetRoot, template_list_item_youtube_aligned, tmpParam);\n\t\titem = targetRoot->GetChild(targetRoot->GetChildrenNum() - 1);\n\t\tbutton = item->FindChild(image_button_list_item_youtube_aligned);\n\t}\n\telse\n\t{\n\t\tg_appPlugin->TemplateOpen(targetRoot, template_list_item_youtube, tmpParam);\n\t\titem = targetRoot->GetChild(targetRoot->GetChildrenNum() - 1);\n\t\tbutton = item->FindChild(image_button_list_item_youtube);\n\t}\n\n\tbutton->SetName(param.cell_index);\n\n\tintrusive_ptr<graph::Surface> tex;\n\n\tif (param.cell_index == totalCount)\n\t{\n\t\tif (m_currentPage == 0)\n\t\t{\n\t\t\ttext16 = g_appPlugin->GetString(msg_next_page);\n\t\t\tsce_paf_swprintf(numPageText, sizeof(numPageText) / 2, L\" (%d)\", m_currentPage + 1 + 1);\n\t\t\ttext16 += numPageText;\n\t\t\tbutton->SetString(text16);\n\t\t\ttex = g_appPlugin->GetTexture(tex_button_arrow_right);\n\t\t\tbutton->SetTexture(tex);\n\t\t\tgoto serviceButton;\n\t\t}\n\t\telse\n\t\t{\n\t\t\ttext16 = g_appPlugin->GetString(msg_previous_page);\n\t\t\tsce_paf_swprintf(numPageText, sizeof(numPageText) / 2, L\" (%d)\", m_currentPage + 1 - 1);\n\t\t\ttext16 += numPageText;\n\t\t\tbutton->SetString(text16);\n\t\t\ttex = g_appPlugin->GetTexture(tex_button_arrow_left);\n\t\t\tbutton->SetTexture(tex);\n\t\t\tgoto serviceButton;\n\t\t}\n\t}\n\telse if (param.cell_index == totalCount + 1)\n\t{\n\t\ttext16 = g_appPlugin->GetString(msg_next_page);\n\t\tsce_paf_swprintf(numPageText, sizeof(numPageText) / 2, L\" (%d)\", m_currentPage + 1 + 1);\n\t\ttext16 += numPageText;\n\t\tbutton->SetString(text16);\n\t\ttex = g_appPlugin->GetTexture(tex_button_arrow_right);\n\t\tbutton->SetTexture(tex);\n\t\tgoto serviceButton;\n\t}\n\n\tItem *workItem = &m_results.at(param.cell_index);\n\ttimeText = static_cast<ui::Text *>(button->FindChild(text_list_item_youtube_time));\n\tsubText = button->FindChild(text_list_item_youtube_subtext);\n\tif (workItem->time == L\"LIVE\")\n\t{\n\t\tmath::v4 col(1.0f, 0.0f, 0.0f, 0.5f);\n\t\ttimeText->SetStyleAttribute(graph::TextStyleAttribute_BackColor, 0, 0, col);\n\t}\n\ttimeText->SetString(workItem->time);\n\tsubText->SetString(workItem->stat);\n\tbutton->SetString(workItem->name);\n\tif (m_baseParent->m_texPool->Exist(workItem->texId))\n\t{\n\t\tbutton->SetTexture(m_baseParent->m_texPool->Get(workItem->texId));\n\t}\n\telse\n\t{\n\t\tworkItem->texPool = m_baseParent->m_texPool;\n\t\tbutton->AddEventCallback(ui::Handler::CB_STATE_READY_CACHEIMAGE, OnTexPoolAdd, workItem);\n\t\tm_baseParent->m_texPool->AddAsync(workItem->texId, workItem->texId.GetID().c_str());\n\t}\n\nserviceButton:\n\n\tbutton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<Submenu *>(userdata)->OnListButton(static_cast<ui::Widget *>(self));\n\t}, this);\n\n\treturn static_cast<ui::ListItem *>(item);\n}\n\nvoid menu::YouTube::SearchSubmenu::Search()\n{\n\tstring text8;\n\tFTItem *ftItem = NULL;\n\tvoid *ftCtx = NULL;\n\tint32_t ret = -1;\n\tbool isId = false;\n\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tm_baseParent->m_loaderIndicator->Start();\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\tSCE_DBG_LOG_INFO(\"[Search] Begin search\");\n\n\tif ((sce_paf_strstr(m_request.c_str(), \"id:\") == m_request.c_str()) && m_request.length() == 14)\n\t{\n\t\tisId = true;\n\t}\n\n\tif (!isId)\n\t{\n\t\tFTSort sort;\n\t\tFTDate date;\n\t\tFTDuration duration;\n\t\tFTFeature feature;\n\t\tconst char *contTmp = NULL;\n\t\tconst char *currentCont = NULL;\n\t\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\t\tsettings->GetInt(\"yt_search_sort\", (int32_t *)&sort, 0);\n\t\tsettings->GetInt(\"yt_search_date\", (int32_t *)&date, 0);\n\t\tsettings->GetInt(\"yt_search_dur\", (int32_t *)&duration, 0);\n\t\tsettings->GetInt(\"yt_search_feature\", (int32_t *)&feature, 0);\n\t\tif (!m_continuations[m_currentPage].empty())\n\t\t{\n\t\t\tcurrentCont = m_continuations[m_currentPage].c_str();\n\t\t}\n\t\tSCE_DBG_LOG_INFO(\"[Search] ftParseSearch(): cont: %s, req: %s\", currentCont, m_request.c_str());\n\t\tret = ftParseSearch(&ftCtx, m_request.c_str(), currentCont, FT_ITEM_TYPE_VIDEO, sort, date, feature, duration, &ftItem, &contTmp);\n\t\tSCE_DBG_LOG_INFO(\"[Search] ftParseSearch(): 0x%08X, current page: %d\", ret, m_currentPage);\n\t\tm_continuations[m_currentPage + 1] = contTmp;\n\t}\n\telse\n\t{\n\t\tret = ftParseVideo(&ftCtx, m_request.c_str() + 3, FT_VIDEO_VOD_QUALITY_NONE, FT_AUDIO_VOD_QUALITY_NONE, &ftItem);\n\t\tif (ret == FT_OK)\n\t\t{\n\t\t\tret = 1;\n\t\t}\n\t}\n\n\tif (ret <= 0)\n\t{\n\t\tdialog::OpenError(g_appPlugin, ret, Framework::Instance()->GetCommonString(\"msg_error_connect_server_peer\"));\n\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t\tm_baseParent->m_loaderIndicator->Stop();\n\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t\tm_allJobsComplete = true;\n\t\treturn;\n\t}\n\n\tdo\n\t{\n\t\tItem item;\n\t\titem.type = ftItem->type;\n\t\tswitch (item.type)\n\t\t{\n\t\tcase FT_ITEM_TYPE_VIDEO:\n\t\t\titem.videoId = ftItem->videoItem->id;\n\t\t\ttext8 = \"\\n\";\n\t\t\ttext8 += ftItem->videoItem->title;\n\t\t\tcommon::Utf8ToUtf16(text8, &item.name);\n\t\t\titem.texId = ftItem->videoItem->thmbUrl;\n\t\t\tif (ftItem->videoItem->isLive || ftItem->videoItem->lengthSec == 0)\n\t\t\t{\n\t\t\t\ttext8 = \"LIVE\";\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tutils::ConvertSecondsToString(text8, ftItem->videoItem->lengthSec, false);\n\t\t\t}\n\t\t\tcommon::Utf8ToUtf16(text8, &item.time);\n\t\t\tif (ftItem->videoItem->author)\n\t\t\t{\n\t\t\t\ttext8 = \"by \";\n\t\t\t\ttext8 += ftItem->videoItem->author;\n\t\t\t}\n\t\t\tif (ftItem->videoItem->published)\n\t\t\t{\n\t\t\t\ttext8 += \"\\n\";\n\t\t\t\ttext8 += ftItem->videoItem->published;\n\t\t\t\tif (ftItem->videoItem->isLive || ftItem->videoItem->lengthSec == 0)\n\t\t\t\t{\n\t\t\t\t\ttext8 += \" watching\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tcommon::Utf8ToUtf16(text8, &item.stat);\n\t\t\tbreak;\n\t\t}\n\n\t\tm_results.push_back(item);\n\n\t\tftItem = ftItem->next;\n\t} while (ftItem);\n\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tm_baseParent->m_loaderIndicator->Stop();\n\tif (m_currentPage == 0)\n\t{\n\t\tif (!isId)\n\t\t{\n\t\t\tm_list->InsertCell(0, 0, m_results.size() + 1);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tm_list->InsertCell(0, 0, m_results.size());\n\t\t}\n\t}\n\telse\n\t{\n\t\tm_list->InsertCell(0, 0, m_results.size() + 2);\n\t}\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\tftCleanup(ftCtx);\n\n\tm_allJobsComplete = true;\n}\n\nvoid menu::YouTube::SearchSubmenu::OnSearchButton()\n{\n\twstring text16;\n\tstring text8;\n\n\tReleaseCurrentPage();\n\tm_searchBox->EndEdit();\n\n\tm_request.clear();\n\tm_searchBox->GetString(text16);\n\tcommon::Utf16ToUtf8(text16, &m_request);\n\n\tif (m_request.empty())\n\t{\n\t\treturn;\n\t}\n\n\tm_currentPage = 0;\n\n\tSearchJob *job = new SearchJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nvoid menu::YouTube::SearchSubmenu::GoToNextPage()\n{\n\tReleaseCurrentPage();\n\tm_currentPage++;\n\n\tSearchJob *job = new SearchJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nvoid menu::YouTube::SearchSubmenu::GoToPrevPage()\n{\n\tReleaseCurrentPage();\n\tm_currentPage--;\n\n\tSearchJob *job = new SearchJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nvoid menu::YouTube::SearchSubmenu::GoToBasePageForSync()\n{\n\t\n}\n\nmenu::YouTube::SearchSubmenu::SearchSubmenu(YouTube *parentObj) : Submenu(parentObj)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\n\tg_appPlugin->TemplateOpen(m_baseParent->m_browserRoot, template_list_view_youtube_search, tmpParam);\n\tm_submenuRoot = m_baseParent->m_browserRoot->FindChild(plane_list_view_youtube_search_root);\n\tm_list = static_cast<ui::ListView *>(m_submenuRoot->FindChild(list_view_youtube));\n\tListViewCb *lwCb = new ListViewCb(this);\n\tm_list->SetItemFactory(lwCb);\n\tm_list->InsertSegment(0, 1);\n\tmath::v4 sz(960.0f, 100.0f);\n\tm_list->SetCellSizeDefault(0, sz);\n\tm_list->SetSegmentLayoutType(0, ui::ListView::LAYOUT_TYPE_LIST);\n\n\tm_searchBox = static_cast<ui::TextBox *>(m_submenuRoot->FindChild(text_box_top_youtube_search));\n\tm_searchButton = m_submenuRoot->FindChild(button_top_youtube_search);\n\n\tm_searchBox->AddEventCallback(ui::TextBox::CB_TEXT_BOX_ENTER_PRESSED,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<SearchSubmenu *>(userdata)->OnSearchButton();\n\t}, this);\n\n\tm_searchButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<SearchSubmenu *>(userdata)->OnSearchButton();\n\t}, this);\n\n\tcommon::transition::Do(0.0f, m_submenuRoot, common::transition::Type_FadeinFast, true, false);\n}\n\nmenu::YouTube::SearchSubmenu::~SearchSubmenu()\n{\n\n}\n\nvoid menu::YouTube::HistorySubmenu::Parse()\n{\n\tstring text8;\n\tchar *entryData;\n\tint32_t sync = 0;\n\tint32_t ret = 0;\n\tFTItem *ftItem = NULL;\n\tvoid *ftCtx = NULL;\n\tchar key[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tm_baseParent->m_loaderIndicator->Start();\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetInt(\"cloud_sync_auto\", static_cast<int32_t *>(&sync), 0);\n\tif (sync)\n\t{\n\t\tytutils::GetHistLog()->UpdateFromTUS();\n\t}\n\n\tytutils::GetHistLog()->Reset();\n\tint32_t totalNum = ytutils::GetHistLog()->GetSize();\n\n\twhile (totalNum > 30)\n\t{\n\t\tytutils::GetHistLog()->GetNext(key);\n\t\tytutils::GetHistLog()->Remove(key);\n\t\tytutils::GetHistLog()->Reset();\n\t\ttotalNum = ytutils::GetHistLog()->GetSize();\n\t}\n\n\tentryData = static_cast<char *>(sce_paf_calloc(totalNum, SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE));\n\n\tfor (int32_t i = 0; i < totalNum; i++)\n\t{\n\t\tytutils::GetHistLog()->GetNext(entryData + (i * SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE));\n\t}\n\n\tfor (int32_t i = totalNum - 1; i >= 0; i--)\n\t{\n\t\tif (m_interrupted)\n\t\t{\n\t\t\tbreak;\n\t\t}\n\n\t\tret = ftParseVideo(&ftCtx, entryData + (i * SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE), FT_VIDEO_VOD_QUALITY_NONE, FT_AUDIO_VOD_QUALITY_NONE, &ftItem);\n\t\tif (ret == SCE_OK)\n\t\t{\n\t\t\tif (ftItem->videoItem->id)\n\t\t\t{\n\t\t\t\tItem item;\n\t\t\t\titem.type = FT_ITEM_TYPE_VIDEO;\n\t\t\t\titem.videoId = ftItem->videoItem->id;\n\t\t\t\ttext8 = \"\\n\";\n\t\t\t\ttext8 += ftItem->videoItem->title;\n\t\t\t\tcommon::Utf8ToUtf16(text8, &item.name);\n\t\t\t\titem.texId = ftItem->videoItem->thmbUrl;\n\t\t\t\tif (ftItem->videoItem->isLive || ftItem->videoItem->lengthSec == 0)\n\t\t\t\t{\n\t\t\t\t\ttext8 = \"LIVE\";\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tutils::ConvertSecondsToString(text8, ftItem->videoItem->lengthSec, false);\n\t\t\t\t}\n\t\t\t\tcommon::Utf8ToUtf16(text8, &item.time);\n\t\t\t\ttext8 = \"by \";\n\t\t\t\ttext8 += ftItem->videoItem->author;\n\t\t\t\ttext8 += \"\\n\";\n\t\t\t\tcommon::Utf8ToUtf16(text8, &item.stat);\n\t\t\t\tytutils::FormatViews(item.stat, ftItem->videoItem->viewCount, true);\n\n\t\t\t\tm_results.push_back(item);\n\t\t\t}\n\n\t\t\tftCleanup(ftCtx);\n\t\t}\n\t}\n\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tm_baseParent->m_loaderIndicator->Stop();\n\tif (!m_interrupted)\n\t{\n\t\tm_list->InsertCell(0, 0, m_results.size());\n\t}\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\tsce_paf_free(entryData);\n\n\tm_allJobsComplete = true;\n}\n\nvoid menu::YouTube::HistorySubmenu::GoToNextPage()\n{\n\n}\n\nvoid menu::YouTube::HistorySubmenu::GoToPrevPage()\n{\n\n}\n\nvoid menu::YouTube::HistorySubmenu::GoToBasePageForSync()\n{\n\tHistoryJob *job = new HistoryJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nmenu::YouTube::HistorySubmenu::HistorySubmenu(YouTube *parentObj) : Submenu(parentObj)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\n\tg_appPlugin->TemplateOpen(m_baseParent->m_browserRoot, template_list_view_youtube_history, tmpParam);\n\tm_submenuRoot = m_baseParent->m_browserRoot->FindChild(plane_list_view_youtube_history_root);\n\tm_list = static_cast<ui::ListView *>(m_submenuRoot->FindChild(list_view_youtube));\n\tListViewCb *lwCb = new ListViewCb(this);\n\tm_list->SetItemFactory(lwCb);\n\tm_list->InsertSegment(0, 1);\n\tmath::v4 sz(960.0f, 100.0f);\n\tm_list->SetCellSizeDefault(0, sz);\n\tm_list->SetSegmentLayoutType(0, ui::ListView::LAYOUT_TYPE_LIST);\n\n\twstring title = g_appPlugin->GetString(msg_youtube_history);\n\tm_baseParent->m_topText->SetString(title);\n\n\tcommon::transition::Do(0.0f, m_submenuRoot, common::transition::Type_FadeinFast, true, false);\n\n\tHistoryJob *job = new HistoryJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nmenu::YouTube::HistorySubmenu::~HistorySubmenu()\n{\n\twstring title;\n\tm_baseParent->m_topText->SetString(title);\n}\n\nvoid menu::YouTube::FavouriteSubmenu::Parse()\n{\n\tstring text8;\n\tchar *entryData;\n\tint32_t sync = 0;\n\tint32_t ret = 0;\n\tFTItem *ftItem = NULL;\n\tvoid *ftCtx = NULL;\n\tbool isLastPage = false;\n\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tm_baseParent->m_loaderIndicator->Start();\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetInt(\"cloud_sync_auto\", static_cast<int32_t *>(&sync), 0);\n\tif (sync && m_currentPage == 0)\n\t{\n\t\tytutils::GetFavLog()->UpdateFromTUS();\n\t}\n\n\tytutils::GetFavLog()->Reset();\n\tint32_t totalNum = ytutils::GetFavLog()->GetSize();\n\n\tif (!m_request.empty())\n\t{\n\t\tisLastPage = true;\n\t\tchar key[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\n\t\tfor (int32_t i = 0; i < totalNum; i++)\n\t\t{\n\t\t\tif (m_interrupted)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tytutils::GetFavLog()->GetNext(key);\n\t\t\tret = ftParseVideo(&ftCtx, key, FT_VIDEO_VOD_QUALITY_NONE, FT_AUDIO_VOD_QUALITY_NONE, &ftItem);\n\t\t\tif (ret == FT_OK)\n\t\t\t{\n\t\t\t\tif (ftItem->videoItem->id && sce_paf_strstr(ftItem->videoItem->title, m_request.c_str()) && m_results.size() < 30)\n\t\t\t\t{\n\t\t\t\t\tItem item;\n\t\t\t\t\titem.type = FT_ITEM_TYPE_VIDEO;\n\t\t\t\t\titem.videoId = ftItem->videoItem->id;\n\t\t\t\t\ttext8 = \"\\n\";\n\t\t\t\t\ttext8 += ftItem->videoItem->title;\n\t\t\t\t\tcommon::Utf8ToUtf16(text8, &item.name);\n\t\t\t\t\titem.texId = ftItem->videoItem->thmbUrl;\n\t\t\t\t\tif (ftItem->videoItem->isLive || ftItem->videoItem->lengthSec == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\ttext8 = \"LIVE\";\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tutils::ConvertSecondsToString(text8, ftItem->videoItem->lengthSec, false);\n\t\t\t\t\t}\n\t\t\t\t\tcommon::Utf8ToUtf16(text8, &item.time);\n\t\t\t\t\ttext8 = \"by \";\n\t\t\t\t\ttext8 += ftItem->videoItem->author;\n\t\t\t\t\ttext8 += \"\\n\";\n\t\t\t\t\tcommon::Utf8ToUtf16(text8, &item.stat);\n\t\t\t\t\tytutils::FormatViews(item.stat, ftItem->videoItem->viewCount, true);\n\n\t\t\t\t\tm_results.push_back(item);\n\t\t\t\t}\n\n\t\t\t\tftCleanup(ftCtx);\n\t\t\t}\n\t\t}\n\t}\n\telse\n\t{\n\t\tint32_t startNum = m_currentPage * 30;\n\n\t\tint32_t realNum = 30;\n\t\tif ((totalNum - startNum) < 30)\n\t\t{\n\t\t\trealNum = totalNum - startNum;\n\t\t\tisLastPage = true;\n\t\t}\n\n\t\tentryData = (char *)sce_paf_calloc(realNum, SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE);\n\n\t\tfor (int32_t i = 0; i < startNum; i++)\n\t\t{\n\t\t\tytutils::GetFavLog()->GetNext(entryData);\n\t\t}\n\n\t\tfor (int32_t i = 0; i < realNum; i++)\n\t\t{\n\t\t\tytutils::GetFavLog()->GetNext(entryData + (i * SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE));\n\t\t}\n\n\t\tfor (int32_t i = 0; i < realNum; i++)\n\t\t{\n\t\t\tif (m_interrupted)\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tret = ftParseVideo(&ftCtx, entryData + (i * SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE), FT_VIDEO_VOD_QUALITY_NONE, FT_AUDIO_VOD_QUALITY_NONE, &ftItem);\n\t\t\tif (ret == FT_OK)\n\t\t\t{\n\t\t\t\tif (ftItem->videoItem->id)\n\t\t\t\t{\n\t\t\t\t\tItem item;\n\t\t\t\t\titem.type = FT_ITEM_TYPE_VIDEO;\n\t\t\t\t\titem.videoId = ftItem->videoItem->id;\n\t\t\t\t\ttext8 = \"\\n\";\n\t\t\t\t\ttext8 += ftItem->videoItem->title;\n\t\t\t\t\tcommon::Utf8ToUtf16(text8, &item.name);\n\t\t\t\t\titem.texId = ftItem->videoItem->thmbUrl;\n\t\t\t\t\tif (ftItem->videoItem->isLive || ftItem->videoItem->lengthSec == 0)\n\t\t\t\t\t{\n\t\t\t\t\t\ttext8 = \"LIVE\";\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tutils::ConvertSecondsToString(text8, ftItem->videoItem->lengthSec, false);\n\t\t\t\t\t}\n\t\t\t\t\tcommon::Utf8ToUtf16(text8, &item.time);\n\t\t\t\t\ttext8 = \"by \";\n\t\t\t\t\ttext8 += ftItem->videoItem->author;\n\t\t\t\t\ttext8 += \"\\n\";\n\t\t\t\t\tcommon::Utf8ToUtf16(text8, &item.stat);\n\t\t\t\t\tytutils::FormatViews(item.stat, ftItem->videoItem->viewCount, true);\n\t\t\t\t\tm_results.push_back(item);\n\t\t\t\t}\n\n\t\t\t\tftCleanup(ftCtx);\n\t\t\t}\n\t\t}\n\n\t\tsce_paf_free(entryData);\n\t}\n\n\tthread::RMutex::MainThreadMutex()->Lock();\n\tm_baseParent->m_loaderIndicator->Stop();\n\tif (!m_interrupted)\n\t{\n\t\tif (m_currentPage == 0)\n\t\t{\n\t\t\tif (!isLastPage)\n\t\t\t{\n\t\t\t\tm_list->InsertCell(0, 0, m_results.size() + 1);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tm_list->InsertCell(0, 0, m_results.size());\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (!isLastPage)\n\t\t\t{\n\t\t\t\tm_list->InsertCell(0, 0, m_results.size() + 2);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tm_list->InsertCell(0, 0, m_results.size() + 1);\n\t\t\t}\n\t\t}\n\t}\n\tthread::RMutex::MainThreadMutex()->Unlock();\n\n\tm_allJobsComplete = true;\n}\n\nvoid menu::YouTube::FavouriteSubmenu::OnSearchButton()\n{\n\twstring text16;\n\tstring text8;\n\n\tReleaseCurrentPage();\n\tm_searchBox->EndEdit();\n\n\tm_request.clear();\n\tm_searchBox->GetString(text16);\n\tcommon::Utf16ToUtf8(text16, &m_request);\n\n\tif (m_request.empty() || ytutils::GetFavLog()->GetSize() == 0)\n\t{\n\t\treturn;\n\t}\n\n\tFavouriteJob *job = new FavouriteJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nvoid menu::YouTube::FavouriteSubmenu::GoToNextPage()\n{\n\tReleaseCurrentPage();\n\tm_currentPage++;\n\n\tFavouriteJob *job = new FavouriteJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nvoid menu::YouTube::FavouriteSubmenu::GoToPrevPage()\n{\n\tReleaseCurrentPage();\n\tm_currentPage--;\n\n\tFavouriteJob *job = new FavouriteJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nvoid menu::YouTube::FavouriteSubmenu::GoToBasePageForSync()\n{\n\tm_currentPage = 0;\n\n\tFavouriteJob *job = new FavouriteJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nmenu::YouTube::FavouriteSubmenu::FavouriteSubmenu(YouTube *parentObj) : Submenu(parentObj)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\n\tg_appPlugin->TemplateOpen(m_baseParent->m_browserRoot, template_list_view_youtube_fav, tmpParam);\n\tm_submenuRoot = m_baseParent->m_browserRoot->FindChild(plane_list_view_youtube_fav_root);\n\tm_list = static_cast<ui::ListView *>(m_submenuRoot->FindChild(list_view_youtube));\n\tListViewCb *lwCb = new ListViewCb(this);\n\tm_list->SetItemFactory(lwCb);\n\tm_list->InsertSegment(0, 1);\n\tmath::v4 sz(960.0f, 100.0f);\n\tm_list->SetCellSizeDefault(0, sz);\n\tm_list->SetSegmentLayoutType(0, ui::ListView::LAYOUT_TYPE_LIST);\n\n\tm_searchBox = static_cast<ui::TextBox *>(m_submenuRoot->FindChild(text_box_top_youtube_search));\n\tm_searchButton = m_submenuRoot->FindChild(button_top_youtube_search);\n\n\tm_searchBox->AddEventCallback(ui::TextBox::CB_TEXT_BOX_ENTER_PRESSED,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<FavouriteSubmenu *>(userdata)->OnSearchButton();\n\t}, this);\n\n\tm_searchButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<FavouriteSubmenu *>(userdata)->OnSearchButton();\n\t}, this);\n\n\tcommon::transition::Do(0.0f, m_submenuRoot, common::transition::Type_FadeinFast, true, false);\n\n\tFavouriteJob *job = new FavouriteJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_allJobsComplete = false;\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nmenu::YouTube::FavouriteSubmenu::~FavouriteSubmenu()\n{\n\n}\n\nvoid menu::YouTube::OnSettingsButton()\n{\n\tint32_t sync = 0;\n\tvector<OptionMenu::Button> buttons;\n\tOptionMenu::Button bt;\n\tbt.label = g_appPlugin->GetString(msg_settings);\n\tbuttons.push_back(bt);\n\tbt.label = g_appPlugin->GetString(msg_settings_youtube_clean_history);\n\tbuttons.push_back(bt);\n\tbt.label = g_appPlugin->GetString(msg_settings_youtube_clean_fav);\n\tbuttons.push_back(bt);\n\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetInt(\"cloud_sync\", static_cast<int32_t *>(&sync), 0);\n\tif (sync)\n\t{\n\t\tbt.label = g_appPlugin->GetString(msg_settings_youtube_cloud_upload);\n\t\tbuttons.push_back(bt);\n\t\tbt.label = g_appPlugin->GetString(msg_settings_youtube_cloud_download);\n\t\tbuttons.push_back(bt);\n\t}\n\n\tnew OptionMenu(g_appPlugin, m_root, &buttons);\n}\n\nvoid menu::YouTube::OnOptionMenuEvent(int32_t type, int32_t subtype)\n{\n\tif (menu::GetTopMenu()->GetMenuType() != menu::MenuType_Youtube)\n\t{\n\t\treturn;\n\t}\n\n\tif (type == OptionMenu::OptionMenuEvent_Close)\n\t{\n\t\treturn;\n\t}\n\n\tCloudJob *cloudJob = NULL;\n\n\tswitch (subtype)\n\t{\n\tcase 0:\n\t\tmenu::SettingsButtonCbFun(ui::Button::CB_BTN_DECIDE, NULL, 0, NULL);\n\t\tbreak;\n\tcase 1:\n\t\tdialog::OpenYesNo(g_appPlugin, NULL, g_appPlugin->GetString(msg_settings_youtube_clean_history_confirm));\n\t\tm_dialogIdx = subtype;\n\t\tbreak;\n\tcase 2:\n\t\tdialog::OpenYesNo(g_appPlugin, NULL, g_appPlugin->GetString(msg_settings_youtube_clean_fav_confirm));\n\t\tm_dialogIdx = subtype;\n\t\tbreak;\n\tcase 3:\n\t\tcloudJob = new CloudJob(CloudJob::Type_Upload, m_currentSubmenu);\n\t\tbreak;\n\tcase 4:\n\t\tcloudJob = new CloudJob(CloudJob::Type_Download, m_currentSubmenu);\n\t\tbreak;\n\t}\n\n\tif (cloudJob)\n\t{\n\t\tm_currentSubmenu->ReleaseCurrentPage();\n\t\tcommon::SharedPtr<job::JobItem> itemParam(cloudJob);\n\t\tjob::JobQueue::DefaultQueue()->Enqueue(itemParam);\n\t}\n}\n\nvoid menu::YouTube::OnDialogEvent(int32_t type)\n{\n\tif (menu::GetTopMenu()->GetMenuType() != menu::MenuType_Youtube)\n\t{\n\t\treturn;\n\t}\n\n\tif (type == dialog::ButtonCode_Yes)\n\t{\n\t\tLogClearJob::Type clearType = LogClearJob::Type_Hist;\n\t\tswitch (m_dialogIdx)\n\t\t{\n\t\tcase 1:\n\t\t\tclearType = LogClearJob::Type_Hist;\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tclearType = LogClearJob::Type_Fav;\n\t\t\tbreak;\n\t\t}\n\n\t\tm_currentSubmenu->ReleaseCurrentPage();\n\t\tLogClearJob *job = new LogClearJob(clearType, m_currentSubmenu);\n\t\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\t\tjob::JobQueue::DefaultQueue()->Enqueue(itemParam);\n\t}\n}\n\nvoid menu::YouTube::OnSettingsEvent(int32_t type)\n{\n\tif (type == Settings::SettingsEvent_ValueChange)\n\t{\n\t\tFTRegion region;\n\t\tmenu::Settings::GetAppSetInstance()->GetInt(\"yt_search_region\", (int32_t *)&region, 0);\n\t\tftSetRegion(region);\n\t}\n}\n\nvoid menu::YouTube::OnBackButton()\n{\n\tdelete this;\n}\n\nvoid menu::YouTube::OnSubmenuButton(ui::Widget *wdg)\n{\n\tSwitchSubmenu(static_cast<Submenu::SubmenuType>(wdg->GetName().GetIDHash()));\n}\n\nint32_t menu::YouTube::LogClearJob::Run()\n{\n\tdialog::OpenPleaseWait(g_appPlugin, NULL, Framework::Instance()->GetCommonString(\"msg_wait\"));\n\n\tswitch (m_type)\n\t{\n\tcase Type_Hist:\n\t\tytutils::HistLog::Clean();\n\t\tbreak;\n\tcase Type_Fav:\n\t\tytutils::FavLog::Clean();\n\t\tbreak;\n\t}\n\n\tif (m_submenu)\n\t{\n\t\tm_submenu->GoToBasePageForSync();\n\t}\n\n\tdialog::Close();\n\n\treturn SCE_PAF_OK;\n}\n\nint32_t menu::YouTube::CloudJob::Run()\n{\n\tdialog::OpenPleaseWait(g_appPlugin, NULL, Framework::Instance()->GetCommonString(\"msg_wait\"));\n\n\tif (!nputils::IsAllGreen())\n\t{\n\t\tdialog::Close();\n\t\tdialog::OpenError(g_appPlugin, SCE_ERROR_ERRNO_EUNSUP, g_appPlugin->GetString(msg_error_psn_connection));\n\t\treturn SCE_PAF_OK;\n\t}\n\n\tswitch (m_type)\n\t{\n\tcase Type_Upload:\n\t\tytutils::GetFavLog()->UploadToTUS();\n\t\tytutils::GetHistLog()->UploadToTUS();\n\t\tbreak;\n\tcase Type_Download:\n\t\tytutils::GetFavLog()->UpdateFromTUS();\n\t\tytutils::GetHistLog()->UpdateFromTUS();\n\t\tif (m_submenu)\n\t\t{\n\t\t\tm_submenu->GoToBasePageForSync();\n\t\t}\n\t\tbreak;\n\t}\n\n\tdialog::Close();\n\n\treturn SCE_PAF_OK;\n}\n\nmenu::YouTube::YouTube() :\n\tGenericMenu(\"page_youtube\",\n\tMenuOpenParam(false, 200.0f, Plugin::TransitionType_SlideFromBottom),\n\tMenuCloseParam(false, 200.0f, Plugin::TransitionType_SlideFromBottom))\n{\n\tm_currentSubmenu = NULL;\n\n\tutils::SetRequestShare(ytutils::GetShare());\n\n\tm_root->AddEventCallback(OptionMenu::OptionMenuEvent,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<YouTube *>(userdata)->OnOptionMenuEvent(e->GetValue(0), e->GetValue(1));\n\t}, this);\n\n\tm_root->AddEventCallback(dialog::DialogEvent,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<YouTube *>(userdata)->OnDialogEvent(e->GetValue(0));\n\t}, this);\n\n\tm_root->AddEventCallback(Settings::SettingsEvent,\n\t\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<YouTube *>(userdata)->OnSettingsEvent(e->GetValue(0));\n\t}, this);\n\n\tui::Widget *settingsButton = m_root->FindChild(button_settings_page_youtube);\n\tsettingsButton->Show(common::transition::Type_Reset);\n\tsettingsButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<YouTube *>(userdata)->OnSettingsButton();\n\t}, this);\n\n\tui::Widget *backButton = m_root->FindChild(button_back_page_youtube);\n\tbackButton->Show(common::transition::Type_Reset);\n\tbackButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<YouTube *>(userdata)->OnBackButton();\n\t}, this);\n\n\tm_browserRoot = m_root->FindChild(plane_browser_root_page_youtube);\n\tm_loaderIndicator = static_cast<ui::BusyIndicator *>(m_root->FindChild(busyindicator_loader_page_youtube));\n\tm_topText = static_cast<ui::Text *>(m_root->FindChild(text_top));\n\tm_btMenu = static_cast<ui::Box *>(m_root->FindChild(box_bottommenu_page_youtube));\n\n\tm_searchBt = m_btMenu->FindChild(button_yt_btmenu_search);\n\tm_histBt = m_btMenu->FindChild(button_yt_btmenu_history);\n\tm_favBt = m_btMenu->FindChild(button_yt_btmenu_favourite);\n\n\tauto submenuButtonCb = [](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<YouTube *>(userdata)->OnSubmenuButton(static_cast<ui::Widget *>(self));\n\t};\n\tm_searchBt->AddEventCallback(ui::Button::CB_BTN_DECIDE, submenuButtonCb, this);\n\tm_histBt->AddEventCallback(ui::Button::CB_BTN_DECIDE, submenuButtonCb, this);\n\tm_favBt->AddEventCallback(ui::Button::CB_BTN_DECIDE, submenuButtonCb, this);\n\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tFTRegion region;\n\tsettings->GetInt(\"yt_search_region\", (int32_t *)&region, 0);\n\tftSetRegion(region);\n\n\tchar proxy[256];\n\tproxy[0] = 0;\n\tsettings->GetString(\"yt_search_proxy\", proxy, sizeof(proxy) - 1, \"\");\n\tif (proxy[0] != 0)\n\t{\n\t\tutils::SetGlobalProxy(proxy);\n\t}\n\n\tm_texPool = new TexPool(g_appPlugin);\n\tm_texPool->SetShare(utils::GetShare());\n\n\tSwitchSubmenu(Submenu::SubmenuType_Search);\n}\n\nmenu::YouTube::~YouTube()\n{\n\tdelete m_currentSubmenu;\n\tm_texPool->DestroyAsync();\n\tutils::SetGlobalProxy(NULL);\n\tutils::SetRequestShare(NULL);\n}\n\nvoid menu::YouTube::SwitchSubmenu(Submenu::SubmenuType type)\n{\n\tif (m_currentSubmenu)\n\t{\n\t\tif (m_currentSubmenu->GetType() == type)\n\t\t{\n\t\t\treturn;\n\t\t}\n\t\tdelete m_currentSubmenu;\n\t\tm_currentSubmenu = NULL;\n\t}\n\n\tswitch (type)\n\t{\n\tcase Submenu::SubmenuType_Search:\n\t\tm_currentSubmenu = new SearchSubmenu(this);\n\t\tbreak;\n\tcase Submenu::SubmenuType_History:\n\t\tm_currentSubmenu = new HistorySubmenu(this);\n\t\tbreak;\n\tcase Submenu::SubmenuType_Favourites:\n\t\tm_currentSubmenu = new FavouriteSubmenu(this);\n\t\tbreak;\n\t}\n}"
  },
  {
    "path": "NetStream/source/np_utils.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <stdlib.h>\n#include <np.h>\n#include <libsysmodule.h>\n#include <common_dialog.h>\n#include <netcheck_dialog_internal.h>\n\n#include \"np_utils.h\"\n\nstatic const SceNpCommunicationId s_CommId = {\n\t{'N', 'P', 'W', 'R', '0', '0', '6', '4', '9'},\n\t'\\0',\n\t0,\n\t0\n};\n\nstatic const SceNpCommunicationPassphrase s_CommPassphrase =\n{\n\t{\n\t0x4F, 0x09, 0x1C, 0xF6, 0x6F, 0x7A, 0xEB, 0xE2, 0xC5, 0x1D, 0x68, 0x9B,\n\t0x61, 0x7E, 0x3B, 0x49, 0xFC, 0x10, 0xCB, 0xBF, 0xCA, 0xD4, 0x7D, 0x6C,\n\t0x5C, 0x2F, 0x79, 0x70, 0x06, 0x71, 0x03, 0x5F, 0x36, 0xCE, 0x99, 0x28,\n\t0xC5, 0xAE, 0x42, 0xAB, 0xBA, 0x39, 0xCE, 0xF0, 0x6E, 0x8E, 0x63, 0xAF,\n\t0x25, 0x6D, 0x76, 0xA1, 0x9B, 0x44, 0x07, 0xB0, 0x9B, 0xDB, 0xEF, 0xB5,\n\t0x10, 0x80, 0x86, 0x43, 0x21, 0xED, 0xF5, 0x0A, 0x05, 0x62, 0x4C, 0x61,\n\t0xF7, 0xFE, 0x18, 0xDB, 0x96, 0x3E, 0xA6, 0x36, 0x9C, 0xB7, 0xB9, 0xFE,\n\t0x9A, 0x7A, 0x33, 0x33, 0x72, 0xAD, 0x90, 0x0F, 0x60, 0x7D, 0x59, 0x46,\n\t0x88, 0xB1, 0xC3, 0xE7, 0x71, 0xCE, 0x83, 0xF8, 0x3F, 0x3E, 0x50, 0x0F,\n\t0x3E, 0xE4, 0x8C, 0x3C, 0x58, 0xF1, 0xF5, 0x3C, 0x25, 0xA5, 0xE2, 0x14,\n\t0x5B, 0x83, 0xCA, 0x34, 0xE9, 0x15, 0x38, 0x3D\n\t}\n};\n\nstatic const SceNpCommunicationSignature s_CommSignature =\n{\n\t{\n\t0xB9, 0xDD, 0xE1, 0x3B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\n\t0x9C, 0x62, 0x47, 0xCC, 0xD5, 0x2A, 0xEF, 0x7D, 0xE6, 0xC9, 0x36, 0xC3,\n\t0xB4, 0x19, 0xD4, 0x8E, 0xD4, 0x95, 0x00, 0x71, 0xC4, 0xCD, 0xC7, 0xF8,\n\t0x3C, 0xD3, 0xFC, 0x3D, 0xF3, 0xA5, 0x96, 0x30, 0xC0, 0xF0, 0x1D, 0x69,\n\t0xAF, 0xEE, 0x37, 0xB9, 0x4B, 0xB2, 0x3D, 0xE4, 0x02, 0xE1, 0xCE, 0xF6,\n\t0x90, 0xEB, 0x08, 0x4B, 0xCC, 0xB2, 0x50, 0x57, 0xCE, 0x33, 0xB3, 0xA9,\n\t0xAA, 0xC6, 0x77, 0x1D, 0x6A, 0x19, 0xF9, 0x2E, 0x55, 0x4E, 0x03, 0x83,\n\t0x60, 0x4F, 0x0A, 0xB5, 0x08, 0x49, 0xBE, 0x11, 0xC1, 0xEF, 0x2F, 0x69,\n\t0x32, 0xD2, 0xCF, 0x6F, 0x7C, 0x4C, 0xD4, 0x0D, 0x27, 0xB2, 0x34, 0x4F,\n\t0x5A, 0x2B, 0x12, 0x2F, 0xD0, 0xEF, 0xE4, 0xD7, 0x22, 0xE4, 0x9B, 0x80,\n\t0x5A, 0x8E, 0xBB, 0x3A, 0xE1, 0x9A, 0xE3, 0x8C, 0x29, 0x3F, 0x9C, 0xEC,\n\t0x58, 0x74, 0x6C, 0xB0, 0x55, 0x37, 0x9C, 0x93, 0xAE, 0x0A, 0x92, 0x1C,\n\t0x13, 0x41, 0x06, 0x67, 0x04, 0x53, 0x7A, 0xD4, 0x6E, 0xCC, 0x0F, 0xED,\n\t0xC6, 0xB3, 0x8F, 0x57\n\t}\n};\n\n\nstatic const SceNpCommunicationConfig s_commConfig = {\n\t/* .commId =\t\t*/ &s_CommId,\n\t/* .commPassphrase =*/ &s_CommPassphrase,\n\t/* .commSignature = */ &s_CommSignature\n};\n\nstatic nputils::TUS *s_tus = NULL;\nstatic char s_opbuf[SCE_KERNEL_1KiB];\nstatic string s_tag;\nstatic int32_t s_preInitRet = SCE_OK;\n\nnputils::TUS::TUS()\n{\n\tm_ctx = 0;\n}\n\nnputils::TUS::~TUS()\n{\n\tTerm();\n}\n\nint32_t nputils::TUS::Init()\n{\n\tint32_t ret = sceNpTusInit(SCE_KERNEL_DEFAULT_PRIORITY_USER, SCE_KERNEL_THREAD_CPU_AFFINITY_MASK_DEFAULT, NULL);\n\tif (ret < 0)\n\t{\n\t\treturn ret;\n\t}\n\n\tret = sceNpManagerGetNpId(&m_npid);\n\tif (ret < 0)\n\t{\n\t\tsceNpTusTerm();\n\t\treturn ret;\n\t}\n\n\tret = sceNpTusCreateTitleCtx(NULL, NULL, NULL);\n\tif (ret < 0)\n\t{\n\t\tsceNpTusTerm();\n\t\treturn ret;\n\t}\n\n\tm_ctx = ret;\n\n\treturn SCE_OK;\n}\n\nint32_t nputils::TUS::Term()\n{\n\tint32_t ret = sceNpTusDeleteTitleCtx(m_ctx);\n\tif (ret < 0)\n\t{\n\t\treturn ret;\n\t}\n\n\treturn sceNpTusTerm();\n}\n\nint32_t nputils::TUS::UploadFile(uint32_t slot, const char *path)\n{\n\tint32_t ret = SCE_OK;\n\tint32_t request = 0;\n\tSceNpTusDataInfo labelInfo;\n\n\tret = sceNpTusCreateRequest(m_ctx);\n\tif (ret < 0)\n\t{\n\t\treturn ret;\n\t}\n\trequest = ret;\n\n\tcommon::SharedPtr<LocalFile> file = LocalFile::Open(path, File::RDONLY, 0, &ret);\n\tif (ret < 0)\n\t{\n\t\tsceNpTusDeleteRequest(request);\n\t\treturn ret;\n\t}\n\n\tuint32_t fsz = file->GetFileSize();\n\tchar *fbuf = static_cast<char*>(sce_paf_malloc(fsz));\n\tif (!fbuf)\n\t{\n\t\tfile->Close();\n\t\tsceNpTusDeleteRequest(request);\n\t\treturn SCE_ERROR_ERRNO_ENOMEM;\n\t}\n\tfile->Read(fbuf, fsz);\n\tfile->Close();\n\n\tsce_paf_memset(&labelInfo, 0, sizeof(SceNpTusDataInfo));\n\tsce_paf_strncpy(reinterpret_cast<char*>(labelInfo.data), s_tag.c_str(), sizeof(labelInfo.data) - 1);\n\tlabelInfo.infoSize = sce_paf_strlen(reinterpret_cast<char*>(labelInfo.data)) + 1;\n\n\tret = sceNpTusSetData(request, &m_npid, slot, fsz, fsz, fbuf, &labelInfo, sizeof(SceNpTusDataInfo), NULL, NULL, NULL);\n\n\tsce_paf_free(fbuf);\n\n\tsceNpTusDeleteRequest(request);\n\n\treturn ret;\n}\n\nint32_t nputils::TUS::DownloadFile(uint32_t slot, const char *path)\n{\n\tint32_t ret = SCE_OK;\n\tint32_t request = 0;\n\tint32_t recvedSize = 0;\n\tSceNpTusDataStatus dataStatus;\n\n\tret = sceNpTusCreateRequest(m_ctx);\n\tif (ret < 0)\n\t{\n\t\treturn ret;\n\t}\n\trequest = ret;\n\n\tcommon::SharedPtr<LocalFile> file = LocalFile::Open(path, File::WRONLY | File::CREAT, File::RWU, &ret);\n\tif (ret < 0)\n\t{\n\t\tsceNpTusDeleteRequest(request);\n\t\treturn ret;\n\t}\n\n\tdo\n\t{\n\t\tret = sceNpTusGetData(request, &m_npid, slot, &dataStatus, sizeof(SceNpTusDataStatus), s_opbuf, sizeof(s_opbuf), NULL);\n\t\tif (ret < 0)\n\t\t{\n\t\t\trecvedSize = ret;\n\t\t\tbreak;\n\t\t}\n\t\tif (dataStatus.hasData == 0)\n\t\t{\n\t\t\trecvedSize = -1;\n\t\t\tbreak;\n\t\t}\n\n\t\tfile->Write(s_opbuf, ret);\n\t\trecvedSize += ret;\n\n\t} while (recvedSize < dataStatus.dataSize);\n\n\tfile->Close();\n\n\tsceNpTusDeleteRequest(request);\n\n\treturn recvedSize;\n}\n\nint32_t nputils::TUS::UploadString(uint32_t slot, const string& data)\n{\n\tint32_t ret = SCE_OK;\n\tint32_t request = 0;\n\tSceNpTusDataInfo labelInfo;\n\n\tret = sceNpTusCreateRequest(m_ctx);\n\tif (ret < 0)\n\t{\n\t\treturn ret;\n\t}\n\trequest = ret;\n\n\tsce_paf_memset(&labelInfo, 0, sizeof(SceNpTusDataInfo));\n\tsce_paf_strncpy(reinterpret_cast<char*>(labelInfo.data), s_tag.c_str(), sizeof(labelInfo.data) - 1);\n\tlabelInfo.infoSize = sce_paf_strlen(reinterpret_cast<char*>(labelInfo.data)) + 1;\n\n\tret = sceNpTusSetData(request, &m_npid, slot, data.length(), data.length(), data.c_str(), &labelInfo, sizeof(SceNpTusDataInfo), NULL, NULL, NULL);\n\n\tsceNpTusDeleteRequest(request);\n\n\treturn ret;\n}\n\nint32_t nputils::TUS::DownloadString(uint32_t slot, string& data)\n{\n\tint32_t ret = SCE_OK;\n\tint32_t request = 0;\n\tint32_t recvedSize = 0;\n\tSceNpTusDataStatus dataStatus;\n\n\tret = sceNpTusCreateRequest(m_ctx);\n\tif (ret < 0)\n\t{\n\t\treturn ret;\n\t}\n\trequest = ret;\n\n\tdo\n\t{\n\t\tret = sceNpTusGetData(request, &m_npid, slot, &dataStatus, sizeof(SceNpTusDataStatus), s_opbuf, sizeof(s_opbuf), NULL);\n\t\tif (ret < 0)\n\t\t{\n\t\t\trecvedSize = ret;\n\t\t\tbreak;\n\t\t}\n\t\tif (dataStatus.hasData == 0)\n\t\t{\n\t\t\trecvedSize = -1;\n\t\t\tbreak;\n\t\t}\n\n\t\tdata.append(s_opbuf, ret);\n\t\trecvedSize += ret;\n\n\t} while (recvedSize < dataStatus.dataSize);\n\n\tsceNpTusDeleteRequest(request);\n\n\treturn recvedSize;\n}\n\nint32_t nputils::TUS::GetDataStatus(uint32_t slot, SceNpTusDataStatus *status)\n{\n\tint32_t ret = SCE_OK;\n\tint32_t request = 0;\n\n\tret = sceNpTusCreateRequest(m_ctx);\n\tif (ret < 0)\n\t{\n\t\treturn ret;\n\t}\n\trequest = ret;\n\n\tret = sceNpTusGetMultiSlotDataStatus(request, &m_npid, reinterpret_cast<const SceNpTusSlotId*>(&slot), status, sizeof(SceNpTusDataStatus), 1, NULL);\n\n\tsceNpTusDeleteRequest(request);\n\n\treturn ret;\n}\n\nint32_t nputils::TUS::DeleteData(uint32_t slot)\n{\n\tvector<uint32_t> lslots;\n\tlslots.push_back(slot);\n\n\treturn DeleteData(&lslots);\n}\n\nint32_t nputils::TUS::DeleteData(const vector<uint32_t> *slots)\n{\n\tint32_t ret = SCE_OK;\n\tint32_t request = 0;\n\tSceNpTusSlotId lslots[16];\n\n\tif (!slots)\n\t{\n\t\treturn ret;\n\t}\n\n\tret = sceNpTusCreateRequest(m_ctx);\n\tif (ret < 0)\n\t{\n\t\treturn ret;\n\t}\n\trequest = ret;\n\n\tfor (int i = 0; i < slots->size(); i++)\n\t{\n\t\tlslots[i] = slots->at(i);\n\t}\n\n\tret = sceNpTusDeleteMultiSlotData(request, &m_npid, lslots, slots->size(), NULL);\n\n\tsceNpTusDeleteRequest(request);\n\n\treturn ret;\n}\n\nint32_t nputils::PreInit(thread::SyncCall::Function onComplete)\n{\n\ts_preInitRet = SCE_OK;\n\n\tint32_t ret = sceNpInit(&s_commConfig, NULL);\n\tif (ret < 0)\n\t{\n\t\ts_preInitRet = ret;\n\t\tthread::SyncCall::MainThreadSyncCall()->Call(onComplete, &s_preInitRet);\n\t\treturn ret;\n\t}\n\n\tthread::SyncCall::MainThreadSyncCall()->Call(NetDialogInit, NULL);\n\tcommon::MainThreadCallList::Register(NetDialogCheck, onComplete);\n\n\treturn ret;\n}\n\nint32_t nputils::Init(const char *tag, bool needTUS, const vector<uint32_t> *usedTUSSlots)\n{\n\tint32_t ret = sceNpAuthInit();\n\tif (ret < 0)\n\t{\n\t\tTerm();\n\t\treturn ret;\n\t}\n\n\tif (tag)\n\t{\n\t\ts_tag = tag;\n\t}\n\n\tif (needTUS)\n\t{\n\t\ts_tus = new TUS();\n\t\tret = s_tus->Init();\n\t\tif (ret < 0)\n\t\t{\n\t\t\tTerm();\n\t\t\treturn ret;\n\t\t}\n\n\t\tif (usedTUSSlots)\n\t\t{\n\t\t\tSceNpTusDataStatus status;\n\t\t\tret = s_tus->GetDataStatus(usedTUSSlots->at(0), &status);\n\t\t\tif (ret < 0)\n\t\t\t{\n\t\t\t\tTerm();\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\tif (status.hasData)\n\t\t\t{\n\t\t\t\tif ((status.info.infoSize != s_tag.length() + 1) || sce_paf_strcmp(reinterpret_cast<char*>(status.info.data), s_tag.c_str()))\n\t\t\t\t{\n\t\t\t\t\ts_tus->DeleteData(usedTUSSlots);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nint32_t nputils::Term()\n{\n\tif (s_tus)\n\t{\n\t\tdelete s_tus;\n\t\ts_tus = NULL;\n\t}\n\n\tsceNpAuthTerm();\n\n\treturn sceNpTerm();\n}\n\nbool nputils::IsAllGreen()\n{\n\tSceNpServiceState state;\n\n\tif (sceNpGetServiceState(&state) == SCE_OK)\n\t{\n\t\tif (state == SCE_NP_SERVICE_STATE_ONLINE)\n\t\t{\n\t\t\treturn true;\n\t\t}\n\t}\n\t\n\treturn false;\n}\n\nnputils::TUS *nputils::GetTUS()\n{\n\treturn s_tus;\n}\n\nint32_t nputils::NetDialogInit(void *data)\n{\n\tint32_t ret = 0;\n\n\tsceSysmoduleLoadModule(SCE_SYSMODULE_HTTP);\n\tsceSysmoduleLoadModule(SCE_SYSMODULE_SSL);\n\n\tsceSslInit(SCE_NETCHECK_DIALOG_LEAST_SSL_POOL_SIZE + SCE_KERNEL_4KiB);\n\tsceHttpInit(SCE_NETCHECK_DIALOG_LEAST_HTTP_POOL_SIZE + SCE_KERNEL_4KiB);\n\n\tSceNetCheckDialogParam param;\n\tSceNetCheckDialogParamInternal iparam;\n\tsceNetCheckDialogParamInitInternal(&param, &iparam);\n\n\tparam.defaultAgeRestriction = 1;\n\n\tparam.mode = SCE_NETCHECK_DIALOG_MODE_PSN_ONLINE;\n\n\tiparam.unk_00 = 1;\n\tiparam.skipSignIn = 1;\n\n\tret = sceNetCheckDialogInitInternal(&param, &iparam);\n\tif (ret < 0)\n\t{\n\t\tsceSslTerm();\n\t\tsceHttpTerm();\n\t\tsceSysmoduleUnloadModule(SCE_SYSMODULE_SSL);\n\t\tsceSysmoduleUnloadModule(SCE_SYSMODULE_HTTP);\n\t\ts_preInitRet = ret;\n\t}\n\n\treturn 0;\n}\n\nvoid nputils::NetDialogCheck(void *data)\n{\n\tthread::SyncCall::Function func = reinterpret_cast<thread::SyncCall::Function>(data);\n\tSceNetCheckDialogResult result;\n\n\tif (s_preInitRet < 0)\n\t{\n\t\t/*sceSslTerm();\n\t\tsceHttpTerm();\n\t\tsceSysmoduleUnloadModule(SCE_SYSMODULE_SSL);\n\t\tsceSysmoduleUnloadModule(SCE_SYSMODULE_HTTP);*/\n\t\tfunc(&s_preInitRet);\n\t\tcommon::MainThreadCallList::Unregister(NetDialogCheck, data);\n\t}\n\n\tint32_t ret = sceNetCheckDialogGetStatus();\n\tif (ret == SCE_COMMON_DIALOG_STATUS_FINISHED)\n\t{\n\t\tsceNetCheckDialogGetResult(&result);\n\t\tif (result.result != SCE_OK)\n\t\t{\n\t\t\ts_preInitRet = result.result;\n\t\t\tif (s_preInitRet == 1)\n\t\t\t{\n\t\t\t\ts_preInitRet = SCE_NETCHECK_DIALOG_ERROR_SIGN_OUT;\n\t\t\t}\n\t\t}\n\t\tsceNetCheckDialogTerm();\n\t\tsceSslTerm();\n\t\tsceHttpTerm();\n\t\tsceSysmoduleUnloadModule(SCE_SYSMODULE_SSL);\n\t\tsceSysmoduleUnloadModule(SCE_SYSMODULE_HTTP);\n\t\tfunc(&s_preInitRet);\n\t\tcommon::MainThreadCallList::Unregister(NetDialogCheck, data);\n\t}\n\telse if (ret < 0)\n\t{\n\t\ts_preInitRet = ret;\n\t}\n}"
  },
  {
    "path": "NetStream/source/option_menu.cpp",
    "content": "#include <kernel.h>\n#include <libdbg.h>\n#include <paf.h>\n\n#include \"event.h\"\n#include \"option_menu.h\"\n\n#define template_option_menu_base (0xed36b1c7)\n#define plane_option_menu_base (0x4446ff86)\n#define box_option_menu (0xae3d8acd)\n#define button_option_menu_close (0x655c6a32)\n#define template_option_menu_button_single (0x9227a229)\n#define button_option_menu_single (0x242a5612)\n#define template_option_menu_button_top (0x9e7aa431)\n#define button_option_menu_top (0x1f350609)\n#define template_option_menu_button_bottom (0xeaf5dc69)\n#define button_option_menu_bottom (0xe034ff9c)\n#define template_option_menu_button_middle (0x429cab34)\n#define button_option_menu_middle (0xbbc3bf22)\n#define page_option_menu (0xd098335e)\n#define text_option_menu_ruler (0xc9cdb2cc)\n\nusing namespace paf;\n\nconst float k_minBtLen = 202.0f;\n\nvoid OptionMenu::OnButton(ui::Widget *wdg)\n{\n\tuint32_t hash = wdg->GetName().GetIDHash();\n\tPlugin *plugin = m_plugin;\n\tdelete this;\n\n\tif (hash == button_option_menu_close)\n\t{\n\t\tevent::BroadcastGlobalEvent(plugin, OptionMenuEvent, OptionMenuEvent_Close);\n\t}\n\telse\n\t{\n\t\tevent::BroadcastGlobalEvent(plugin, OptionMenuEvent, OptionMenuEvent_Button, hash - OPTION_MENU_BUTTON_MAGIC);\n\t}\n}\n\nvoid OptionMenu::OnSizeAdjust(int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n{\n\tui::Widget *button = NULL;\n\tfloat len = 0.0f;\n\tui::Text *wdg = static_cast<ui::Text *>(self);\n\tOptionMenu *workObj = static_cast<OptionMenu *>(userdata);\n\n\tlen = wdg->GetDrawObj(ui::Text::OBJ_ROOT)->GetSize().extract_x() + 40.0f;\n\n\tif (len < k_minBtLen)\n\t{\n\t\tlen = k_minBtLen;\n\t}\n\n\tmath::v4 btSz(len, 60.0f);\n\tmath::v4 plSz(len + 12.0f, 12.0f + 60.0f * workObj->m_buttonCount);\n\tmath::v4 plPos(264.0f + ((202.0f - plSz.extract_x()) / 2.0f), 43.0f);\n\n\tui::Widget *optRoot = workObj->m_optPlaneRoot->FindChild(box_option_menu);\n\n\tfor (int i = 0; i < workObj->m_buttonCount; i++)\n\t{\n\t\tbutton = optRoot->FindChild(OPTION_MENU_BUTTON_MAGIC + i);\n\t\tbutton->SetAdjust(ui::Widget::ADJUST_NONE, ui::Widget::ADJUST_NONE, ui::Widget::ADJUST_NONE);\n\t\tbutton->SetSize(btSz);\n\t}\n\n\tworkObj->m_optPlaneRoot->SetSize(plSz);\n\tworkObj->m_optPlaneRoot->SetPos(plPos);\n\tworkObj->m_optPlaneRoot->Show(common::transition::Type_Popup4, 0.0f);\n\n\tself->DeleteEventCallback(ui::Handler::CB_STATE_READY, OnSizeAdjust, userdata);\n}\n\nOptionMenu::OptionMenu(Plugin *workPlugin, ui::Widget *root, vector<Button> *buttons)\n{\n\tPlugin::TemplateOpenParam tmpParam;\n\tui::Widget *closeButton = NULL;\n\tui::Widget *button = NULL;\n\n\tm_parentRoot = root;\n\tm_plugin = workPlugin;\n\tm_buttonCount = buttons->size();\n\n\tPlugin::PageOpenParam openParam;\n\topenParam.option = Plugin::PageOption_Create;\n\topenParam.overwrite_draw_priority = 8;\n\topenParam.graphics_flag = 0x80;\n\tm_rootScene = m_plugin->PageOpen(page_option_menu, openParam);\n\tif (!m_rootScene)\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[OPTION_MENU] Attempt to create option menu twice!\\n\");\n\t\treturn;\n\t}\n\n\tm_parentRoot->SetActivate(false);\n\n\tm_plugin->TemplateOpen(m_rootScene, template_option_menu_base, tmpParam);\n\n\tcloseButton = m_rootScene->FindChild(button_option_menu_close);\n\tcloseButton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t{\n\t\treinterpret_cast<OptionMenu *>(userdata)->OnButton(static_cast<ui::Widget *>(self));\n\t}, this);\n\n\tcloseButton->SetKeycode(inputdevice::pad::Data::PAD_ESCAPE | inputdevice::pad::Data::PAD_MENU);\n\n\tm_optPlaneRoot = closeButton->FindChild(plane_option_menu_base);\n\tui::Widget *optRoot = m_optPlaneRoot->FindChild(box_option_menu);\n\n\tuint32_t maxLen = 0;\n\tuint32_t curLen = 0;\n\tuint32_t maxLenIdx = 0;\n\tuint32_t idhash = 0;\n\n\tfor (int i = 0; i < m_buttonCount; i++)\n\t{\n\t\tButton btItem = buttons->at(i);\n\n\t\tif (i == 0)\n\t\t{\n\t\t\tif (m_buttonCount == 1)\n\t\t\t{\n\t\t\t\tidhash = template_option_menu_button_single;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tidhash = template_option_menu_button_top;\n\t\t\t}\n\t\t}\n\t\telse if (i == m_buttonCount - 1)\n\t\t{\n\t\t\tidhash = template_option_menu_button_bottom;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tidhash = template_option_menu_button_middle;\n\t\t}\n\n\t\tm_plugin->TemplateOpen(optRoot, idhash, tmpParam);\n\t\tbutton = optRoot->GetChild(optRoot->GetChildrenNum() - 1);\n\t\tbutton->SetName(OPTION_MENU_BUTTON_MAGIC + i);\n\t\tbutton->SetString(btItem.label);\n\t\tbutton->AddEventCallback(ui::Button::CB_BTN_DECIDE,\n\t\t[](int32_t type, ui::Handler *self, ui::Event *e, void *userdata)\n\t\t{\n\t\t\treinterpret_cast<OptionMenu *>(userdata)->OnButton(static_cast<ui::Widget *>(self));\n\t\t}, this);\n\n\t\tcurLen = btItem.label.length();\n\t\tif (curLen > maxLen)\n\t\t{\n\t\t\tmaxLen = curLen;\n\t\t\tmaxLenIdx = i;\n\t\t}\n\t}\n\n\tui::Widget *ruler = m_optPlaneRoot->FindChild(text_option_menu_ruler);\n\truler->SetString(buttons->at(maxLenIdx).label);\n\truler->AddEventCallback(ui::Handler::CB_STATE_READY, OnSizeAdjust, this);\n}\n\nOptionMenu::~OptionMenu()\n{\n\tPlugin::PageCloseParam closeParam;\n\n\tm_optPlaneRoot->Hide(common::transition::Type_Popup4, 0.0f);\n\n\tcloseParam.fade = true;\n\tcloseParam.fade_time_ms = 1000;\n\tm_plugin->PageClose(page_option_menu, closeParam);\n\n\tm_parentRoot->SetActivate(true);\n}"
  },
  {
    "path": "NetStream/source/paf_runtime.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <libsysmodule.h>\n\nextern \"C\" {\n\n\ttypedef struct SceSysmoduleOpt {\n\t\tint flags;\n\t\tint *result;\n\t\tint unused[2];\n\t} SceSysmoduleOpt;\n\n\tint sceAppMgrGrowMemory3(unsigned int a1, int a2);\n\n\tvoid __cxa_set_dso_handle_main(void *dso)\n\t{\n\n\t}\n\n\tint _sceLdTlsRegisterModuleInfo()\n\t{\n\t\treturn 0;\n\t}\n\n\tint __at_quick_exit()\n\t{\n\t\treturn 0;\n\t}\n\t\n\tvoid user_malloc_init(void)\n\t{\n\n\t}\n\n\tvoid user_malloc_finalize(void)\n\t{\n\n\t}\n\n\tvoid *user_malloc(size_t size)\n\t{\n\t\treturn sce_paf_malloc(size);\n\t}\n\n\tvoid user_free(void *ptr)\n\t{\n\t\tsce_paf_free(ptr);\n\t}\n\n\tvoid *user_calloc(size_t nelem, size_t size)\n\t{\n\t\treturn sce_paf_calloc(nelem, size);\n\t}\n\n\tvoid *user_realloc(void *ptr, size_t size)\n\t{\n\t\treturn sce_paf_realloc(ptr, size);\n\t}\n\n\tvoid *user_memalign(size_t boundary, size_t size)\n\t{\n\t\treturn sce_paf_memalign(boundary, size);\n\t}\n\n\tvoid *user_reallocalign(void *ptr, size_t size, size_t boundary)\n\t{\n\t\tsceClibPrintf(\"[PAF2LIBC] reallocalign is not supported\\n\");\n\t\tabort();\n\t\treturn NULL;\n\t}\n\n\tint user_malloc_stats(struct malloc_managed_size *mmsize)\n\t{\n\t\tsceClibPrintf(\"[PAF2LIBC] malloc_stats is not supported\\n\");\n\t\tabort();\n\t\treturn 0;\n\t}\n\n\tint user_malloc_stats_fast(struct malloc_managed_size *mmsize)\n\t{\n\t\tsceClibPrintf(\"[PAF2LIBC] malloc_stats_fast is not supported\\n\");\n\t\tabort();\n\t\treturn 0;\n\t}\n\n\tsize_t user_malloc_usable_size(void *ptr)\n\t{\n\t\treturn sce_paf_musable_size(ptr);\n\t}\n}\n\nvoid *user_new(std::size_t size)\n{\n\tvoid *ret = sce_paf_malloc(size);\n\t/*\n\t\tSceAvPlayer bugfix: yucca::DashManifestParser::FinishParse() tries to use uninitialized pointers in MediaLookUpMmap member\n\t\tThis bug is not visible with SceLibc because it always memsets heap with 0's and yucca probably checks: if(ptr){...}\n\t*/\n\t/*\n\tif (size == 112)\n\t{\n\t\tsce_paf_memset(ret, 0, size);\n\t}\n\t*/\n\treturn ret;\n}\n\nvoid *user_new(std::size_t size, const std::nothrow_t& x)\n{\n\treturn sce_paf_malloc(size);\n}\n\nvoid *user_new_array(std::size_t size)\n{\n\treturn sce_paf_malloc(size);\n}\n\nvoid *user_new_array(std::size_t size, const std::nothrow_t& x)\n{\n\treturn sce_paf_malloc(size);\n}\n\nvoid user_delete(void *ptr)\n{\n\tsce_paf_free(ptr);\n}\n\nvoid user_delete(void *ptr, const std::nothrow_t& x)\n{\n\tsce_paf_free(ptr);\n}\n\nvoid user_delete_array(void *ptr)\n{\n\tsce_paf_free(ptr);\n}\n\nvoid user_delete_array(void *ptr, const std::nothrow_t& x)\n{\n\tsce_paf_free(ptr);\n}\n\n__attribute__((constructor(101))) void preloadPaf()\n{\n\tint32_t ret = -1, load_res;\n\n\tScePafInit init_param;\n\tSceSysmoduleOpt sysmodule_opt;\n\n\tinit_param.global_heap_size = SCE_KERNEL_128MiB;\n\tinit_param.cdlg_mode = 0;\n\tinit_param.global_heap_alignment = 0;\n\tinit_param.global_heap_disable_assert_on_alloc_failure = 0;\n\n\tsysmodule_opt.flags = 0;\n\tsysmodule_opt.result = &load_res;\n\n\tret = sceSysmoduleLoadModuleInternalWithArg(SCE_SYSMODULE_INTERNAL_PAF, sizeof(init_param), &init_param, &sysmodule_opt);\n\n\tif (ret < 0) {\n\t\tsceClibPrintf(\"[PAF PRX] Loader: 0x%x\\n\", ret);\n\t\tsceClibPrintf(\"[PAF PRX] Loader result: 0x%x\\n\", load_res);\n\t}\n}"
  },
  {
    "path": "NetStream/source/players/player_av.cpp",
    "content": "﻿#include <kernel.h>\n#include <kernel/dmacmgr.h>\n#include <paf.h>\n#include <libdbg.h>\n#include <appmgr.h>\n#include <libsysmodule.h>\n#include <sceavplayer_webmaf.h>\n#include <avcdec.h>\n#include <audioout.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"event.h\"\n#include \"players/player_av.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[AV]\"\n\nusing namespace paf;\n\nstatic const char *k_supportedExtensions[] = {\n\t\t\".ts\",\n\t\t\".mpg\",\n\t\t\".m2ts\",\n\t\t\".mp4\",\n\t\t\".m4v\",\n\t\t\".m4a\",\n\t\t\".mpd\"\n};\n\nAVPlayer::SmoothStreaming *AVPlayer::SmoothStreaming::s_vodObjStorage = NULL;\n\nAVPlayer::SmoothStreaming::SmoothStreaming()\n{\n\tm_curl = NULL;\n\tm_tmpBuf = NULL;\n\tm_total = 0;\n\tm_lastError = 200;\n\tm_prVod = NULL;\n\n\tm_curl = curl_easy_init();\n\t//curl_easy_setopt(m_curl, CURLOPT_SHARE, s_fileCurlSh);\n\tcurl_easy_setopt(m_curl, CURLOPT_BUFFERSIZE, SCE_KERNEL_64KiB);\n\tcurl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, CurlDownload);\n\tcurl_easy_setopt(m_curl, CURLOPT_USERAGENT, USER_AGENT);\n\tcurl_easy_setopt(m_curl, CURLOPT_ACCEPT_ENCODING, \"\");\n\tcurl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, 0L);\n\tcurl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 0L);\n\tcurl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1L);\n\tcurl_easy_setopt(m_curl, CURLOPT_TCP_KEEPALIVE, 1L);\n\tcurl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, 1L);\n\tcurl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this);\n\tcurl_easy_setopt(m_curl, CURLOPT_CONNECTTIMEOUT, 5L);\n\tcurl_easy_setopt(m_curl, CURLOPT_TIMEOUT, 15L);\n\tif (utils::GetGlobalProxy())\n\t{\n\t\tcurl_easy_setopt(m_curl, CURLOPT_PROXY, utils::GetGlobalProxy());\n\t}\n\n\tm_tmpBuf = static_cast<uint8_t *>(sce_paf_malloc(SCE_KERNEL_4MiB));\n\tsce_paf_memset(m_tmpBuf, 0, SCE_KERNEL_4MiB);\n}\n\nAVPlayer::SmoothStreaming::~SmoothStreaming()\n{\n\tif (m_curl)\n\t{\n\t\tcurl_easy_cleanup(m_curl);\n\t}\n\tif (m_tmpBuf)\n\t{\n\t\tsce_paf_free(m_tmpBuf);\n\t}\n}\n\nvoid AVPlayer::SmoothStreaming::GetLiveReplacement(SceAvPlayerHttpReplacement *repl)\n{\n\tif (!repl)\n\t{\n\t\treturn;\n\t}\n\n\trepl->init =\n\t[](SceAvPlayerHttpInstance *instancePP, void *objPtr, SceAvPlayerHTTPAllocate alloc,\n\t\tSceAvPlayerHTTPDeallocate dealloc, char *userAgent, SceAvPlayerHTTPCtx *httpCtxId)\n\t{\n\t\tSmoothStreaming *client = new SmoothStreaming();\n\t\t*instancePP = static_cast<void *>(client);\n\t\treturn SCE_OK;\n\t};\n\trepl->deInit =\n\t[](SceAvPlayerHttpInstance *instancePP)\n\t{\n\t\tif (!instancePP || !*instancePP)\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\t\tSmoothStreaming *client = static_cast<SmoothStreaming *>(*instancePP);\n\t\tdelete client;\n\t\treturn SCE_OK;\n\t};\n\trepl->post =\n\t[](SceAvPlayerHttpInstance instanceP, char *url, bool continuation,\n\t\tSceAvPlayerHTTPHeader *headers, uint8_t numHeaders, uint8_t *body, uint32_t len,\n\t\tuint8_t *buf, uint32_t bufLen, bool *completed)\n\t{\n\t\treturn (static_cast<SmoothStreaming *>(instanceP))->LivePostImpl(url, continuation, headers, numHeaders, body, len, buf, bufLen, completed);\n\t};\n\trepl->get =\n\t[](SceAvPlayerHttpInstance instanceP, char *url, bool continuation,\n\t\tuint64_t rangeStart, uint64_t rangeEnd, uint8_t *buf, uint32_t bufLen, bool *completed)\n\t{\n\t\treturn (static_cast<SmoothStreaming *>(instanceP))->LiveGetImpl(url, continuation, rangeStart, rangeEnd, buf, bufLen, completed);\n\t};\n\trepl->setRedirectCb = [](SceAvPlayerHttpInstance instanceP, SceAvPlayerHttpRedirectCb *redirectCb, void *object) { return SCE_OK; };\n\trepl->setCert = [](SceAvPlayerHttpInstance instanceP, SceAvPlayerHTTPSData *cert, SceAvPlayerHTTPSData *privKey) { return SCE_OK; };\n\trepl->setRecvTimeout = [](SceAvPlayerHttpInstance instanceP, int64_t usec) { return SCE_OK; };\n\trepl->getLastStatus = [](SceAvPlayerHttpInstance instanceP) { return (static_cast<SmoothStreaming *>(instanceP))->GetLastStatusImpl(); };\n\n}\n\nvoid AVPlayer::SmoothStreaming::GetVODReplacement(SceAvPlayerFileReplacement *repl)\n{\n\tif (!repl)\n\t{\n\t\treturn;\n\t}\n\n\trepl->open =\n\t[](void *argP, const char *argFilename)\n\t{\n\t\tSmoothStreaming *client = new SmoothStreaming();\n\t\tSmoothStreaming **instancePP = static_cast<SmoothStreaming **>(argP);\n\t\t*instancePP = client;\n\t\treturn client->VodOpenFileImpl(argFilename);\n\t};\n\trepl->close =\n\t[](void *argP)\n\t{\n\t\tSmoothStreaming *client = *(static_cast<SmoothStreaming **>(argP));\n\t\tint32_t ret = client->VodCloseFileImpl();\n\t\tdelete client;\n\t\treturn ret;\n\t};\n\trepl->readOffset = [](void *argP, uint8_t *argBuffer, uint64_t argPosition, uint32_t argLength) { return (*(static_cast<SmoothStreaming **>(argP)))->VodReadOffsetFileImpl(argBuffer, argPosition, argLength); };\n\trepl->size = [](void *argP) { return (*(static_cast<SmoothStreaming **>(argP)))->VodSizeFileImpl(); };\n\trepl->objectPointer = &s_vodObjStorage;\n}\n\nsize_t AVPlayer::SmoothStreaming::CurlDownload(char *buffer, size_t size, size_t nitems, void *userdata)\n{\n\tSmoothStreaming *obj = static_cast<SmoothStreaming *>(userdata);\n\tsize_t toWrite = size * nitems;\n\n\tif (toWrite != 0)\n\t{\n\t\tif (obj->m_total + toWrite >= SCE_KERNEL_4MiB)\n\t\t{\n\t\t\tSCE_DBG_LOG_ERROR(\"[CurlDownload] tmp buffer is too small!\");\n\t\t\treturn 0;\n\t\t}\n\t\tsce_paf_memcpy(obj->m_tmpBuf + obj->m_total, buffer, toWrite);\n\t\tobj->m_total += toWrite;\n\t}\n\n\treturn toWrite;\n}\n\nint64_t AVPlayer::SmoothStreaming::LivePostImpl(char *url, bool continuation,\n\tSceAvPlayerHTTPHeader *headers, uint8_t numHeaders, uint8_t *body, uint32_t len,\n\tuint8_t *buf, uint32_t bufLen, bool *completed)\n{\n\t*completed = false;\n\n\treturn -1;\n}\n\n/*\nNotes on behaviour:\n\n*completed = false\nif(!continuation)\n{\n\tif (rangeStart || rangeEnd)\n\t{\n\t\tsetup ranged request\n\t\treturn ranged request size in bytes\n\t}\n\telse\n\t{\n\t\treturn content-length or -1 if it is unknown, but last status should be set to 200\n\t}\n}\nelse\n{\n\tif (ranged request)\n\t{\n\t\treadBytes = read(buf, bufLen);\n\t\t*completed = true\n\t\treturn readBytes\n\t}\n\telse\n\t{\n\t\treadBytes = read(buf, bufLen);\n\n\t\tif (eof)\n\t\t{\n\t\t\t*completed = true\n\t\t}\n\n\t\treturn readBytes\n\t}\n}\n\nNote that if size is unknown, next calls with continuation=true will come with arbitrary 4 KiB bufLen, expecting to read the file in chunks until EOF (as if it is normal local file)\n\n*/\nint64_t AVPlayer::SmoothStreaming::LiveGetImpl(\n\tchar *url,\n\tbool continuation,\n\tuint64_t rangeStart,\n\tuint64_t rangeEnd,\n\tuint8_t *buf,\n\tuint32_t bufLen,\n\tbool *completed)\n{\n\t*completed = false;\n\n\tSCE_DBG_LOG_TRACE(\"[LiveGetImpl] LiveGetImpl(): try read %d, %llu-%llu (%llu), %u, 0x%08X\", continuation, rangeStart, rangeEnd, rangeEnd - rangeStart, bufLen, buf);\n\n\tif (!continuation)\n\t{\n\t\t// Reset state\n\t\tm_readSz = 0;\n\t\tm_hasRange = (rangeStart || rangeEnd);\n\t\tm_rangeStart = rangeStart;\n\t\tm_rangeEnd = rangeEnd;\n\t\tm_downloadDone = false;\n\t\tm_total = 0;\n\t\tm_vod.reset();\n\n\t\tcurl_easy_setopt(m_curl, CURLOPT_URL, url);\n\n\t\tm_lastError = 200;\n\n\t\tif (!sce_paf_strncmp(url + 7, \"localfile:\", 10))\n\t\t{\n\t\t\t//SCE_DBG_LOG_INFO(\"[LiveGetImpl] Is a local file: %s\", url);\n\t\t\tint32_t ret = SCE_OK;\n\t\t\tm_vod = LocalFile::Open(url + 17, File::RDONLY, 0, &ret);\n\t\t\tif (ret != SCE_PAF_OK)\n\t\t\t{\n\t\t\t\tm_lastError = 404;\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\t//SCE_DBG_LOG_INFO(\"[LiveGetImpl] Open ok\");\n\t\t}\n\n\t\tif (m_hasRange)\n\t\t{\n\t\t\tif (rangeEnd >= rangeStart)\n\t\t\t{\n\t\t\t\t//SCE_DBG_LOG_INFO(\"[LiveGetImpl] Req type: ranged, normal\");\n\t\t\t\treturn static_cast<int64_t>(rangeEnd - rangeStart + 1);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//SCE_DBG_LOG_ERROR(\"[LiveGetImpl] Req type: ranged, open-ended, aborting...\");\n\t\t\t\tm_lastError = 404;\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\t//SCE_DBG_LOG_INFO(\"[LiveGetImpl] Req type: normal\");\n\n\t\t\tif (m_vod.get())\n\t\t\t{\n\t\t\t\treturn m_vod->GetFileSize();\n\t\t\t}\n\n\t\t\treturn -1;\n\t\t}\n\t}\n\telse\n\t{\n\t\t// If already downloaded fully, just return EOF\n\t\tif (m_downloadDone && m_readSz >= m_total)\n\t\t{\n\t\t\t//SCE_DBG_LOG_ERROR(\"[LiveGetImpl] Trying to repeat completed request!\");\n\t\t\t*completed = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Configure curl on first continuation\n\t\tif (m_total == 0 && !m_downloadDone)\n\t\t{\n\t\t\tif (m_vod.get())\n\t\t\t{\n\t\t\t\tif (m_hasRange)\n\t\t\t\t{\n\t\t\t\t\t//SCE_DBG_LOG_INFO(\"[LiveGetImpl] Setup ranges...\");\n\t\t\t\t\tm_vod->Seek(m_rangeStart, File::SET);\n\t\t\t\t}\n\t\t\t\tm_total = m_vod->GetFileSize();\n\t\t\t\tif (m_total > SCE_KERNEL_4MiB)\n\t\t\t\t{\n\t\t\t\t\tSCE_DBG_LOG_ERROR(\"[LiveGetImpl] tmp buffer is too small!\");\n\t\t\t\t\tm_lastError = 404;\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\tm_total = m_vod->Read(m_tmpBuf, m_total);\n\t\t\t\t//SCE_DBG_LOG_INFO(\"[LiveGetImpl] m_vod->Read(): %u\", m_total);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tif (m_hasRange)\n\t\t\t\t{\n\t\t\t\t\tchar range[128];\n\t\t\t\t\tif (m_rangeEnd > 0)\n\t\t\t\t\t{\n\t\t\t\t\t\tsce_paf_snprintf(range, sizeof(range), \"%llu-%llu\", m_rangeStart, m_rangeEnd);\n\t\t\t\t\t}\n\t\t\t\t\telse\n\t\t\t\t\t{\n\t\t\t\t\t\tsce_paf_snprintf(range, sizeof(range), \"%llu-\", m_rangeStart);\n\t\t\t\t\t}\n\t\t\t\t\tcurl_easy_setopt(m_curl, CURLOPT_RANGE, range);\n\t\t\t\t\t//SCE_DBG_LOG_INFO(\"[LiveGetImpl] Setup ranges: %s\", range);\n\t\t\t\t}\n\n\t\t\t\tCURLcode res = curl_easy_perform(m_curl);\n\t\t\t\tif (res == CURLE_OPERATION_TIMEDOUT)\n\t\t\t\t{\n\t\t\t\t\tres = curl_easy_perform(m_curl);\n\t\t\t\t}\n\t\t\t\tcurl_easy_getinfo(m_curl, CURLINFO_RESPONSE_CODE, &m_lastError);\n\t\t\t\tif (res != CURLE_OK)\n\t\t\t\t{\n\t\t\t\t\tSCE_DBG_LOG_ERROR(\"[LiveGetImpl] curl_easy_perform() returned %d, %d\\n\", res, m_lastError);\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm_readSz = 0;\n\t\t\tm_downloadDone = true;\n\n\t\t\t//SCE_DBG_LOG_INFO(\"[LiveGetImpl] Total: %u\", m_total);\n\t\t}\n\n\t\tuint32_t remain = m_total - m_readSz;\n\t\tsize_t toRead = paf::min<size_t>(remain, bufLen);\n\t\t//SCE_DBG_LOG_INFO(\"[LiveGetImpl] To read: %u\", toRead);\n\t\tif (toRead > 0)\n\t\t{\n\t\t\tsce_paf_memcpy(buf, m_tmpBuf + m_readSz, toRead);\n\t\t\tm_readSz += toRead;\n\t\t}\n\n\t\tif (m_readSz >= m_total)\n\t\t{\n\t\t\t//SCE_DBG_LOG_INFO(\"[LiveGetImpl] EOF\");\n\t\t\t*completed = true;\n\t\t}\n\n\t\treturn static_cast<int64_t>(toRead);\n\t}\n\n\treturn -1;\n}\n\nint32_t AVPlayer::SmoothStreaming::GetLastStatusImpl()\n{\n\treturn m_lastError;\n}\n\nint64_t AVPlayer::SmoothStreaming::GetFileSizeImpl()\n{\n\tif (m_vod.get())\n\t{\n\t\treturn m_vod->GetFileSize();\n\t}\n\n\treturn 0;\n}\n\nint32_t AVPlayer::SmoothStreaming::VodOpenFileImpl(const char *argFilename)\n{\n\tint32_t ret = SCE_OK;\n\n\tSCE_DBG_LOG_INFO(\"[VodOpenFileImpl] VodOpenFileImpl: %s\", argFilename);\n\n\tif (!sce_paf_strncmp(argFilename, \"localfile:\", 10))\n\t{\n\t\tm_vod = LocalFile::Open(argFilename + 10, File::RDONLY, 0, &ret);\n\t}\n\telse\n\t{\n\t\tm_vod = CurlFile::Open(argFilename, File::RDONLY, 0, &ret, NULL, utils::GetGlobalProxy());\n\t}\n\tif (ret < 0)\n\t{\n\t\treturn -1;\n\t}\n\n\tm_vodBuf = MallocBuffer::Allocate(SCE_KERNEL_16MiB);\n\tm_prVod = new PredictiveFile(m_vodBuf);\n\n\tret = m_prVod->Open(m_vod);\n\tif (ret < 0)\n\t{\n\t\treturn -1;\n\t}\n\n\treturn 0;\n}\n\nint32_t AVPlayer::SmoothStreaming::VodCloseFileImpl()\n{\n\tm_prVod->Close();\n\tdelete m_prVod;\n\tm_vodBuf.reset();\n\tm_vod.reset();\n\n\treturn 0;\n}\n\nint32_t AVPlayer::SmoothStreaming::VodReadOffsetFileImpl(uint8_t *argBuffer, uint64_t argPosition, uint32_t argLength)\n{\n\tint32_t ret = m_prVod->ReadEx(argBuffer, argPosition, argLength);\n\tif (ret == PredictiveFile::PRF_ERR_EX_WAIT)\n\t{\n\t\tret = 0;\n\t}\n\treturn  ret;\n}\n\nuint64_t AVPlayer::SmoothStreaming::VodSizeFileImpl()\n{\n\treturn m_prVod->GetDwlSize();\n}\n\nvoid AVPlayer::AVAudioThread::EntryFunction()\n{\n\tint32_t ret = false;\n\tSceAvPlayerFrameInfo data;\n\tint32_t outPortId = -1;\n\tbool usingFallback = false;\n\n\tSCE_DBG_LOG_INFO(\"[AVAudioThread] AVAudioThread start\");\n\n\tuint8_t *silence = (uint8_t *)sce_paf_memalign(0x20, SCE_AV_PLAYER_PCM_BUFFER_SIZE * 2  * 4);\n\tsce_paf_memset(silence, 0, SCE_AV_PLAYER_PCM_BUFFER_SIZE * 2 * 4);\n\n\toutPortId = sceAudioOutOpenPort(\n\t\tSCE_AUDIO_OUT_PORT_TYPE_VOICE,\n\t\t(SCE_AV_PLAYER_PCM_BUFFER_SIZE / sizeof(int16_t)),\n\t\t44100,\n\t\t1);\n\tif (outPortId < 0)\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[AVAudioThread] Failed to open VOICE audio port\");\n\t}\n\n\twhile (!IsCanceled())\n\t{\n\t\tif (sceAvPlayerIsActive(m_playerCore))\n\t\t{\n\t\t\tret = sceAvPlayerGetAudioData(m_playerCore, &data);\n\t\t\tif (ret)\n\t\t\t{\n\t\t\t\tif (m_parent->m_lastAudioDetails.channelCount != data.details.audio.channelCount ||\n\t\t\t\t\tm_parent->m_lastAudioDetails.sampleRate != data.details.audio.sampleRate)\n\t\t\t\t{\n\t\t\t\t\tSCE_DBG_LOG_INFO(\"[AVAudioThread] Audio params changed, reconfiguring port\");\n\t\t\t\t\tSCE_DBG_LOG_INFO(\"[AVAudioThread] New params: %u %u\", data.details.audio.channelCount, data.details.audio.sampleRate);\n\n\t\t\t\t\tusingFallback = false;\n\n\t\t\t\t\tret = sceAudioOutSetConfig(\n\t\t\t\t\t\toutPortId,\n\t\t\t\t\t\t(SCE_AV_PLAYER_PCM_BUFFER_SIZE / sizeof(int16_t)),\n\t\t\t\t\t\tdata.details.audio.sampleRate,\n\t\t\t\t\t\tdata.details.audio.channelCount - 1);\n\n\t\t\t\t\tif (ret != SCE_OK)\n\t\t\t\t\t{\n\t\t\t\t\t\tSCE_DBG_LOG_ERROR(\"[AVAudioThread] Could not reconfigure audio port, using failsafe to keep timing\");\n\t\t\t\t\t\tusingFallback = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tint32_t maxVolumeArray[2] = { SCE_AUDIO_VOLUME_0DB, SCE_AUDIO_VOLUME_0DB };\n\t\t\t\t\tsceAudioOutSetVolume(outPortId, SCE_AUDIO_VOLUME_FLAG_L_CH | SCE_AUDIO_VOLUME_FLAG_R_CH, maxVolumeArray);\n\n\t\t\t\t\tm_parent->m_lastAudioDetails.channelCount = data.details.audio.channelCount;\n\t\t\t\t\tm_parent->m_lastAudioDetails.sampleRate = data.details.audio.sampleRate;\n\t\t\t\t}\n\n\t\t\t\tconst void *outData = data.pData;\n\t\t\t\tif (usingFallback)\n\t\t\t\t{\n\t\t\t\t\toutData = silence;\n\t\t\t\t}\n\t\t\t\tsceAudioOutOutput(outPortId, outData);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tsceAudioOutOutput(outPortId, silence);\n\t\t\t}\n\t\t}\n\t}\n\n\tsceAudioOutReleasePort(outPortId);\n\n\tsce_paf_free(silence);\n\n\twhile (!IsCanceled())\n\t{\n\t\tthread::Sleep(1000);\n\t}\n\n\tCancel();\n}\n\nvoid AVPlayer::SurfaceUpdateTask(void *pArgBlock)\n{\n\tstatic_cast<AVPlayer *>(pArgBlock)->OnSurfaceUpdate();\n}\n\nvoid AVPlayer::OnSurfaceUpdate()\n{\n\tSceAvPlayerFrameInfoEx data;\n\tbool ret = false;\n\n\tsce_paf_memset(&data, 0, sizeof(SceAvPlayerFrameInfo));\n\n\tif (sceAvPlayerIsActive(m_playerCore))\n\t{\n\t\tdata.pData = NULL;\n\t\tret = sceAvPlayerGetVideoDataEx(m_playerCore, &data);\n\t\tif (ret && data.pData && !m_powerSaving)\n\t\t{\n\t\t\t//SCE_DBG_LOG_INFO(\"TEXDBG got texture 0x%08X\", data.pData);\n\t\t\t\n\t\t\tif (m_lastVideoDetails.width != data.details.video.width ||\n\t\t\t\tm_lastVideoDetails.height != data.details.video.height)\n\t\t\t{\n\t\t\t\tSCE_DBG_LOG_INFO(\"[SurfaceUpdateTask] Video dimensions changed, clearing draw surface map\");\n\t\t\t\tSCE_DBG_LOG_INFO(\"[SurfaceUpdateTask] New dimensions: %u %u\", data.details.video.width, data.details.video.height);\n\t\t\t\tSCE_DBG_LOG_INFO(\"[SurfaceUpdateTask] New pitch: %u\", data.details.video.pitch);\n\n\t\t\t\tauto itr = m_drawSurf.begin();\n\t\t\t\twhile (itr != m_drawSurf.end())\n\t\t\t\t{\n\t\t\t\t\t(*itr).second.clear();\n\t\t\t\t\titr = m_drawSurf.erase(itr);\n\t\t\t\t}\n\n\t\t\t\t//float aspect = (float)data.uTexWidth / (float)data.uTexHeight;\n\t\t\t\t//if (aspect > 1.78f || aspect < 1.76f)\n\t\t\t\t{\n\t\t\t\t\t//SCE_DBG_LOG_INFO(\"[BEAV] Suspicious aspect ratio (%.03f), so respect it\", aspect);\n\t\t\t\t\tgraph::PlaneObj *po = static_cast<graph::PlaneObj *>(m_target->GetDrawObj(ui::Plane::OBJ_PLANE));\n\t\t\t\t\tpo->SetScaleMode(graph::PlaneObj::SCALE_ASPECT_SIZE, graph::PlaneObj::SCALE_ASPECT_SIZE);\n\t\t\t\t}\n\n\t\t\t\tm_lastVideoDetails.width = data.details.video.width;\n\t\t\t\tm_lastVideoDetails.height = data.details.video.height;\n\t\t\t}\n\n\t\t\tuint64_t detailMagic = (uint32_t)data.pData + data.details.video.width + data.details.video.height;\n\n\t\t\tif (!m_drawSurf[detailMagic].get())\n\t\t\t{\n\t\t\t\tSCE_DBG_LOG_INFO(\"[SurfaceUpdateTask] Initting new texture...\");\n\n\t\t\t\tm_drawSurf[detailMagic] = new graph::Surface(\n\t\t\t\t\tdata.details.video.width,\n\t\t\t\t\tdata.details.video.height,\n\t\t\t\t\tImageMode_RGBA8888,\n\t\t\t\t\tImageOrder_Linear,\n\t\t\t\t\t1,\n\t\t\t\t\tdata.pData,\n\t\t\t\t\tdata.details.video.pitch * 4,\n\t\t\t\t\t1,\n\t\t\t\t\t0);\n\t\t\t}\n\n\t\t\tm_target->SetTexture(m_drawSurf[detailMagic]);\n\t\t}\n\t}\n}\n\nvoid AVPlayer::OnBootJob()\n{\n\tint32_t ret = false;\n\tm_playerCore = 0;\n\tm_audioThread = NULL;\n\tm_currentState = PlayerState_Stop;\n\tsce_paf_memset(&m_lastVideoDetails, 0, sizeof(SceAvPlayerVideo));\n\tsce_paf_memset(&m_lastAudioDetails, 0, sizeof(SceAvPlayerAudio));\n\tm_currentVideoStreamId = -1;\n\tm_currentAudioStreamId = -1;\n\tm_jumpTimeMs = -1;\n\tm_duration = 0;\n\tm_lastSeekState = SeekState_Ok;\n\tm_ssStream = false;\n\n\tSceAvPlayerInitData playerInit;\n\tsce_paf_memset(&playerInit, 0, sizeof(SceAvPlayerInitData));\n\tplayerInit.memoryReplacement.allocate = PlayerAllocate;\n\tplayerInit.memoryReplacement.deallocate = PlayerDeallocate;\n\tplayerInit.memoryReplacement.allocateTexture = PlayerAllocateTexture;\n\tplayerInit.memoryReplacement.deallocateTexture = PlayerDeallocateTexture;\n\tplayerInit.eventReplacement.objectPointer = this;\n\tplayerInit.eventReplacement.eventCallback = PlayerChangeStateCb;\n\tplayerInit.autoStart = false;\n\tSmoothStreaming::GetVODReplacement(&playerInit.fileReplacement);\n\tplayerInit.debugLevel = SCE_AVPLAYER_DBG_WARNINGS;\n\tm_playerCore = sceAvPlayerInit(&playerInit);\n\tif (!m_playerCore)\n\t{\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\n\tSceAvPlayerPostInitDataNew postData;\n\tsce_paf_memset(&postData, 0, sizeof(SceAvPlayerPostInitDataNew));\n\tSmoothStreaming::GetLiveReplacement(&postData.httpReplacement);\n\tret = sceAvPlayerPostInit(m_playerCore, (SceAvPlayerPostInitData *)&postData);\n\tif (ret != SCE_OK)\n\t{\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\n\t/*\n\tSceAvPlayerPostInitDataEx postDataEx;\n\tsce_paf_memset(&postDataEx, 0, sizeof(SceAvPlayerPostInitDataEx));\n\tpostDataEx.demuxSharedHeapSize = 64 * 1014 * 1024;\n\tpostDataEx.demuxAudioBufferSize = 4 * 1024 * 1024;\n\tpostDataEx.demuxVideoBufferSize = 4 * 1024 * 1024;\n\tret = sceAvPlayerPostInitEx(m_playerCore, &postDataEx);\n\tif (ret != SCE_OK)\n\t{\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\t*/\n\n\tSCE_DBG_LOG_INFO(\"[BootJob] sceAvPlayerAddSource: %s\", m_path.c_str());\n\tret = sceAvPlayerAddSource(m_playerCore, m_path.c_str());\n\tif (ret != SCE_OK)\n\t{\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\n\tSCE_DBG_LOG_INFO(\"[BootJob] sceAvPlayerAddSource(): ok\");\n\n\twhile (m_currentState != PlayerState_Ready)\n\t{\n\t\tthread::Sleep(100);\n\t}\n\n\tSCE_DBG_LOG_INFO(\"[BootJob] Stream ready...\");\n\n\tcommon::MainThreadCallList::Register(SurfaceUpdateTask, this);\n\n\tthread::Thread::Option opt;\n\topt.affinity = thread::Thread::Affinity_All;\n\tm_audioThread = new AVAudioThread(this, m_playerCore, &opt);\n\tm_audioThread->Start();\n\n\tsceAvPlayerStart(m_playerCore);\n\n\tsceAvPlayerSetLogger(\n\t[](void *userData, const char *format, _Va_list ap)\n\t{\n\t\tstatic_cast<AVPlayer *>(userData)->OnPlayerWarning(format, ap);\n\t\treturn SCE_OK;\n\t}, this);\n\n\tSetInitState(InitState_InitOk);\n}\n\nvoid AVPlayer::OnPlayerWarning(const char *format, _Va_list ap)\n{\n\tconst char *msg = va_arg(ap, const char *);\n\tif (m_lastSeekState == SeekState_Waiting)\n\t{\n\t\tif (!sce_paf_strncmp(msg, \"E/ Seek [467]\", 13))\n\t\t{\n\t\t\tm_lastSeekState = SeekState_Failed;\n\t\t}\n\t\telse if (!sce_paf_strncmp(msg, \"W/ ProcessAckEvent [307]\", 24))\n\t\t{\n\t\t\tm_lastSeekState = SeekState_Ok;\n\t\t}\n\t}\n}\n\nAVPlayer::AVPlayer(ui::Widget *targetPlane, const char *url, Option *opt)\n{\n\tSCE_DBG_LOG_INFO(\"[AV] Open url: %s\", url);\n\tm_target = targetPlane;\n\tm_basePath = url;\n\tif (utils::IsLocalPath(url))\n\t{\n\t\tm_path = \"localfile:\";\n\t}\n\tm_path += url;\n\tif (opt)\n\t{\n\t\tif (opt->playerType == GenericPlayer::PlayerType_AV)\n\t\t{\n\t\t\tm_opt = *opt;\n\t\t}\n\t\telse\n\t\t{\n\t\t\topt->CommonCopy(m_opt);\n\t\t}\n\t}\n}\n\nAVPlayer::~AVPlayer()\n{\n\tTerm();\n}\n\nvoid AVPlayer::InitAsync()\n{\n\tBootJob *job = new BootJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tutils::GetJobQueue()->Enqueue(itemParam);\n\tSetInitState(InitState_InProgress);\n}\n\nvoid AVPlayer::Term()\n{\n\tif (m_initState != InitState_NotInit)\n\t{\n\t\tif (m_playerCore)\n\t\t{\n\t\t\tsceAvPlayerStop(m_playerCore);\n\t\t}\n\n\t\tcommon::MainThreadCallList::Unregister(SurfaceUpdateTask, this);\n\n\t\tif (m_audioThread)\n\t\t{\n\t\t\tm_audioThread->Cancel();\n\t\t\tm_audioThread->Join();\n\t\t\tdelete m_audioThread;\n\t\t}\n\n\t\tm_target->SetTexture(g_texTransparent);\n\n\t\tauto itr = m_drawSurf.begin();\n\t\twhile (itr != m_drawSurf.end())\n\t\t{\n\t\t\t(*itr).second.clear();\n\t\t\titr = m_drawSurf.erase(itr);\n\t\t}\n\n\t\tif (m_playerCore)\n\t\t{\n\t\t\tsceAvPlayerClose(m_playerCore);\n\t\t\tm_playerCore = NULL;\n\t\t}\n\t}\n\n\tSetInitState(InitState_NotInit);\n}\n\nGenericPlayer::InitState AVPlayer::GetInitState()\n{\n\treturn m_initState;\n}\n\nvoid AVPlayer::SetInitState(GenericPlayer::InitState state)\n{\n\tm_initState = state;\n\tSCE_DBG_LOG_INFO(\"[SetInitState] State changed to: %d\", state);\n\tevent::BroadcastGlobalEvent(g_appPlugin, GenericPlayerChangeState, m_initState);\n}\n\nvoid AVPlayer::ParseStreamInfo()\n{\n\tint32_t ret = SCE_OK;\n\tbool videoEnabled = false;\n\tbool audioEnabled = false;\n\n\tint32_t streamCount = sceAvPlayerStreamCount(m_playerCore);\n\tif (streamCount < 0)\n\t{\n\t\tstreamCount = 0;\n\t}\n\tm_streams.clear();\n\n\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] scount: %d\", streamCount);\n\n\tfor (int i = 0; i < streamCount; i++)\n\t{\n\t\tStreamInfo streamInfo;\n\t\tSceAvPlayerStreamInfo avStreamInfo;\n\t\tret = sceAvPlayerGetStreamInfo(m_playerCore, i, &avStreamInfo);\n\t\tif (ret == SCE_OK)\n\t\t{\n\t\t\tswitch (avStreamInfo.type)\n\t\t\t{\n\t\t\tcase SCE_AVPLAYER_VIDEO:\n\t\t\t\tif (!videoEnabled)\n\t\t\t\t{\n\t\t\t\t\tsceAvPlayerEnableStream(m_playerCore, i);\n\t\t\t\t\tm_currentVideoStreamId = i;\n\t\t\t\t\tvideoEnabled = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsceAvPlayerDisableStream(m_playerCore, i);\n\t\t\t\t\tSCE_DBG_LOG_WARNING(\"[ParseStreamInfo] Multiple video streams detected, only one stream is supported at the time\");\n\t\t\t\t}\n\t\t\t\tstreamInfo.type = StreamType_Video;\n\t\t\t\tbreak;\n\t\t\tcase SCE_AVPLAYER_AUDIO:\n\t\t\t\tif (!audioEnabled)\n\t\t\t\t{\n\t\t\t\t\tsceAvPlayerEnableStream(m_playerCore, i);\n\t\t\t\t\tm_currentAudioStreamId = i;\n\t\t\t\t\taudioEnabled = true;\n\t\t\t\t}\n\t\t\t\telse\n\t\t\t\t{\n\t\t\t\t\tsceAvPlayerDisableStream(m_playerCore, i);\n\t\t\t\t\tSCE_DBG_LOG_WARNING(\"[ParseStreamInfo] Multiple audio streams detected, only one stream is supported at the time\");\n\t\t\t\t}\n\t\t\t\tstreamInfo.type = StreamType_Audio;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (m_duration == 0)\n\t\t\t{\n\t\t\t\tm_duration = avStreamInfo.duration;\n\t\t\t\tSCE_DBG_LOG_INFO(\"[AV] Total stream duration: %u\", m_duration);\n\t\t\t}\n\n\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] Got stream %d of type %d\", i, streamInfo.type);\n\n\t\t\t// For local streams this will return negative error\n\t\t\t// Also representationCount > 0 means we are using SmoothStreaming/yucca\n\t\t\tint32_t representationCount = sceAvPlayerRepresentationCount(m_playerCore, i);\n\t\t\tif (representationCount < 0)\n\t\t\t{\n\t\t\t\trepresentationCount = 0;\n\t\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] repcount: %d\", 1);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tm_ssStream = true;\n\t\t\t\tsceAvPlayerSetLooping(m_playerCore, true);\n\t\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] repcount: %d\", representationCount);\n\t\t\t}\n\n\t\t\tif (representationCount == 0)\n\t\t\t{\n\t\t\t\tStreamInfo::RepresentationInfo repInfo;\n\t\t\t\t{\n\t\t\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] Got representation %d - %d\", i, 0);\n\t\t\t\t\trepInfo.bitrate = 0;\n\t\t\t\t\tswitch (avStreamInfo.type)\n\t\t\t\t\t{\n\t\t\t\t\tcase SCE_AVPLAYER_VIDEO:\n\t\t\t\t\t\trepInfo.width = avStreamInfo.details.video.width;\n\t\t\t\t\t\trepInfo.height = avStreamInfo.details.video.height;\n\t\t\t\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] repinfo - bitrate: %u, width: %u, height: %u\", repInfo.bitrate, repInfo.width, repInfo.height);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SCE_AVPLAYER_AUDIO:\n\t\t\t\t\t\trepInfo.ch = avStreamInfo.details.audio.channelCount;\n\t\t\t\t\t\trepInfo.srate = avStreamInfo.details.audio.sampleRate;\n\t\t\t\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] repinfo - bitrate: %u, ch: %u, srate: %u\", repInfo.bitrate, repInfo.ch, repInfo.srate);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tstreamInfo.representation.push_back(repInfo);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tfor (int j = 0; j < representationCount; j++)\n\t\t\t\t{\n\t\t\t\t\tStreamInfo::RepresentationInfo repInfo;\n\t\t\t\t\tSceAvPlayerRepresentationInfo avRepInfo;\n\t\t\t\t\tret = sceAvPlayerGetRepresentationInfo(m_playerCore, i, j, &avRepInfo);\n\t\t\t\t\tif (ret == SCE_OK)\n\t\t\t\t\t{\n\t\t\t\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] Got representation %d - %d\", i, j);\n\t\t\t\t\t\trepInfo.bitrate = avRepInfo.bitrate;\n\t\t\t\t\t\tswitch (avRepInfo.type)\n\t\t\t\t\t\t{\n\t\t\t\t\t\tcase SCE_AVPLAYER_REPRESENTATION_VIDEO:\n\t\t\t\t\t\t\trepInfo.width = avRepInfo.details.video.width;\n\t\t\t\t\t\t\trepInfo.height = avRepInfo.details.video.height;\n\t\t\t\t\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] repinfo - bitrate: %u, width: %u, height: %u\", repInfo.bitrate, repInfo.width, repInfo.height);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase SCE_AVPLAYER_REPRESENTATION_AUDIO:\n\t\t\t\t\t\t\trepInfo.ch = avRepInfo.details.audio.channelCount;\n\t\t\t\t\t\t\trepInfo.srate = avRepInfo.details.audio.sampleRate;\n\t\t\t\t\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] repinfo - bitrate: %u, ch: %u, srate: %u\", repInfo.bitrate, repInfo.ch, repInfo.srate);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstreamInfo.representation.push_back(repInfo);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tm_streams.push_back(streamInfo);\n\t\t}\n\t}\n}\n\nuint32_t AVPlayer::GetTotalTimeMs()\n{\n\treturn m_duration;\n}\n\nuint32_t AVPlayer::GetCurrentTimeMs()\n{\n\tif (m_jumpTimeMs != -1)\n\t{\n\t\treturn m_jumpTimeMs;\n\t}\n\treturn sceAvPlayerCurrentTime(m_playerCore);\n}\n\nbool AVPlayer::JumpToTimeMs(uint32_t time)\n{\n\tSCE_DBG_LOG_INFO(\"[AV] JumpToTime: %u\", time);\n\tif (time > (m_duration - 100))\n\t{\n\t\ttime = m_duration - 100;\n\t}\n\n\tif (m_currentState == PlayerState_Eof && !m_ssStream)\n\t{\n\t\tsceAvPlayerStop(m_playerCore);\n\t\tsceAvPlayerStart(m_playerCore);\n\t\tm_currentState = PlayerState_Stop;\n\t}\n\tsceAvPlayerJumpToTime(m_playerCore, time);\n\n\tm_lastSeekState = SeekState_Waiting;\n\twhile (m_lastSeekState == SeekState_Waiting)\n\t{\n\t\tthread::Sleep(10);\n\t}\n\tif (m_lastSeekState != SeekState_Ok)\n\t{\n\t\treturn false;\n\t}\n\n\tm_jumpTimeMs = time;\n\n\treturn true;\n}\n\nGenericPlayer::PlayerState AVPlayer::GetState()\n{\n\treturn m_currentState;\n}\n\nvoid AVPlayer::SetPowerSaving(bool enable)\n{\n\tm_powerSaving = enable;\n}\n\nuint32_t AVPlayer::GetVideoRepresentationNum()\n{\n\treturn 1;\n}\n\nuint32_t AVPlayer::GetAudioRepresentationNum()\n{\n\treturn 1;\n}\n\nvoid AVPlayer::GetActiveRepresentationsInfo(StreamInfo::RepresentationInfo *info)\n{\n\tif (!info)\n\t{\n\t\treturn;\n\t}\n\n\tuint32_t vidBitrate = 0;\n\tsceAvPlayerGetStreamSetBitrate(m_playerCore, m_currentVideoStreamId, &vidBitrate);\n\tsceAvPlayerGetStreamSetBitrate(m_playerCore, m_currentAudioStreamId, &info->bitrate);\n\tinfo->bitrate += vidBitrate;\n\tinfo->width = m_lastVideoDetails.width;\n\tinfo->height = m_lastVideoDetails.height;\n\tinfo->srate = m_lastAudioDetails.sampleRate;\n\tinfo->ch = m_lastAudioDetails.channelCount;\n}\n\nvoid AVPlayer::SwitchPlaybackState()\n{\n\tif (m_currentState == PlayerState_Stop || m_currentState == PlayerState_Ready)\n\t{\n\t\tsceAvPlayerStart(m_playerCore);\n\t\tsceAvPlayerJumpToTime(m_playerCore, 1000);\n\t}\n\telse if (m_currentState == PlayerState_Pause)\n\t{\n\t\tsceAvPlayerResume(m_playerCore);\n\t}\n\telse if (m_currentState == PlayerState_Play)\n\t{\n\t\tsceAvPlayerPause(m_playerCore);\n\t}\n}\n\nbool AVPlayer::IsPaused()\n{\n\treturn (m_currentState == PlayerState_Pause);\n}\n\nvoid AVPlayer::SetState(int32_t argEventId)\n{\n\tswitch (argEventId)\n\t{\n\tcase SCE_AVPLAYER_STATE_STOP:\n\t\tm_currentState = PlayerState_Stop;\n\t\tbreak;\n\tcase SCE_AVPLAYER_STATE_READY:\n\t\tParseStreamInfo();\n\t\tm_currentState = PlayerState_Ready;\n\t\tbreak;\n\tcase SCE_AVPLAYER_STATE_PLAY:\n\t\tm_currentState = PlayerState_Play;\n\t\tm_jumpTimeMs = -1;\n\t\tbreak;\n\tcase SCE_AVPLAYER_STATE_PAUSE:\n\t\tm_currentState = PlayerState_Pause;\n\t\tbreak;\n\tcase SCE_AVPLAYER_STATE_BUFFERING:\n\t\tm_currentState = PlayerState_Buffering;\n\t\tbreak;\n\tcase SCE_AVPLAYER_STATE_EOS:\n\t\tm_currentState = PlayerState_Eof;\n\t\tbreak;\n\tcase SCE_AVPLAYER_TIMED_TEXT_DELIVERY:\n\t\tbreak;\n\tcase SCE_AVPLAYER_WARNING_ID:\n\t\t// If both are empty - player failed to init\n\t\tif (m_lastVideoDetails.width == 0 && m_lastAudioDetails.sampleRate == 0)\n\t\t{\n\t\t\tSetInitState(InitState_InitFail);\n\t\t}\n\t\t// Sometimes SceAvPlayer doesn't send PLAY event after seeking, but always sends this (warning about being out of sync for a frame)\n\t\tm_jumpTimeMs = -1;\n\t\tbreak;\n\tcase SCE_AVPLAYER_ENCRYPTION:\n\t\tbreak;\n\t}\n}\n\nvoid *AVPlayer::PlayerAllocate(void *jumpback, uint32_t alignment, uint32_t size)\n{\n\treturn sce_paf_memalign(alignment, size);\n};\n\nvoid AVPlayer::PlayerDeallocate(void *jumpback, void *pMemory)\n{\n\tsce_paf_free(pMemory);\n};\n\nvoid *AVPlayer::PlayerAllocateTexture(void *jumpback, uint32_t alignment, uint32_t size)\n{\n\tSceKernelAllocMemBlockOpt blkOpt;\n\tif (alignment < SCE_KERNEL_256KiB)\n\t{\n\t\talignment = SCE_KERNEL_256KiB;\n\t}\n\tsce_paf_memset(&blkOpt, 0, sizeof(SceKernelAllocMemBlockOpt));\n\tblkOpt.size = sizeof(SceKernelAllocMemBlockOpt);\n\tblkOpt.attr = SCE_KERNEL_ALLOC_MEMBLOCK_ATTR_HAS_ALIGNMENT;\n\tblkOpt.alignment = alignment;\n\n\tGraphMem::Option opt;\n\topt.memblock_option = &blkOpt;\n\topt.gpu_map_attrib = SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE;\n\n\tvoid *ret = GraphMem::AllocOSMemory(GraphMem::DeviceType_VideoMemory, ROUND_UP(size, alignment), \"AVPlayer::DecodeMemoryPool\", &opt);\n\tif (!ret)\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[PlayerDeallocateTexture] Out of memory\");\n\t}\n\telse\n\t{\n\t\tSCE_DBG_LOG_TRACE(\"[PlayerAllocateTexture] Allocate texture 0x%08X : 0x%08X : %u\", ret, alignment, size);\n\t}\n\n\treturn ret;\n};\n\nvoid AVPlayer::PlayerDeallocateTexture(void *jumpback, void *pMemory)\n{\n\tSCE_DBG_LOG_TRACE(\"[PlayerDeallocateTexture] Free texture 0x%08X\", pMemory);\n\tGraphMem::FreeOSMemory(GraphMem::DeviceType_VideoMemory, pMemory);\n};\n\nvoid AVPlayer::PlayerChangeStateCb(void *instance, int32_t argEventId, int32_t argSourceId, void *argEventData)\n{\n\tAVPlayer *obj = static_cast<AVPlayer *>(instance);\n\tSCE_DBG_LOG_INFO(\"[PlayerChangeStateCb] State type: 0x%08X\", argEventId);\n\tobj->SetState(argEventId);\n}\n\nvoid AVPlayer::PreInit()\n{\n\tnew Module(\"app0:module/libSceAvPlayerPSVitaRGBA8888.suprx\");\n}\n\nGenericPlayer::SupportType AVPlayer::IsSupported(const char *path)\n{\n\tchar *extStart = sce_paf_strrchr(path, '.');\n\tif (!extStart)\n\t{\n\t\treturn SupportType_MaybeSupported;\n\t}\n\n\tfor (int i = 0; i < sizeof(k_supportedExtensions) / sizeof(char*); i++)\n\t{\n\t\tif (!sce_paf_strcasecmp(extStart, k_supportedExtensions[i]))\n\t\t\treturn SupportType_Supported;\n\t}\n\n\treturn SupportType_NotSupported;\n}\n\nconst char *AVPlayer::GetVersion()\n{\n\tstatic char sversion[64];\n\tuint32_t resLen = 0;\n\n\tsversion[0] = ' ';\n\tsversion[1] = 0;\n\tsceAvPlayerGetVersionInfo(sversion, sizeof(sversion), &resLen);\n\n\treturn sversion;\n}"
  },
  {
    "path": "NetStream/source/players/player_beav.cpp",
    "content": "#include <kernel.h>\n#include <kernel/dmacmgr.h>\n#include <paf.h>\n#include <libdbg.h>\n#include <appmgr.h>\n#include <libsysmodule.h>\n#include <scebeavplayer.h>\n#include <avcdec.h>\n#include <audioout.h>\n#include <taihen.h>\n#include <psp2_compat/curl/curl.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"event.h\"\n#include \"players/player_beav.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[BEAV]\"\n\nusing namespace paf;\n\nCURL *BEAVPlayer::LibLSInterface::s_plCurl = NULL;\nCURL *BEAVPlayer::LibLSInterface::s_fileCurl = NULL;\nthread::RMutex BEAVPlayer::LibLSInterface::s_plMtx = thread::RMutex(\"BEAVPlayer::plMtx\");\nthread::RMutex BEAVPlayer::LibLSInterface::s_fileMtx = thread::RMutex(\"BEAVPlayer::fileMtx\");\nSceBeavCorePlayerLibLSInterface BEAVPlayer::s_liblsInterface;\ntai_hook_ref_t BEAVPlayer::s_liblsInitHookRef;\n\nstatic const char *k_supportedExtensions[] = {\n\t\t\".m3u8\"\n};\n\nBEAVPlayer::LibLSInterface::LibLSInterface()\n{\n\tm_curl = NULL;\n\tm_readPos = 0;\n\tm_buf = NULL;\n\tm_pos = 0;\n\tm_lastError = 0;\n}\n\nBEAVPlayer::LibLSInterface::~LibLSInterface()\n{\n\tAbort();\n\tif (m_curl != s_plCurl && m_curl != s_fileCurl)\n\t{\n\t\tcurl_easy_cleanup(m_curl);\n\t}\n}\n\nvoid BEAVPlayer::LibLSInterface::Init()\n{\n\ts_plCurl = curl_easy_init();\n\tcurl_easy_setopt(s_plCurl, CURLOPT_WRITEFUNCTION, DownloadCore);\n\tcurl_easy_setopt(s_plCurl, CURLOPT_USERAGENT, USER_AGENT);\n\tcurl_easy_setopt(s_plCurl, CURLOPT_ACCEPT_ENCODING, \"\");\n\tcurl_easy_setopt(s_plCurl, CURLOPT_SSL_VERIFYHOST, 0L);\n\tcurl_easy_setopt(s_plCurl, CURLOPT_SSL_VERIFYPEER, 0L);\n\tcurl_easy_setopt(s_plCurl, CURLOPT_FOLLOWLOCATION, 1L);\n\tcurl_easy_setopt(s_plCurl, CURLOPT_TCP_KEEPALIVE, 1L);\n\tcurl_easy_setopt(s_plCurl, CURLOPT_NOPROGRESS, 1L);\n\tif (utils::GetGlobalProxy())\n\t{\n\t\tcurl_easy_setopt(s_plCurl, CURLOPT_PROXY, utils::GetGlobalProxy());\n\t}\n\n\ts_fileCurl = curl_easy_init();\n\tcurl_easy_setopt(s_fileCurl, CURLOPT_WRITEFUNCTION, DownloadCore);\n\tcurl_easy_setopt(s_fileCurl, CURLOPT_USERAGENT, USER_AGENT);\n\tcurl_easy_setopt(s_fileCurl, CURLOPT_ACCEPT_ENCODING, \"\");\n\tcurl_easy_setopt(s_fileCurl, CURLOPT_SSL_VERIFYHOST, 0L);\n\tcurl_easy_setopt(s_fileCurl, CURLOPT_SSL_VERIFYPEER, 0L);\n\tcurl_easy_setopt(s_fileCurl, CURLOPT_FOLLOWLOCATION, 1L);\n\tcurl_easy_setopt(s_fileCurl, CURLOPT_TCP_KEEPALIVE, 1L);\n\tcurl_easy_setopt(s_fileCurl, CURLOPT_NOPROGRESS, 1L);\n\tcurl_easy_setopt(s_fileCurl, CURLOPT_BUFFERSIZE, SCE_KERNEL_64KiB);\n\tif (utils::GetGlobalProxy())\n\t{\n\t\tcurl_easy_setopt(s_fileCurl, CURLOPT_PROXY, utils::GetGlobalProxy());\n\t}\n}\n\nvoid BEAVPlayer::LibLSInterface::GetReplacement(SceBeavCorePlayerLsInputPluginInterface *repl)\n{\n\tif (!repl)\n\t{\n\t\treturn;\n\t}\n\n\trepl->Open =\n\t[](char *pcURI, uint64_t uOffset, uint32_t uTimeOutMSecs, LSInputHandle *pHandle)\n\t{\n\t\tLibLSInterface *instance = new LibLSInterface();\n\t\t*pHandle = instance;\n\t\treturn instance->Open(pcURI, uOffset, uTimeOutMSecs);\n\t};\n\trepl->GetSize = [](LSInputHandle handle, uint64_t *pSize) { return static_cast<LibLSInterface *>(handle)->GetSize(pSize); };\n\trepl->Read = [](LSInputHandle handle, void *pBuffer, uint32_t uSize, uint32_t uTimeOutMSecs, uint32_t *pReadSize) { return static_cast<LibLSInterface *>(handle)->Read(pBuffer, uSize, uTimeOutMSecs, pReadSize); };\n\trepl->Abort = [](LSInputHandle handle) { return static_cast<LibLSInterface *>(handle)->Abort(); };\n\trepl->Close = [](LSInputHandle *pHandle) { delete static_cast<LibLSInterface *>(*pHandle); return LS_INPUT_OK; };\n\trepl->GetLastError = [](LSInputHandle handle, uint32_t *pNativeError) { return static_cast<LibLSInterface *>(handle)->GetLastError(pNativeError); };\n}\n\nvoid BEAVPlayer::LibLSInterface::Term()\n{\n\tcurl_easy_cleanup(s_plCurl);\n\tcurl_easy_cleanup(s_fileCurl);\n}\n\nsize_t BEAVPlayer::LibLSInterface::DownloadCore(char *buffer, size_t size, size_t nitems, void *userdata)\n{\n\tLibLSInterface *obj = static_cast<LibLSInterface *>(userdata);\n\tsize_t toCopy = size * nitems;\n\n\tif (toCopy != 0) {\n\t\tobj->m_buf = sce_paf_realloc(obj->m_buf, obj->m_pos + toCopy);\n\t\tsce_paf_memcpy(static_cast<char *>(obj->m_buf) + obj->m_pos, buffer, toCopy);\n\t\tobj->m_pos += toCopy;\n\t}\n\n\treturn toCopy;\n}\n\nLSInputResult BEAVPlayer::LibLSInterface::ConvertError(int err)\n{\n\tLSInputResult ret = LS_INPUT_OK;\n\n\tswitch (err) {\n\tcase CURLE_OK:\n\t\tbreak;\n\tcase CURLE_COULDNT_RESOLVE_PROXY:\n\t\tret = LS_INPUT_ERROR_NO_CONNECTION;\n\t\tbreak;\n\tcase CURLE_FTP_ACCEPT_TIMEOUT:\n\tcase CURLE_OPERATION_TIMEDOUT:\n\t\tret = LS_INPUT_ERROR_TIME_OUT;\n\t\tbreak;\n\tcase CURLE_AGAIN:\n\t\tret = LS_INPUT_ERROR_NO_CONNECTION;\n\t\tbreak;\n\tdefault:\n\t\tret = LS_INPUT_ERROR_NOT_SUPPORTED;\n\t\tbreak;\n\t}\n\n\treturn ret;\n}\n\nLSInputResult BEAVPlayer::LibLSInterface::Open(char *pcURI, uint64_t uOffset, uint32_t uTimeOutMSecs)\n{\n\tthread::RMutex *lockMtx = NULL;\n\n\tif (!pcURI)\n\t{\n\t\treturn LS_INPUT_ERROR_INVALID_URI_PTR;\n\t}\n\n\tchar *ext = NULL;\n\text = sce_paf_strrchr(pcURI, '.');\n\tif (ext)\n\t{\n\t\tif (!sce_paf_strncmp(ext, \".m3u8\", 5))\n\t\t{\n\t\t\tm_curl = s_plCurl;\n\t\t\tlockMtx = &s_plMtx;\n\t\t}\n\t\telse if (!sce_paf_strncmp(ext, \".ts\", 3))\n\t\t{\n\t\t\tm_curl = s_fileCurl;\n\t\t\tlockMtx = &s_fileMtx;\n\t\t}\n\t}\n\n\tif (!m_curl)\n\t{\n\t\tm_curl = curl_easy_init();\n\t\tcurl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, DownloadCore);\n\t\tcurl_easy_setopt(m_curl, CURLOPT_USERAGENT, USER_AGENT);\n\t\tcurl_easy_setopt(m_curl, CURLOPT_ACCEPT_ENCODING, \"\");\n\t\tcurl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYHOST, 0L);\n\t\tcurl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 0L);\n\t\tcurl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1L);\n\t\tcurl_easy_setopt(m_curl, CURLOPT_TCP_KEEPALIVE, 1L);\n\t\tcurl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, 1L);\n\t\tif (utils::GetGlobalProxy())\n\t\t{\n\t\t\tcurl_easy_setopt(m_curl, CURLOPT_PROXY, utils::GetGlobalProxy());\n\t\t}\n\t}\n\telse\n\t{\n\t\tlockMtx->Lock();\n\t}\n\n\tcurl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this);\n\tcurl_easy_setopt(m_curl, CURLOPT_URL, pcURI);\n\tcurl_easy_setopt(m_curl, CURLOPT_CONNECTTIMEOUT_MS, uTimeOutMSecs);\n\tcurl_easy_setopt(m_curl, CURLOPT_TIMEOUT, 15L);\n\n\tif (uOffset)\n\t{\n\t\tcurl_easy_setopt(m_curl, CURLOPT_RESUME_FROM_LARGE, uOffset);\n\t}\n\n\tCURLcode ret = curl_easy_perform(m_curl);\n\tif (lockMtx)\n\t{\n\t\tlockMtx->Unlock();\n\t}\n\tif (ret != CURLE_OK)\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[LS::Open] curl_easy_perform returned %d\", ret);\n\t\tm_lastError = ret;\n\t\treturn ConvertError(ret);\n\t}\n\n\treturn LS_INPUT_OK;\n}\n\nLSInputResult BEAVPlayer::LibLSInterface::GetSize(uint64_t *pSize)\n{\n\tif (!pSize)\n\t{\n\t\treturn LS_INPUT_ERROR_INVALID_SIZE_PTR;\n\t}\n\n\t*pSize = static_cast<uint64_t>(m_pos);\n\n\treturn LS_INPUT_OK;\n}\n\nLSInputResult BEAVPlayer::LibLSInterface::Read(void *pBuffer, uint32_t uSize, uint32_t uTimeOutMSecs, uint32_t *pReadSize)\n{\n\tif (!pBuffer)\n\t{\n\t\treturn LS_INPUT_ERROR_INVALID_BUFFER_PTR;\n\t}\n\n\tif (!pReadSize)\n\t{\n\t\treturn LS_INPUT_ERROR_INVALID_SIZE_PTR;\n\t}\n\n\tif (m_readPos + uSize > m_pos)\n\t{\n\t\tuSize = m_pos - m_readPos;\n\t}\n\tif (uSize != 0)\n\t{\n\t\tsce_paf_memcpy(pBuffer, static_cast<char *>(m_buf) + m_readPos, uSize);\n\t}\n\telse\n\t{\n\t\tsce_paf_free(m_buf);\n\t\tm_buf = NULL;\n\t\tm_pos = 0;\n\t\tm_readPos = 0;\n\t}\n\tm_readPos += uSize;\n\n\t*pReadSize = uSize;\n\n\tSCE_DBG_LOG_TRACE(\"[LS::Read] Read actual %u\", *pReadSize);\n\n\treturn LS_INPUT_OK;\n}\n\nLSInputResult BEAVPlayer::LibLSInterface::Abort()\n{\n\tif (m_buf)\n\t{\n\t\tsce_paf_free(m_buf);\n\t\tm_buf = NULL;\n\t\tm_pos = 0;\n\t\tm_readPos = 0;\n\t}\n\n\treturn LS_INPUT_OK;\n}\n\nLSInputResult BEAVPlayer::LibLSInterface::GetLastError(uint32_t *pNativeError)\n{\n\tif (!pNativeError)\n\t{\n\t\treturn LS_INPUT_ERROR_INVALID_HANDLE;\n\t}\n\n\t*pNativeError = m_lastError;\n\n\treturn LS_INPUT_OK;\n}\n\nvoid BEAVPlayer::BEAVAudioThread::EntryFunction()\n{\n\tint32_t err = false;\n\tSceBeavCorePlayerAudioData data;\n\tint32_t outPortId = -1;\n\tbool usingFallback = false;\n\n\tSCE_DBG_LOG_INFO(\"[BEAVAudioThread] BEAVAudioThread start\");\n\n\tvoid *silence = sce_paf_memalign(0x20, 4096 * 4);\n\tsce_paf_memset(silence, 0, 4096 * 4);\n\n\twhile (!IsCanceled())\n\t{\n\t\terr = sceBeavCorePlayerGetAudioData(m_playerCore, &data);\n\t\tif (err)\n\t\t{\n\t\t\tif (m_parent->m_lastAudioChannelCount != data.uChannelCount ||\n\t\t\t\tm_parent->m_lastAudioSampleRate != data.uSampleRate)\n\t\t\t{\n\t\t\t\tSCE_DBG_LOG_INFO(\"[BEAVAudioThread] Audio params changed, opening port\");\n\t\t\t\tSCE_DBG_LOG_INFO(\"[BEAVAudioThread] New params: %u %u\", data.uChannelCount, data.uSampleRate);\n\n\t\t\t\tif (outPortId > 0)\n\t\t\t\t{\n\t\t\t\t\tsceAudioOutReleasePort(outPortId);\n\t\t\t\t}\n\n\t\t\t\toutPortId = sceAudioOutOpenPort(\n\t\t\t\t\tSCE_AUDIO_OUT_PORT_TYPE_VOICE,\n\t\t\t\t\tdata.uPcmSize,\n\t\t\t\t\tdata.uSampleRate,\n\t\t\t\t\tdata.uChannelCount - 1);\n\t\t\t\tif (outPortId < 0)\n\t\t\t\t{\n\t\t\t\t\tSCE_DBG_LOG_ERROR(\"[BEAVAudioThread] Could not open audio port, using failsafe to keep timing\");\n\n\t\t\t\t\toutPortId = sceAudioOutOpenPort(\n\t\t\t\t\t\tSCE_AUDIO_OUT_PORT_TYPE_VOICE,\n\t\t\t\t\t\tdata.uPcmSize,\n\t\t\t\t\t\t44100,\n\t\t\t\t\t\t1);\n\t\t\t\t\tusingFallback = true;\n\t\t\t\t}\n\n\t\t\t\tint32_t maxVolumeArray[2] = { SCE_AUDIO_VOLUME_0DB, SCE_AUDIO_VOLUME_0DB };\n\t\t\t\tsceAudioOutSetVolume(outPortId, SCE_AUDIO_VOLUME_FLAG_L_CH | SCE_AUDIO_VOLUME_FLAG_R_CH, maxVolumeArray);\n\n\t\t\t\tif (m_parent->GetInitState() != InitState_InitOk)\n\t\t\t\t{\n\t\t\t\t\tm_parent->SetInitState(InitState_InitOk);\n\t\t\t\t}\n\n\t\t\t\tm_parent->m_lastAudioChannelCount = data.uChannelCount;\n\t\t\t\tm_parent->m_lastAudioSampleRate = data.uSampleRate;\n\t\t\t}\n\n\t\t\tif (outPortId > 0)\n\t\t\t{\n\t\t\t\tconst void *outData = silence;\n\t\t\t\tif (!usingFallback)\n\t\t\t\t{\n\t\t\t\t\toutData = data.pBuffer;\n\t\t\t\t}\n\t\t\t\tsceAudioOutOutput(outPortId, outData);\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tif (outPortId > 0)\n\t\t\t{\n\t\t\t\tsceAudioOutOutput(outPortId, silence);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (outPortId > 0)\n\t{\n\t\tsceAudioOutReleasePort(outPortId);\n\t}\n\n\tsce_paf_free(silence);\n\n\tCancel();\n}\n\nvoid BEAVPlayer::SurfaceUpdateTask(void *pArgBlock)\n{\n\tstatic_cast<BEAVPlayer *>(pArgBlock)->OnSurfaceUpdate();\n}\n\nvoid BEAVPlayer::OnSurfaceUpdate()\n{\n\tSceBeavCorePlayerVideoData data;\n\tint32_t err = false;\n\n\tdata.pFrameBuffer = NULL;\n\terr = sceBeavCorePlayerGetVideoData(m_playerCore, &data);\n\tif (err && data.pFrameBuffer && !m_powerSaving)\n\t{\n\t\tif (m_lastVideoWidth != data.uTexWidth ||\n\t\t\tm_lastVideoHeight != data.uTexHeight)\n\t\t{\n\t\t\tSCE_DBG_LOG_INFO(\"[SurfaceUpdateTask] Video dimensions changed, clearing draw surface map\");\n\t\t\tSCE_DBG_LOG_INFO(\"[SurfaceUpdateTask] New dimensions: %u %u\", data.uTexWidth, data.uTexHeight);\n\t\t\tSCE_DBG_LOG_INFO(\"[SurfaceUpdateTask] New pitch: %u\", data.uTexPitch);\n\n\t\t\tauto itr = m_drawSurf.begin();\n\t\t\twhile (itr != m_drawSurf.end())\n\t\t\t{\n\t\t\t\t(*itr).second.clear();\n\t\t\t\titr = m_drawSurf.erase(itr);\n\t\t\t}\n\n\t\t\t//float aspect = (float)data.uTexWidth / (float)data.uTexHeight;\n\t\t\t//if (aspect > 1.78f || aspect < 1.76f)\n\t\t\t{\n\t\t\t\t//SCE_DBG_LOG_INFO(\"[BEAV] Suspicious aspect ratio (%.03f), so respect it\", aspect);\n\t\t\t\tgraph::PlaneObj *po = static_cast<graph::PlaneObj *>(m_target->GetDrawObj(ui::Plane::OBJ_PLANE));\n\t\t\t\tpo->SetScaleMode(graph::PlaneObj::SCALE_ASPECT_SIZE, graph::PlaneObj::SCALE_ASPECT_SIZE);\n\t\t\t}\n\n\t\t\tm_lastVideoWidth = data.uTexWidth;\n\t\t\tm_lastVideoHeight = data.uTexHeight;\n\t\t}\n\n\t\tuint64_t detailMagic = (uint32_t)data.pFrameBuffer + data.uTexWidth + data.uTexHeight;\n\n\t\tif (!m_drawSurf[detailMagic].get())\n\t\t{\n\t\t\tSCE_DBG_LOG_INFO(\"[SurfaceUpdateTask] Initting new texture...\");\n\n\t\t\tm_drawSurf[detailMagic] = new graph::Surface(\n\t\t\t\tdata.uTexWidth,\n\t\t\t\tdata.uTexHeight,\n\t\t\t\tImageMode_RGBA8888,\n\t\t\t\tImageOrder_Linear,\n\t\t\t\t1,\n\t\t\t\tdata.pFrameBuffer,\n\t\t\t\tdata.uTexPitch * 4,\n\t\t\t\t1,\n\t\t\t\t0);\n\t\t}\n\n\t\tm_target->SetTexture(m_drawSurf[detailMagic]);\n\t}\n}\n\nvoid BEAVPlayer::OnBootJob()\n{\n\tint32_t ret = false;\n\tm_playerCore = 0;\n\tm_audioThread = NULL;\n\tm_decodeBuffer = NULL;\n\tm_lastVideoWidth = 0;\n\tm_lastVideoHeight = 0;\n\tm_lastAudioChannelCount = 0;\n\tm_lastAudioSampleRate = 0;\n\tm_bootEarlyExit = false;\n\tm_currentLsStreamlist = NULL;\n\n\tLibLSInterface::Init();\n\n\tret = sceBeavCorePlayerInitialize();\n\tif (!ret)\n\t{\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\n\tm_playerCore = sceBeavCorePlayerCreate();\n\tif (!m_playerCore)\n\t{\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\n\ts_liblsInterface.lsSetErrorHandler(0xFFFFFFFF, LsErrorHandler, this);\n\ts_liblsInterface.lsSetStatusHandler(0xFFFFFFFF, LsStatusHandler, this);\n\tsceBeavCorePlayerSetAgent(m_playerCore, USER_AGENT);\n\n\tm_decodeBuffer = GraphMem::AllocOSMemory(GraphMem::DeviceType_VideoMemory, BEAV_DECODE_BUFFER_SIZE, \"BEAVPlayer::DecodeMemory\");\n\tif (!m_decodeBuffer)\n\t{\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\n\tret = sceBeavCorePlayerSetVideoBuffer(m_playerCore, BEAV_VIDEO_BUFFER_WIDTH, BEAV_VIDEO_BUFFER_HEIGHT, BEAV_VIDEO_BUFFER_COUNT, m_decodeBuffer);\n\tif (ret != 0)\n\t{\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\n\tsceBeavCorePlayerSetLsBandwidthOpt(m_playerCore, SCE_BEAV_CORE_PLAYER_BW_SELECT_LOWEST, 10000, 10, 11000);\n\n\tret = sceBeavCorePlayerOpenTargetUrl(m_playerCore, m_path.c_str(), true);\n\tif (ret != 1)\n\t{\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\n\tthread::Thread::Option opt;\n\topt.affinity = SCE_KERNEL_CPU_MASK_USER_2;\n\tm_audioThread = new BEAVAudioThread(this, m_playerCore, &opt);\n\tm_audioThread->Start();\n\n\tSceBeavCorePlayerVideoData data;\n\tbool err = false;\n\twhile (err == false)\n\t{\n\t\tif (m_bootEarlyExit)\n\t\t{\n\t\t\tSCE_DBG_LOG_ERROR(\"[BootJob] Exit video waiting loop early\");\n\t\t\treturn;\n\t\t}\n\t\tsceBeavCorePlayerGetVideoData(m_playerCore, &data);\n\t\terr = sceBeavCorePlayerIsReady(m_playerCore);\n\t\tthread::Sleep(1000);\n\t}\n\n\tSCE_DBG_LOG_INFO(\"[BootJob] Video ready...\");\n\n\tif (GetInitState() != InitState_InitOk)\n\t{\n\t\tSetInitState(InitState_InitOk);\n\t}\n\n\tcommon::MainThreadCallList::Register(SurfaceUpdateTask, this);\n\n\twhile (m_lastVideoWidth == 0)\n\t{\n\t\tthread::Sleep(100);\n\t}\n\n\tSCE_DBG_LOG_INFO(\"[BootJob] Stream ready...\");\n}\n\nBEAVPlayer::BEAVPlayer(ui::Widget *targetPlane, const char *url, Option *opt)\n{\n\tSCE_DBG_LOG_INFO(\"[BEAVPlayer] Open url: %s\", url);\n\tm_target = targetPlane;\n\tm_path = url;\n\tif (opt)\n\t{\n\t\tif (opt->playerType == GenericPlayer::PlayerType_BEAV)\n\t\t{\n\t\t\tm_opt = *opt;\n\t\t}\n\t\telse\n\t\t{\n\t\t\topt->CommonCopy(m_opt);\n\t\t}\n\t}\n}\n\nBEAVPlayer::~BEAVPlayer()\n{\n\tTerm();\n}\n\nvoid BEAVPlayer::InitAsync()\n{\n\tBootJob *job = new BootJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tutils::GetJobQueue()->Enqueue(itemParam);\n\tSetInitState(InitState_InProgress);\n}\n\nvoid BEAVPlayer::Term()\n{\n\tif (m_initState != InitState_NotInit)\n\t{\n\t\tm_bootEarlyExit = true;\n\n\t\tif (m_playerCore)\n\t\t{\n\t\t\tsceBeavCorePlayerStop(m_playerCore);\n\t\t}\n\n\t\tcommon::MainThreadCallList::Unregister(SurfaceUpdateTask, this);\n\n\t\tif (m_audioThread)\n\t\t{\n\t\t\tm_audioThread->Cancel();\n\t\t\tm_audioThread->Join();\n\t\t\tdelete m_audioThread;\n\t\t}\n\n\t\tm_target->SetTexture(g_texTransparent);\n\n\t\tauto itr = m_drawSurf.begin();\n\t\twhile (itr != m_drawSurf.end())\n\t\t{\n\t\t\t(*itr).second.clear();\n\t\t\titr = m_drawSurf.erase(itr);\n\t\t}\n\n\t\tif (m_playerCore)\n\t\t{\n\t\t\tsceBeavCorePlayerDestroy(m_playerCore);\n\t\t\tm_playerCore = 0;\n\t\t}\n\n\t\tsceBeavCorePlayerFinalize();\n\n\t\tif (m_decodeBuffer)\n\t\t{\n\t\t\tGraphMem::FreeOSMemory(GraphMem::DeviceType_VideoMemory, m_decodeBuffer);\n\t\t}\n\n\t\tLibLSInterface::Term();\n\t}\n}\n\nGenericPlayer::InitState BEAVPlayer::GetInitState()\n{\n\treturn m_initState;\n}\n\nvoid BEAVPlayer::SetInitState(GenericPlayer::InitState state)\n{\n\tm_initState = state;\n\tSCE_DBG_LOG_INFO(\"[SetInitState] State changed to: %d\", state);\n\tevent::BroadcastGlobalEvent(g_appPlugin, GenericPlayerChangeState, m_initState);\n}\n\nvoid BEAVPlayer::ParseStreamInfo(LSStreamlist *streamlist, uint32_t representationCount)\n{\n\tint32_t ret;\n\n\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] scount: 1\");\n\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] Got stream 0 of type 0\");\n\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] repcount: %d\", representationCount);\n\n\tm_currentLsStreamlist = streamlist;\n\n\tm_streams.clear();\n\n\tStreamInfo streamInfo;\n\tstreamInfo.type = StreamType_Video;\n\n\tuint32_t defaultHeight = 0;\n\tswitch (m_opt.defaultRes)\n\t{\n\tcase Option::Resolution_144p:\n\t\tdefaultHeight = 144;\n\t\tbreak;\n\tcase Option::Resolution_240p:\n\t\tdefaultHeight = 240;\n\t\tbreak;\n\tcase Option::Resolution_360p:\n\t\tdefaultHeight = 360;\n\t\tbreak;\n\tcase Option::Resolution_480p:\n\t\tdefaultHeight = 480;\n\t\tbreak;\n\tcase Option::Resolution_720p:\n\t\tdefaultHeight = 720;\n\t\tbreak;\n\t}\n\n\tfor (int i = 0; i < representationCount; i++)\n\t{\n\t\tStreamInfo::RepresentationInfo repInfo;\n\t\ts_liblsInterface.lsStreamlistGetStreamResolution(streamlist, i, &repInfo.width, &repInfo.height);\n\t\tret = s_liblsInterface.lsStreamlistGetStreamBandwidth(streamlist, i, &repInfo.bitrate);\n\t\tif (ret == LS_OK)\n\t\t{\n\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] Got representation 0 - %d\", i);\n\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] repinfo - bitrate: %u, width: %u, height: %u\", repInfo.bitrate, repInfo.width, repInfo.height);\n\n\t\t\tif (!utils::IsVideoSupported(repInfo.width, repInfo.height))\n\t\t\t{\n\t\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] ^^^ This representation is unsupported and will be disabled\");\n\t\t\t\ts_liblsInterface.lsStreamlistDisableStream(streamlist, i);\n\t\t\t}\n\n\t\t\tif (repInfo.width == defaultHeight || repInfo.height == defaultHeight)\n\t\t\t{\n\t\t\t\ts_liblsInterface.lsStreamlistSelectStream(streamlist, i);\n\t\t\t\tSCE_DBG_LOG_INFO(\"[ParseStreamInfo] Stream 0: selected rep %d as default\", i);\n\t\t\t}\n\n\t\t\tstreamInfo.representation.push_back(repInfo);\n\t\t}\n\t}\n\n\tm_streams.push_back(streamInfo);\n}\n\nuint32_t BEAVPlayer::GetTotalTimeMs()\n{\n\treturn sceBeavCorePlayerGetTotalTime(m_playerCore);\n}\n\nuint32_t BEAVPlayer::GetCurrentTimeMs()\n{\n\treturn sceBeavCorePlayerGetElapsedTime(m_playerCore);\n}\n\nbool BEAVPlayer::JumpToTimeMs(uint32_t time)\n{\n\tSCE_DBG_LOG_INFO(\"[JumpToTimeMs] Jump to seconds: %u\", time / 1000);\n\treturn sceBeavCorePlayerJumpToTimeCode(m_playerCore, time / 1000);\n}\n\nGenericPlayer::PlayerState BEAVPlayer::GetState()\n{\n\treturn static_cast<GenericPlayer::PlayerState>(sceBeavCorePlayerGetPlayerState(m_playerCore));\n}\n\nvoid BEAVPlayer::SetPowerSaving(bool enable)\n{\n\tm_powerSaving = enable;\n}\n\nuint32_t BEAVPlayer::GetVideoRepresentationNum()\n{\n\tfor (StreamInfo const& stream : m_streams)\n\t{\n\t\tif (stream.type == StreamType_Video)\n\t\t{\n\t\t\treturn stream.representation.size();\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nuint32_t BEAVPlayer::GetAudioRepresentationNum()\n{\n\tif (m_streams.empty())\n\t{\n\t\treturn 0;\n\t}\n\n\treturn 1;\n}\n\nvoid BEAVPlayer::GetVideoRepresentationInfo(GenericRepresentationInfo *info, uint32_t idx)\n{\n\tint32_t currRepIdx = 0;\n\n\ts_liblsInterface.lsStreamlistGetStreamIndex(m_currentLsStreamlist, &currRepIdx);\n\n\tfor (StreamInfo const& stream : m_streams)\n\t{\n\t\tif (stream.type == StreamType_Video && stream.representation.size() > idx)\n\t\t{\n\t\t\tStreamInfo::RepresentationInfo const& repinfo = stream.representation.at(idx);\n\t\t\tinfo->type = stream.type;\n\t\t\tif (currRepIdx == idx)\n\t\t\t{\n\t\t\t\tinfo->currentlySelected = true;\n\t\t\t}\n\n\t\t\tif (!utils::IsVideoSupported(repinfo.width, repinfo.height))\n\t\t\t{\n\t\t\t\tinfo->enabled = false;\n\t\t\t}\n\n\t\t\tutils::ResolutionToQualityString(info->string, repinfo.width, repinfo.height, info->currentlySelected);\n\t\t}\n\t}\n}\n\nvoid BEAVPlayer::SelectVideoRepresentation(uint32_t idx)\n{\n\ts_liblsInterface.lsStreamlistSelectStream(m_currentLsStreamlist, idx);\n}\n\nvoid BEAVPlayer::GetActiveRepresentationsInfo(StreamInfo::RepresentationInfo *info)\n{\n\tif (!info)\n\t{\n\t\treturn;\n\t}\n\n\tint32_t currRepIdx = 0;\n\ts_liblsInterface.lsStreamlistGetStreamIndex(m_currentLsStreamlist, &currRepIdx);\n\ts_liblsInterface.lsStreamlistGetStreamBandwidth(m_currentLsStreamlist, currRepIdx, &info->bitrate);\n\tinfo->width = m_lastVideoWidth;\n\tinfo->height = m_lastVideoHeight;\n\tinfo->srate = m_lastAudioSampleRate;\n\tinfo->ch = m_lastAudioChannelCount;\n}\n\nvoid BEAVPlayer::SwitchPlaybackState()\n{\n\tsceBeavCorePlayerSwitchPlayState(m_playerCore);\n}\n\nbool BEAVPlayer::IsPaused()\n{\n\treturn sceBeavCorePlayerIsPaused(m_playerCore);\n}\n\nuint32_t BEAVPlayer::GetFreeHeapSize()\n{\n\treturn static_cast<memory::HeapAllocator *>(GetGlobalHeapAllocator())->GetFreeSize() - SCE_KERNEL_512KiB;\n}\n\nLSResult BEAVPlayer::LsErrorHandler(LSResult error, LSSession *session, LSStreamlist *streamlist, LSStreamfile *streamfile, void *userdata)\n{\n\tif (error != LS_STREAMFILE_ERROR_ABORTED)\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[LsErrorHandler] %d\", error);\n\t\ts_liblsInterface.lsSetErrorHandler(0xFFFFFFFF, NULL, NULL);\n\t\t(static_cast<BEAVPlayer *>(userdata))->SetInitState(InitState_InitFail);\n\t}\n\treturn LS_OK;\n}\n\nLSResult BEAVPlayer::LsStatusHandler(LSStatus status, LSSession *session, LSStreamlist *streamlist, LSStreamfile *streamfile, void *userdata)\n{\n\tint32_t ret = LS_OK;\n\tuint32_t representationCount = 0;\n\n\tBEAVPlayer *player = static_cast<BEAVPlayer *>(userdata);\n\n\tret = s_liblsInterface.lsStreamlistGetBandwidthTableCount(streamlist, &representationCount);\n\tif (ret == LS_OK)\n\t{\n\t\ts_liblsInterface.lsSessionSetBandwidthControl(session, LS_BW_CONTROL_DISABLED);\n\t\tplayer->ParseStreamInfo(streamlist, representationCount);\n\t\ts_liblsInterface.lsSetStatusHandler(0xFFFFFFFF, NULL, NULL);\n\t}\n\n\treturn LS_OK;\n}\n\n// Most of the things in this hook can be ignored, but uMaxM3U8FileSize and uM3U8WorkingMemSize are important,\n// sometimes YouTube likes to provide absolute units of a playlist, almost 1MiB in size\nLSResult BEAVPlayer::LsInitGlobalsHook(LSLibraryInitParams *params)\n{\n\t//params->uOptionFlags = ;\n\t//params->uOptionFlags |= ;\n\tparams->uNoContentTimeOutSecs = 10;\n\tparams->uNoConnectionTimeOutSecs = 10;\n\tparams->uM3u8RetrySleepMSecs = 500;\n\tparams->uM3u8RetryTimeOutMSecs = 10000;\n\tparams->uSegmentMaxRetryCount = 5;\n\tparams->uMinBufferPercentBeforeSwitchUp = 50;\n\tparams->uMinSegmentsStreamedBeforeSwitchUp = 2;\n\t//params->uMaxNumFailOversPerVariant = 10;\n\t//params->uMaxNumVariantsToCache = 5;\n\tparams->uMaxM3U8FileSize = SCE_KERNEL_1MiB;\n\tparams->uM3U8WorkingMemSize = SCE_KERNEL_512KiB;\n\t//params->uMinUnPlayedCachedSegmentsBeforeSwitchUp = 2;\n\n\treturn TAI_NEXT(LsInitGlobalsHook, s_liblsInitHookRef, params);\n}\n\nvoid BEAVPlayer::PreInit()\n{\n\tsceSysmoduleLoadModule(SCE_SYSMODULE_BEISOBMF);\n\tsceSysmoduleLoadModule(SCE_SYSMODULE_BEMP2SYS);\n\n\tModule *beavCoreModule = new Module(\"vs0:vsh/common/libBEAVCorePlayer.suprx\");\n\n\tsceBeavCorePlayerGetLibLSInterface(beavCoreModule->GetHandle(), &s_liblsInterface);\n\n\tif (utils::IsTaihenLoaded())\n\t{\n\t\ttaiHookFunctionOffset(&s_liblsInitHookRef, beavCoreModule->GetHandle(), 0, 0x14908, 1, LsInitGlobalsHook);\n\t}\n\telse\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[PreInit] Taihen not loaded\");\n\t}\n\n\tsceBeavCorePlayerMemmanagerSet(sce_paf_malloc, sce_paf_memalign, sce_paf_free);\n\tsceBeavCorePlayerMemmanagerSetGetFreeSize(GetFreeHeapSize);\n\n\tsceBeavCorePlayerLsHttpSetResolveConfig(1000, 3);\n\tsceBeavCorePlayerLsSetTimeout(5000, 5000);\n\n\tsceBeavCorePlayerSetProperty(SCE_BEAV_CORE_PLAYER_PROP_AVCDEC_MEMBLOCK_TYPE, SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW);\n\tsceBeavCorePlayerSetProperty(SCE_BEAV_CORE_PLAYER_PROP_AVCDEC_INIT_WITH_UNMAPMEM, true);\n\tsceBeavCorePlayerSetProperty(SCE_BEAV_CORE_PLAYER_PROP_AACDEC_INIT_WITH_UNMAPMEM, true);\n\tsceBeavCorePlayerSetProperty(SCE_BEAV_CORE_PLAYER_PROP_MP4DEC_START_TIMEOUT, 180000);\n\tsceBeavCorePlayerSetProperty(SCE_BEAV_CORE_PLAYER_PROP_VDEC_PIXTYPE, SCE_AVCDEC_PIXEL_RGBA8888);\n\n#ifdef _DEBUG\n\tsceBeavCorePlayerSetLogLevel(SCE_BEAV_CORE_PLAYER_LOG_LEVEL_CRITICAL | SCE_BEAV_CORE_PLAYER_LOG_LEVEL_WARNING | SCE_BEAV_CORE_PLAYER_LOG_LEVEL_VERBOSE);\n#endif\n\n\tSceBeavCorePlayerLsInputPluginInterface *interface = new SceBeavCorePlayerLsInputPluginInterface();\n\tLibLSInterface::GetReplacement(interface);\n\tsceBeavCorePlayerLsHttpSetInputPluginInterface(interface);\n}\n\nGenericPlayer::SupportType BEAVPlayer::IsSupported(const char *path)\n{\n\tchar *extStart = sce_paf_strrchr(path, '.');\n\tif (!extStart)\n\t{\n\t\treturn SupportType_MaybeSupported;\n\t}\n\n\tfor (int i = 0; i < sizeof(k_supportedExtensions) / sizeof(char*); i++)\n\t{\n\t\tif (!sce_paf_strcasecmp(extStart, k_supportedExtensions[i]))\n\t\t\treturn SupportType_Supported;\n\t}\n\n\treturn SupportType_NotSupported;\n}\n\nconst char *BEAVPlayer::GetVersion()\n{\n\treturn \"3.60\";\n}"
  },
  {
    "path": "NetStream/source/players/player_fmod.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <libdbg.h>\n#include <libsysmodule.h>\n#include <fmod/fmod.hpp>\n#include <fmod/fmod_psvita.h>\n#include <fmodngpext.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"event.h\"\n#include \"players/player_fmod.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[FMOD]\"\n\nusing namespace paf;\n\nFMOD::System *FMODPlayer::s_system = NULL;\nFMOD::ChannelGroup *FMODPlayer::s_chg = NULL;\n\nstatic const char *k_supportedExtensions[] = {\n\t\".it\",\n\t\".mod\",\n\t\".xm\",\n\t\".s3m\",\n\t\".oma\",\n\t\".aa3\",\n\t\".at3\",\n\t\".ogg\",\n\t\".mp3\",\n\t\".opus\",\n\t\".flac\",\n\t\".wav\",\n\t\".at9\",\n\t\".webm\"\n};\n\nFMOD_RESULT FMODPlayer::HybridInterface::Open(const char *name, unsigned int *filesize, void **handle, void *userdata)\n{\n\tint32_t ret = 0;\n\tcommon::SharedPtr<File> *file = new common::SharedPtr<File>;\n\n\tif (LocalFile::Exists(name))\n\t{\n\t\t*file = LocalFile::Open(name, File::RDONLY, 0, &ret);\n\t}\n\telse\n\t{\n\t\t*file = CurlFile::Open(name, File::RDONLY, 0, &ret, NULL, utils::GetGlobalProxy());\n\t}\n\n\tif (ret == SCE_PAF_OK)\n\t{\n\t\t*filesize = file->get()->GetFileSize();\n\t\t*handle = file;\n\t\treturn FMOD_OK;\n\t}\n\tdelete file;\n\t*handle = NULL;\n\treturn FMOD_ERR_FILE_NOTFOUND;\n}\n\nFMOD_RESULT FMODPlayer::HybridInterface::Close(void *handle, void *userdata)\n{\n\tcommon::SharedPtr<File> *file = reinterpret_cast<common::SharedPtr<File> *>(handle);\n\tdelete file;\n\treturn FMOD_OK;\n}\n\nFMOD_RESULT FMODPlayer::HybridInterface::Read(void *handle, void *buffer, unsigned int sizebytes, unsigned int *bytesread, void *userdata)\n{\n\tint32_t readres = 0;\n\tcommon::SharedPtr<File> *file = reinterpret_cast<common::SharedPtr<File> *>(handle);\n\treadres = file->get()->Read(buffer, sizebytes);\n\tsceClibPrintf(\"read req: %u, actual: %d\\n\", sizebytes, readres);\n\tif (readres >= 0)\n\t{\n\t\t*bytesread = readres;\n\t\tif (readres == sizebytes)\n\t\t{\n\t\t\treturn FMOD_OK;\n\t\t}\n\t\treturn FMOD_ERR_FILE_EOF;\n\t}\n\t*bytesread = 0;\n\treturn FMOD_ERR_FILE_BAD;\n}\n\nFMOD_RESULT FMODPlayer::HybridInterface::Seek(void *handle, unsigned int pos, void *userdata)\n{\n\toff_t seekres = 0;\n\tcommon::SharedPtr<File> *file = reinterpret_cast<common::SharedPtr<File> *>(handle);\n\tseekres = file->get()->Seek(pos, File::SET);\n\tsceClibPrintf(\"seek req: %u, actual: %lld\\n\", pos, seekres);\n\tif (seekres == pos)\n\t{\n\t\treturn FMOD_OK;\n\t}\n\treturn FMOD_ERR_FILE_BAD;\n}\n\nvoid FMODPlayer::OnBootJob()\n{\n\tFMOD_RESULT ret = FMOD_OK;\n\tm_snd = NULL;\n\tm_ch = NULL;\n\n\tret = s_system->createSound(m_path.c_str(), FMOD_UNIQUE | FMOD_CREATESTREAM, NULL, &m_snd);\n\tif (ret != FMOD_OK)\n\t{\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\n\tFMOD_TAG tg;\n\ttg.data = NULL;\n\n\tif (m_snd->getTag(\"PIC\", -1, &tg) != FMOD_OK)\n\t{\n\t\tif (m_snd->getTag(\"APIC\", -1, &tg) != FMOD_OK)\n\t\t{\n\t\t\tm_snd->getTag(\"METADATA_BLOCK_PICTURE\", -1, &tg);\n\t\t}\n\t}\n\n\tif (tg.data && tg.datatype == FMOD_TAGDATATYPE_BINARY)\n\t{\n\t\tfor (int i = 0; i < tg.datalen; i++)\n\t\t{\n\t\t\tif (!sce_paf_memcmp(tg.data, \"\\xFF\\xD8\\xFF\", 3) || !sce_paf_memcmp(tg.data, \"\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A\\x00\\x00\\x00\\x0D\\x49\\x48\\x44\\x52\", 16))\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\ttg.data = (char *)tg.data + 1;\n\t\t\ttg.datalen--;\n\t\t}\n\n\t\tgraph::Surface::LoadOption opt;\n\t\tintrusive_ptr<graph::Surface> tex = graph::Surface::Load(gutil::GetDefaultSurfacePool(), tg.data, tg.datalen, &opt);\n\n\t\tif (tex.get())\n\t\t{\n\t\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t\t\tm_target->SetTexture(tex);\n\t\t\tgraph::PlaneObj *po = static_cast<graph::PlaneObj *>(m_target->GetDrawObj(ui::Plane::OBJ_PLANE));\n\t\t\tpo->SetScaleMode(graph::PlaneObj::SCALE_ASPECT_SIZE, graph::PlaneObj::SCALE_ASPECT_SIZE);\n\t\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t\t}\n\t}\n\telse if (!m_opt.auxStreamUrl.empty())\n\t{\n\t\tint32_t res = -1;\n\t\tCurlFile::OpenArg oarg;\n\t\toarg.ParseUrl(m_opt.auxStreamUrl.c_str());\n\t\toarg.SetOption(3000, CurlFile::OpenArg::OptionType_ConnectTimeOut);\n\t\toarg.SetOption(5000, CurlFile::OpenArg::OptionType_RecvTimeOut);\n\t\toarg.SetProxy(utils::GetGlobalProxy());\n\n\t\tCurlFile *file = new CurlFile();\n\t\tres = file->Open(&oarg);\n\t\tif (res == SCE_PAF_OK)\n\t\t{\n\t\t\tcommon::SharedPtr<CurlFile> hfile(file);\n\t\t\tintrusive_ptr<graph::Surface> tex = graph::Surface::Load(gutil::GetDefaultSurfacePool(), reinterpret_cast<common::SharedPtr<File>&>(hfile));\n\n\t\t\tif (tex.get())\n\t\t\t{\n\t\t\t\tthread::RMutex::MainThreadMutex()->Lock();\n\t\t\t\tm_target->SetTexture(tex);\n\t\t\t\tgraph::PlaneObj *po = static_cast<graph::PlaneObj *>(m_target->GetDrawObj(ui::Plane::OBJ_PLANE));\n\t\t\t\tpo->SetScaleMode(graph::PlaneObj::SCALE_ASPECT_SIZE, graph::PlaneObj::SCALE_ASPECT_SIZE);\n\t\t\t\tthread::RMutex::MainThreadMutex()->Unlock();\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tdelete file;\n\t\t}\n\t}\n\n\tret = s_system->playSound(m_snd, s_chg, false, &m_ch);\n\tif (ret != FMOD_OK)\n\t{\n\t\tm_snd->release();\n\t\tm_snd = NULL;\n\t\tSetInitState(InitState_InitFail);\n\t\treturn;\n\t}\n\n\tSetInitState(InitState_InitOk);\n}\n\nFMODPlayer::FMODPlayer(ui::Widget *targetPlane, const char *url, Option *opt)\n{\n\tSCE_DBG_LOG_INFO(\"[FMODPlayer] Open url: %s\", url);\n\tm_target = targetPlane;\n\tm_path = url;\n\tif (opt)\n\t{\n\t\tif (opt->playerType == GenericPlayer::PlayerType_FMOD)\n\t\t{\n\t\t\tm_opt = *opt;\n\t\t}\n\t\telse\n\t\t{\n\t\t\topt->CommonCopy(m_opt);\n\t\t}\n\t}\n\ts_system->attachChannelGroupToPort(FMOD_PSVITA_PORT_TYPE_VOICE, 0, s_chg);\n\tcommon::MainThreadCallList::Register(UpdateTask, this);\n}\n\nFMODPlayer::~FMODPlayer()\n{\n\tcommon::MainThreadCallList::Unregister(UpdateTask, this);\n\tTerm();\n\ts_system->detachChannelGroupFromPort(s_chg);\n}\n\nvoid FMODPlayer::InitAsync()\n{\n\tBootJob *job = new BootJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tutils::GetJobQueue()->Enqueue(itemParam);\n\tSetInitState(InitState_InProgress);\n}\n\nvoid FMODPlayer::Term()\n{\n\tif (m_initState != InitState_NotInit)\n\t{\n\t\tif (m_ch)\n\t\t{\n\t\t\tm_ch->stop();\n\t\t}\n\n\t\tif (m_snd)\n\t\t{\n\t\t\tm_snd->release();\n\t\t}\n\t}\n\n\tSetInitState(InitState_NotInit);\n}\n\nGenericPlayer::InitState FMODPlayer::GetInitState()\n{\n\treturn m_initState;\n}\n\nvoid FMODPlayer::SetInitState(GenericPlayer::InitState state)\n{\n\tm_initState = state;\n\tSCE_DBG_LOG_INFO(\"[SetInitState] State changed to: %d\", state);\n\tevent::BroadcastGlobalEvent(g_appPlugin, GenericPlayerChangeState, m_initState);\n}\n\nuint32_t FMODPlayer::GetTotalTimeMs()\n{\n\tuint32_t ret = 0;\n\tm_snd->getLength(&ret, FMOD_TIMEUNIT_MS);\n\treturn ret;\n}\n\nuint32_t FMODPlayer::GetCurrentTimeMs()\n{\n\tuint32_t ret = 0;\n\tm_ch->getPosition(&ret, FMOD_TIMEUNIT_MS);\n\treturn ret;\n}\n\nbool FMODPlayer::JumpToTimeMs(uint32_t time)\n{\n\tSCE_DBG_LOG_INFO(\"[JumpToTimeMs] Jump to seconds: %u\\n\", time / 1000);\n\tuint32_t total = GetTotalTimeMs();\n\tif (time >= total)\n\t{\n\t\tm_ch->stop();\n\t\treturn true;\n\t}\n\treturn (m_ch->setPosition(time, FMOD_TIMEUNIT_MS) == FMOD_OK);\n}\n\nGenericPlayer::PlayerState FMODPlayer::GetState()\n{\n\tbool play = false;\n\tbool pause = false;\n\n\tm_ch->isPlaying(&play);\n\tif (play)\n\t{\n\t\treturn PlayerState_Play;\n\t}\n\n\tm_ch->getPaused(&pause);\n\tif (pause)\n\t{\n\t\treturn PlayerState_Pause;\n\t}\n\n\treturn PlayerState_Eof;\n}\n\nvoid FMODPlayer::SetPowerSaving(bool enable)\n{\n\tm_powerSaving = enable;\n}\n\nuint32_t FMODPlayer::GetAudioRepresentationNum()\n{\n\treturn 1;\n}\n\nvoid FMODPlayer::SwitchPlaybackState()\n{\n\tbool play = false;\n\tbool pause = false;\n\n\tm_ch->getPaused(&pause);\n\tm_ch->isPlaying(&play);\n\n\tif (!play)\n\t{\n\t\ts_system->playSound(m_snd, NULL, false, &m_ch);\n\t\treturn;\n\t}\n\n\tif (pause)\n\t{\n\t\tm_ch->setPaused(false);\n\t}\n\telse\n\t{\n\t\tm_ch->setPaused(true);\n\t}\n}\n\nbool FMODPlayer::IsPaused()\n{\n\tbool pause = false;\n\tm_ch->getPaused(&pause);\n\treturn pause;\n}\n\nvoid FMODPlayer::UpdateTask(void *pArgBlock)\n{\n\ts_system->update();\n}\n\nvoid FMODPlayer::PreInit()\n{\n\tnew Module(\"app0:module/libfmodstudio.suprx\");\n\tnew Module(\"app0:module/libfmodngpext.suprx\");\n\tFMOD::System_Create(&s_system);\n\tFMOD_NGPEXT_PARAM param;\n\tsce_paf_memset(&param, 0, sizeof(FMOD_NGPEXT_PARAM));\n\tparam.at9prio = 1;\n\tFMOD_NGP_System_Init(reinterpret_cast<FMOD_SYSTEM *>(s_system), &param);\n\ts_system->setSoftwareFormat(48000, FMOD_SPEAKERMODE_STEREO, 2);\n\ts_system->setStreamBufferSize(SCE_KERNEL_256KiB, FMOD_TIMEUNIT_RAWBYTES);\n\ts_system->setFileSystem(HybridInterface::Open, HybridInterface::Close, HybridInterface::Read, HybridInterface::Seek, NULL, NULL, -1);\n\ts_system->init(1, FMOD_INIT_NORMAL, NULL);\n\ts_system->createChannelGroup(\"FMODPlayer::Output\", &s_chg);\n}\n\nGenericPlayer::SupportType FMODPlayer::IsSupported(const char *path)\n{\n\tchar *extStart = sce_paf_strrchr(path, '.');\n\tif (!extStart)\n\t{\n\t\treturn SupportType_MaybeSupported;\n\t}\n\n\tfor (int i = 0; i < sizeof(k_supportedExtensions) / sizeof(char*); i++)\n\t{\n\t\tif (!sce_paf_strcasecmp(extStart, k_supportedExtensions[i]))\n\t\t\treturn SupportType_Supported;\n\t}\n\n\treturn SupportType_NotSupported;\n}\n\nconst char *FMODPlayer::GetVersion()\n{\n\tstatic char sversion[16];\n\tunsigned int version = 0;\n\n\tif (s_system)\n\t{\n\t\ts_system->getVersion(&version);\n\t}\n\n\tunsigned int major = (version & 0xFFFF0000) >> 16;\n\tunsigned int minor = (version & 0x0000FF00) >> 8;\n\tunsigned int dev = (version & 0x000000FF);\n\tsce_paf_snprintf(sversion, sizeof(sversion), \"%u.%u.%u\", major, minor, dev);\n\n\treturn sversion;\n}"
  },
  {
    "path": "NetStream/source/subs/subs_generic.cpp",
    "content": "#include <kernel.h>\n#include <registrymgr.h>\n#include <paf.h>\n#include <libdbg.h>\n\n#include \"subs/subs_generic.h\"\n#include \"subs/subs_srt.h\"\n\nusing namespace paf;\n\nvoid GenericSubtitles::GetSystemSettings(SystemSettings& settings)\n{\n\tsceRegMgrGetKeyInt(\"/CONFIG/ACCESSIBILITY/CC\", \"enable_cc\", &settings.enable);\n\tsceRegMgrGetKeyInt(\"/CONFIG/ACCESSIBILITY/CC\", \"char_size\", &settings.size);\n\tsceRegMgrGetKeyInt(\"/CONFIG/ACCESSIBILITY/CC\", \"char_edge\", &settings.edge);\n\tsceRegMgrGetKeyInt(\"/CONFIG/ACCESSIBILITY/CC\", \"font_type\", &settings.fontType);\n}\n\nGenericSubtitles::GenericSubtitles()\n{\n\n}\n\nGenericSubtitles::~GenericSubtitles()\n{\n\n}\n\nvoid GenericSubtitles::GetActiveSubtitleIndices(vector<uint32_t>& result, uint64_t currentTimeMs)\n{\n\tresult.clear();\n\n\t// Use binary search to find first subtitle with startTime > currentTime\n\tauto iter = upper_bound(m_entries.begin(), m_entries.end(), currentTimeMs,\n\t\t[](uint64_t time, SubtitleEntry const& s)\n\t{\n\t\treturn time < s.startTime;\n\t});\n\n\t// Scan backwards from there to collect all active subtitles\n\tfor (auto rit = iter; rit != m_entries.begin(); )\n\t{\n\t\t--rit;\n\t\tif (rit->endTime > currentTimeMs)\n\t\t{\n\t\t\tresult.push_back(static_cast<uint32_t>(rit - m_entries.begin()));\n\t\t}\n\t\telse\n\t\t{\n\t\t\tbreak; // no need to go further, since earlier ones end even earlier\n\t\t}\n\t}\n}\n\nvector<GenericSubtitles::SubtitleEntry> const& GenericSubtitles::GetSubtitlieEntries()\n{\n\treturn m_entries;\n}"
  },
  {
    "path": "NetStream/source/subs/subs_srt.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <libdbg.h>\n\n#include \"common.h\"\n#include \"utils.h\"\n#include \"event.h\"\n#include \"subs/subs_srt.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[SRTSubtitles]\"\n\n#define SUB_SCALE_BASE\t(26.0f)\n#define SUB_MARGIN_H\t(0.0f)\n#define SUB_MARGIN_V\t(12.0f)\n#define RGBA8(r,g,b,a) ((((a)&0xFF)<<24) | (((b)&0xFF)<<16) | (((g)&0xFF)<<8) | (((r)&0xFF)<<0))\n\nusing namespace paf;\n\nconst char *SRTSubtitles::s_srtDelim = \" --> \"; // Most if not all SRT should have this for time\n\n// http://www.w3.org/TR/css3-color/\ntypedef struct NamedColor { const char *const name; const unsigned int color; } NamedColor;\nconst NamedColor s_namedColors[] = {\n\t{ \"transparent\", RGBA8(0, 0, 0, 0) }, { \"aliceblue\", RGBA8(240, 248, 255, 255) },\n\t{ \"antiquewhite\", RGBA8(250, 235, 215, 255) }, { \"aqua\", RGBA8(0, 255, 255, 255) },\n\t{ \"aquamarine\", RGBA8(127, 255, 212, 255) }, { \"azure\", RGBA8(240, 255, 255, 255) },\n\t{ \"beige\", RGBA8(245, 245, 220, 255) }, { \"bisque\", RGBA8(255, 228, 196, 255) },\n\t{ \"black\", RGBA8(0, 0, 0, 1) }, { \"blanchedalmond\", RGBA8(255, 235, 205, 255) },\n\t{ \"blue\", RGBA8(0, 0, 255, 255) }, { \"blueviolet\", RGBA8(138, 43, 226, 255) },\n\t{ \"brown\", RGBA8(165, 42, 42, 255) }, { \"burlywood\", RGBA8(222, 184, 135, 255) },\n\t{ \"cadetblue\", RGBA8(95, 158, 160, 255) }, { \"chartreuse\", RGBA8(127, 255, 0, 255) },\n\t{ \"chocolate\", RGBA8(210, 105, 30, 255) }, { \"coral\", RGBA8(255, 127, 80, 255) },\n\t{ \"cornflowerblue\", RGBA8(100, 149, 237, 255) }, { \"cornsilk\", RGBA8(255, 248, 220, 255) },\n\t{ \"crimson\", RGBA8(220, 20, 60, 255) }, { \"cyan\", RGBA8(0, 255, 255, 255) },\n\t{ \"darkblue\", RGBA8(0, 0, 139, 255) }, { \"darkcyan\", RGBA8(0, 139, 139, 255) },\n\t{ \"darkgoldenrod\", RGBA8(184, 134, 11, 255) }, { \"darkgray\", RGBA8(169, 169, 169, 255) },\n\t{ \"darkgreen\", RGBA8(0, 100, 0, 255) }, { \"darkgrey\", RGBA8(169, 169, 169, 255) },\n\t{ \"darkkhaki\", RGBA8(189, 183, 107, 255) }, { \"darkmagenta\", RGBA8(139, 0, 139, 255) },\n\t{ \"darkolivegreen\", RGBA8(85, 107, 47, 255) }, { \"darkorange\", RGBA8(255, 140, 0, 255) },\n\t{ \"darkorchid\", RGBA8(153, 50, 204, 255) }, { \"darkred\", RGBA8(139, 0, 0, 255) },\n\t{ \"darksalmon\", RGBA8(233, 150, 122, 255) }, { \"darkseagreen\", RGBA8(143, 188, 143, 255) },\n\t{ \"darkslateblue\", RGBA8(72, 61, 139, 255) }, { \"darkslategray\", RGBA8(47, 79, 79, 255) },\n\t{ \"darkslategrey\", RGBA8(47, 79, 79, 255) }, { \"darkturquoise\", RGBA8(0, 206, 209, 255) },\n\t{ \"darkviolet\", RGBA8(148, 0, 211, 255) }, { \"deeppink\", RGBA8(255, 20, 147, 255) },\n\t{ \"deepskyblue\", RGBA8(0, 191, 255, 255) }, { \"dimgray\", RGBA8(105, 105, 105, 255) },\n\t{ \"dimgrey\", RGBA8(105, 105, 105, 255) }, { \"dodgerblue\", RGBA8(30, 144, 255, 255) },\n\t{ \"firebrick\", RGBA8(178, 34, 34, 255) }, { \"floralwhite\", RGBA8(255, 250, 240, 255) },\n\t{ \"forestgreen\", RGBA8(34, 139, 34, 255) }, { \"fuchsia\", RGBA8(255, 0, 255, 255) },\n\t{ \"gainsboro\", RGBA8(220, 220, 220, 255) }, { \"ghostwhite\", RGBA8(248, 248, 255, 255) },\n\t{ \"gold\", RGBA8(255, 215, 0, 255) }, { \"goldenrod\", RGBA8(218, 165, 32, 255) },\n\t{ \"gray\", RGBA8(128, 128, 128, 255) }, { \"green\", RGBA8(0, 128, 0, 255) },\n\t{ \"greenyellow\", RGBA8(173, 255, 47, 255) }, { \"grey\", RGBA8(128, 128, 128, 255) },\n\t{ \"honeydew\", RGBA8(240, 255, 240, 255) }, { \"hotpink\", RGBA8(255, 105, 180, 255) },\n\t{ \"indianred\", RGBA8(205, 92, 92, 255) }, { \"indigo\", RGBA8(75, 0, 130, 255) },\n\t{ \"ivory\", RGBA8(255, 255, 240, 255) }, { \"khaki\", RGBA8(240, 230, 140, 255) },\n\t{ \"lavender\", RGBA8(230, 230, 250, 255) }, { \"lavenderblush\", RGBA8(255, 240, 245, 255) },\n\t{ \"lawngreen\", RGBA8(124, 252, 0, 255) }, { \"lemonchiffon\", RGBA8(255, 250, 205, 255) },\n\t{ \"lightblue\", RGBA8(173, 216, 230, 255) }, { \"lightcoral\", RGBA8(240, 128, 128, 255) },\n\t{ \"lightcyan\", RGBA8(224, 255, 255, 255) }, { \"lightgoldenrodyellow\", RGBA8(250, 250, 210, 255) },\n\t{ \"lightgray\", RGBA8(211, 211, 211, 255) }, { \"lightgreen\", RGBA8(144, 238, 144, 255) },\n\t{ \"lightgrey\", RGBA8(211, 211, 211, 255) }, { \"lightpink\", RGBA8(255, 182, 193, 255) },\n\t{ \"lightsalmon\", RGBA8(255, 160, 122, 255) }, { \"lightseagreen\",RGBA8(32, 178, 170, 255) },\n\t{ \"lightskyblue\", RGBA8(135, 206, 250, 255) }, { \"lightslategray\",RGBA8(119, 136, 153, 255) },\n\t{ \"lightslategrey\", RGBA8(119, 136, 153, 255) }, { \"lightsteelblue\", RGBA8(176, 196, 222, 255) },\n\t{ \"lightyellow\", RGBA8(255, 255, 224, 255) }, { \"lime\", RGBA8(0, 255, 0, 255) },\n\t{ \"limegreen\", RGBA8(50, 205, 50, 255) }, { \"linen\", RGBA8(250, 240, 230, 255) },\n\t{ \"magenta\", RGBA8(255, 0, 255, 255) }, { \"maroon\", RGBA8(128, 0, 0, 255) },\n\t{ \"mediumaquamarine\", RGBA8(102, 205, 170, 255) }, { \"mediumblue\", RGBA8(0, 0, 205, 255) },\n\t{ \"mediumorchid\", RGBA8(186, 85, 211, 255) }, { \"mediumpurple\", RGBA8(147, 112, 219, 255) },\n\t{ \"mediumseagreen\", RGBA8(60, 179, 113, 255) }, { \"mediumslateblue\", RGBA8(123, 104, 238, 255) },\n\t{ \"mediumspringgreen\", RGBA8(0, 250, 154, 255) }, { \"mediumturquoise\", RGBA8(72, 209, 204, 255) },\n\t{ \"mediumvioletred\", RGBA8(199, 21, 133, 255) }, { \"midnightblue\", RGBA8(25, 25, 112, 255) },\n\t{ \"mintcream\", RGBA8(245, 255, 250, 255) }, { \"mistyrose\", RGBA8(255, 228, 225, 255) },\n\t{ \"moccasin\", RGBA8(255, 228, 181, 255) }, { \"navajowhite\", RGBA8(255, 222, 173, 255) },\n\t{ \"navy\", RGBA8(0, 0, 128, 255) }, { \"oldlace\", RGBA8(253, 245, 230, 255) },\n\t{ \"olive\", RGBA8(128, 128, 0, 255) }, { \"olivedrab\", RGBA8(107, 142, 35, 255) },\n\t{ \"orange\", RGBA8(255, 165, 0, 255) }, { \"orangered\",RGBA8(255, 69, 0, 255) },\n\t{ \"orchid\", RGBA8(218, 112, 214, 255) }, { \"palegoldenrod\", RGBA8(238, 232, 170, 255) },\n\t{ \"palegreen\", RGBA8(152, 251, 152, 255) }, { \"paleturquoise\", RGBA8(175, 238, 238, 255) },\n\t{ \"palevioletred\", RGBA8(219, 112, 147, 255) }, { \"papayawhip\", RGBA8(255, 239, 213, 255) },\n\t{ \"peachpuff\", RGBA8(255, 218, 185, 255) }, { \"peru\", RGBA8(205, 133, 63, 255) },\n\t{ \"pink\", RGBA8(255, 192, 203, 255) }, { \"plum\", RGBA8(221, 160, 221, 255) },\n\t{ \"powderblue\", RGBA8(176, 224, 230, 255) }, { \"purple\", RGBA8(128, 0, 128, 255) },\n\t{ \"red\", RGBA8(255, 0, 0, 1) }, { \"rosybrown\", RGBA8(188, 143, 143, 255) },\n\t{ \"royalblue\", RGBA8(65, 105, 225, 255) }, { \"saddlebrown\", RGBA8(139, 69, 19, 255) },\n\t{ \"salmon\", RGBA8(250, 128, 114, 255) }, { \"sandybrown\", RGBA8(244, 164, 96, 255) },\n\t{ \"seagreen\", RGBA8(46, 139, 87, 255) }, { \"seashell\", RGBA8(255, 245, 238, 255) },\n\t{ \"sienna\", RGBA8(160, 82, 45, 255) }, { \"silver\", RGBA8(192, 192, 192, 255) },\n\t{ \"skyblue\", RGBA8(135, 206, 235, 255) }, { \"slateblue\", RGBA8(106, 90, 205, 255) },\n\t{ \"slategray\", RGBA8(112, 128, 144, 255) }, { \"slategrey\", RGBA8(112, 128, 144, 255) },\n\t{ \"snow\", RGBA8(255, 250, 250, 255) }, { \"springgreen\",RGBA8(0, 255, 127, 255) },\n\t{ \"steelblue\", RGBA8(70, 130, 180, 255) }, { \"tan\",RGBA8(210, 180, 140, 255) },\n\t{ \"teal\", RGBA8(0, 128, 128, 255) }, { \"thistle\",RGBA8(216, 191, 216, 255) },\n\t{ \"tomato\", RGBA8(255, 99, 71, 255) }, { \"turquoise\", RGBA8(64, 224, 208, 255) },\n\t{ \"violet\", RGBA8(238, 130, 238, 255) }, { \"wheat\", RGBA8(245, 222, 179, 255) },\n\t{ \"white\", RGBA8(255, 255, 255, 255) }, { \"whitesmoke\", RGBA8(245, 245, 245, 255) },\n\t{ \"yellow\", RGBA8(255, 255, 0, 255) }, { \"yellowgreen\", RGBA8(154, 205, 50, 255) }\n};\n\nSRTSubtitles::SRTSubtitles(const char *videoPath, Option *opt)\n{\n\tm_path = common::StripFilename(videoPath, \"PF\");\n\tm_path += \".srt\";\n}\n\nSRTSubtitles::~SRTSubtitles()\n{\n\n}\n\nvoid SRTSubtitles::OnBootJob()\n{\n\tint32_t ret;\n\tcommon::SharedPtr<File> file;\n\n\tSCE_DBG_LOG_INFO(\"[OnBootJob] Opening %s\", m_path.c_str());\n\n\tif (utils::IsLocalPath(m_path.c_str()))\n\t{\n\t\tfile = LocalFile::Open(m_path.c_str(), File::RDONLY, File::RU, &ret);\n\t}\n\telse\n\t{\n\t\tfile = CurlFile::Open(m_path.c_str(), File::RDONLY, File::RU, &ret, NULL, utils::GetGlobalProxy());\n\t}\n\tif (ret != SCE_PAF_OK)\n\t{\n\t\treturn;\n\t}\n\n\tParseSrt(file);\n\n\tSCE_DBG_LOG_INFO(\"[OnBootJob] ParseSrt() ok\");\n}\n\nvoid SRTSubtitles::ParseSrt(common::SharedPtr<File> file)\n{\n\tSrtMemFile memfile(file);\n\n\tchar buf[SCE_KERNEL_1KiB]; // line buffer\n\tchar *sbuf = new char[SCE_KERNEL_2KiB]; // string buffer\n\tif (!sbuf)\n\t{\n\t\treturn;\n\t}\n\twhile (memfile.Fgets(buf, sizeof(buf))) // New line\n\t{\n\t\tchar *timeLine = sce_paf_strstr(buf, s_srtDelim); // Check to see if current line contains timestamp data\n\t\tif (timeLine)\n\t\t{\n\t\t\tchar *start = sce_paf_strtok(buf, s_srtDelim);\n\t\t\t//sceClibPrintf(\"Start Text: %s\\n\", start);\n\t\t\tchar *end = sce_paf_strtok(NULL, s_srtDelim);\n\t\t\t//sceClibPrintf(\"End Text: %s\\n\", end);\n\n\t\t\tSubtitleEntry entry;\n\n\t\t\tentry.startTime = GetMilliseconds(start);\n\t\t\tentry.endTime = GetMilliseconds(end);\n\n\t\t\t//sceClibPrintf(\"Start Time %llu\\nEnd Time %llu\\nStart Text: %s\\nEnd Text: %s\\n\", entry.startTime, entry.endTime, start, end);\n\n\t\t\tuint32_t fullLen = 0;\n\t\t\tsbuf[0] = 0;\n\t\t\twhile (memfile.Fgets(buf, sizeof(buf)))\n\t\t\t{\n\t\t\t\tuint32_t len = sce_paf_strlen(buf);\n\t\t\t\tif (len == 1)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tfullLen += len;\n\t\t\t\tif (fullLen >= SCE_KERNEL_2KiB)\n\t\t\t\t{\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tsce_paf_strcat(sbuf, buf);\n\t\t\t}\n\n\t\t\tint32_t size = GetSize(sbuf);\n\t\t\tif (size != -1)\n\t\t\t{\n\t\t\t\tentry.charSizeScale = (static_cast<float>(size) / SUB_SCALE_BASE);\n\t\t\t}\n\n\t\t\tuint32_t color = GetColor(sbuf);\n\t\t\tentry.colorPacked = color;\n\t\t\tentry.color = ConvertColor(color);\n\n\t\t\tswitch (GetPosition(sbuf))\n\t\t\t{\n\t\t\tcase SRT_POSITION_BOTTOM_LEFT:\n\t\t\t\tentry.anchorX = ui::Widget::ANCHOR_LEFT;\n\t\t\t\tentry.anchorY = ui::Widget::ANCHOR_BOTTOM;\n\t\t\t\tentry.alignX = ui::Widget::ALIGN_LEFT;\n\t\t\t\tentry.alignY = ui::Widget::ALIGN_BOTTOM;\n\t\t\t\tentry.position.set_x(SUB_MARGIN_H);\n\t\t\t\tentry.position.set_y(SUB_MARGIN_V);\n\t\t\t\tbreak;\n\t\t\tcase SRT_POSITION_BOTTOM_CENTER:\n\t\t\t\tentry.anchorY = ui::Widget::ANCHOR_BOTTOM;\n\t\t\t\tentry.alignY = ui::Widget::ALIGN_BOTTOM;\n\t\t\t\tentry.position.set_y(SUB_MARGIN_V);\n\t\t\t\tbreak;\n\t\t\tcase SRT_POSITION_BOTTOM_RIGHT:\n\t\t\t\tentry.anchorX = ui::Widget::ANCHOR_RIGHT;\n\t\t\t\tentry.anchorY = ui::Widget::ANCHOR_BOTTOM;\n\t\t\t\tentry.alignX = ui::Widget::ALIGN_RIGHT;\n\t\t\t\tentry.alignY = ui::Widget::ALIGN_BOTTOM;\n\t\t\t\tentry.position.set_x(SUB_MARGIN_H);\n\t\t\t\tentry.position.set_y(SUB_MARGIN_V);\n\t\t\t\tbreak;\n\t\t\tcase SRT_POSITION_MIDDLE_LEFT:\n\t\t\t\tentry.anchorX = ui::Widget::ANCHOR_LEFT;\n\t\t\t\tentry.alignX = ui::Widget::ALIGN_LEFT;\n\t\t\t\tentry.position.set_x(SUB_MARGIN_H);\n\t\t\t\tbreak;\n\t\t\tcase SRT_POSITION_MIDDLE_CENTER:\n\t\t\t\tbreak;\n\t\t\tcase SRT_POSITION_MIDDLE_RIGHT:\n\t\t\t\tentry.anchorX = ui::Widget::ANCHOR_RIGHT;\n\t\t\t\tentry.alignX = ui::Widget::ALIGN_RIGHT;\n\t\t\t\tentry.position.set_x(SUB_MARGIN_H);\n\t\t\t\tbreak;\n\t\t\tcase SRT_POSITION_TOP_LEFT:\n\t\t\t\tentry.anchorX = ui::Widget::ANCHOR_LEFT;\n\t\t\t\tentry.anchorY = ui::Widget::ANCHOR_TOP;\n\t\t\t\tentry.alignX = ui::Widget::ALIGN_LEFT;\n\t\t\t\tentry.alignY = ui::Widget::ALIGN_TOP;\n\t\t\t\tentry.position.set_x(SUB_MARGIN_H);\n\t\t\t\tentry.position.set_y(-SUB_MARGIN_V);\n\t\t\t\tbreak;\n\t\t\tcase SRT_POSITION_TOP_CENTER:\n\t\t\t\tentry.anchorY = ui::Widget::ANCHOR_TOP;\n\t\t\t\tentry.alignY = ui::Widget::ALIGN_TOP;\n\t\t\t\tentry.position.set_y(-SUB_MARGIN_V);\n\t\t\t\tbreak;\n\t\t\tcase SRT_POSITION_TOP_RIGHT:\n\t\t\t\tentry.anchorX = ui::Widget::ANCHOR_RIGHT;\n\t\t\t\tentry.anchorY = ui::Widget::ANCHOR_TOP;\n\t\t\t\tentry.alignX = ui::Widget::ALIGN_RIGHT;\n\t\t\t\tentry.alignY = ui::Widget::ALIGN_TOP;\n\t\t\t\tentry.position.set_x(SUB_MARGIN_H);\n\t\t\t\tentry.position.set_y(-SUB_MARGIN_V);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcommon::Utf8ToUtf16(CleanSrtDialog(sbuf), &entry.string);\n\n\t\t\tm_entries.push_back(entry);\n\t\t}\n\t}\n\n\tdelete sbuf;\n}\n\nuint64_t SRTSubtitles::GetMilliseconds(const char *time)\n{\n\tint32_t hours, mins, seconds, milliseconds;\n\n\tchar chunk[4] = { 0 };\n\tchunk[0] = time[0];\n\tchunk[1] = time[1];\n\thours = sce_paf_atoi(chunk);\n\tchunk[0] = time[3];\n\tchunk[1] = time[4];\n\tmins = sce_paf_atoi(chunk);\n\tchunk[0] = time[6];\n\tchunk[1] = time[7];\n\tseconds = sce_paf_atoi(chunk);\n\tchunk[0] = time[9];\n\tchunk[1] = time[10];\n\tchunk[2] = time[11];\n\tmilliseconds = sce_paf_atoi(chunk);\n\n\t//sceClibPrintf(\"Hours %d\\nMins %d\\nSecs %d\\nMilliseconds %d\\n\", hours, mins, seconds, milliseconds);\n\n\treturn hours * 3600000 + mins * 60000 + seconds * 1000 + milliseconds;\n}\n\nint32_t SRTSubtitles::GetSize(const char *dialog)\n{\n\tchar *sz = sce_paf_strstr(dialog, \"size=\\\"\");\n\tif (sz)\n\t{\n\t\tsz += 6;\n\t\treturn (int32_t)sce_paf_strtol(sz, NULL, 10);\n\t}\n\n\treturn -1;\n}\n\nuint32_t SRTSubtitles::GetColor(const char *dialog)\n{\n\tchar *col = sce_paf_strstr(dialog, \"color=\\\"#\");\n\tif (col)\n\t{\n\t\tcol += 8;\n\t\tunsigned int ret = (unsigned int)sce_paf_strtoul(col, NULL, 16);\n\t\tret |= (0xFF << 24);\n\t\treturn ret;\n\t}\n\telse\n\t{\n\t\tcol = sce_paf_strstr(dialog, \"color=\\\"\");\n\t\tif (col)\n\t\t{\n\t\t\tcol += 7;\n\t\t\tchar collen = sce_paf_strchr(col, '\"') - col;\n\t\t\tchar tmp[100];\n\t\t\tsce_paf_memset(tmp, 0, sizeof(tmp));\n\t\t\tsce_paf_strncpy(tmp, col, collen);\n\t\t\tfor (int i = 0; i < sizeof(s_namedColors) / sizeof(NamedColor); i++)\n\t\t\t{\n\t\t\t\tif (!sce_paf_strcmp(tmp, s_namedColors[i].name))\n\t\t\t\t{\n\t\t\t\t\treturn s_namedColors[i].color;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn RGBA8(255, 255, 255, 255);\n}\n\nSRTSubtitles::SrtPosition SRTSubtitles::GetPosition(const char *dialog)\n{\n\tchar *pos = sce_paf_strstr(dialog, \"{\\\\an\");\n\tif (pos)\n\t{\n\t\tpos += 4;\n\t\treturn (SrtPosition)sce_paf_strtol(pos, NULL, 10);\n\t}\n\n\treturn SRT_POSITION_BOTTOM_CENTER;\n}\n\nchar *SRTSubtitles::CleanSrtDialog(char *dialog)\n{\n\tchar *tempChar = sce_paf_strstr(dialog, \"</\");\n\tchar *out = NULL;\n\tif (tempChar) // Found XML data\n\t{\n\t\t*tempChar = 0;\n\t\tchar *strStart = sce_paf_strrchr(dialog, '>') + 1;\n\t\tchar *pos = sce_paf_strstr(strStart, \"{\\\\an\");\n\t\tif (pos)\n\t\t{\n\t\t\tout = pos + 6;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tout = strStart;\n\t\t}\n\t}\n\n\tif (!out)\n\t{\n\t\tout = dialog;\n\t}\n\n\tfor (int i = 0; i <= sce_paf_strlen(out); i++)\n\t{\n\t\tif (out[i] == 0x0D)\n\t\t{\n\t\t\tout[i] = ' ';\n\t\t}\n\t}\n\n\treturn out;\n}\n\nmath::v4 SRTSubtitles::ConvertColor(uint32_t color)\n{\n\tmath::v4 ret;\n\n\tret.set_x(((color >> 0) & 0xFF) / 255.0f);\n\tret.set_y(((color >> 8) & 0xFF) / 255.0f);\n\tret.set_z(((color >> 16) & 0xFF) / 255.0f);\n\tret.set_w(((color >> 24) & 0xFF) / 255.0f);\n\n\treturn ret;\n}\n\nvoid SRTSubtitles::InitAsync()\n{\n\tBootJob *job = new BootJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tutils::GetJobQueue()->Enqueue(itemParam);\n}\n\nGenericSubtitles::SupportType SRTSubtitles::IsSupported(const char *videoPath)\n{\n\tstring subPath = common::StripFilename(videoPath, \"PF\");\n\tsubPath += \".srt\";\n\n\tSCE_DBG_LOG_INFO(\"[IsSupported] Probe subs at: %s\", subPath.c_str());\n\n\tif (utils::IsLocalPath(videoPath))\n\t{\n\t\tif (LocalFile::Exists(subPath.c_str()))\n\t\t{\n\t\t\tSCE_DBG_LOG_INFO(\"[IsSupported] Detected local subs\");\n\t\t\treturn GenericSubtitles::SupportType_Supported;\n\t\t}\n\t}\n\telse\n\t{\n\t\tCurlFile::CurlFileStat stat;\n\t\tif (CurlFile::Getstat(subPath.c_str(), &stat, NULL, utils::GetGlobalProxy()) == SCE_PAF_OK)\n\t\t{\n\t\t\tSCE_DBG_LOG_INFO(\"[IsSupported] Detected remote subs\");\n\t\t\treturn GenericSubtitles::SupportType_Supported;\n\t\t}\n\t}\n\n\treturn GenericSubtitles::SupportType_NotSupported;\n}"
  },
  {
    "path": "NetStream/source/tex_pool.cpp",
    "content": "#include <kernel.h>\n#include <libdbg.h>\n#include <paf.h>\n#include <paf_file_ext.h>\n\n#include \"utils.h\"\n#include \"tex_pool.h\"\n\nTexPool::TexPool(Plugin *_cbPlugin, bool useDefaultQueue)\n{\n\tm_storMtx = new thread::RMutex(\"TexPool::StorMtx\");\n\tif (useDefaultQueue)\n\t{\n\t\tm_addAsyncQueue = job::JobQueue::DefaultQueue();\n\t}\n\telse\n\t{\n\t\tm_addAsyncQueue = new job::JobQueue(\"TexPool::AddAsyncJobQueue\");\n\t}\n\tm_share = NULL;\n\tm_alive = true;\n\tm_cbPlugin = _cbPlugin;\n}\n\nTexPool::~TexPool()\n{\n\tSetAlive(false);\n\tAddAsyncCancelPending();\n\tRemoveAll();\n\tif (m_addAsyncQueue != job::JobQueue::DefaultQueue())\n\t{\n\t\tdelete m_addAsyncQueue;\n\t}\n\tdelete m_storMtx;\n}\n\nvoid TexPool::DestroyAsync()\n{\n\tSetAlive(false);\n\tDestroyJob *job = new DestroyJob(this);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tjob::JobQueue::DefaultQueue()->Enqueue(itemParam);\n}\n\nbool TexPool::Add(Plugin *plugin, IDParam const& id, bool allowReplace)\n{\n\tif (!m_alive)\n\t{\n\t\treturn false;\n\t}\n\n\tif (!allowReplace)\n\t{\n\t\tif (Exist(id))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tintrusive_ptr<graph::Surface> tex = plugin->GetTexture(id);\n\tif (tex.get())\n\t{\n\t\tm_storMtx->Lock();\n\t\tRemoveForReplace(id);\n\t\tm_stor[id.GetIDHash()] = tex;\n\t\tm_storMtx->Unlock();\n\t\treturn true;\n\t}\n\n\tRemove(id);\n\n\treturn false;\n}\n\nbool TexPool::Add(IDParam const& id, uint8_t *buffer, size_t bufferSize, bool allowReplace)\n{\n\tif (!m_alive)\n\t{\n\t\treturn false;\n\t}\n\n\tif (!allowReplace)\n\t{\n\t\tif (Exist(id))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tint32_t res = -1;\n\tcommon::SharedPtr<MemFile> mfile = MemFile::Open(buffer, bufferSize, &res);\n\tif (res != SCE_PAF_OK)\n\t{\n\t\tRemove(id);\n\t\treturn false;\n\t}\n\n\tintrusive_ptr<graph::Surface> tex = graph::Surface::Load(gutil::GetDefaultSurfacePool(), (common::SharedPtr<File>&)mfile);\n\tif (tex.get())\n\t{\n\t\tm_storMtx->Lock();\n\t\tRemoveForReplace(id);\n\t\tm_stor[id.GetIDHash()] = tex;\n\t\tm_storMtx->Unlock();\n\t\treturn true;\n\t}\n\n\tRemove(id);\n\n\treturn false;\n}\n\nbool TexPool::Add(IDParam const& id, const char *path, bool allowReplace)\n{\n\tif (!m_alive)\n\t{\n\t\treturn false;\n\t}\n\n\tif (!allowReplace)\n\t{\n\t\tif (Exist(id))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tif (!sce_paf_strncmp(path, \"http\", 4))\n\t{\n\t\treturn AddHttp(id, path);\n\t}\n\t\n\treturn AddLocal(id, path);\n}\n\nbool TexPool::Add(IDParam const& id, intrusive_ptr<graph::Surface>& surf, bool allowReplace)\n{\n\tif (!m_alive)\n\t{\n\t\treturn false;\n\t}\n\n\tif (!allowReplace)\n\t{\n\t\tif (Exist(id))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tif (surf.get())\n\t{\n\t\tm_storMtx->Lock();\n\t\tRemoveForReplace(id);\n\t\tm_stor[id.GetIDHash()] = surf;\n\t\tm_storMtx->Unlock();\n\t\treturn true;\n\t}\n\n\tRemove(id);\n\n\treturn false;\n}\n\nbool TexPool::AddAsync(IDParam const& id, uint8_t *buffer, size_t bufferSize, bool allowReplace)\n{\n\tif (!m_alive)\n\t{\n\t\treturn false;\n\t}\n\n\tif (!allowReplace)\n\t{\n\t\tif (Exist(id))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\tAddAsyncJob *job = new AddAsyncJob(this, id.GetIDHash(), buffer, bufferSize);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_addAsyncQueue->Enqueue(itemParam);\n\treturn true;\n}\n\nbool TexPool::AddAsync(IDParam const& id, const char *path, bool allowReplace)\n{\n\tif (!m_alive)\n\t{\n\t\treturn false;\n\t}\n\n\tif (!allowReplace)\n\t{\n\t\tif (Exist(id))\n\t\t{\n\t\t\treturn false;\n\t\t}\n\t}\n\n\tAddAsyncJob *job = new AddAsyncJob(this, id.GetIDHash(), path);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tm_addAsyncQueue->Enqueue(itemParam);\n\treturn true;\n}\n\nvoid TexPool::Remove(IDParam const& id)\n{\n\tm_storMtx->Lock();\n\tm_stor[id.GetIDHash()].clear();\n\tm_stor.erase(id.GetIDHash());\n\tm_storMtx->Unlock();\n}\n\nvoid TexPool::RemoveAll()\n{\n\tm_storMtx->Lock();\n\tmap<uint32_t, intrusive_ptr<graph::Surface>>::iterator it = m_stor.begin();\n\twhile (it != m_stor.end())\n\t{\n\t\tit->second.clear();\n\t\tit++;\n\t}\n\tm_stor.clear();\n\tm_storMtx->Unlock();\n}\n\nbool TexPool::Exist(IDParam const& id)\n{\n\tm_storMtx->Lock();\n\tbool ret = (m_stor[id.GetIDHash()].get() != NULL);\n\tm_storMtx->Unlock();\n\treturn ret;\n}\n\nintrusive_ptr<graph::Surface> TexPool::Get(IDParam const& id)\n{\n\tm_storMtx->Lock();\n\tintrusive_ptr<graph::Surface> tex = m_stor[id.GetIDHash()];\n\tm_storMtx->Unlock();\n\treturn tex;\n}\n\nvoid TexPool::AddAsyncWaitComplete()\n{\n\tm_addAsyncQueue->WaitEmpty();\n}\n\nint32_t TexPool::AddAsyncActiveNum()\n{\n\treturn m_addAsyncQueue->NumItems();\n}\n\nvoid TexPool::AddAsyncCancelPending()\n{\n\tm_addAsyncQueue->CancelAllItems();\n}\n\nuint32_t TexPool::GetSize()\n{\n\tm_storMtx->Lock();\n\tuint32_t sz = m_stor.size();\n\tm_storMtx->Unlock();\n\treturn sz;\n}\n\nvoid TexPool::RemoveForReplace(IDParam const& id)\n{\n\tm_stor[id.GetIDHash()].clear();\n}\n\nbool TexPool::AddHttp(IDParam const& id, const char *path)\n{\n\tint32_t res = -1;\n\tCurlFile::OpenArg oarg;\n\toarg.ParseUrl(path);\n\toarg.SetOption(3000, CurlFile::OpenArg::OptionType_ConnectTimeOut);\n\toarg.SetOption(5000, CurlFile::OpenArg::OptionType_RecvTimeOut);\n\toarg.SetProxy(utils::GetGlobalProxy());\n\tif (m_share)\n\t{\n\t\toarg.SetShare(m_share);\n\t}\n\n\tif (!m_alive)\n\t{\n\t\treturn false;\n\t}\n\tCurlFile *file = new CurlFile();\n\tres = file->Open(&oarg);\n\tif (res != SCE_PAF_OK)\n\t{\n\t\tdelete file;\n\t\tRemove(id);\n\t\treturn false;\n\t}\n\n\tif (!m_alive)\n\t{\n\t\tdelete file;\n\t\treturn false;\n\t}\n\tcommon::SharedPtr<CurlFile> hfile(file);\n\tintrusive_ptr<graph::Surface> tex = graph::Surface::Load(gutil::GetDefaultSurfacePool(), reinterpret_cast<common::SharedPtr<File>&>(hfile));\n\tif (tex.get())\n\t{\n\t\tm_storMtx->Lock();\n\t\tRemoveForReplace(id);\n\t\tm_stor[id.GetIDHash()] = tex;\n\t\tm_storMtx->Unlock();\n\t\treturn true;\n\t}\n\n\tRemove(id);\n\n\treturn false;\n}\n\nbool TexPool::AddLocal(IDParam const& id, const char *path)\n{\n\tif (!m_alive)\n\t{\n\t\treturn false;\n\t}\n\tint32_t res = -1;\n\tcommon::SharedPtr<LocalFile> lfile = LocalFile::Open(path, File::RDONLY, 0, &res);\n\tif (res != SCE_PAF_OK)\n\t{\n\t\tRemove(id);\n\t\treturn false;\n\t}\n\n\tif (!m_alive)\n\t{\n\t\tlfile.reset();\n\t\treturn false;\n\t}\n\tintrusive_ptr<graph::Surface> tex = graph::Surface::Load(gutil::GetDefaultSurfacePool(), reinterpret_cast<common::SharedPtr<File>&>(lfile));\n\tif (tex.get())\n\t{\n\t\tm_storMtx->Lock();\n\t\tRemoveForReplace(id);\n\t\tm_stor[id.GetIDHash()] = tex;\n\t\tm_storMtx->Unlock();\n\t\treturn true;\n\t}\n\n\tRemove(id);\n\n\treturn false;\n}"
  },
  {
    "path": "NetStream/source/tw_utils.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <psp2_compat/curl/curl.h>\n#include <ini_file_processor.h>\n\n#include \"common.h\"\n#include \"tw_utils.h\"\n#include \"lootkit.h\"\n\nusing namespace paf;\nusing namespace sce;\n\nstatic twutils::HistLog *s_histLog = NULL;\nstatic twutils::FavLog *s_favLog = NULL;\n\nint32_t twutils::Log::GetNext(char *data)\n{\n\tint32_t ret;\n\tchar *sptr;\n\tchar val[2];\n\n\tret = m_ini->parse(data, val, sizeof(val));\n\n\tif (ret == SCE_OK)\n\t{\n\t\t// Restore '='\n\t\tsptr = sce_paf_strchr(data, '}');\n\t\twhile (sptr) {\n\t\t\t*sptr = '=';\n\t\t\tsptr = sce_paf_strchr(sptr, '}');\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nint32_t twutils::Log::Get(const char *data)\n{\n\tchar *sptr;\n\tchar dataCopy[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\tchar val[2];\n\n\tsce_paf_strncpy(dataCopy, data, SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE);\n\n\t// Restore '}'\n\tsptr = sce_paf_strchr(dataCopy, '=');\n\twhile (sptr)\n\t{\n\t\t*sptr = '}';\n\t\tsptr = sce_paf_strchr(sptr, '=');\n\t}\n\n\treturn  m_ini->get(dataCopy, val, sizeof(val), 0);\n}\n\nvoid twutils::Log::Flush()\n{\n\tm_ini->flush();\n}\n\nint32_t twutils::Log::GetSize()\n{\n\treturn m_ini->size();\n}\n\nvoid twutils::Log::Reset()\n{\n\tm_ini->reset();\n}\n\nvoid twutils::Log::Add(const char *data)\n{\n\tchar *sptr;\n\tchar dataCopy[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\tsce_paf_strncpy(dataCopy, data, SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE);\n\n\t// Replace '=' in playlists with '}' to not confuse INI processor\n\tsptr = sce_paf_strchr(dataCopy, '=');\n\n\twhile (sptr)\n\t{\n\t\t*sptr = '}';\n\t\tsptr = sce_paf_strchr(sptr, '=');\n\t}\n\n\tm_ini->add(dataCopy, \"\");\n\tm_ini->flush();\n}\n\nint32_t twutils::Log::AddAsyncJob::Run()\n{\n\tchar *sptr;\n\n\t// Replace '=' in playlists with '}' to not confuse INI processor\n\tsptr = sce_paf_strchr(m_data.c_str(), '=');\n\n\twhile (sptr)\n\t{\n\t\t*sptr = '}';\n\t\tsptr = sce_paf_strchr(sptr, '=');\n\t}\n\n\tm_parent->m_ini->add(m_data.c_str(), \"\");\n\tm_parent->m_ini->flush();\n\n\treturn SCE_PAF_OK;\n}\n\nvoid twutils::Log::AddAsync(const char *data)\n{\n\tAddAsyncJob *job = new AddAsyncJob(this, data);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tjob::JobQueue::DefaultQueue()->Enqueue(itemParam);\n}\n\nvoid twutils::Log::Remove(const char *data)\n{\n\tchar *sptr;\n\tchar dataCopy[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\tsce_paf_strncpy(dataCopy, data, SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE);\n\n\t// Replace '=' in playlists with '}' to not confuse INI processor\n\tsptr = sce_paf_strchr(dataCopy, '=');\n\n\twhile (sptr)\n\t{\n\t\t*sptr = '}';\n\t\tsptr = sce_paf_strchr(sptr, '=');\n\t}\n\n\tm_ini->del(dataCopy);\n\tm_ini->flush();\n}\n\ntwutils::HistLog::HistLog()\n{\n\tuint32_t i = 0;\n\tchar val[2];\n\tchar data[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\tIni::InitParameter param;\n\tIni::MemAllocator alloc;\n\talloc.allocate = sce_paf_malloc;\n\talloc.deallocate = sce_paf_free;\n\n\tparam.workmemSize = SCE_KERNEL_4KiB;\n\tparam.unk_0x4 = SCE_KERNEL_4KiB;\n\tparam.allocator = &alloc;\n\n\tm_ini = new Ini::IniFileProcessor();\n\tm_ini->initialize(&param);\n\tm_ini->open(\"savedata0:tw_hist_log.ini\", \"rw\", 0);\n\n\ti = m_ini->size();\n\tif (i <= k_maxHistItems)\n\t\treturn;\n\n\ti = i - k_maxHistItems;\n\n\twhile (i != 0)\n\t{\n\t\tm_ini->parse(data, val, sizeof(val));\n\t\tm_ini->del(data);\n\t\ti--;\n\t}\n\n\tm_ini->reset();\n}\n\ntwutils::FavLog::FavLog()\n{\n\tIni::InitParameter param;\n\tIni::MemAllocator alloc;\n\talloc.allocate = sce_paf_malloc;\n\talloc.deallocate = sce_paf_free;\n\n\tparam.workmemSize = SCE_KERNEL_4KiB;\n\tparam.unk_0x4 = SCE_KERNEL_4KiB;\n\tparam.allocator = &alloc;\n\n\tm_ini = new Ini::IniFileProcessor();\n\tm_ini->initialize(&param);\n\tm_ini->open(\"savedata0:tw_fav_log.ini\", \"rw\", 0);\n}\n\nvoid twutils::FavLog::Clean()\n{\n\tif (s_favLog)\n\t{\n\t\tdelete s_favLog;\n\t\tLocalFile::RemoveFile(\"savedata0:tw_fav_log.ini\");\n\t\ts_favLog = new twutils::FavLog();\n\t}\n}\n\nvoid twutils::HistLog::Clean()\n{\n\tif (s_histLog)\n\t{\n\t\tdelete s_histLog;\n\t\tLocalFile::RemoveFile(\"savedata0:tw_hist_log.ini\");\n\t\ts_histLog = new twutils::HistLog();\n\t}\n}\n\nvoid twutils::Init()\n{\n\tltkInit(sce_paf_malloc, sce_paf_free, \"https://github.com/GrapheneCt/NetStream/raw/main/loot.bin\");\n\n\t/*\n\tLtkItem *ch = NULL;\n\tLtkItemVideo *vid = NULL;\n\tint32_t ret = 0;\n\tchar dummy[1024];\n\n\tret = ltkParseSearch(\"\", NULL, LTK_SEARCH_TYPE_CHANNEL, LTK_SEARCH_DIR_AFTER, &ch);\n\tsceClibPrintf(\"ltkParseSearch: 0x%08X\\n\", ret);\n\tltkParseVideo(ch[0].channelItem, LTK_VIDEO_TYPE_VOD, NULL, LTK_SEARCH_DIR_AFTER, &vid);\n\tltkGetVideoUrl(&vid[0], LTK_HLS_QUALITY_360P, dummy, sizeof(dummy));\n\tsceClibPrintf(\"video url: %s\\n\", dummy);\n\t*/\n\n\tif (!s_histLog)\n\t\ts_histLog = new twutils::HistLog();\n\tif (!s_favLog)\n\t\ts_favLog = new twutils::FavLog();\n}\n\nvoid twutils::Flush()\n{\n\tif (s_histLog)\n\t{\n\t\ts_histLog->Flush();\n\t}\n\tif (s_favLog)\n\t{\n\t\ts_favLog->Flush();\n\t}\n}\n\nvoid twutils::Term()\n{\n\tif (s_histLog)\n\t{\n\t\tdelete s_histLog;\n\t\ts_histLog = NULL;\n\t}\n\tif (s_favLog)\n\t{\n\t\tdelete s_favLog;\n\t\ts_favLog = NULL;\n\t}\n\n\tltkTerm();\n}\n\ntwutils::HistLog *twutils::GetHistLog()\n{\n\treturn s_histLog;\n}\n\ntwutils::FavLog *twutils::GetFavLog()\n{\n\treturn s_favLog;\n}"
  },
  {
    "path": "NetStream/source/utils.cpp",
    "content": "﻿#include <kernel.h>\n#include <apputil.h> \n#include <power.h> \n#include <libdbg.h>\n#include <paf.h>\n#include <stdlib.h>\n#include <paf_file_ext.h>\n\n#include \"utils.h\"\n#include \"yt_utils.h\"\n#include \"common.h\"\n#include \"menus/menu_player_simple.h\"\n#include \"players/player_av.h\"\n#include \"players/player_beav.h\"\n#include \"players/player_fmod.h\"\n\n#undef SCE_DBG_LOG_COMPONENT\n#define SCE_DBG_LOG_COMPONENT \"[utils]\"\n\nstatic SceUID s_lock = SCE_UID_INVALID_UID;\nstatic job::JobQueue *s_utilsJobQueue = NULL;\nstatic CurlFile::Share *s_curlShare = NULL;\nstatic utils::PowerTick s_powerTickMode = utils::PowerTick_None;\nstatic string s_globalProxy;\nstatic CURLSH *s_reqShare = NULL;\n\nextern \"C\"\n{\n\tSceUID _vshKernelSearchModuleByName(const char *, int *);\n}\n\nstatic size_t CurlDownloadCore(char *buffer, size_t size, size_t nitems, void *userdata)\n{\n\tutils::CurlDownloadContext *obj = static_cast<utils::CurlDownloadContext *>(userdata);\n\tsize_t toCopy = size * nitems;\n\n\tif (toCopy != 0)\n\t{\n\t\tobj->m_buf = sce_paf_realloc(obj->m_buf, obj->m_pos + toCopy);\n\t\tsce_paf_memcpy(static_cast<char *>(obj->m_buf) + obj->m_pos, buffer, toCopy);\n\t\tobj->m_pos += toCopy;\n\t}\n\n\treturn toCopy;\n}\n\nstatic void PowerTickTask(void *pUserData)\n{\n\tif (s_powerTickMode == utils::PowerTick_All)\n\t\tsceKernelPowerTick(SCE_KERNEL_POWER_TICK_DEFAULT);\n\telse if (s_powerTickMode == utils::PowerTick_Suspend)\n\t\tsceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND);\n}\n\nuint32_t utils::GetHash(const char *name)\n{\n\tIDParam param(name);\n\treturn param.GetIDHash();\n}\n\nwchar_t *utils::GetStringWithNum(const char *name, uint32_t num)\n{\n\tchar fullName[128];\n\tsce_paf_snprintf(fullName, sizeof(fullName), \"%s%u\", name, num);\n\treturn g_appPlugin->GetString(fullName);\n}\n\nvoid utils::SetPowerTickTask(PowerTick mode)\n{\n\tcommon::MainThreadCallList::Unregister(PowerTickTask, NULL);\n\tif (mode == PowerTick_None)\n\t\treturn;\n\n\ts_powerTickMode = mode;\n\tcommon::MainThreadCallList::Register(PowerTickTask, NULL);\n}\n\nvoid utils::Lock(uint32_t flag)\n{\n\tsceKernelClearEventFlag(s_lock, ~flag);\n}\n\nvoid utils::Unlock(uint32_t flag)\n{\n\tsceKernelSetEventFlag(s_lock, flag);\n}\n\nvoid utils::Wait(uint32_t flag)\n{\n\tsceKernelWaitEventFlag(s_lock, flag, SCE_KERNEL_EVF_WAITMODE_OR, NULL, NULL);\n}\n\nvoid utils::ConvertSecondsToString(string& string, uint64_t seconds, bool needSeparator)\n{\n\tint32_t h = 0, m = 0, s = 0;\n\th = (seconds / 3600);\n\tm = (seconds - (3600 * h)) / 60;\n\ts = (seconds - (3600 * h) - (m * 60));\n\n\tstring.clear();\n\n\tif (needSeparator) {\n\t\tif (h > 0) {\n\t\t\tstring = common::FormatString(\"%02d:%02d:%02d / \", h, m, s);\n\t\t}\n\t\telse {\n\t\t\tstring = common::FormatString(\"%02d:%02d / \", m, s);\n\t\t}\n\t}\n\telse {\n\t\tif (h > 0) {\n\t\t\tstring = common::FormatString(\"%02d:%02d:%02d\", h, m, s);\n\t\t}\n\t\telse {\n\t\t\tstring = common::FormatString(\"%02d:%02d\", m, s);\n\t\t}\n\t}\n}\n\nvoid utils::SetDisplayResolution(uint32_t resolution)\n{\n\tif (SCE_PAF_IS_DOLCE)\n\t{\n\t\tui::Environment *env = Framework::Instance()->GetEnvironmentInstance();\n\t\tswitch (resolution)\n\t\t{\n\t\tcase ui::EnvironmentParam::RESOLUTION_PSP2:\n\t\t\tenv->SetResolution(960, 544);\n\t\t\tbreak;\n\t\tcase ui::EnvironmentParam::RESOLUTION_HD_HALF:\n\t\t\tenv->SetResolution(1280, 725);\n\t\t\tbreak;\n\t\tcase ui::EnvironmentParam::RESOLUTION_HD_FULL:\n\t\t\tenv->SetResolution(1920, 1088);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid utils::Init()\n{\n\ts_lock = sceKernelCreateEventFlag(\"utils::Lock\", SCE_KERNEL_ATTR_MULTI, 0, NULL);\n\n\tjob::JobQueue::Option queueOpt;\n\tqueueOpt.num_thread = 1;\n\tqueueOpt.worker_opt = NULL;\n\tqueueOpt.priority = SCE_KERNEL_COMMON_QUEUE_HIGHEST_PRIORITY;\n\tqueueOpt.stack_size = SCE_KERNEL_256KiB;\n\n\ts_utilsJobQueue = new job::JobQueue(\"utils::JobQueue\", &queueOpt);\n\n\ts_curlShare = CurlFile::Share::Create();\n\ts_curlShare->AddRef();\n}\n\njob::JobQueue *utils::GetJobQueue()\n{\n\treturn s_utilsJobQueue;\n}\n\nCurlFile::Share *utils::GetShare()\n{\n\treturn s_curlShare;\n}\n\nuint32_t utils::SafememGetSettingsSize()\n{\n\treturn 0x400;\n}\n\nvoid utils::SafememWrite(string const& str, uint32_t offset)\n{\n\tint32_t strlen = str.length();\n\tuint32_t baseOffset = SafememGetSettingsSize();\n\tsceAppUtilSaveSafeMemory(&strlen, 4, baseOffset + offset);\n\tsceAppUtilSaveSafeMemory(str.c_str(), strlen, baseOffset + offset + 4);\n}\n\nstring utils::SafememRead(uint32_t offset)\n{\n\tstring ret;\n\tint32_t strlen = 0;\n\tuint32_t baseOffset = SafememGetSettingsSize();\n\tsceAppUtilLoadSafeMemory(&strlen, 4, baseOffset + offset);\n\tif (strlen <= 0 || strlen > SCE_KERNEL_64KiB - baseOffset + offset + 4)\n\t{\n\t\treturn ret;\n\t}\n\tchar *tmp = new char[strlen + 1];\n\ttmp[strlen] = 0;\n\tsceAppUtilLoadSafeMemory(tmp, strlen, baseOffset + offset + 4);\n\tret = tmp;\n\tdelete tmp;\n\treturn ret;\n}\n\nbool utils::IsTaihenLoaded()\n{\n\tint sarg[2];\n\treturn (_vshKernelSearchModuleByName(\"taihen\", sarg) > 0);\n}\n\nutils::TimeoutID utils::SetTimeout(TimeoutFunc func, float timeoutMs, void *userdata1, void *userdata2)\n{\n\tTimer *t = new Timer(timeoutMs);\n\tTimeoutListener *listener = new TimeoutListener(t, func);\n\tTimerListenerList::ListenerParam lparam(listener, true, userdata1, userdata2);\n\tTimerListenerList::DefaultList()->Register(lparam);\n\treturn listener;\n}\n\nvoid utils::ClearTimeout(utils::TimeoutID id)\n{\n\tif (id)\n\t{\n\t\tTimerListenerList::DefaultList()->Unregister(id);\n\t\tdelete id;\n\t}\n}\n\nvoid utils::SetGlobalProxy(const char *proxy)\n{\n\tif (!proxy)\n\t{\n\t\ts_globalProxy.clear();\n\t}\n\telse\n\t{\n\t\ts_globalProxy = proxy;\n\t}\n}\n\nconst char *utils::GetGlobalProxy()\n{\n\tif (s_globalProxy.empty())\n\t{\n\t\treturn NULL;\n\t}\n\n\treturn s_globalProxy.c_str();\n}\n\nbool utils::DoGETRequest(const char *url, void **ppRespBuf, size_t *pRespBufSize, const char **ppHeaders, uint32_t headerNum,\n\tint32_t *pRespCode, void*(*liballoc)(size_t), void(*libdealloc)(void *), void*(*librealloc)(void *, size_t))\n{\n\tCURL *curl = curl_easy_init();\n\tcurl_easy_setopt(curl, CURLOPT_SHARE, s_reqShare);\n\tcurl_easy_setopt(curl, CURLOPT_BUFFERSIZE, SCE_KERNEL_64KiB);\n\tcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlDownloadCore);\n\tcurl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);\n\tcurl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, \"\");\n\tcurl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);\n\tcurl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);\n\tcurl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);\n\tcurl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);\n\tcurl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);\n\tcurl_easy_setopt(curl, CURLOPT_URL, url);\n\tcurl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);\n\tcurl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);\n\tif (utils::GetGlobalProxy())\n\t{\n\t\tcurl_easy_setopt(curl, CURLOPT_PROXY, utils::GetGlobalProxy());\n\t}\n\n\tcurl_slist *headers = NULL;\n\tif (headerNum)\n\t{\n\t\tfor (int i = 0; i < headerNum; i++)\n\t\t{\n\t\t\theaders = curl_slist_append(headers, ppHeaders[i]);\n\t\t}\n\n\t\tcurl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);\n\t}\n\n\tutils::CurlDownloadContext ctx;\n\tcurl_easy_setopt(curl, CURLOPT_WRITEDATA, &ctx);\n\n\tlong responseCode = 0;\n\tCURLcode ret = curl_easy_perform(curl);\n\tcurl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);\n\tcurl_slist_free_all(headers);\n\tif (pRespCode)\n\t{\n\t\t*pRespCode = responseCode;\n\t}\n\tif (ret != CURLE_OK || responseCode != 200)\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[DoGETRequest] Error: %d, resp: %d\", ret, responseCode);\n\t\tif (ctx.m_buf)\n\t\t{\n\t\t\tsce_paf_free(ctx.m_buf);\n\t\t}\n\t\tcurl_easy_cleanup(curl);\n\t\treturn false;\n\t}\n\n\tcurl_easy_cleanup(curl);\n\n\t*ppRespBuf = ctx.m_buf;\n\t*pRespBufSize = ctx.m_pos;\n\n\treturn true;\n}\n\nbool utils::DoPOSTRequest(const char *url, void *pBuf, size_t bufSize, const char **ppHeaders, uint32_t headerNum, void **ppRespBuf,\n\tsize_t *pRespBufSize, int32_t *pRespCode, void*(*liballoc)(size_t), void(*libdealloc)(void *), void*(*librealloc)(void *, size_t))\n{\n\tCURL *curl = curl_easy_init();\n\tcurl_easy_setopt(curl, CURLOPT_SHARE, s_reqShare);\n\tcurl_easy_setopt(curl, CURLOPT_BUFFERSIZE, SCE_KERNEL_64KiB);\n\tcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlDownloadCore);\n\tcurl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);\n\tcurl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, \"\");\n\tcurl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);\n\tcurl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);\n\tcurl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);\n\tcurl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);\n\tcurl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);\n\tcurl_easy_setopt(curl, CURLOPT_URL, url);\n\tcurl_easy_setopt(curl, CURLOPT_POSTFIELDS, pBuf);\n\tcurl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)bufSize);\n\tcurl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);\n\tcurl_easy_setopt(curl, CURLOPT_TIMEOUT, 15L);\n\tif (utils::GetGlobalProxy())\n\t{\n\t\tcurl_easy_setopt(curl, CURLOPT_PROXY, utils::GetGlobalProxy());\n\t}\n\n\tcurl_slist *headers = NULL;\n\tif (headerNum)\n\t{\n\t\tfor (int i = 0; i < headerNum; i++)\n\t\t{\n\t\t\theaders = curl_slist_append(headers, ppHeaders[i]);\n\t\t}\n\n\t\tcurl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);\n\t}\n\n\tutils::CurlDownloadContext ctx;\n\tcurl_easy_setopt(curl, CURLOPT_WRITEDATA, &ctx);\n\n\tlong responseCode = 0;\n\tCURLcode ret = curl_easy_perform(curl);\n\tcurl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);\n\tcurl_slist_free_all(headers);\n\tif (pRespCode)\n\t{\n\t\t*pRespCode = responseCode;\n\t}\n\tif (ret != CURLE_OK || responseCode != 200)\n\t{\n\t\tSCE_DBG_LOG_ERROR(\"[DoPOSTRequest] Error: %d, resp: %d\", ret, responseCode);\n\t\tif (ctx.m_buf)\n\t\t{\n\t\t\tsce_paf_free(ctx.m_buf);\n\t\t}\n\t\tcurl_easy_cleanup(curl);\n\t\treturn false;\n\t}\n\n\tcurl_easy_cleanup(curl);\n\n\t*ppRespBuf = ctx.m_buf;\n\t*pRespBufSize = ctx.m_pos;\n\n\treturn true;\n}\n\nvoid utils::SetRequestShare(CURLSH *share)\n{\n\ts_reqShare = share;\n}\n\nvoid utils::ResolutionToQualityString(wstring& res, uint32_t width, uint32_t height, bool selected)\n{\n\tbool detected = true;\n\n\tif (selected)\n\t{\n\t\tres = L\"→ \";\n\t}\n\n\tif (!IsVideoSupported(width, height))\n\t{\n\t\tres += L\"(Unsupported) \";\n\t}\n\n\tswitch (height)\n\t{\n\tcase 144:\n\t\tres += L\"144p\";\n\t\tbreak;\n\tcase 240:\n\t\tres += L\"240p\";\n\t\tbreak;\n\tcase 360:\n\t\tres += L\"360p\";\n\t\tbreak;\n\tcase 480:\n\t\tres += L\"480p\";\n\t\tbreak;\n\tcase 720:\n\t\tres += L\"720p\";\n\t\tbreak;\n\tcase 1080:\n\t\tres += L\"1080p\";\n\t\tbreak;\n\tdefault:\n\t\tdetected = false;\n\t\tbreak;\n\t}\n\n\tif (!detected)\n\t{\n\t\tswitch (width)\n\t\t{\n\t\tcase 144:\n\t\t\tres += L\"144p\";\n\t\t\tbreak;\n\t\tcase 240:\n\t\t\tres += L\"240p\";\n\t\t\tbreak;\n\t\tcase 360:\n\t\t\tres += L\"360p\";\n\t\t\tbreak;\n\t\tcase 480:\n\t\t\tres += L\"480p\";\n\t\t\tbreak;\n\t\tcase 720:\n\t\t\tres += L\"720p\";\n\t\t\tbreak;\n\t\tcase 1080:\n\t\t\tres += L\"1080p\";\n\t\t\tbreak;\n\t\tdefault:\n\t\t\twchar_t tmp[128];\n\t\t\tsce_paf_swprintf(tmp, 64, L\"%ux%u\", width, height);\n\t\t\tres += tmp;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (selected)\n\t{\n\t\tres += L\" ←\";\n\t}\n}\n\nvoid utils::AudioParamsToQualityString(wstring& res, uint32_t ch, uint32_t srate, bool selected)\n{\n\tif (selected)\n\t{\n\t\tres = L\"→ \";\n\t}\n\n\tif (!IsAudioSupported(ch, srate))\n\t{\n\t\tres += L\"(Unsupported) \";\n\t}\n\n\tswitch (ch)\n\t{\n\tcase 1:\n\t\tres += L\"Mono, \";\n\t\tbreak;\n\tcase 2:\n\t\tres += L\"Stereo, \";\n\t\tbreak;\n\t}\n\n\twchar_t tmp[64];\n\tsce_paf_swprintf(tmp, 64, L\"%.3f KHz\", srate / 1000.0f);\n\tres += tmp;\n\n\tif (selected)\n\t{\n\t\tres += L\" ←\";\n\t}\n}\n\nbool utils::IsVideoSupported(uint32_t width, uint32_t height)\n{\n\tif (width > 1280 || height > 720)\n\t{\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nbool utils::IsAudioSupported(uint32_t ch, uint32_t srate)\n{\n\tif (ch > 2 || srate > 48000)\n\t{\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nbool utils::IsLocalPath(const char *path)\n{\n\tif (!sce_paf_strncmp(path, \"http\", 4) || !sce_paf_strncmp(path, \"ftp\", 3) || !sce_paf_strncmp(path, \"smb\", 3))\n\t{\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n\nmenu::GenericMenu *utils::CreatePlayer(string const& url)\n{\n\tstring ext = common::StripFilename(url, \"E\");\n\t// TODO: implement\n\treturn NULL;\n}\n\nGenericPlayer::SupportType utils::GetContentSupportType(const char *path)\n{\n\tGenericPlayer::SupportType supportType = AVPlayer::IsSupported(path);\n\tif (supportType == GenericPlayer::SupportType_NotSupported)\n\t{\n\t\tsupportType = BEAVPlayer::IsSupported(path);\n\t\tif (supportType == GenericPlayer::SupportType_NotSupported)\n\t\t{\n\t\t\tsupportType = FMODPlayer::IsSupported(path);\n\t\t}\n\t}\n\n\treturn supportType;\n}"
  },
  {
    "path": "NetStream/source/yt_utils.cpp",
    "content": "#include <kernel.h>\n#include <paf.h>\n#include <psp2_compat/curl/curl.h>\n#include <ini_file_processor.h>\n\n#include \"common.h\"\n#include \"downloader.h\"\n#include \"utils.h\"\n#include \"yt_utils.h\"\n#include \"np_utils.h\"\n#include \"ftube.h\"\n\nusing namespace paf;\nusing namespace sce;\n\nstatic ytutils::HistLog *s_histLog = NULL;\nstatic ytutils::FavLog *s_favLog = NULL;\nstatic Downloader *s_downloader = NULL;\nstatic CURLSH *s_share = NULL;\n\nint32_t ytutils::Log::GetNext(char *data)\n{\n\tint32_t ret;\n\tchar *sptr;\n\tchar val[2];\n\n\tret = m_ini->parse(data, val, sizeof(val));\n\n\tif (ret == SCE_OK)\n\t{\n\t\t// Restore '='\n\t\tsptr = sce_paf_strchr(data, '}');\n\t\twhile (sptr) {\n\t\t\t*sptr = '=';\n\t\t\tsptr = sce_paf_strchr(sptr, '}');\n\t\t}\n\t}\n\n\treturn ret;\n}\n\nint32_t ytutils::Log::Get(const char *data)\n{\n\tchar *sptr;\n\tchar dataCopy[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\tchar val[2];\n\n\tsce_paf_strncpy(dataCopy, data, SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE);\n\n\t// Restore '}'\n\tsptr = sce_paf_strchr(dataCopy, '=');\n\twhile (sptr)\n\t{\n\t\t*sptr = '}';\n\t\tsptr = sce_paf_strchr(sptr, '=');\n\t}\n\n\treturn  m_ini->get(dataCopy, val, sizeof(val), 0);\n}\n\nvoid ytutils::Log::Flush()\n{\n\tm_ini->flush();\n}\n\nint32_t ytutils::Log::GetSize()\n{\n\treturn m_ini->size();\n}\n\nvoid ytutils::Log::Reset()\n{\n\tm_ini->reset();\n}\n\nvoid ytutils::Log::Add(const char *data)\n{\n\tint32_t sync = 0;\n\tchar *sptr;\n\tchar dataCopy[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\tsce_paf_strncpy(dataCopy, data, SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE);\n\n\t// Replace '=' in playlists with '}' to not confuse INI processor\n\tsptr = sce_paf_strchr(dataCopy, '=');\n\n\twhile (sptr)\n\t{\n\t\t*sptr = '}';\n\t\tsptr = sce_paf_strchr(sptr, '=');\n\t}\n\n\tm_ini->add(dataCopy, \"\");\n\tm_ini->flush();\n\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetInt(\"cloud_sync_auto\", static_cast<int32_t *>(&sync), 0);\n\tif (sync)\n\t{\n\t\tUploadToTUS();\n\t}\n}\n\nint32_t ytutils::Log::AddAsyncJob::Run()\n{\n\tint32_t sync = 0;\n\tchar *sptr;\n\n\t// Replace '=' in playlists with '}' to not confuse INI processor\n\tsptr = sce_paf_strchr(m_data.c_str(), '=');\n\n\twhile (sptr)\n\t{\n\t\t*sptr = '}';\n\t\tsptr = sce_paf_strchr(sptr, '=');\n\t}\n\n\tm_parent->m_ini->add(m_data.c_str(), \"\");\n\tm_parent->m_ini->flush();\n\n\tsce::AppSettings *settings = menu::Settings::GetAppSetInstance();\n\tsettings->GetInt(\"cloud_sync_auto\", static_cast<int32_t *>(&sync), 0);\n\tif (sync)\n\t{\n\t\tm_parent->UploadToTUS();\n\t}\n\n\treturn SCE_PAF_OK;\n}\n\nvoid ytutils::Log::AddAsync(const char *data)\n{\n\tAddAsyncJob *job = new AddAsyncJob(this, data);\n\tcommon::SharedPtr<job::JobItem> itemParam(job);\n\tjob::JobQueue::DefaultQueue()->Enqueue(itemParam);\n}\n\nvoid ytutils::Log::Remove(const char *data)\n{\n\tchar *sptr;\n\tchar dataCopy[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\tsce_paf_strncpy(dataCopy, data, SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE);\n\n\t// Replace '=' in playlists with '}' to not confuse INI processor\n\tsptr = sce_paf_strchr(dataCopy, '=');\n\n\twhile (sptr)\n\t{\n\t\t*sptr = '}';\n\t\tsptr = sce_paf_strchr(sptr, '=');\n\t}\n\n\tm_ini->del(dataCopy);\n\tm_ini->flush();\n}\n\nint32_t ytutils::Log::UpdateFromTUS()\n{\n\treturn SCE_OK;\n}\n\nint32_t ytutils::Log::UploadToTUS()\n{\n\treturn SCE_OK;\n}\n\nytutils::HistLog::HistLog(uint32_t tus) : Log(tus)\n{\n\tuint32_t i = 0;\n\tchar val[2];\n\tchar data[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\tIni::InitParameter param;\n\tIni::MemAllocator alloc;\n\talloc.allocate = sce_paf_malloc;\n\talloc.deallocate = sce_paf_free;\n\n\tparam.workmemSize = SCE_KERNEL_4KiB;\n\tparam.unk_0x4 = SCE_KERNEL_4KiB;\n\tparam.allocator = &alloc;\n\n\tm_ini = new Ini::IniFileProcessor();\n\tm_ini->initialize(&param);\n\tm_ini->open(\"savedata0:yt_hist_log.ini\", \"rw\", 0);\n\n\ti = m_ini->size();\n\tif (i <= k_maxHistItems)\n\t\treturn;\n\n\ti = i - k_maxHistItems;\n\n\twhile (i != 0)\n\t{\n\t\tm_ini->parse(data, val, sizeof(val));\n\t\tm_ini->del(data);\n\t\ti--;\n\t}\n\n\tm_ini->reset();\n}\n\nint32_t ytutils::HistLog::UpdateFromTUS()\n{\n\tint32_t ret = SCE_ERROR_ERRNO_ECONNREFUSED;\n\tuint32_t tus = m_tus;\n\n\tif (!nputils::IsAllGreen())\n\t{\n\t\treturn ret;\n\t}\n\n\tif (tus == UINT_MAX)\n\t{\n\t\treturn ret;\n\t}\n\n\tret = nputils::GetTUS()->DownloadFile(tus, \"savedata0:yt_hist_log_tus.ini\");\n\tif (ret < 0)\n\t{\n\t\tLocalFile::RemoveFile(\"savedata0:yt_hist_log_tus.ini\");\n\t\treturn UploadToTUS();\n\t}\n\n\tm_ini->close();\n\tm_ini->terminate();\n\tdelete m_ini;\n\n\tLocalFile::RemoveFile(\"savedata0:yt_hist_log.ini\");\n\tLocalFile::RenameFile(\"savedata0:yt_hist_log_tus.ini\", \"savedata0:yt_hist_log.ini\");\n\n\tuint32_t i = 0;\n\tchar val[2];\n\tchar data[SCE_INI_FILE_PROCESSOR_KEY_BUFFER_SIZE];\n\tIni::InitParameter param;\n\tIni::MemAllocator alloc;\n\talloc.allocate = sce_paf_malloc;\n\talloc.deallocate = sce_paf_free;\n\n\tparam.workmemSize = SCE_KERNEL_4KiB;\n\tparam.unk_0x4 = SCE_KERNEL_4KiB;\n\tparam.allocator = &alloc;\n\n\tm_ini = new Ini::IniFileProcessor();\n\tm_ini->initialize(&param);\n\tm_ini->open(\"savedata0:yt_hist_log.ini\", \"rw\", 0);\n\n\ti = m_ini->size();\n\tif (i <= k_maxHistItems)\n\t\treturn ret;\n\n\ti = i - k_maxHistItems;\n\n\twhile (i != 0)\n\t{\n\t\tm_ini->parse(data, val, sizeof(val));\n\t\tm_ini->del(data);\n\t\ti--;\n\t}\n\n\tm_ini->reset();\n\n\treturn ret;\n}\n\nint32_t ytutils::HistLog::UploadToTUS()\n{\n\tint32_t ret = SCE_ERROR_ERRNO_ECONNREFUSED;\n\tuint32_t tus = m_tus;\n\n\tif (!nputils::IsAllGreen())\n\t{\n\t\treturn ret;\n\t}\n\n\tif (tus == UINT_MAX)\n\t{\n\t\treturn ret;\n\t}\n\n\tm_ini->flush();\n\n\tret = nputils::GetTUS()->UploadFile(tus, \"savedata0:yt_hist_log.ini\");\n\n\treturn ret;\n}\n\nytutils::FavLog::FavLog(uint32_t tus) : Log(tus)\n{\n\tIni::InitParameter param;\n\tIni::MemAllocator alloc;\n\talloc.allocate = sce_paf_malloc;\n\talloc.deallocate = sce_paf_free;\n\n\tparam.workmemSize = SCE_KERNEL_4KiB;\n\tparam.unk_0x4 = SCE_KERNEL_4KiB;\n\tparam.allocator = &alloc;\n\n\tm_ini = new Ini::IniFileProcessor();\n\tm_ini->initialize(&param);\n\tm_ini->open(\"savedata0:yt_fav_log.ini\", \"rw\", 0);\n}\n\nint32_t ytutils::FavLog::UpdateFromTUS()\n{\n\tint32_t ret = SCE_ERROR_ERRNO_ECONNREFUSED;\n\tuint32_t tus = m_tus;\n\n\tif (!nputils::IsAllGreen())\n\t{\n\t\treturn ret;\n\t}\n\n\tif (tus == UINT_MAX)\n\t{\n\t\treturn ret;\n\t}\n\n\tret = nputils::GetTUS()->DownloadFile(tus, \"savedata0:yt_fav_log_tus.ini\");\n\tif (ret < 0)\n\t{\n\t\tLocalFile::RemoveFile(\"savedata0:yt_fav_log_tus.ini\");\n\t\treturn UploadToTUS();\n\t}\n\n\tm_ini->close();\n\tm_ini->terminate();\n\tdelete m_ini;\n\n\tLocalFile::RemoveFile(\"savedata0:yt_fav_log.ini\");\n\tLocalFile::RenameFile(\"savedata0:yt_fav_log_tus.ini\", \"savedata0:yt_fav_log.ini\");\n\n\tIni::InitParameter param;\n\tIni::MemAllocator alloc;\n\talloc.allocate = sce_paf_malloc;\n\talloc.deallocate = sce_paf_free;\n\n\tparam.workmemSize = SCE_KERNEL_4KiB;\n\tparam.unk_0x4 = SCE_KERNEL_4KiB;\n\tparam.allocator = &alloc;\n\n\tm_ini = new Ini::IniFileProcessor();\n\tm_ini->initialize(&param);\n\tm_ini->open(\"savedata0:yt_fav_log.ini\", \"rw\", 0);\n\n\treturn ret;\n}\n\nint32_t ytutils::FavLog::UploadToTUS()\n{\n\tint32_t ret = SCE_ERROR_ERRNO_ECONNREFUSED;\n\tuint32_t tus = m_tus;\n\n\tif (!nputils::IsAllGreen())\n\t{\n\t\treturn ret;\n\t}\n\n\tif (tus == UINT_MAX)\n\t{\n\t\treturn ret;\n\t}\n\n\tm_ini->flush();\n\n\tret = nputils::GetTUS()->UploadFile(tus, \"savedata0:yt_fav_log.ini\");\n\n\treturn ret;\n}\n\nvoid ytutils::FavLog::Clean()\n{\n\tif (s_favLog)\n\t{\n\t\tuint32_t oldTus = s_favLog->m_tus;\n\t\tif (nputils::IsAllGreen())\n\t\t{\n\t\t\tnputils::GetTUS()->UploadString(s_favLog->m_tus, \" \");\n\t\t}\n\t\tdelete s_favLog;\n\t\tLocalFile::RemoveFile(\"savedata0:yt_fav_log.ini\");\n\t\ts_favLog = new ytutils::FavLog(oldTus);\n\t}\n}\n\nvoid ytutils::HistLog::Clean()\n{\n\tif (s_histLog)\n\t{\n\t\tuint32_t oldTus = s_histLog->m_tus;\n\t\tif (nputils::IsAllGreen())\n\t\t{\n\t\t\tnputils::GetTUS()->UploadString(s_histLog->m_tus, \" \");\n\t\t}\n\t\tdelete s_histLog;\n\t\tLocalFile::RemoveFile(\"savedata0:yt_hist_log.ini\");\n\t\ts_histLog = new ytutils::HistLog(oldTus);\n\t}\n}\n\nvoid ytutils::Init(uint32_t histTUS, uint32_t favTUS)\n{\n\tftInit(sce_paf_malloc, sce_paf_free, sce_paf_realloc, utils::DoGETRequest, utils::DoPOSTRequest);\n\n\tif (!s_histLog)\n\t{\n\t\ts_histLog = new ytutils::HistLog(histTUS);\n\t}\n\tif (!s_favLog)\n\t{\n\t\ts_favLog = new ytutils::FavLog(favTUS);\n\t}\n\n\ts_downloader = new Downloader();\n\n\ts_share = curl_share_init();\n\tcurl_share_setopt(s_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);\n\tcurl_share_setopt(s_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);\n\tcurl_share_setopt(s_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);\n\tcurl_share_setopt(s_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);\n\tcurl_share_setopt(s_share, CURLSHOPT_SHARE, CURL_LOCK_DATA_PSL);\n}\n\nvoid ytutils::Flush()\n{\n\tif (s_histLog)\n\t{\n\t\ts_histLog->Flush();\n\t}\n\tif (s_favLog)\n\t{\n\t\ts_favLog->Flush();\n\t}\n}\n\nvoid ytutils::Term()\n{\n\tcurl_share_cleanup(s_share);\n\n\tdelete s_downloader;\n\n\tif (s_histLog)\n\t{\n\t\tdelete s_histLog;\n\t\ts_histLog = NULL;\n\t}\n\tif (s_favLog)\n\t{\n\t\tdelete s_favLog;\n\t\ts_favLog = NULL;\n\t}\n\n\tftTerm();\n}\n\nytutils::HistLog *ytutils::GetHistLog()\n{\n\treturn s_histLog;\n}\n\nytutils::FavLog *ytutils::GetFavLog()\n{\n\treturn s_favLog;\n}\n\nint32_t ytutils::EnqueueDownload(const char *url, const char *name)\n{\n\treturn s_downloader->Enqueue(g_appPlugin, url, name);\n}\n\nint32_t ytutils::EnqueueDownloadAsync(const char *url, const char *name)\n{\n\treturn s_downloader->EnqueueAsync(g_appPlugin, url, name);\n}\n\nCURLSH *ytutils::GetShare()\n{\n\treturn s_share;\n}\n\nvoid ytutils::FormatViews(wstring& res, uint32_t views, bool add)\n{\n\twchar_t buf[128];\n\tuint32_t bufsize = 128;\n\n\tif (views < 1000)\n\t{\n\t\tsce_paf_swprintf(buf, bufsize, L\"%u views\", views);\n\t}\n\telse if (views < 1000000)\n\t{\n\t\tsce_paf_swprintf(buf, bufsize, L\"%.2gK views\", views / 1000.0f);\n\t}\n\telse if (views < 1000000000)\n\t{\n\t\tsce_paf_swprintf(buf, bufsize, L\"%.2gM views\", views / 1000000.0f);\n\t}\n\telse\n\t{\n\t\tsce_paf_swprintf(buf, bufsize, L\"%.2gB views\", views / 1000000000.0f);\n\t}\n\n\tif (add)\n\t{\n\t\tres += buf;\n\t}\n\telse\n\t{\n\t\tres = buf;\n\t}\n}"
  },
  {
    "path": "NetStream-DE/NetStream-DE.vcxproj",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup Label=\"ProjectConfigurations\">\n    <ProjectConfiguration Include=\"Debug|PSVita\">\n      <Configuration>Debug</Configuration>\n      <Platform>PSVita</Platform>\n    </ProjectConfiguration>\n    <ProjectConfiguration Include=\"Release|PSVita\">\n      <Configuration>Release</Configuration>\n      <Platform>PSVita</Platform>\n    </ProjectConfiguration>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"download_enabler.cpp\" />\n    <ClCompile Include=\"paf_runtime.c\" />\n  </ItemGroup>\n  <PropertyGroup Label=\"Globals\">\n    <ProjectGuid>{A6BB4747-BD6A-4DFC-B213-236038A9E766}</ProjectGuid>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.Default.props\" />\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|PSVita'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n  </PropertyGroup>\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|PSVita'\" Label=\"Configuration\">\n    <ConfigurationType>DynamicLibrary</ConfigurationType>\n  </PropertyGroup>\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.props\" />\n  <PropertyGroup Condition=\"'$(DebuggerFlavor)'=='PSVitaDebugger'\" Label=\"OverrideDebuggerDefaults\">\n    <!--LocalDebuggerCommand>$(TargetPath)</LocalDebuggerCommand-->\n    <!--LocalDebuggerReboot>false</LocalDebuggerReboot-->\n    <!--LocalDebuggerCommandArguments></LocalDebuggerCommandArguments-->\n    <!--LocalDebuggerTarget></LocalDebuggerTarget-->\n    <!--LocalDebuggerWorkingDirectory>$(ProjectDir)</LocalDebuggerWorkingDirectory-->\n    <!--LocalMappingFile></LocalMappingFile-->\n    <!--LocalRunCommandLine></LocalRunCommandLine-->\n  </PropertyGroup>\n  <ImportGroup Label=\"ExtensionSettings\">\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Debug|PSVita'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <ImportGroup Label=\"PropertySheets\" Condition=\"'$(Configuration)|$(Platform)'=='Release|PSVita'\">\n    <Import Project=\"$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props\" Condition=\"exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')\" Label=\"LocalAppDataPlatform\" />\n  </ImportGroup>\n  <PropertyGroup Label=\"UserMacros\" />\n  <PropertyGroup />\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Release|PSVita'\">\n    <ClCompile>\n      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions);</PreprocessorDefinitions>\n      <OptimizationLevel>Level3</OptimizationLevel>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <AdditionalIncludeDirectories>$(SCE_PSP2_SDK_DIR)\\target\\include\\vdsuite\\user;$(SCE_PSP2_SDK_DIR)\\target\\include\\vdsuite\\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <CppLanguageStd>Cpp11</CppLanguageStd>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>-lSceLibKernel_stub;-lScePafStdc_stub;-lScePafCommon_stub;-lScePafMisc_stub;-ltaihen_stub;-lsnc;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalOptions>--no-standard-libraries </AdditionalOptions>\n      <AdditionalLibraryDirectories>$(SCE_PSP2_SDK_DIR)\\target\\lib\\vdsuite;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n    </Link>\n    <PostBuildEvent>\n      <Command>\"$(SCE_PSP2_SDK_DIR)/host_tools/build/bin/vdsuite-pubprx.exe\" --strip --compress \"$(LocalDebuggerCommand)\" \"$(OutDir)download_enabler_netstream.suprx\"\ncopy /Y \"$(OutDir)download_enabler_netstream.suprx\" \"$(SolutionDir)NetStream\\CONTENTS\\module\\download_enabler_netstream.suprx\"</Command>\n    </PostBuildEvent>\n  </ItemDefinitionGroup>\n  <ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='Debug|PSVita'\">\n    <ClCompile>\n      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions);</PreprocessorDefinitions>\n      <GenerateDebugInformation>true</GenerateDebugInformation>\n      <PrecompiledHeader>NotUsing</PrecompiledHeader>\n      <AdditionalIncludeDirectories>$(SCE_PSP2_SDK_DIR)\\target\\include\\vdsuite\\user;$(SCE_PSP2_SDK_DIR)\\target\\include\\vdsuite\\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\n      <CppLanguageStd>Cpp11</CppLanguageStd>\n    </ClCompile>\n    <Link>\n      <AdditionalDependencies>-lSceLibKernel_stub;-lScePafStdc_stub;-lScePafCommon_stub;-lScePafMisc_stub;-ltaihen_stub;-lsnc;%(AdditionalDependencies)</AdditionalDependencies>\n      <AdditionalOptions>--no-standard-libraries </AdditionalOptions>\n      <AdditionalLibraryDirectories>$(SCE_PSP2_SDK_DIR)\\target\\lib\\vdsuite;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>\n    </Link>\n    <PostBuildEvent>\n      <Command>\"$(SCE_PSP2_SDK_DIR)/host_tools/build/bin/vdsuite-pubprx.exe\" --strip --compress \"$(LocalDebuggerCommand)\" \"$(OutDir)download_enabler_netstream.suprx\"\ncopy /Y \"$(OutDir)download_enabler_netstream.suprx\" \"$(SolutionDir)NetStream\\CONTENTS\\module\\download_enabler_netstream.suprx\"</Command>\n    </PostBuildEvent>\n  </ItemDefinitionGroup>\n  <Import Condition=\"'$(ConfigurationType)' == 'Makefile' and Exists('$(VCTargetsPath)\\Platforms\\$(Platform)\\SCE.Makefile.$(Platform).targets')\" Project=\"$(VCTargetsPath)\\Platforms\\$(Platform)\\SCE.Makefile.$(Platform).targets\" />\n  <Import Project=\"$(VCTargetsPath)\\Microsoft.Cpp.targets\" />\n  <ImportGroup Label=\"ExtensionTargets\">\n  </ImportGroup>\n</Project>"
  },
  {
    "path": "NetStream-DE/NetStream-DE.vcxproj.filters",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <ItemGroup>\n    <Filter Include=\"Source Files\">\n      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>\n      <Extensions>cpp;c;cxx;cc;s;asm</Extensions>\n    </Filter>\n    <Filter Include=\"Header Files\">\n      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>\n      <Extensions>h;hpp</Extensions>\n    </Filter>\n  </ItemGroup>\n  <ItemGroup>\n    <ClCompile Include=\"paf_runtime.c\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n    <ClCompile Include=\"download_enabler.cpp\">\n      <Filter>Source Files</Filter>\n    </ClCompile>\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "NetStream-DE/NetStream-DE.vcxproj.user",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\n  <PropertyGroup />\n</Project>"
  },
  {
    "path": "NetStream-DE/download_enabler.cpp",
    "content": "/*\n  VitaTweaks: Download Enabler\n  Copyright (C) 2018, TheFloW\n\n  This program is free software: you can redistribute it and/or modify\n  it under the terms of the GNU General Public License as published by\n  the Free Software Foundation, either version 3 of the License, or\n  (at your option) any later version.\n\n  This program is distributed in the hope that it will be useful,\n  but WITHOUT ANY WARRANTY; without even the implied warranty of\n  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n  GNU General Public License for more details.\n\n  You should have received a copy of the GNU General Public License\n  along with this program.  If not, see <http://www.gnu.org/licenses/>.\n*/\n\n#include <kernel.h>\n#include <taihen.h>\n#include <paf.h>\n\nstatic tai_hook_ref_t GetFileTypeRef;\nstatic tai_hook_ref_t ExportFileRef;\nstatic SceUID hooks[2];\n\nstatic int ExportFilePatched(uint32_t *data)\n{\n\tint res = TAI_NEXT(ExportFilePatched, ExportFileRef, data);\n\n\tif (res == 0x80101A09)\n\t{\n\t\tpaf::string download_path;\n\t\tpaf::string bgdl_path;\n\t\tchar file_name[256];\n\t\tchar short_name[256];\n\t\tuint16_t url_length = 0;\n\t\tuint32_t count = 0;\n\n\t\tuint32_t num = *reinterpret_cast<uint32_t *>(data[0]);\n\n\t\tbgdl_path = paf::common::FormatString(\"ux0:bgdl/t/%08x/d0.pdb\", num);\n\n\t\tint ret = 0;\n\t\tpaf::common::SharedPtr<paf::LocalFile> fd = paf::LocalFile::Open(bgdl_path.c_str(), paf::File::RDONLY, 0, &ret);\n\t\tif (ret != SCE_PAF_OK)\n\t\t{\n\t\t\treturn ret;\n\t\t}\n\n\t\tfd->Seek(0xD6, paf::File::SET);\n\t\tfd->Read(&url_length, sizeof(uint16_t));\n\t\tfd->Seek(0xF7 + url_length, paf::File::SET);\n\t\tfd->Read(file_name, sizeof(file_name));\n\t\tfd->Close();\n\n\t\tbgdl_path.clear();\n\t\tbgdl_path = paf::common::FormatString(\"ux0:bgdl/t/%08x/%s\", num, file_name);\n\n\t\tchar *ext = sce_paf_strrchr(file_name, '.');\n\t\tif (ext)\n\t\t{\n\t\t\tint len = ext - file_name;\n\t\t\tif (len > sizeof(short_name) - 1)\n\t\t\t\tlen = sizeof(short_name) - 1;\n\t\t\tsce_paf_strncpy(short_name, file_name, len);\n\t\t\tshort_name[len] = '\\0';\n\t\t}\n\t\telse\n\t\t{\n\t\t\tsce_paf_strncpy(short_name, file_name, sizeof(short_name));\n\t\t\text = \"\";\n\t\t}\n\n\t\twhile (1)\n\t\t{\n\t\t\tif (count == 0)\n\t\t\t{\n\t\t\t\tdownload_path = paf::common::FormatString(\"ux0:download/%s\", file_name);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tdownload_path = paf::common::FormatString(\"ux0:download/%s (%d)%s\", short_name, count, ext);\n\t\t\t}\n\n\t\t\tif (!paf::LocalFile::Exists(download_path.c_str()))\n\t\t\t{\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcount++;\n\t\t}\n\n\t\tres = sceIoMkdir(\"ux0:download\", 0006);\n\t\tif (res < 0 && res != 0x80010011)\n\t\t{\n\t\t\treturn res;\n\t\t}\n\n\t\treturn paf::LocalFile::RenameFile(bgdl_path.c_str(), download_path.c_str());\n\t}\n\n\treturn res;\n}\n\nstatic int32_t GetFileTypePatched(int unk, int *type, char **filename, char **mime_type)\n{\n\tint res = TAI_NEXT(GetFileTypePatched, GetFileTypeRef, unk, type, filename, mime_type);\n\n\tif (!sceClibStrcmp(*mime_type, \"video/mp4\"))\n\t{\n\t\t*type = 3;\n\t\treturn 0;\n\t}\n\tif (res == 0x80103A21)\n\t{\n\t\t*type = 1;\n\t\treturn 0;\n\t}\n\n\treturn res;\n}\n\nextern \"C\" {\n\n\t#include <moduleinfo.h>\n\n\tSCE_MODULE_INFO(NetStream_DE, 2, 1, 1)\n\n\tint module_start(size_t args, const void * argp)\n\t{\n\t\ttai_module_info_t info;\n\t\tinfo.size = sizeof(info);\n\t\tif (taiGetModuleInfo(\"SceShell\", &info) >= 0)\n\t\t{\n\t\t\tswitch (info.module_nid)\n\t\t\t{\n\t\t\tcase 0x0552F692: // 3.60 retail\n\t\t\t{\n\t\t\t\thooks[0] = taiHookFunctionOffset(&ExportFileRef, info.modid, 0, 0x1163F6, 1, ExportFilePatched);\n\t\t\t\thooks[1] = taiHookFunctionOffset(&GetFileTypeRef, info.modid, 0, 0x11B5E4, 1, GetFileTypePatched);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 0x6CB01295: // 3.60 PDEL\n\t\t\t{\n\t\t\t\thooks[0] = taiHookFunctionOffset(&ExportFileRef, info.modid, 0, 0x111D5A, 1, ExportFilePatched);\n\t\t\t\thooks[1] = taiHookFunctionOffset(&GetFileTypeRef, info.modid, 0, 0x116F48, 1, GetFileTypePatched);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 0xEAB89D5C: // 3.60 PTEL\n\t\t\t{\n\t\t\t\thooks[0] = taiHookFunctionOffset(&ExportFileRef, info.modid, 0, 0x112756, 1, ExportFilePatched);\n\t\t\t\thooks[1] = taiHookFunctionOffset(&GetFileTypeRef, info.modid, 0, 0x117944, 1, GetFileTypePatched);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 0x5549BF1F: // 3.65 retail\n\t\t\tcase 0x34B4D82E: // 3.67 retail\n\t\t\tcase 0x12DAC0F3: // 3.68 retail\n\t\t\t{\n\t\t\t\thooks[0] = taiHookFunctionOffset(&ExportFileRef, info.modid, 0, 0x11644E, 1, ExportFilePatched);\n\t\t\t\thooks[1] = taiHookFunctionOffset(&GetFileTypeRef, info.modid, 0, 0x11B63C, 1, GetFileTypePatched);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 0x0703C828: // 3.69 retail\n\t\t\tcase 0x2053B5A5: // 3.70 retail\n\t\t\tcase 0xF476E785: // 3.71 retail\n\t\t\tcase 0x939FFBE9: // 3.72 retail\n\t\t\tcase 0x734D476A: // 3.73 retail\n\t\t\tcase 0x51CB6207: // 3.74 retail\n\t\t\t{\n\t\t\t\thooks[0] = taiHookFunctionOffset(&ExportFileRef, info.modid, 0, 0x11644E, 1, ExportFilePatched);\n\t\t\t\thooks[1] = taiHookFunctionOffset(&GetFileTypeRef, info.modid, 0, 0x11B63C, 1, GetFileTypePatched);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 0xE6A02F2B: // 3.65 PDEL\n\t\t\t{\n\t\t\t\thooks[0] = taiHookFunctionOffset(&ExportFileRef, info.modid, 0, 0x111DB2, 1, ExportFilePatched);\n\t\t\t\thooks[1] = taiHookFunctionOffset(&GetFileTypeRef, info.modid, 0, 0x116FA0, 1, GetFileTypePatched);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase 0x587F9CED: // 3.65 PTEL\n\t\t\t{\n\t\t\t\thooks[0] = taiHookFunctionOffset(&ExportFileRef, info.modid, 0, 0x1127AE, 1, ExportFilePatched);\n\t\t\t\thooks[1] = taiHookFunctionOffset(&GetFileTypeRef, info.modid, 0, 0x11799C, 1, GetFileTypePatched);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn SCE_KERNEL_START_SUCCESS;\n\t}\n\n\tint module_stop(size_t args, const void * argp)\n\t{\n\t\treturn SCE_KERNEL_STOP_SUCCESS;\n\t}\n}"
  },
  {
    "path": "NetStream-DE/paf_runtime.c",
    "content": "int _sceLdTlsRegisterModuleInfo()\n{\n\treturn 0;\n}\n\nint _sceLdTlsUnregisterModuleInfo()\n{\n\treturn 0;\n}\n\nint __at_quick_exit()\n{\n\treturn 0;\n}"
  },
  {
    "path": "NetStream.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.28307.1525\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"NetStream\", \"NetStream\\NetStream.vcxproj\", \"{CA4F859F-6FE6-413C-A24A-44CF552FCE91}\"\n\tProjectSection(ProjectDependencies) = postProject\n\t\t{A6BB4747-BD6A-4DFC-B213-236038A9E766} = {A6BB4747-BD6A-4DFC-B213-236038A9E766}\n\tEndProjectSection\nEndProject\nProject(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"NetStream-DE\", \"NetStream-DE\\NetStream-DE.vcxproj\", \"{A6BB4747-BD6A-4DFC-B213-236038A9E766}\"\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|PSVita = Debug|PSVita\n\t\tRelease|PSVita = Release|PSVita\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{CA4F859F-6FE6-413C-A24A-44CF552FCE91}.Debug|PSVita.ActiveCfg = Debug|PSVita\n\t\t{CA4F859F-6FE6-413C-A24A-44CF552FCE91}.Debug|PSVita.Build.0 = Debug|PSVita\n\t\t{CA4F859F-6FE6-413C-A24A-44CF552FCE91}.Release|PSVita.ActiveCfg = Release|PSVita\n\t\t{CA4F859F-6FE6-413C-A24A-44CF552FCE91}.Release|PSVita.Build.0 = Release|PSVita\n\t\t{A6BB4747-BD6A-4DFC-B213-236038A9E766}.Debug|PSVita.ActiveCfg = Debug|PSVita\n\t\t{A6BB4747-BD6A-4DFC-B213-236038A9E766}.Debug|PSVita.Build.0 = Debug|PSVita\n\t\t{A6BB4747-BD6A-4DFC-B213-236038A9E766}.Release|PSVita.ActiveCfg = Release|PSVita\n\t\t{A6BB4747-BD6A-4DFC-B213-236038A9E766}.Release|PSVita.Build.0 = Release|PSVita\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {C50D68BE-AABF-49D8-B1F9-47902DAEB14E}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "README.md",
    "content": "![](https://github.com/GrapheneCt/NetStream/raw/main/logo.PNG)\n\n### Universal video streaming client for PS Vita\n\n![](https://github.com/GrapheneCt/NetStream/raw/main/demo.png)\n\nSupports:\n- YouTube videos and livestreams\n- HTTP server\n- FTP server\n- Local storage\n\nPlanned in the future releases:\n- Twitch\n- NicoNico\n\nPlease read included PS Vita user manual for more information and controls!\n\n![](https://github.com/GrapheneCt/NetStream/raw/main/manual.png)\n"
  },
  {
    "path": "README_MODULE.md",
    "content": "### About modules used in this project (module folder)\n\n## download_enabler_netstream.suprx\n\nModification of download_enabler plugin from VitaTweaks collection that enables NetStream-specific downloads while keeping the original download_enabler functionality.\nIf original download_enabler is present, it will override it.\nThis module is optional: if taihen is not running or fails for some reason, NetStream will still work, but without option to download streams.\n\n## libcurl.suprx\n\nVersion of libcurl for PS Vita without any external dependencies. Uses mbedtls. You only need to provide memory allocators via curl_global_memmanager_set_np().\n\n## libfmodstudio.suprx\n\nFMOD Studio for PS Vita.\n\n## libfmodngpext.suprx\n\nExtension for FMOD that adds some Vita-specific codec support, such as ATRAC3+, ATRAC9, OPUS etc.\n\n## libFourthTube.suprx\n\nInnerTube API parser.\n\n## libLootkit.suprx\n\nTwitch API parser (currently unfinished).\n\n## libBEAVCorePlayer.suprx\n\nBEAVCorePlayer is the system module that implements playback of HLS and DASH streams, remote and locally stored video files.\nIt uses Sony's libLivestream (libLS) library which can be explored in detail in PS4 Trilithium unstripped video.prx.\nThe reason this module is provided with NetStream instead of just loading it from vs0: is beacuse we need to adjust some internal values without using taihen.\nThis adjustments are hardcoded into this module and are the following:\n1. Module is linked with libSceHttpForBEAVCorePlayer instead of SceHttp (see libSceHttpForBEAVCorePlayer.suprx desc.).\n2. Maximum playlist size in libLS options (lsSetLibraryParamDefaults()) is ncreased from 0x80000 to 0xF0000 since YouTube likes to use some absolute units of playlists, sometimes reaching 1 MiB in size.\n\n## libSceHttpForBEAVCorePlayer.suprx\n\nPartial reimplementation of SceHttp that uses libcurl. Needed to support modern cypher methods that are used pretty much everywhere nowadays.\n\n## libSceAvPlayerPSVitaRGBA8888.suprx\n\nSceAvPlayer for WebMAF, modified to output RGBA8888 decoded frames."
  },
  {
    "path": "hls_test.m3u8",
    "content": "#EXTM3U\n#EXT-X-INDEPENDENT-SEGMENTS\n#EXT-X-MEDIA:URI=\"https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/233/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/goi/133/sgoap/clen%3D1379830%3Bdur%3D226.115%3Bgir%3Dyes%3Bitag%3D139%3Blmt%3D1717003443652515/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,goi,sgoap,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRQIgeElfn3Dn45vHc3sowOq6NSRN1w92fW6_oE8UgES2XuQCIQCqgaDAykqT59zXwGYNhH_acnw8rK5kgltm2aGbyfWR9A%3D%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIganqmYqbZiWNkeUP2hPGGs_ANjik3-3Utrm7OZly4n8ICICsIT50_KlqjFey3RvYRfuqH5g6eEceCQdkZmvruOZ6A/playlist/index.m3u8\",TYPE=AUDIO,GROUP-ID=\"233\",NAME=\"Default\",DEFAULT=YES,AUTOSELECT=YES\n#EXT-X-MEDIA:URI=\"https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/234/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/goi/133/sgoap/clen%3D3659103%3Bdur%3D226.046%3Bgir%3Dyes%3Bitag%3D140%3Blmt%3D1717003079097368/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,goi,sgoap,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRgIhAOZAo85HqsWpTB-3ieKCn4NEK9u8LHHKTnrypnZkdZ9JAiEAulAndrj7kNieQGN0l21tBLofSpwQ0ABDo-Ku7BQAenY%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIhAOX9wIUtyH8c_sQG0ufA8XscMAn2wlgdhpO2PN6iBjt_AiARE-Kl2_8tFKASwb1GdMkrdCHT7_XRTJ2R84so6mTe9Q%3D%3D/playlist/index.m3u8\",TYPE=AUDIO,GROUP-ID=\"234\",NAME=\"Default\",DEFAULT=YES,AUTOSELECT=YES\n#EXT-X-MEDIA:URI=\"https://manifest.googlevideo.com/api/manifest/hls_timedtext_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/source/youtube/requiressl/yes/dur/225.992/tts_params/caps%3Dasr%26v%3DStWH_ToJcOU%26lang%3Den%26ip%3D2a09:bac5:5068:2432::39b:e8%26ipbits%3D0%26expire%3D1759217923%26sparams%3Dip,ipbits,expire,caps,v%26signature%3D61EE3550C0C5AA7E5E66DB99DB653EB68E8E35FF.5FD81F0E9738041899CABA5F973DBC85542B6C6C%26key%3Ddg_yt0/rqh/4/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,source,requiressl,dur,tts_params,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRgIhAI5Hg0R26Tv_FTS3rrzHkhKaRg2i8nSIopcbPYh_7LVzAiEAtxTVpjWir5vxIBZxZqKMlidLT2Hbh6jOO_JhoxGgbGc%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRgIhAKsteAMtVTUNIKBAU5LYAxERFG_SoO1PH0pcE5lKSv33AiEAnd7G9KCUEHVQmJlj4i6OPS0NPxAHwk7-yBS1tS8dftI%3D/playlist/index.m3u8\",TYPE=SUBTITLES,GROUP-ID=\"vtt\",LANGUAGE=\"en\",NAME=\"English\",DEFAULT=NO,AUTOSELECT=YES\n#EXT-X-MEDIA:URI=\"https://manifest.googlevideo.com/api/manifest/hls_timedtext_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/source/youtube/requiressl/yes/dur/225.992/tts_params/caps%3Dasr%26v%3DStWH_ToJcOU%26lang%3Dru%26ip%3D2a09:bac5:5068:2432::39b:e8%26ipbits%3D0%26expire%3D1759217923%26sparams%3Dip,ipbits,expire,caps,v%26signature%3D3F73A7D5098D7B5F83899B7170C6108BC9108BF1.6FFCE96ED2A91194678809460E279847D3B73EA4%26key%3Ddg_yt0/rqh/4/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,source,requiressl,dur,tts_params,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRQIhANlwNf2lEHmByHRRToLHNCa-Op2yv5RuC6KQuyTCshNJAiBOZ9TRZA7mf-0HDA3KZA3e_kL_We1TYRCCoJaTQdQrQw%3D%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRgIhAKRHqASvOLA9LtiLLBzSfQ6eDF8pBAKVvpbTbLQ5gKfsAiEAhtIqyiZYNZ2n5HGbbGMMgr0Wy2imnBzoSot1rmTDq-8%3D/playlist/index.m3u8\",TYPE=SUBTITLES,GROUP-ID=\"vtt\",LANGUAGE=\"ru\",NAME=\"Русский\",DEFAULT=NO,AUTOSELECT=YES\n#EXT-X-MEDIA:URI=\"https://manifest.googlevideo.com/api/manifest/hls_timedtext_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/source/youtube/requiressl/yes/dur/225.992/tts_params/caps%3Dasr%26v%3DStWH_ToJcOU%26lang%3Des%26ip%3D2a09:bac5:5068:2432::39b:e8%26ipbits%3D0%26expire%3D1759217923%26sparams%3Dip,ipbits,expire,caps,v%26signature%3D764E12D95BA6A78B50418D934E789512DAAE3CF2.1D65A1F0E6814D7B5D8DF5F389F4411F3109A44B%26key%3Ddg_yt0/rqh/4/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,source,requiressl,dur,tts_params,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRgIhAOn_EBAH8qRPuSDZgJUfiDHf-nr-N5dpKIpL-I7d9tp5AiEAmgsYuGxqG4OIdlm1MPiTLOxFceqEwK-y29oZ3UNsGCs%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIgW6euSFZ8W9UfW6Sjcve-rEYL8kv0Pf8hjrkllrXbLPgCIEnPDK89NSlrsKCgKdAKW4cMa1pIWVr5VQXCwlcRbKqi/playlist/index.m3u8\",TYPE=SUBTITLES,GROUP-ID=\"vtt\",LANGUAGE=\"es\",NAME=\"Español\",DEFAULT=NO,AUTOSELECT=YES\n#EXT-X-STREAM-INF:BANDWIDTH=310870,CODECS=\"avc1.4D4015,mp4a.40.5\",RESOLUTION=426x240,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"233\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/229/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D3539769%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D133%3Blmt%3D1717005936397016/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRAIgNDa5MPNMPOwSpHNpHJw1HriKyWwLfi04X80FfL0KpW8CIEmcykif1oJawrnX66N_Gr775PoZ5zhs21Cz4NxFkrM9/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIgduNF3j7ol45eVTcbQgOdtpl0TDO8c7g98cESN0PNpFACIQCnGlvFZKXUtkzMFsXSmxwr5Mf72EAixEhE1OzRaXjA4Q%3D%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=395468,CODECS=\"avc1.4D4015,mp4a.40.2\",RESOLUTION=426x240,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/229/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D3539769%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D133%3Blmt%3D1717005936397016/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRAIgNDa5MPNMPOwSpHNpHJw1HriKyWwLfi04X80FfL0KpW8CIEmcykif1oJawrnX66N_Gr775PoZ5zhs21Cz4NxFkrM9/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIgduNF3j7ol45eVTcbQgOdtpl0TDO8c7g98cESN0PNpFACIQCnGlvFZKXUtkzMFsXSmxwr5Mf72EAixEhE1OzRaXjA4Q%3D%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=697464,CODECS=\"avc1.4D401E,mp4a.40.2\",RESOLUTION=640x360,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/230/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D6264212%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D134%3Blmt%3D1717005903379199/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRQIgcidRIlEA48uW-bT3gZEoa6gGlfkR9wgvqVAlfCbZFkACIQCPNyK4WqdgkGhvNv4zOEzSyTxZACZfNJDJhBInY8Q_0g%3D%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIgBFFNt2f0M7u4atz_JKigbzkWjVHpIENxA-F6nQV0DVwCIQCciOriU_twscKQi0s6ia_6fSwAtCx2iejsyNg0OFfiUg%3D%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=947327,CODECS=\"avc1.4D401F,mp4a.40.2\",RESOLUTION=854x480,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/231/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D9838679%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D135%3Blmt%3D1717005883206866/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRgIhANpfuSPUxu6WCnNbyB8aRD7NqrbgpZbkbszvF7lybDbmAiEA5Qib3LqQtkYC2ph9qbTznAXB9et1J3kGvGkATnrVsno%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIgXjQUsgqNtZU-j42CoBzkb7yIY4U19TMinZ4w6nT4eHMCIDKe5tz45tal3eKgKao_hO9bPOltNTeD0tTtwF9UQWvJ/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=1288550,CODECS=\"avc1.4D401F,mp4a.40.2\",RESOLUTION=1280x720,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/232/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D17029830%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D136%3Blmt%3D1717005901053781/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRQIhAIcKYtPcUUuMlAnMK-ZNYGUKA_gOKwUv7OiVIUnb3_QfAiBeKfmBNDYtxvc0-6tcyIOpn5NSgAYy1O3_43XE3qjm0g%3D%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRgIhANpGJJU5xzf5x01Cwf3_YZ3SNgdVCN8QvyCv_d9gP6A8AiEA-cAFcwI-ASTsB8Zp0LWCpZQxW1jXu9EupxR0SfBe8Yg%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=169476,CODECS=\"avc1.4D400C,mp4a.40.5\",RESOLUTION=256x144,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"233\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/269/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D1746573%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D160%3Blmt%3D1717006436614228/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRAIgChGf-Roae0o1dv0264mlXdYEFRj4YJK8g-bajE9OSSoCIDSd_TixQQRUegxgiZwx1htRPrmAv1j01_brwTlqelze/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIgYqm7LcuUwrOXZW2lgY-0HTFQ7eXg35z2cL4mGNr2rBYCIA1NtbAzT5g4C3FqK1-O_vr16cE9lxYSxVQuBAXDEMT7/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=3556438,CODECS=\"avc1.640028,mp4a.40.2\",RESOLUTION=1920x1080,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/270/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D39484164%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D137%3Blmt%3D1717006004870890/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRQIgSxy1jHqR24uK2b2jcVdS9eeLynCj_iaz3u1UD5HCBwsCIQDqedexcnv2UaLyfruJ-_FPwW5sMBmODolqWHqrM3_nWQ%3D%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIgfT6wtydlQj1vAF2g6XXnooEHG67bl_FNZtmN8J2kwnQCIBaxPVyi5gxTIQ5NNhoZ3jV0t9J1D2tIfLcmKbLO7epc/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=166947,CODECS=\"vp09.00.11.08,mp4a.40.5\",RESOLUTION=256x144,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"233\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/603/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D1956430%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D278%3Blmt%3D1717007054669933/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4437434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRAIgclE72K1hUSoxN670xtUle2BABzYBrPwWHFrVnw1exP0CIHnEVdlVl8CXhxE059o4TJmWwLT6drgzGZdGdHXvQGEo/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRgIhAJbHQLhd_sLJ8OGgVXCJLJRl9TUq8-dJr2XD5TiwPDgfAiEAgpkxKTGx4QZV35_mkTLEXR_jHa8F6N3UZyDHUt8VxYE%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=307650,CODECS=\"vp09.00.20.08,mp4a.40.5\",RESOLUTION=426x240,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"233\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/604/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D3666752%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D242%3Blmt%3D1717006724994876/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4437434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRgIhAJhVP_T1BaIhy6jn1P0xVwB7PF1yEcVHLprkXT_1QjVXAiEAwO5vvzgJ3g8lb7Pi-Dc1YnFWFx_8_W2mn17u2ciJPzk%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIgFRvoM9G4SO3YqfMHuDwOyOdV6YK1KfFOVV-7UTc2oSECIQDK63Zo56a7_4u2fJ_eSzZoOnQAf8hSHZ80cEhy4V--gg%3D%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=392248,CODECS=\"vp09.00.20.08,mp4a.40.2\",RESOLUTION=426x240,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/604/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D3666752%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D242%3Blmt%3D1717006724994876/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4437434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRgIhAJhVP_T1BaIhy6jn1P0xVwB7PF1yEcVHLprkXT_1QjVXAiEAwO5vvzgJ3g8lb7Pi-Dc1YnFWFx_8_W2mn17u2ciJPzk%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIgFRvoM9G4SO3YqfMHuDwOyOdV6YK1KfFOVV-7UTc2oSECIQDK63Zo56a7_4u2fJ_eSzZoOnQAf8hSHZ80cEhy4V--gg%3D%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=705015,CODECS=\"vp09.00.21.08,mp4a.40.2\",RESOLUTION=640x360,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/605/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D8595627%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D243%3Blmt%3D1717006486503966/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4437434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRAIgI2DDnuTrJyulz6ZOiFDcyeGSwdvnjVaICkE20Yq1SYYCIFOtXNcutlrtmkD-b1rnn6aEB6pwR0kdbZdVNRPIzy_v/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIgU_MX4DHJj7eqAxEFqhrvwKAQDndOmGXWMemiJ6UdrrkCIHPWEwNUTRq2fxJxyFVAruK_6zckW8oPpSp2-ABhtOu9/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=1161960,CODECS=\"vp09.00.30.08,mp4a.40.2\",RESOLUTION=854x480,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/606/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D11543956%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D244%3Blmt%3D1717007175952386/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4437434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRgIhAKaMEoWEVafmRPucxeJQbVi9L_i9jGW5NzWtuM1X0_-UAiEAqLhMFmdM1QVMibgAD2L3eASg6dw7qSetAkYWxr77N2Y%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIhAIDtRjrjlYDuhjj51BaSsb9Vlq3m6aIZa60uCHtfzuf2AiBls8wAUMH6SejOrU7ILuCCoAUN-DUJI_-mCn7JBp-lqQ%3D%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=1580653,CODECS=\"vp09.00.31.08,mp4a.40.2\",RESOLUTION=1280x720,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/609/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D20118329%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D247%3Blmt%3D1717006636897201/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4437434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRAIgAN4MMVqC45cdKdXYdsslIdpeydGEi7zD5vl17DPsxwICIFUU8h3XUHXKIwLXTVMULuH_XlvjJqOIJkgyUuzLPRKp/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIgSopWnvkrIMdxTEDV1Ijkl-loXhcSxA1OSGZbfaFEFsQCIE54M-sj8BzossCjyocKsZkL_X0Bt745-7Lezaq7Pg4x/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=2479083,CODECS=\"vp09.00.40.08,mp4a.40.2\",RESOLUTION=1920x1080,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/614/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/wft/1/sgovp/clen%3D31306520%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D248%3Blmt%3D1717004951605057/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4437434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,wft,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRQIgc-9Ai7LaXgogpoYNGgsHKEtGVrKXFfIuHGaO1gIYzsgCIQDvkUnKqOCuU7zEcP6vyciiP_97NVpayAtRJkjpbsA1Sw%3D%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIgfskPbtapzBFkOIEiky8kR-5fQsGDvXEr9UyKrY3mzOgCIGy5oYDWTCxj7C_AyyNlWZSewLZscPIJ4f_J22Ssx-tM/playlist/index.m3u8\n"
  },
  {
    "path": "hls_test_clean_multi_aux.m3u8",
    "content": "#EXTM3U\n#EXT-X-INDEPENDENT-SEGMENTS\n#EXT-X-MEDIA:URI=\"https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/233/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/goi/133/sgoap/clen%3D1379830%3Bdur%3D226.115%3Bgir%3Dyes%3Bitag%3D139%3Blmt%3D1717003443652515/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,goi,sgoap,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRQIgeElfn3Dn45vHc3sowOq6NSRN1w92fW6_oE8UgES2XuQCIQCqgaDAykqT59zXwGYNhH_acnw8rK5kgltm2aGbyfWR9A%3D%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIganqmYqbZiWNkeUP2hPGGs_ANjik3-3Utrm7OZly4n8ICICsIT50_KlqjFey3RvYRfuqH5g6eEceCQdkZmvruOZ6A/playlist/index.m3u8\",TYPE=AUDIO,GROUP-ID=\"233\",NAME=\"Default\",DEFAULT=YES,AUTOSELECT=YES\n#EXT-X-MEDIA:URI=\"https://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/234/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/goi/133/sgoap/clen%3D3659103%3Bdur%3D226.046%3Bgir%3Dyes%3Bitag%3D140%3Blmt%3D1717003079097368/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,goi,sgoap,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRgIhAOZAo85HqsWpTB-3ieKCn4NEK9u8LHHKTnrypnZkdZ9JAiEAulAndrj7kNieQGN0l21tBLofSpwQ0ABDo-Ku7BQAenY%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIhAOX9wIUtyH8c_sQG0ufA8XscMAn2wlgdhpO2PN6iBjt_AiARE-Kl2_8tFKASwb1GdMkrdCHT7_XRTJ2R84so6mTe9Q%3D%3D/playlist/index.m3u8\",TYPE=AUDIO,GROUP-ID=\"234\",NAME=\"Default\",DEFAULT=YES,AUTOSELECT=YES\n#EXT-X-STREAM-INF:BANDWIDTH=310870,CODECS=\"avc1.4D4015,mp4a.40.5\",RESOLUTION=426x240,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"233\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/229/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D3539769%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D133%3Blmt%3D1717005936397016/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRAIgNDa5MPNMPOwSpHNpHJw1HriKyWwLfi04X80FfL0KpW8CIEmcykif1oJawrnX66N_Gr775PoZ5zhs21Cz4NxFkrM9/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIgduNF3j7ol45eVTcbQgOdtpl0TDO8c7g98cESN0PNpFACIQCnGlvFZKXUtkzMFsXSmxwr5Mf72EAixEhE1OzRaXjA4Q%3D%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=395468,CODECS=\"avc1.4D4015,mp4a.40.2\",RESOLUTION=426x240,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/229/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D3539769%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D133%3Blmt%3D1717005936397016/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRAIgNDa5MPNMPOwSpHNpHJw1HriKyWwLfi04X80FfL0KpW8CIEmcykif1oJawrnX66N_Gr775PoZ5zhs21Cz4NxFkrM9/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIgduNF3j7ol45eVTcbQgOdtpl0TDO8c7g98cESN0PNpFACIQCnGlvFZKXUtkzMFsXSmxwr5Mf72EAixEhE1OzRaXjA4Q%3D%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=697464,CODECS=\"avc1.4D401E,mp4a.40.2\",RESOLUTION=640x360,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/230/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D6264212%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D134%3Blmt%3D1717005903379199/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRQIgcidRIlEA48uW-bT3gZEoa6gGlfkR9wgvqVAlfCbZFkACIQCPNyK4WqdgkGhvNv4zOEzSyTxZACZfNJDJhBInY8Q_0g%3D%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRQIgBFFNt2f0M7u4atz_JKigbzkWjVHpIENxA-F6nQV0DVwCIQCciOriU_twscKQi0s6ia_6fSwAtCx2iejsyNg0OFfiUg%3D%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=947327,CODECS=\"avc1.4D401F,mp4a.40.2\",RESOLUTION=854x480,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/231/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D9838679%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D135%3Blmt%3D1717005883206866/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRgIhANpfuSPUxu6WCnNbyB8aRD7NqrbgpZbkbszvF7lybDbmAiEA5Qib3LqQtkYC2ph9qbTznAXB9et1J3kGvGkATnrVsno%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIgXjQUsgqNtZU-j42CoBzkb7yIY4U19TMinZ4w6nT4eHMCIDKe5tz45tal3eKgKao_hO9bPOltNTeD0tTtwF9UQWvJ/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=1288550,CODECS=\"avc1.4D401F,mp4a.40.2\",RESOLUTION=1280x720,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/232/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D17029830%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D136%3Blmt%3D1717005901053781/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRQIhAIcKYtPcUUuMlAnMK-ZNYGUKA_gOKwUv7OiVIUnb3_QfAiBeKfmBNDYtxvc0-6tcyIOpn5NSgAYy1O3_43XE3qjm0g%3D%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRgIhANpGJJU5xzf5x01Cwf3_YZ3SNgdVCN8QvyCv_d9gP6A8AiEA-cAFcwI-ASTsB8Zp0LWCpZQxW1jXu9EupxR0SfBe8Yg%3D/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=169476,CODECS=\"avc1.4D400C,mp4a.40.5\",RESOLUTION=256x144,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"233\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/269/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D1746573%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D160%3Blmt%3D1717006436614228/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRAIgChGf-Roae0o1dv0264mlXdYEFRj4YJK8g-bajE9OSSoCIDSd_TixQQRUegxgiZwx1htRPrmAv1j01_brwTlqelze/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIgYqm7LcuUwrOXZW2lgY-0HTFQ7eXg35z2cL4mGNr2rBYCIA1NtbAzT5g4C3FqK1-O_vr16cE9lxYSxVQuBAXDEMT7/playlist/index.m3u8\n#EXT-X-STREAM-INF:BANDWIDTH=3556438,CODECS=\"avc1.640028,mp4a.40.2\",RESOLUTION=1920x1080,FRAME-RATE=30,VIDEO-RANGE=SDR,AUDIO=\"234\",SUBTITLES=\"vtt\",CLOSED-CAPTIONS=NONE\nhttps://manifest.googlevideo.com/api/manifest/hls_playlist/expire/1759217923/ei/ozTbaODzJd6vi9oPqr67UQ/ip/2a09:bac5:5068:2432::39b:e8/id/4ad587fd3a0970e5/itag/270/source/youtube/requiressl/yes/ratebypass/yes/pfa/1/sgovp/clen%3D39484164%3Bdur%3D225.992%3Bgir%3Dyes%3Bitag%3D137%3Blmt%3D1717006004870890/rqh/1/hls_chunk_host/rr5---sn-f5f7kn7e.googlevideo.com/xpc/EgVo2aDSNQ%3D%3D/met/1759196323,/mh/45/mm/31,29/mn/sn-f5f7kn7e,sn-f5f7lnl6/ms/au,rdu/mv/m/mvi/5/pl/43/rms/au,au/force_finished/1/initcwndbps/2498750/bui/ATw7iSVhWsyJc6z3FrgIAfpdrj8lz3YDbDPFbg0UXtzskI4eDwE9VduTr-IMNRsBpN3gBxc4z8LfjIhM/spc/hcYD5eoGzKf7mf8Js5Trq91DHjeIobUAJ9rKSkFs_hPjNudGFXp2nmGAfqA823OW/vprv/1/playlist_type/DVR/dover/13/txp/4432434/mt/1759195786/fvip/3/short_key/1/keepalive/yes/fexp/51552689,51565115,51565681,51580968/sparams/expire,ei,ip,id,itag,source,requiressl,ratebypass,pfa,sgovp,rqh,xpc,force_finished,bui,spc,vprv,playlist_type/sig/AJfQdSswRQIgSxy1jHqR24uK2b2jcVdS9eeLynCj_iaz3u1UD5HCBwsCIQDqedexcnv2UaLyfruJ-_FPwW5sMBmODolqWHqrM3_nWQ%3D%3D/lsparams/hls_chunk_host,met,mh,mm,mn,ms,mv,mvi,pl,rms,initcwndbps/lsig/APaTxxMwRAIgfT6wtydlQj1vAF2g6XXnooEHG67bl_FNZtmN8J2kwnQCIBaxPVyi5gxTIQ5NNhoZ3jV0t9J1D2tIfLcmKbLO7epc/playlist/index.m3u8"
  }
]