├── .clang-format
├── .gitignore
├── .gitmodules
├── CMakeLists.txt
├── CPPLINT.cfg
├── LICENSE
├── README.md
├── build
├── .gitignore
├── brands
│ └── fastotv
│ │ └── fastotv.txt
├── build.py
├── build_env.py
├── build_server_remote.py
├── devices
│ ├── __init__.py
│ ├── orange_pi
│ │ ├── __init__.py
│ │ ├── hardware
│ │ │ └── lirc
│ │ │ │ └── hardware.conf
│ │ └── orange_pi.py
│ └── raspberry_pi
│ │ ├── __init__.py
│ │ └── raspberry_pi.py
└── patch
│ └── orange-pi
│ └── sdl2
│ └── SDL_render_gles2.c.patch
├── docs
└── Doxyfile.in
├── images
├── 1024 px_horizontal-01.png
├── 128 px-01.png
├── 144 px-01.png
├── 256 px-01.png
├── 256 px_horizontal-01.png
├── 48 px-01.png
├── 480 px-01.png
├── 480_2 px-01.png
├── 512 px-01.png
├── 512 px_horizontal-01.png
├── 72 px-01.png
├── Horizontal Black-01.png
├── Horizontal White-01.png
├── Logo Black-01.png
├── Logo White-01.png
├── Logo license.txt
├── Logotype 2.png
├── Logotype 2_black.png
└── Logotype 2_white.png
├── install
└── fastotv
│ ├── CHANGELOG
│ ├── COPYRIGHT
│ ├── android
│ ├── AndroidManifest.xml.in
│ ├── configAndroid.json.in
│ ├── icon.png
│ ├── res
│ │ ├── drawable-hdpi
│ │ │ └── icon.png
│ │ ├── drawable-ldpi
│ │ │ └── icon.png
│ │ ├── drawable-mdpi
│ │ │ └── icon.png
│ │ └── drawable-xhdpi
│ │ │ └── icon.png
│ └── strings.xml.in
│ ├── autostart.sh.in
│ ├── config.ini.in
│ ├── desktop.in
│ ├── fonts
│ └── FreeSans.ttf
│ ├── hardware
│ └── lirc
│ │ └── lircrc.conf.in
│ ├── linux
│ ├── gentoo.ebuild.in
│ ├── icon.png
│ ├── postinst.in
│ ├── prerm.in
│ └── xinitrc.in
│ ├── macosx
│ └── icon.icns
│ ├── resources
│ ├── connection_error.png
│ ├── down_arrow.png
│ ├── left_arrow.png
│ ├── offline_channel.png
│ ├── right_arrow.png
│ ├── unknown_channel.png
│ └── up_arrow.png
│ └── windows
│ ├── database.bmp
│ ├── icon.ico
│ ├── nsis-top-logo.bmp
│ └── winres.rc.in
├── scripts
├── create_pre_commit_hook.sh
└── pre-commit
├── src
├── CMakeLists.txt
├── client
│ ├── cmdutils.cpp
│ ├── cmdutils.h
│ ├── events
│ │ ├── network_events.cpp
│ │ └── network_events.h
│ ├── inner
│ │ ├── inner_tcp_handler.cpp
│ │ ├── inner_tcp_handler.h
│ │ ├── inner_tcp_server.cpp
│ │ └── inner_tcp_server.h
│ ├── inputs
│ │ ├── lirc_input_client.cpp
│ │ └── lirc_input_client.h
│ ├── ioservice.cpp
│ ├── ioservice.h
│ ├── live_stream
│ │ ├── playlist_entry.cpp
│ │ ├── playlist_entry.h
│ │ ├── playlist_window.cpp
│ │ └── playlist_window.h
│ ├── load_config.cpp
│ ├── load_config.h
│ ├── player.cpp
│ ├── player.h
│ ├── programs_window.cpp
│ ├── programs_window.h
│ ├── tv_player_main.cpp
│ ├── utils.cpp
│ ├── utils.h
│ ├── vod
│ │ ├── vod_entry.cpp
│ │ ├── vod_entry.h
│ │ ├── vods_window.cpp
│ │ └── vods_window.h
│ ├── vods_window.cpp
│ └── vods_window.h
└── third-party
│ └── ini
│ └── CMakeLists.txt
└── tests
└── unit_tests
└── test_commands.cpp
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | BasedOnStyle: Chromium
3 | ColumnLimit: 120
4 | Standard: Cpp11
5 | ...
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Compiled Dynamic libraries
12 | *.so
13 | *.dylib
14 | *.dll
15 |
16 | # Fortran module files
17 | *.mod
18 | *.smod
19 |
20 | # Compiled Static libraries
21 | *.lai
22 | *.la
23 | *.a
24 | *.lib
25 |
26 | # Executables
27 | *.exe
28 | *.out
29 | *.app
30 |
31 | # other
32 | *.pyc
33 | CMakeLists.txt.user
34 | *~
35 |
36 | # fastogt tmp files
37 | build/.idea/
38 | build_cmake/
39 | .idea/
40 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "cmake"]
2 | path = cmake
3 | url = https://github.com/fastogt/cmake.git
4 | [submodule "src/third-party/ini/inih"]
5 | path = src/third-party/ini/inih
6 | url = https://github.com/benhoyt/inih.git
7 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.3.0) # deb package fix in 3.3.0
2 | ###################### Branding ##########################
3 |
4 | SET(BRANDING_PROJECT_NAME "FastoTV" CACHE STRING "Branding for ${BRANDING_PROJECT_NAME}") #default
5 | SET(BRANDING_PROJECT_VERSION "1.25.0.60" CACHE STRING "Branding version for ${BRANDING_PROJECT_NAME}") #default
6 | SET(BRANDING_PROJECT_BUILD_TYPE_VERSION "release" CACHE STRING "Build version type for ${BRANDING_PROJECT_NAME}") #default
7 | #possible variables: alfa, beta, rc, release
8 |
9 | SET(BRANDING_PROJECT_DOMAIN "https://fastotv.com" CACHE STRING "Branding domain url for ${BRANDING_PROJECT_NAME}") #default
10 | SET(BRANDING_PROJECT_DOWNLOAD_LINK "https://fastotv.com/downloads" CACHE STRING "Branding download root url for ${BRANDING_PROJECT_NAME}")
11 | SET(BRANDING_PROJECT_COMPANYNAME "FastoGT" CACHE STRING "Company name for ${BRANDING_PROJECT_NAME}") #default
12 | SET(BRANDING_PROJECT_COMPANYNAME_DOMAIN "https://fastogt.com" CACHE STRING "Internet domain name company for ${BRANDING_PROJECT_NAME}") #default
13 | SET(BRANDING_PROJECT_MAINTAINER_MAIL "atopilski@fastogt.com" CACHE STRING "Internet mail address maintainer of ${BRANDING_PROJECT_NAME}") #default
14 | SET(BRANDING_PROJECT_MAINTAINER_NAME "Alexandr Topilski" CACHE STRING "Name of maintainer for ${BRANDING_PROJECT_NAME}") #default
15 |
16 | SET(BRANDING_PROJECT_GITHUB_FORK "https://github.com/fastogt/fastotv" CACHE STRING "Branding fork url for ${BRANDING_PROJECT_NAME}") #default
17 | SET(BRANDING_PROJECT_GITHUB_ISSUES "https://github.com/fastogt/fastotv/issues" CACHE STRING "Branding issues url for ${BRANDING_PROJECT_NAME}") #default
18 |
19 | SET(BRANDING_PROJECT_HOMEPAGE_LINK "https://fastotv.com" CACHE STRING "Home page link for ${BRANDING_PROJECT_NAME}") #default
20 | SET(BRANDING_PROJECT_FACEBOOK_LINK "https://facebook.com/profile.php?id=100016809641223" CACHE STRING "FaceBook link for ${BRANDING_PROJECT_NAME}") #default
21 | SET(BRANDING_PROJECT_TWITTER_LINK "https://twitter.com/FastoTv" CACHE STRING "Twitter link for ${BRANDING_PROJECT_NAME}") #default
22 | SET(BRANDING_PROJECT_GITHUB_LINK "https://github.com/fastogt/fastotv" CACHE STRING "GitHub link for ${BRANDING_PROJECT_NAME}") #default
23 |
24 | SET(BRANDING_PROJECT_SUMMARY "Cross-platform open source TV player." CACHE STRING "Short description of ${BRANDING_PROJECT_NAME}")
25 | SET(BRANDING_PROJECT_DESCRIPTION "${BRANDING_PROJECT_NAME} it is TV player." CACHE STRING "Description of ${BRANDING_PROJECT_NAME}")
26 | SET(BRANDING_PROJECT_COPYRIGHT "Copyright (C) 2014-2022 ${BRANDING_PROJECT_COMPANYNAME} All Rights Reserved." CACHE STRING "Copyright notice for ${BRANDING_PROJECT_NAME}") #default
27 |
28 | PROJECT(${BRANDING_PROJECT_NAME} VERSION ${BRANDING_PROJECT_VERSION} LANGUAGES CXX C)
29 | SET(CMAKE_CXX_STANDARD 14)
30 | SET(CMAKE_CXX_STANDARD_REQUIRED ON)
31 | SET(CMAKE_CXX_EXTENSIONS OFF)
32 | SET(CMAKE_C_STANDARD 99)
33 | SET(CMAKE_C_STANDARD_REQUIRED ON)
34 | #SET(CMAKE_C_EXTENSIONS OFF)
35 | #################### Project Settings ####################
36 | SET(PROJECT_NAME_TITLE ${PROJECT_NAME}) #PROJECT_NAME in cache
37 | SET(PROJECT_DOMAIN ${BRANDING_PROJECT_DOMAIN})
38 | SET(PROJECT_DOWNLOAD_LINK ${BRANDING_PROJECT_DOWNLOAD_LINK})
39 | SET(PROJECT_COMPANYNAME ${BRANDING_PROJECT_COMPANYNAME})
40 | SET(PROJECT_COPYRIGHT ${BRANDING_PROJECT_COPYRIGHT})
41 | SET(PROJECT_SUMMARY ${BRANDING_PROJECT_SUMMARY})
42 | SET(PROJECT_DESCRIPTION ${BRANDING_PROJECT_DESCRIPTION})
43 | SET(PROJECT_COMPANYNAME_DOMAIN ${BRANDING_PROJECT_COMPANYNAME_DOMAIN})
44 | SET(PROJECT_MAINTAINER_MAIL ${BRANDING_PROJECT_MAINTAINER_MAIL})
45 | SET(PROJECT_MAINTAINER_NAME ${BRANDING_PROJECT_MAINTAINER_NAME})
46 | SET(PROJECT_GITHUB_FORK ${BRANDING_PROJECT_GITHUB_FORK})
47 | SET(PROJECT_GITHUB_ISSUES ${BRANDING_PROJECT_GITHUB_ISSUES})
48 |
49 | SET(PROJECT_BUILD_TYPE_VERSION ${BRANDING_PROJECT_BUILD_TYPE_VERSION})
50 | SET(PROJECT_HOMEPAGE_LINK ${BRANDING_PROJECT_HOMEPAGE_LINK})
51 | SET(PROJECT_FACEBOOK_LINK ${BRANDING_PROJECT_FACEBOOK_LINK})
52 | SET(PROJECT_TWITTER_LINK ${BRANDING_PROJECT_TWITTER_LINK})
53 | SET(PROJECT_GITHUB_LINK ${BRANDING_PROJECT_GITHUB_LINK})
54 | ##########################################################
55 |
56 | STRING(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE)
57 | STRING(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPERRCASE)
58 |
59 | SET(PROJECT_BRANDING_FOLDER ${CMAKE_SOURCE_DIR}/install/${PROJECT_NAME_LOWERCASE})
60 | SET(PROJECT_VERSION_SHORT ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) #PROJECT_VERSION_* in cache
61 | SET(PROJECT_VERSION_INTEGER ${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR}${PROJECT_VERSION_PATCH}) #PROJECT_VERSION_* in cache
62 |
63 | MESSAGE(STATUS "PROJECT_VERSION: ${PROJECT_VERSION}")
64 |
65 | SET(PROJECT_CHANGELOG_FILE ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/CHANGELOG)
66 | SET(DATE_CMD "date")
67 | SET(DATE_ARGS "+%a %b %d %Y")
68 | EXECUTE_PROCESS(COMMAND ${DATE_CMD} ${DATE_ARGS} RESULT_VARIABLE CHANGELOG_TIMESTAMP_RESULT OUTPUT_VARIABLE CHANGELOG_TIMESTAMP) #for rpm package
69 | IF (NOT "${CHANGELOG_TIMESTAMP}" STREQUAL "")
70 | STRING(REPLACE "\n" "" CHANGELOG_TIMESTAMP ${CHANGELOG_TIMESTAMP})
71 | ELSE()
72 | MESSAGE(WARNING "Failed to get timestamp: ${CHANGELOG_TIMESTAMP_RESULT}")
73 | ENDIF(NOT "${CHANGELOG_TIMESTAMP}" STREQUAL "")
74 | FILE(WRITE ${PROJECT_CHANGELOG_FILE} "* ${CHANGELOG_TIMESTAMP} ${PROJECT_MAINTAINER_NAME} <${PROJECT_MAINTAINER_MAIL}>\n")
75 | FILE(READ ${PROJECT_BRANDING_FOLDER}/CHANGELOG CHANGELOG_TEXT)
76 | FILE(APPEND ${PROJECT_CHANGELOG_FILE} ${CHANGELOG_TEXT})
77 |
78 | IF(APPLE AND CMAKE_OSX_SYSROOT)
79 | STRING(REGEX REPLACE ".*MacOSX([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_SDK_VERSION "${CMAKE_OSX_SYSROOT}")
80 | STRING(REGEX REPLACE ".*MacOSX([0-9]+)\\.([0-9]+).*$" "\\2" DARWIN_MINOR_SDK_VERSION "${CMAKE_OSX_SYSROOT}")
81 | IF(EXISTS "${CMAKE_OSX_SYSROOT}")
82 | SET(MACOSX_DEPLOYMENT_TARGET ${DARWIN_MAJOR_SDK_VERSION}.${DARWIN_MINOR_SDK_VERSION})
83 | SET(CMAKE_CXX_FLAGS "--sysroot ${CMAKE_OSX_SYSROOT} ${CMAKE_CXX_FLAGS}")
84 | MESSAGE(STATUS "Setting MACOSX_DEPLOYMENT_TARGET to '${MACOSX_DEPLOYMENT_TARGET}'.")
85 | ENDIF()
86 | ENDIF(APPLE AND CMAKE_OSX_SYSROOT)
87 |
88 | ########################## Options #########################
89 | OPTION(CPACK_SUPPORT "Enable package support" ON)
90 | OPTION(LOG_TO_FILE "Logging to file" OFF)
91 | OPTION(DEVELOPER_ENABLE_TESTS "Enable tests for ${PROJECT_NAME_TITLE} project" OFF)
92 | OPTION(DEVELOPER_CHECK_STYLE "Enable check style for ${PROJECT_NAME_TITLE} project" OFF)
93 | OPTION(DEVELOPER_GENERATE_DOCS "Generate docs api for ${PROJECT_NAME_TITLE} project" OFF)
94 | IF (DEVELOPER_ENABLE_TESTS)
95 | OPTION(DEVELOPER_ENABLE_UNIT_TESTS "Enable tests for ${PROJECT_NAME_TITLE} project" ON)
96 | ENDIF(DEVELOPER_ENABLE_TESTS)
97 | ##################################DEFAULT VALUES##########################################
98 | IF(NOT CMAKE_BUILD_TYPE)
99 | SET(CMAKE_BUILD_TYPE DEBUG)
100 | ENDIF(NOT CMAKE_BUILD_TYPE)
101 |
102 | # If the user did not customize the install prefix,
103 | # set it to live under build so we don't inadvertently pollute /usr/local
104 | IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
105 | SET(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "default install path" FORCE)
106 | ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
107 |
108 | IF("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
109 | MESSAGE(SEND_ERROR "In-source builds are not allowed.")
110 | ENDIF("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}")
111 |
112 | MESSAGE(STATUS "CMAKE_INSTALL_PREFIX: ${CMAKE_INSTALL_PREFIX}")
113 |
114 | ############################################################################
115 |
116 | SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake")
117 | INCLUDE(config) ###################
118 | DEFINE_DEFAULT_DEFINITIONS(OFF ON OFF)
119 | DEFINE_PROJECT_DEFINITIONS()
120 |
121 | ##########################################################
122 |
123 | # pwd + RELATIVE_SOURCE_DIR = install directory
124 | IF(OS_WINDOWS)
125 | SET(LIB_INSTALL_DESTINATION .)
126 | SET(TARGET_INSTALL_DESTINATION .)
127 | SET(SHARE_INSTALL_DESTINATION share)
128 | SET(RELATIVE_SOURCE_DIR .)
129 | SET(EXECUTABLE_NAME ${PROJECT_NAME}.exe)
130 | ELSEIF(OS_MACOSX)
131 | SET(BUNDLE_BASE_NAME ${PROJECT_NAME})
132 | SET(BUNDLE_NAME ${BUNDLE_BASE_NAME}.app)
133 | SET(LIB_INSTALL_DESTINATION .)
134 | SET(TARGET_INSTALL_DESTINATION .)
135 | SET(SHARE_INSTALL_DESTINATION ${BUNDLE_NAME}/Contents/share)
136 | SET(RELATIVE_SOURCE_DIR Contents)
137 | SET(EXECUTABLE_NAME ${BUNDLE_NAME})
138 | ELSEIF(OS_LINUX)
139 | SET(LIB_INSTALL_DESTINATION lib)
140 | SET(TARGET_INSTALL_DESTINATION bin)
141 | SET(SHARE_INSTALL_DESTINATION share)
142 | SET(RELATIVE_SOURCE_DIR ..)
143 | SET(EXECUTABLE_NAME ${PROJECT_NAME})
144 | ELSEIF(OS_FREEBSD)
145 | SET(LIB_INSTALL_DESTINATION lib)
146 | SET(TARGET_INSTALL_DESTINATION bin)
147 | SET(SHARE_INSTALL_DESTINATION share)
148 | SET(RELATIVE_SOURCE_DIR ..)
149 | SET(EXECUTABLE_NAME ${PROJECT_NAME})
150 | ELSEIF(OS_ANDROID)
151 | SET(LIB_INSTALL_DESTINATION libs/${ANDROID_NDK_ABI_NAME})
152 | SET(TARGET_INSTALL_DESTINATION libs/${ANDROID_NDK_ABI_NAME}) #libs/armeabi-v7a
153 | SET(SHARE_INSTALL_DESTINATION libs/${ANDROID_NDK_ABI_NAME/share)
154 | SET(RELATIVE_SOURCE_DIR .)
155 | ENDIF(OS_WINDOWS)
156 |
157 | ADD_DEFINITIONS(-DRELATIVE_SOURCE_DIR="${RELATIVE_SOURCE_DIR}")
158 |
159 | # project sources
160 | SET_PROPERTY(GLOBAL PROPERTY USE_FOLDERS ON)
161 |
162 | IF(LOG_TO_FILE)
163 | ADD_DEFINITIONS(-DLOG_TO_FILE)
164 | ENDIF(LOG_TO_FILE)
165 |
166 | ADD_DEFINITIONS(
167 | -DPROJECT_SUMMARY="${PROJECT_SUMMARY}"
168 | -DPROJECT_DESCRIPTION="${PROJECT_DESCRIPTION}"
169 | -DPROJECT_GITHUB_FORK="${PROJECT_GITHUB_FORK}"
170 | -DPROJECT_GITHUB_ISSUES="${PROJECT_GITHUB_ISSUES}"
171 | -DPROJECT_DOWNLOAD_LINK="${PROJECT_DOWNLOAD_LINK}"
172 | )
173 |
174 | SET(PROJECT_VERSION_HUMAN "${PROJECT_VERSION} ${PROJECT_BUILD_TYPE_VERSION} Revision: ${PROJECT_VERSION_GIT}")
175 | ADD_DEFINITIONS(-DPROJECT_VERSION_HUMAN="${PROJECT_VERSION_HUMAN}")
176 |
177 | ADD_SUBDIRECTORY(src)
178 |
179 | #CPACK
180 | IF(CPACK_SUPPORT)
181 | SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_SUMMARY} ${PROJECT_NAME}")
182 | SET(CPACK_PACKAGE_DESCRIPTION ${PROJECT_DESCRIPTION})
183 | # CPACK_DEBIAN_PACKAGE_DESCRIPTION CPACK_RPM_PACKAGE_SUMMARY
184 | SET(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_BRANDING_FOLDER}/COPYRIGHT")#CPACK_RPM_PACKAGE_DESCRIPTION
185 | SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
186 | SET(CPACK_RESOURCE_FILE_README "${CMAKE_SOURCE_DIR}/README.md")
187 | SET(CPACK_RESOURCE_FILE_WELCOME "${CMAKE_SOURCE_DIR}/README.md")
188 |
189 | SET(CPACK_PACKAGE_VENDOR "${PROJECT_COMPANYNAME}")#CPACK_RPM_PACKAGE_VENDOR
190 | SET(CPACK_PACKAGE_CONTACT "${PROJECT_MAINTAINER_NAME} <${PROJECT_MAINTAINER_MAIL}>")#CPACK_DEBIAN_PACKAGE_MAINTAINER
191 |
192 | SET(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
193 | SET(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
194 | SET(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_SHORT})
195 |
196 | IF(NOT PROJECT_BUILD_TYPE_VERSION STREQUAL "release")
197 | SET(CPACK_PACKAGE_VERSION_PATCH "${CPACK_PACKAGE_VERSION_PATCH}-${PROJECT_BUILD_TYPE_VERSION}${PROJECT_VERSION_TWEAK}")
198 | ENDIF(NOT PROJECT_BUILD_TYPE_VERSION STREQUAL "release")
199 |
200 | SET(CPACK_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION_PATCH})#CPACK_DEBIAN_PACKAGE_VERSION CPACK_RPM_PACKAGE_VERSION
201 | SET(CPACK_PACKAGE_NAME ${PROJECT_NAME_LOWERCASE})#CPACK_DEBIAN_PACKAGE_NAME CPACK_RPM_PACKAGE_NAME
202 | SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${PLATFORM_ARCH_FULL_NAME}-${PROJECT_VERSION_GIT}")#out package name
203 | SET(CPACK_SOURCE_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}")
204 | SET(CPACK_PACKAGE_INSTALL_DIRECTORY ${PROJECT_NAME})
205 | SET(CPACK_PACKAGE_EXECUTABLES "${PROJECT_NAME_TITLE};${PROJECT_NAME}")
206 | MESSAGE(STATUS "CPACK_PACKAGE_FILE_NAME: ${CPACK_PACKAGE_FILE_NAME}")
207 | SET(CPACK_MONOLITHIC_INSTALL ON)
208 |
209 | IF(OS_WINDOWS)
210 | #NSIS
211 | IF(PLATFORM_X86_64)
212 | SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64")
213 | ELSE()
214 | SET(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES")
215 | ENDIF(PLATFORM_X86_64)
216 | # There is a bug in NSI that does not handle full unix paths properly. Make
217 | # sure there is at least one set of four (4) backslashes.
218 | # SET(CPACK_NSIS_MODIFY_PATH ON)
219 | SET(CPACK_PACKAGE_ICON "${PROJECT_BRANDING_FOLDER}/windows\\\\nsis-top-logo.bmp")
220 | SET(CPACK_NSIS_INSTALLED_ICON_NAME "\\\\${PROJECT_NAME}.exe")
221 | SET(CPACK_CREATE_DESKTOP_LINKS "${PROJECT_NAME}.exe")
222 | SET(CPACK_NSIS_CREATE_ICONS "CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${PROJECT_NAME}.lnk\\\" \\\"$INSTDIR\\\\${PROJECT_NAME}.exe\\\"")
223 | SET(CPACK_NSIS_CREATE_ICONS_EXTRA "CreateShortCut \\\"$DESKTOP\\\\${PROJECT_NAME}.lnk\\\" \\\"$INSTDIR\\\\${PROJECT_NAME}.exe\\\"")
224 | SET(CPACK_NSIS_DELETE_ICONS_EXTRA "Delete \\\"$DESKTOP\\\\${PROJECT_NAME}.lnk\\\"")
225 | SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY}")
226 | SET(CPACK_NSIS_HELP_LINK "${PROJECT_COMPANYNAME_DOMAIN}")
227 | SET(CPACK_NSIS_URL_INFO_ABOUT "${PROJECT_DOMAIN}")
228 | SET(SIDEBAR_IMAGE ${PROJECT_BRANDING_FOLDER}/windows\\\\database.bmp)
229 | SET(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "!define MUI_WELCOMEFINISHPAGE_BITMAP \\\"${SIDEBAR_IMAGE}\\\"")
230 | SET(CPACK_NSIS_CONTACT "me@my-personal-home-page.com")
231 | SET(CPACK_NSIS_MUI_FINISHPAGE_RUN "..\\\\${PROJECT_NAME}.exe")
232 | ELSEIF(OS_MACOSX)
233 | # SET(CPACK_OSX_PACKAGE_VERSION "10.5")
234 | ELSEIF(OS_LINUX)
235 | SET(CPACK_STRIP_FILES ON)
236 | #SET(UBUNTU_LP_BUG 300472)
237 | #SET(CPACK_STRIP_FILES "bin/${PROJECT_NAME}")
238 | #SET(CPACK_SOURCE_STRIP_FILES "")
239 |
240 | SET(CPACK_PACKAGING_INSTALL_PREFIX "/opt/${PROJECT_NAME_LOWERCASE}")
241 |
242 | SET(FIXED_SCRIPT_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}")
243 |
244 | SET(POST_INSTALL_SCRIPT_GENERATED_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/scripts/postinst")
245 | SET(POST_INSTALL_SCRIPT_GENERATED_FIXED_PATH ${FIXED_SCRIPT_DESTINATION}/postinst)
246 | CONFIGURE_FILE("${PROJECT_BRANDING_FOLDER}/linux/postinst.in" ${POST_INSTALL_SCRIPT_GENERATED_PATH} @ONLY IMMEDIATE)
247 | FILE(COPY ${POST_INSTALL_SCRIPT_GENERATED_PATH} DESTINATION ${FIXED_SCRIPT_DESTINATION}
248 | FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
249 |
250 | SET(PRE_UNINSTALL_SCRIPT_GENERATED_PATH "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/scripts/prerm")
251 | SET(PRE_UNINSTALL_SCRIPT_GENERATED_FIXED_PATH ${FIXED_SCRIPT_DESTINATION}/prerm)
252 | CONFIGURE_FILE("${PROJECT_BRANDING_FOLDER}/linux/prerm.in" ${PRE_UNINSTALL_SCRIPT_GENERATED_PATH} @ONLY IMMEDIATE)
253 | FILE(COPY ${PRE_UNINSTALL_SCRIPT_GENERATED_PATH} DESTINATION ${FIXED_SCRIPT_DESTINATION}
254 | FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
255 |
256 | #RPM
257 | # CPACK_RPM_PACKAGE_ARCHITECTURE CPACK_RPM_PACKAGE_LICENSE CPACK_RPM_PACKAGE_DESCRIPTION CPACK_RPM_SPEC_INSTALL_POST
258 | # SET(CPACK_PACKAGE_RELEASE 1)
259 | SET(CPACK_RPM_PACKAGE_LICENSE "GPL v3")
260 | SET(CPACK_RPM_PACKAGE_AUTOREQPROV "no")
261 | SET(CPACK_RPM_PACKAGE_REQUIRES "libstdc++, xorg-x11-xinit")
262 | SET(CPACK_RPM_PACKAGE_RELEASE 1)
263 | SET(CPACK_RPM_PACKAGE_GROUP "Development/video")
264 | SET(CPACK_RPM_PACKAGE_ARCHITECTURE ${PLATFORM_PACKAGE_ARCH_NAME})
265 | SET(CPACK_RPM_PACKAGE_VERSION ${PROJECT_VERSION_SHORT})
266 | SET(CPACK_RPM_POST_INSTALL_SCRIPT_FILE ${POST_INSTALL_SCRIPT_GENERATED_FIXED_PATH})
267 | SET(CPACK_RPM_PRE_UNINSTALL_SCRIPT_FILE ${PRE_UNINSTALL_SCRIPT_GENERATED_FIXED_PATH})
268 | SET(CPACK_RPM_CHANGELOG_FILE ${PROJECT_CHANGELOG_FILE})
269 | #DEB
270 | # SET(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
271 | # CPACK_DEBIAN_PACKAGE_HOMEPAGE The URL of the web site for this package
272 | # SET(CPACK_DEBIAN_PACKAGE_DEBUG ON)
273 | # libva-drm1 (>= 1.1.0), libva-x11-1 (>= 1.0.3), libvdpau1 (>= 0.2), xinit
274 | SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.11), libstdc++6 (>= 4.8.2)")
275 | SET(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
276 | SET(CPACK_DEBIAN_PACKAGE_SECTION "video") #input our section
277 | SET(CPACK_DEBIAN_PACKAGE_RECOMMENDS "Unknown")
278 | SET(CPACK_DEBIAN_PACKAGE_SUGGESTS "Unknown")
279 | SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${PLATFORM_PACKAGE_ARCH_NAME})#i386
280 | SET(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${POST_INSTALL_SCRIPT_GENERATED_FIXED_PATH};${PRE_UNINSTALL_SCRIPT_GENERATED_FIXED_PATH}")
281 | ELSEIF(OS_ANDROID)
282 | ENDIF(OS_WINDOWS)
283 | INCLUDE(CPack)
284 | ENDIF(CPACK_SUPPORT)
285 |
286 | #DOCS
287 | IF(DEVELOPER_GENERATE_DOCS)
288 | CREATE_DOCS(${PROJECT_NAME_LOWERCASE} ${CMAKE_SOURCE_DIR}/docs/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
289 | ENDIF(DEVELOPER_GENERATE_DOCS)
290 |
291 | IF(NOT EXISTS ${CMAKE_SOURCE_DIR}/.git/hooks/pre-commit)
292 | EXECUTE_PROCESS(COMMAND ${CMAKE_SOURCE_DIR}/scripts/create_pre_commit_hook.sh)
293 | ENDIF(NOT EXISTS ${CMAKE_SOURCE_DIR}/.git/hooks/pre-commit)
294 |
--------------------------------------------------------------------------------
/CPPLINT.cfg:
--------------------------------------------------------------------------------
1 | # This is the toplevel CPPLINT.cfg file
2 | set noparent
3 |
4 | linelength=120
5 | root=src
6 |
7 | filter=-runtime/int
8 | filter=-build/include_order
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | About FastoTV
4 | ===============
5 | [](https://travis-ci.org/fastogt/fastotv)
6 | [](https://raw.githubusercontent.com/fastogt/fastotv/master/COPYRIGHT)
7 |
8 | FastoTV - is a crossplatform free iptv/stream player.
9 |
10 | ### PC/RaspberryPI/BananaPI/OrangePI:
11 | 
12 |
13 | ### Android Mobile/Tablet:
14 | 
15 |
16 | ### Android TV:
17 | 
18 |
19 | ### iPhone:
20 | 
21 |
22 | ### iPad:
23 | 
24 |
25 | Visit our site: [FastoTV](https://crocott.com)
26 |
27 | Download
28 | ========
29 |
30 | You can download compiled version (for Mac OS X, Windows, FreeBSD and Linux) from our site:
31 | [CrocOTT](https://crocott.com)
32 |
33 | ### [Android PlayStore](https://play.google.com/store/apps/details?id=com.crocott)
34 | ### [Apple Store](https://apps.apple.com/us/app/crocott/id1642691103)
35 |
36 | Contribute
37 | ==========
38 | Contributions are always welcome! Just try to follow our coding style: [FastoGT Coding Style](https://github.com/fastogt/fastonosql/wiki/Coding-Style)
39 |
40 | Build
41 | =====
42 |
43 | Build documentation: [Build FastoTV](https://github.com/fastogt/fastotv/wiki/Build)
44 |
45 | License
46 | =======
47 |
48 | Copyright (c) 2014-2022 FastoGT (https://fastogt.com)
49 |
50 | This program is free software: you can redistribute it and/or modify
51 | it under the terms of the GNU General Public License version 3 as
52 | published by the Free Software Foundation.
53 |
54 | This program is distributed in the hope that it will be useful,
55 | but WITHOUT ANY WARRANTY; without even the implied warranty of
56 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57 | GNU General Public License for more details.
58 |
59 | You should have received a copy of the GNU General Public License
60 | along with this program. If not, see .
61 |
--------------------------------------------------------------------------------
/build/.gitignore:
--------------------------------------------------------------------------------
1 | build_*
2 | config.py
3 |
--------------------------------------------------------------------------------
/build/brands/fastotv/fastotv.txt:
--------------------------------------------------------------------------------
1 | -DBRANDING_PROJECT_BUILD_TYPE_VERSION:STRING=release
2 | -DBRANDING_PROJECT_SUMMARY:STRING=Cross-platform open source IPTV player.
3 | -DBRANDING_PROJECT_DESCRIPTION:STRING=Cross-platform open source IPTV player.
4 |
--------------------------------------------------------------------------------
/build/build.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import os
3 | import re
4 | import shutil
5 | import sys
6 |
7 | from pyfastogt import run_command
8 | from pyfastogt import system_info
9 | from pyfastogt import utils, build_utils
10 |
11 |
12 | def print_usage():
13 | print("Usage:\n"
14 | "[required] argv[1] cmake_root_path\n"
15 | "[optional] argv[2] branding_file_path\n"
16 | "[optional] argv[3] platform\n"
17 | "[optional] argv[4] architecture\n"
18 | "[optional] argv[5] build system(\"ninja\", \"make\", \"gmake\")\n"
19 | "[optional] argv[6] packages for example(\"DEB RPM\")\n")
20 |
21 |
22 | class BuildSystem:
23 | def __init__(self, name, cmd_line: list, cmake_generator_arg, policy: run_command.Policy):
24 | self.name_ = name
25 | self.cmd_line_ = cmd_line
26 | self.cmake_generator_arg_ = cmake_generator_arg
27 | self.policy_ = policy
28 |
29 | def cmake_generator_arg(self) -> str:
30 | return self.cmake_generator_arg_
31 |
32 | def name(self) -> str:
33 | return self.name_
34 |
35 | def policy(self) -> run_command.Policy:
36 | return self.policy_
37 |
38 | def cmd_line(self) -> list: # cmd + args
39 | return self.cmd_line_
40 |
41 |
42 | SUPPORTED_BUILD_SYSTEMS = [BuildSystem('ninja', ['ninja'], '-GNinja', run_command.NinjaPolicy),
43 | BuildSystem('make', ['make', '-j2'], '-GUnix Makefiles', run_command.MakePolicy)]
44 |
45 |
46 | def get_supported_build_system_by_name(name):
47 | return next((x for x in SUPPORTED_BUILD_SYSTEMS if x.name() == name), None)
48 |
49 |
50 | def print_message(progress, message):
51 | print('{0:.1f}% {1}'.format(progress, message))
52 | sys.stdout.flush()
53 |
54 |
55 | class ProgressSaver(object):
56 | def __init__(self, cb):
57 | self.progress_min_ = 0.0
58 | self.progress_max_ = 0.0
59 | self.cb_ = cb
60 |
61 | def update_progress_message_range(self, progress_min, progress_max, message):
62 | self.progress_min_ = progress_min
63 | self.progress_max_ = progress_max
64 | if self.cb_:
65 | self.cb_(progress_min, message)
66 |
67 | def on_update_progress_message(self, progress, message):
68 | if message.type() == run_command.MessageType.STATUS:
69 | return
70 |
71 | diff = self.progress_max_ - self.progress_min_
72 | perc = self.progress_min_ + diff * (progress / 100.0)
73 | if self.cb_:
74 | self.cb_(perc, message.message())
75 |
76 |
77 | class BuildRequest(object):
78 | def __init__(self, platform, arch_name):
79 | platform_or_none = system_info.get_supported_platform_by_name(platform)
80 |
81 | if not platform_or_none:
82 | raise build_utils.BuildError('invalid platform')
83 |
84 | arch = platform_or_none.get_architecture_by_arch_name(arch_name)
85 | if not arch:
86 | raise build_utils.BuildError('invalid arch')
87 |
88 | self.platform_ = platform_or_none.make_platform_by_arch(arch, platform_or_none.package_types())
89 | print("Build request for platform: {0}, arch: {1} created".format(platform, arch.name()))
90 |
91 | def platform(self):
92 | return self.platform_
93 |
94 | def build(self, cmake_project_root_path: str, branding_options: list, dir_path: str, bs: BuildSystem,
95 | package_types: list,
96 | saver: ProgressSaver):
97 | cmake_project_root_abs_path = os.path.abspath(cmake_project_root_path)
98 | if not os.path.exists(cmake_project_root_abs_path):
99 | raise build_utils.BuildError('invalid cmake_project_root_path: %s' % cmake_project_root_path)
100 |
101 | if not bs:
102 | bs = SUPPORTED_BUILD_SYSTEMS[0]
103 |
104 | if not package_types:
105 | package_types = self.platform_.package_types()
106 |
107 | abs_dir_path = os.path.abspath(dir_path)
108 | if os.path.exists(abs_dir_path):
109 | shutil.rmtree(abs_dir_path)
110 |
111 | generator = bs.cmake_generator_arg()
112 | build_system_args = bs.cmd_line()
113 | build_system_policy = bs.policy()
114 |
115 | saver.update_progress_message_range(0.0, 9.0, "Start building project branding_options:\n{0}".format(
116 | "\n".join(branding_options)))
117 |
118 | pwd = os.getcwd()
119 | os.mkdir(abs_dir_path)
120 | os.chdir(abs_dir_path)
121 |
122 | # project static options
123 | log_to_file_args = '-DLOG_TO_FILE=ON'
124 | openssl_args = '-DOPENSSL_USE_STATIC_LIBS=ON'
125 | jsonc_args = '-DJSONC_USE_STATIC=ON'
126 | libev_args = '-DLIBEV_USE_STATIC=ON'
127 |
128 | cmake_line = ['cmake', cmake_project_root_abs_path, generator, '-DCMAKE_BUILD_TYPE=RELEASE', openssl_args,
129 | jsonc_args, log_to_file_args, libev_args]
130 |
131 | if branding_options:
132 | cmake_line.extend(branding_options)
133 |
134 | saver.update_progress_message_range(10.0, 19.0, 'Generate project build')
135 |
136 | def store_closure(cb):
137 | def closure(progress, message):
138 | return cb(progress, message)
139 |
140 | return closure
141 |
142 | store = store_closure(saver.on_update_progress_message)
143 |
144 | try:
145 | cmake_policy = run_command.CmakePolicy(store)
146 | run_command.run_command_cb(cmake_line, cmake_policy)
147 | except Exception as ex:
148 | os.chdir(pwd)
149 | raise ex
150 |
151 | make_install = build_system_args
152 | make_install.append('install')
153 | saver.update_progress_message_range(20.0, 79.0, 'Build project')
154 | try:
155 | policy = build_system_policy(store)
156 | run_command.run_command_cb(make_install, policy)
157 | except Exception as ex:
158 | os.chdir(pwd)
159 | raise ex
160 |
161 | saver.update_progress_message_range(80.0, 84.0, 'Trying to get package file name')
162 | in_file = open('CPackConfig.cmake', 'r')
163 | for line in in_file.readlines():
164 | res = re.search(r'SET\(CPACK_PACKAGE_FILE_NAME "(.+)"\)', line)
165 | if res:
166 | filename = res.group(1)
167 | break
168 | in_file.close()
169 |
170 | saver.update_progress_message_range(85.0, 99.0, 'Start build package')
171 | file_names = []
172 | for generator in package_types:
173 | make_cpack = ['cpack', '-G', generator]
174 | try:
175 | common_policy = run_command.CommonPolicy(store)
176 | run_command.run_command_cb(make_cpack, common_policy)
177 | file_names.append(
178 | os.path.join(abs_dir_path, filename + '.' + system_info.get_extension_by_package(generator)))
179 | except Exception as ex:
180 | os.chdir(pwd)
181 | raise ex
182 |
183 | os.chdir(pwd)
184 |
185 | saver.update_progress_message_range(100.0, 100.0,
186 | "Building finished successfully file_names: {0}".format(file_names))
187 | return file_names
188 |
189 |
190 | if __name__ == "__main__":
191 | argc = len(sys.argv)
192 | dev_null = '/dev/null'
193 |
194 | if argc > 1:
195 | cmake_root = sys.argv[1]
196 | else:
197 | print_usage()
198 | sys.exit(1)
199 |
200 | if argc > 2:
201 | branding_file_path = sys.argv[2]
202 | else:
203 | branding_file_path = 'brands/fastotv/fastotv.txt'
204 |
205 | if argc > 3:
206 | platform_str = sys.argv[3]
207 | else:
208 | platform_str = system_info.get_os()
209 |
210 | if argc > 4:
211 | arch_name_str = sys.argv[4]
212 | else:
213 | arch_name_str = system_info.get_arch_name()
214 |
215 | if argc > 5:
216 | bs_str = sys.argv[5]
217 | bs = get_supported_build_system_by_name(bs_str)
218 | else:
219 | bs = []
220 |
221 | if argc > 6:
222 | packages = sys.argv[6].split()
223 | else:
224 | packages = []
225 |
226 | request = BuildRequest(platform_str, arch_name_str)
227 | abs_branding_file = os.path.abspath(branding_file_path)
228 | args_branding_options = utils.read_file_line_by_line_to_list(abs_branding_file)
229 |
230 | saver = ProgressSaver(print_message)
231 | request.build(cmake_root, args_branding_options, 'build_' + platform_str, bs, packages, saver)
232 |
--------------------------------------------------------------------------------
/build/build_server_remote.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import json
3 | import shlex
4 | import sys
5 |
6 | import build
7 | import config
8 | import pika
9 | from pyfastogt import system_info, build_utils
10 |
11 |
12 | def gen_routing_key(device, platform, arch) -> str:
13 | return device + '_' + platform + '_' + arch
14 |
15 |
16 | def print_usage():
17 | print("Usage:\n"
18 | "[optional] argv[1] device\n"
19 | "[optional] argv[2] platform\n"
20 | "[optional] argv[3] architecture\n")
21 |
22 |
23 | class BuildRpcServer(object):
24 | EXCHANGE = 'build_servers_exchange'
25 | EXCHANGE_TYPE = 'direct'
26 |
27 | def __init__(self, device, platform, arch):
28 | self.connection_ = None
29 | self.channel_ = None
30 | self.closing_ = False
31 | self.consumer_tag_ = None
32 | self.device_ = device
33 | self.platform_ = platform
34 | self.arch_ = arch
35 | routing_key = gen_routing_key(device, platform, arch)
36 | self.routing_key_ = routing_key
37 | print("Build server for {0} inited, routing_key: {1}!".format(platform, routing_key))
38 |
39 | def connect(self):
40 | credentials = pika.PlainCredentials(config.USER_NAME, config.PASSWORD)
41 | params = pika.ConnectionParameters(host=config.REMOTE_HOST, credentials=credentials)
42 | return pika.SelectConnection(params, self.on_connection_open, stop_ioloop_on_close=False)
43 |
44 | def reconnect(self):
45 | self.connection_.ioloop.stop()
46 |
47 | if not self.closing_:
48 | self.connection_ = self.connect()
49 | self.connection_.ioloop.start()
50 |
51 | def on_connection_open(self, unused_connection):
52 | self.add_on_connection_close_callback()
53 | self.open_channel()
54 |
55 | def add_on_connection_close_callback(self):
56 | self.connection_.add_on_close_callback(self.on_connection_closed)
57 |
58 | def open_channel(self):
59 | self.connection_.channel(on_open_callback=self.on_channel_open)
60 |
61 | def on_channel_open(self, channel):
62 | self.channel_ = channel
63 | self.add_on_channel_close_callback()
64 | self.setup_exchange(self.EXCHANGE)
65 |
66 | def add_on_channel_close_callback(self):
67 | self.channel_.add_on_close_callback(self.on_channel_closed)
68 |
69 | def setup_exchange(self, exchange_name):
70 | self.channel_.exchange_declare(self.on_exchange_declareok, exchange_name, self.EXCHANGE_TYPE)
71 |
72 | def on_exchange_declareok(self, unused_frame):
73 | self.setup_queue(self.routing_key_)
74 |
75 | def setup_queue(self, queue_name):
76 | print("setup_queue: {0}".format(queue_name))
77 | self.channel_.queue_declare(self.on_queue_declareok, queue_name)
78 |
79 | def on_queue_declareok(self, method_frame):
80 | self.channel_.queue_bind(self.on_bindok, self.routing_key_, self.EXCHANGE, self.routing_key_)
81 |
82 | def on_bindok(self, unused_frame):
83 | self.start_consuming()
84 |
85 | def start_consuming(self):
86 | self.add_on_cancel_callback()
87 | print("Awaiting RPC build requests")
88 | self.consumer_tag_ = self.channel_.basic_consume(self.on_request, self.routing_key_)
89 |
90 | def on_consumer_cancelled(self, method_frame):
91 | if self.channel_:
92 | self.channel_.close()
93 |
94 | def add_on_cancel_callback(self):
95 | self.channel_.add_on_cancel_callback(self.on_consumer_cancelled)
96 |
97 | def on_channel_closed(self, channel, reply_code, reply_text):
98 | print("on_channel_closed reply_code: {0}, reply_text: {1}".format(reply_code, reply_text))
99 | self.connection_.close()
100 |
101 | def on_connection_closed(self, connection, reply_code, reply_text):
102 | print("on_connection_closed reply_code: {0}, reply_text: {1}".format(reply_code, reply_text))
103 | self.channel_ = None
104 | if self.closing_:
105 | self.connection_.ioloop.stop()
106 | else:
107 | self.connection_.add_timeout(5, self.reconnect)
108 |
109 | def run(self):
110 | self.connection_ = self.connect()
111 | self.connection_.ioloop.start()
112 |
113 | def build_package(self, op_id, branding_options, package_types, destination, routing_key):
114 | build_request = build.BuildRequest(self.platform_, self.arch_)
115 | platform = build_request.platform()
116 | arch = platform.architecture()
117 |
118 | platform_and_arch_str = '{0}_{1}'.format(platform.name(), arch.name())
119 | dir_name = 'build_{0}_for_{1}'.format(platform_and_arch_str, op_id)
120 |
121 | self.send_status(routing_key, op_id, 20.0, 'Building package')
122 |
123 | def store(progress_min, progress_max, routing_key, op_id):
124 | def closure(progress, message):
125 | diff = progress_max - progress_min
126 | perc = round(progress_min + diff * (progress / 100.0), 1)
127 | print('{0}% {1}'.format(perc, message))
128 | sys.stdout.flush()
129 | self.send_status(routing_key, op_id, perc, message)
130 |
131 | return closure
132 |
133 | store = store(21.0, 79.0, routing_key, op_id)
134 |
135 | saver = build.ProgressSaver(store)
136 | file_paths = build_request.build('..', branding_options, dir_name, None, package_types, saver)
137 | file_path = file_paths[0]
138 | self.send_status(routing_key, op_id, 80.0, 'Loading package to server')
139 | try:
140 | result = config.post_install_step(file_path, destination)
141 | except Exception as ex:
142 | raise ex
143 |
144 | return result
145 |
146 | def send_status(self, routing_key, op_id, progress, status):
147 | json_to_send = {'progress': progress, 'status': status}
148 | properties = pika.BasicProperties(content_type='application/json', correlation_id=op_id,
149 | headers={'type': 'status'})
150 | if self.channel_:
151 | self.channel_.basic_publish(exchange='',
152 | routing_key=routing_key,
153 | properties=properties,
154 | body=json.dumps(json_to_send))
155 |
156 | def send_response(self, routing_key, op_id, body):
157 | properties = pika.BasicProperties(
158 | content_type='application/json',
159 | correlation_id=op_id,
160 | headers={'type': 'response'}
161 | )
162 | if self.channel_:
163 | self.channel_.basic_publish(exchange='',
164 | routing_key=routing_key,
165 | properties=properties,
166 | body=body)
167 |
168 | def on_request(self, ch, method, props, body):
169 | platform_and_arch = '{0}_{1}'.format(self.platform_, self.arch_)
170 | if isinstance(body, bytes):
171 | body = body.decode("utf-8")
172 |
173 | data = json.loads(body)
174 | # self.acknowledge_message(method.delivery_tag)
175 | # return
176 |
177 | branding_variables = data.get('branding_variables')
178 | package_type = data.get('package_type')
179 | destination = data.get('destination')
180 | op_id = props.correlation_id
181 | package_types = [package_type]
182 |
183 | self.send_status(props.reply_to, op_id, 0.0, 'Prepare to build package')
184 | print('Build started for: {0}, platform: {1}'.format(op_id, platform_and_arch))
185 | try:
186 | response = self.build_package(op_id, shlex.split(branding_variables), package_types, destination,
187 | props.reply_to)
188 | print('Build finished for: {0}, platform: {1}, response: {2}'.format(op_id, platform_and_arch, response))
189 | json_to_send = {'body': response}
190 | except build_utils.BuildError as ex:
191 | print('Build finished for: {0}, platform: {1}, exception: {2}'.format(op_id, platform_and_arch, str(ex)))
192 | json_to_send = {'error': str(ex)}
193 | except Exception as ex:
194 | print('Build finished for: {0}, platform: {1}, exception: {2}'.format(op_id, platform_and_arch, str(ex)))
195 | json_to_send = {'error': str(ex)}
196 |
197 | self.send_status(props.reply_to, op_id, 100.0, 'Completed')
198 | self.send_response(props.reply_to, op_id, json.dumps(json_to_send))
199 | self.acknowledge_message(method.delivery_tag)
200 |
201 | def acknowledge_message(self, delivery_tag):
202 | if self.channel_:
203 | self.channel_.basic_ack(delivery_tag)
204 |
205 |
206 | if __name__ == "__main__":
207 | argc = len(sys.argv)
208 |
209 | if argc > 1:
210 | device_str = sys.argv[1]
211 | else:
212 | device_str = 'pc'
213 |
214 | if argc > 2:
215 | platform_str = sys.argv[2]
216 | else:
217 | platform_str = system_info.get_os()
218 |
219 | if argc > 3:
220 | arch_str = sys.argv[3]
221 | else:
222 | arch_str = system_info.get_arch_name()
223 |
224 | server = BuildRpcServer(device_str, platform_str, arch_str)
225 | server.run()
226 |
--------------------------------------------------------------------------------
/build/devices/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/build/devices/__init__.py
--------------------------------------------------------------------------------
/build/devices/orange_pi/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/build/devices/orange_pi/__init__.py
--------------------------------------------------------------------------------
/build/devices/orange_pi/hardware/lirc/hardware.conf:
--------------------------------------------------------------------------------
1 | # /etc/lirc/hardware.conf
2 | #
3 | #Chosen Remote Control
4 | REMOTE="None"
5 | REMOTE_MODULES="sunxi_cir"
6 | REMOTE_DRIVER=""
7 | REMOTE_DEVICE="/dev/lirc0"
8 | REMOTE_SOCKET=""
9 | REMOTE_LIRCD_CONF=""
10 | REMOTE_LIRCD_ARGS=""
11 |
12 | #Chosen IR Transmitter
13 | TRANSMITTER="None"
14 | TRANSMITTER_MODULES="sunxi_cir"
15 | TRANSMITTER_DRIVER=""
16 | TRANSMITTER_DEVICE="/dev/lirc0"
17 | TRANSMITTER_SOCKET=""
18 | TRANSMITTER_LIRCD_CONF=""
19 | TRANSMITTER_LIRCD_ARGS=""
20 |
21 | #Disable kernel support.
22 | #Typically, lirc will disable in-kernel support for ir devices in order to
23 | #handle them internally. Set to false to prevent lirc from disabling this
24 | #in-kernel support.
25 | #DISABLE_KERNEL_SUPPORT="true"
26 |
27 | #Enable lircd
28 | START_LIRCD="true"
29 |
30 | #Don't start lircmd even if there seems to be a good config file
31 | #START_LIRCMD="false"
32 |
33 | #Try to load appropriate kernel modules
34 | LOAD_MODULES="true"
35 |
36 | # Default configuration files for your hardware if any
37 | LIRCMD_CONF=""
38 |
39 | #Forcing noninteractive reconfiguration
40 | #If lirc is to be reconfigured by an external application
41 | #that doesn't have a debconf frontend available, the noninteractive
42 | #frontend can be invoked and set to parse REMOTE and TRANSMITTER
43 | #It will then populate all other variables without any user input
44 | #If you would like to configure lirc via standard methods, be sure
45 | #to leave this set to "false"
46 | FORCE_NONINTERACTIVE_RECONFIGURATION="false"
47 | START_LIRCMD=""
48 |
--------------------------------------------------------------------------------
/build/devices/orange_pi/orange_pi.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import os
4 | import shutil
5 | import subprocess
6 |
7 | from pyfastogt import utils
8 |
9 | LIRC_FOLDER = '/etc/lirc/'
10 |
11 |
12 | def install_orange_pi_h3():
13 | subprocess.call(['modprobe', 'mali'])
14 | pwd = os.getcwd()
15 | script_dir = os.path.dirname(os.path.realpath(__file__))
16 | try:
17 | cloned_dir = utils.git_clone('https://github.com/linux-sunxi/sunxi-mali.git')
18 | os.chdir(cloned_dir)
19 | subprocess.call(['make', 'config'])
20 | subprocess.call(['make', 'install'])
21 | os.chdir(pwd)
22 | shutil.rmtree(cloned_dir)
23 | except Exception as ex:
24 | os.chdir(pwd)
25 | raise ex
26 |
27 | try:
28 | cloned_dir = utils.git_clone('https://github.com/fastogt/libvdpau-sunxi.git')
29 | os.chdir(cloned_dir)
30 | subprocess.call(['make', 'install'])
31 | os.chdir(pwd)
32 | shutil.rmtree(cloned_dir)
33 | except Exception as ex:
34 | os.chdir(pwd)
35 | raise ex
36 |
37 | with open('/etc/udev/rules.d/50-mali.rules', 'w') as f:
38 | f.write('KERNEL=="mali", MODE="0660", GROUP="video"\n'
39 | 'KERNEL=="ump", MODE="0660", GROUP="video"')
40 |
41 | with open('/etc/asound.conf', 'w') as f:
42 | f.write('pcm.!default {\n'
43 | 'type hw\n'
44 | 'card 1\n'
45 | '}\n'
46 | 'ctl.!default {\n'
47 | 'type hw\n'
48 | 'card 1\n'
49 | '}')
50 |
51 | standart_egl_path = '/usr/lib/arm-linux-gnueabihf/mesa-egl/'
52 | if os.path.exists(standart_egl_path):
53 | shutil.move(standart_egl_path, '/usr/lib/arm-linux-gnueabihf/.mesa-egl/')
54 |
55 | lirc_conf_path = os.path.join(script_dir, 'hardware/lirc/hardware.conf')
56 | if os.path.exists(LIRC_FOLDER):
57 | dst = os.path.join(LIRC_FOLDER, 'hardware.conf')
58 | shutil.copy(lirc_conf_path, dst)
59 |
60 |
61 | def install_orange_pi_h5():
62 | script_dir = os.path.dirname(os.path.realpath(__file__))
63 |
64 | with open('/etc/asound.conf', 'w') as f:
65 | f.write('pcm.!default {\n'
66 | 'type hw\n'
67 | 'card 1\n'
68 | '}\n'
69 | 'ctl.!default {\n'
70 | 'type hw\n'
71 | 'card 1\n'
72 | '}')
73 |
74 | lirc_conf_path = os.path.join(script_dir, 'hardware/lirc/hardware.conf')
75 | if os.path.exists(LIRC_FOLDER):
76 | dst = os.path.join(LIRC_FOLDER, 'hardware.conf')
77 | shutil.copy(lirc_conf_path, dst)
78 |
--------------------------------------------------------------------------------
/build/devices/raspberry_pi/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/build/devices/raspberry_pi/__init__.py
--------------------------------------------------------------------------------
/build/devices/raspberry_pi/raspberry_pi.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | import os
4 |
5 | from pyfastogt import utils
6 |
7 |
8 | def install_raspberry_pi(gpu_mem_size: int):
9 | # ln -sf /opt/vc/lib/libEGL.so /usr/lib/arm-linux-gnueabihf/libEGL.so
10 | # ln -sf /opt/vc/lib/libEGL.so /usr/lib/arm-linux-gnueabihf/libEGL.so.1
11 | # ln -sf /opt/vc/lib/libGLESv2.so /usr/lib/arm-linux-gnueabihf/libGLESv2.so
12 | # ln -sf /opt/vc/lib/libGLESv2.so /usr/lib/arm-linux-gnueabihf/libGLESv2.so.2
13 | utils.symlink_force('/opt/vc/lib/libEGL.so', '/usr/lib/arm-linux-gnueabihf/libEGL.so')
14 | utils.symlink_force('/opt/vc/lib/libEGL.so', '/usr/lib/arm-linux-gnueabihf/libEGL.so.1')
15 | utils.symlink_force('/opt/vc/lib/libGLESv2.so', '/usr/lib/arm-linux-gnueabihf/libGLESv2.so')
16 | utils.symlink_force('/opt/vc/lib/libGLESv2.so', '/usr/lib/arm-linux-gnueabihf/libGLESv2.so.2')
17 |
18 | with open("/boot/config.txt", "r+") as f:
19 | line_found = any("gpu_mem" in line for line in f)
20 | if not line_found:
21 | f.seek(0, os.SEEK_END)
22 | f.write("gpu_mem={0}\n".format(gpu_mem_size))
23 |
--------------------------------------------------------------------------------
/build/patch/orange-pi/sdl2/SDL_render_gles2.c.patch:
--------------------------------------------------------------------------------
1 | --- src/render/opengles2/SDL_render_gles2.c 2016-10-20 06:56:26.000000000 +0300
2 | +++ SDL_render_gles2.c 2017-04-03 16:45:27.579283000 +0300
3 | @@ -22,6 +22,8 @@
4 |
5 | #if SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED
6 |
7 | +typedef char GLchar;
8 | +
9 | #include "SDL_hints.h"
10 | #include "SDL_opengles2.h"
11 | #include "../SDL_sysrender.h"
12 |
--------------------------------------------------------------------------------
/images/1024 px_horizontal-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/1024 px_horizontal-01.png
--------------------------------------------------------------------------------
/images/128 px-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/128 px-01.png
--------------------------------------------------------------------------------
/images/144 px-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/144 px-01.png
--------------------------------------------------------------------------------
/images/256 px-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/256 px-01.png
--------------------------------------------------------------------------------
/images/256 px_horizontal-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/256 px_horizontal-01.png
--------------------------------------------------------------------------------
/images/48 px-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/48 px-01.png
--------------------------------------------------------------------------------
/images/480 px-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/480 px-01.png
--------------------------------------------------------------------------------
/images/480_2 px-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/480_2 px-01.png
--------------------------------------------------------------------------------
/images/512 px-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/512 px-01.png
--------------------------------------------------------------------------------
/images/512 px_horizontal-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/512 px_horizontal-01.png
--------------------------------------------------------------------------------
/images/72 px-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/72 px-01.png
--------------------------------------------------------------------------------
/images/Horizontal Black-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/Horizontal Black-01.png
--------------------------------------------------------------------------------
/images/Horizontal White-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/Horizontal White-01.png
--------------------------------------------------------------------------------
/images/Logo Black-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/Logo Black-01.png
--------------------------------------------------------------------------------
/images/Logo White-01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/Logo White-01.png
--------------------------------------------------------------------------------
/images/Logo license.txt:
--------------------------------------------------------------------------------
1 | This logo design created by Dee-y (https://github.com/dee-y) is licensed under a Creative Commons Attribution 4.0 International License (http://creativecommons.org/licenses/by/4.0/)
--------------------------------------------------------------------------------
/images/Logotype 2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/Logotype 2.png
--------------------------------------------------------------------------------
/images/Logotype 2_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/Logotype 2_black.png
--------------------------------------------------------------------------------
/images/Logotype 2_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/images/Logotype 2_white.png
--------------------------------------------------------------------------------
/install/fastotv/CHANGELOG:
--------------------------------------------------------------------------------
1 | 1.21.1 / January 5, 2019
2 | [Alexandr Topilski]
3 | - Version Bump
4 |
5 | 1.20.0 / December 20, 2019
6 | [Alexandr Topilski]
7 | - Catchups
8 | - Version patch integration
9 | - Private life streams
10 | - New API 1.2.2
11 | - Removed bandwidth check
12 | - Project info for client
13 | - Version Bump
14 | - Send device id
15 | - Change layout
16 | - Text notification
17 | - Protocol update
18 | - Stabilization
19 | - Raspberry PI
20 | - Realtime login password
21 | - Branding
22 | - Gzip compress
23 | - New scripts
24 | - Channels not showing up in list #42
25 | - User state
26 | - Compress messages
27 | - Service notification
28 | - JSON RPC
29 | - Update external libraries
30 | - Fixed deb package for Ubuntu 18
31 | - Https recover
32 | - libpng fix for Linux
33 | - Search channels
34 | - Fix fonts for MacOSX
35 | - Optimize event loop
36 | - Player mode
37 | - Playlist view
38 | - Save dynamic options
39 | - SDL image linkage
40 | - Video info
41 | - EPG basic support
42 | - MacOSX build
43 | - Device info
44 | - Bandwidth estimation
45 | - Enable/Disable audio/video in channel
46 | - Seek stream
47 | - Cuda hwaccel stabilization
48 | - LIRC support
49 | - Added hwaccels: Cuvid, Videotoolbox
50 | - Footer text
51 | - Config file
52 | - Added hwaccels: VDPAU, VAAPI, DXVA2
53 |
--------------------------------------------------------------------------------
/install/fastotv/COPYRIGHT:
--------------------------------------------------------------------------------
1 | FastoTV, crossplatform free iptv/stream player.
2 |
3 | Copyright 2018, FastoGT.
4 |
5 | The FastoTV is released under the terms of the GNU General Public
6 | License, version 3.
7 |
8 | The FastoTV Project includes files written by third parties
9 | and used with permission or subject to their respective license
10 | agreements.
11 |
12 |
--------------------------------------------------------------------------------
/install/fastotv/android/AndroidManifest.xml.in:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/install/fastotv/android/configAndroid.json.in:
--------------------------------------------------------------------------------
1 | {
2 | "description": "@CPACK_PACKAGE_DESCRIPTION_SUMMARY@",
3 | "qt": "@_qt5Core_install_prefix@",
4 | "sdk": "@ANDROID_SDK@",
5 | "ndk": "@ANDROID_NDK@",
6 | "toolchain-prefix": "@ANDROID_TOOLCHAIN_MACHINE_NAME@",
7 | "tool-prefix": "@ANDROID_TOOLCHAIN_MACHINE_NAME@",
8 | "toolchain-version": "@ANDROID_COMPILER_VERSION@",
9 | "ndk-host": "@ANDROID_NDK_HOST_SYSTEM_NAME@",
10 | "target-architecture": "@ANDROID_TARGET_ARCH@",
11 | "application-binary": "@CMAKE_INSTALL_PREFIX@/libs/@ANDROID_NDK_ABI_NAME@/lib@PROJECT_NAME@.so",
12 | "android-package-source-directory": "@PACKAGE_SOURCE_ANDROID@/",
13 | "android-package": "net.@PROJECT_NAME_LOWERCASE@"
14 | }
15 |
--------------------------------------------------------------------------------
/install/fastotv/android/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/android/icon.png
--------------------------------------------------------------------------------
/install/fastotv/android/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/android/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/install/fastotv/android/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/android/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/install/fastotv/android/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/android/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/install/fastotv/android/res/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/android/res/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/install/fastotv/android/strings.xml.in:
--------------------------------------------------------------------------------
1 |
2 |
3 | @PROJECT_NAME@
4 |
5 | Can\'t find Ministro service.\nThe application can\'t start.
6 | This application requires Ministro service. Would you like to install it?
7 | Your application encountered a fatal error and cannot continue.
8 |
9 |
--------------------------------------------------------------------------------
/install/fastotv/autostart.sh.in:
--------------------------------------------------------------------------------
1 | #!/bin/sh -e
2 |
3 | #adduser test1
4 | #mkpasswd --method=md5
5 | #hashed
6 | #Before editing test1:*:16559:0:99999:7:::
7 | #After editing test1:$hashed:16559:0:99999:7:::
8 |
9 | USER_LOGIN=$1
10 | adduser --home /home/$USER_LOGIN/ --force-badname $USER_LOGIN
11 | usermod -a -G video $USER_LOGIN
12 | cp xinitrc /home/$USER_LOGIN/.xinitrc
13 | chown $USER_LOGIN /home/$USER_LOGIN/.xinitrc
14 |
15 | LINE='if [ -z "$DISPLAY" ] && [ -n "$XDG_VTNR" ] && [ "$XDG_VTNR" -eq 1 ]; then exec startx fi'
16 | FILE=/home/$USER_LOGIN/.bashrc
17 | if [ -f "$FILE" ]; then
18 | grep -qF "$LINE" "$FILE" || echo "$LINE" >> "$FILE"
19 | fi
20 |
21 | FILE2=/home/$USER_LOGIN/.bash_profile
22 | if [ -f "$FILE2" ]; then
23 | grep -qF "$LINE" "$FILE2" || echo "$LINE" >> "$FILE2"
24 | fi
25 |
--------------------------------------------------------------------------------
/install/fastotv/config.ini.in:
--------------------------------------------------------------------------------
1 | [main_options]
2 | poweroffonexit=@CONFIG_POWER_OFF_ON_EXIT@
3 | [player_options]
4 | [app_options]
5 | hwaccel=@CONFIG_HWACCEL_METHOD@
6 | [player_options]
7 | width=@CONFIG_WIDTH@
8 | height=@CONFIG_HEIGHT@
9 |
--------------------------------------------------------------------------------
/install/fastotv/desktop.in:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Type=Application
3 | Exec=@PRODUCTNAME@
4 | Name=@SHORTPRODUCTNAME@
5 | GenericName=The IDE for redis working.
6 | GenericName[de]=Die IDE der
7 | Icon=@ICONNAME@
8 | Terminal=false
9 | Categories=Development;IDE;redis;
10 |
--------------------------------------------------------------------------------
/install/fastotv/fonts/FreeSans.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/fonts/FreeSans.ttf
--------------------------------------------------------------------------------
/install/fastotv/hardware/lirc/lircrc.conf.in:
--------------------------------------------------------------------------------
1 | begin
2 | prog = @PROJECT_NAME_LOWERCASE@
3 | button = KEY_OK
4 | config = LIRC_KEY_OK
5 | end
6 |
7 | begin
8 | prog = @PROJECT_NAME_LOWERCASE@
9 | button = KEY_LEFT
10 | config = LIRC_KEY_LEFT
11 | end
12 |
13 | begin
14 | prog = @PROJECT_NAME_LOWERCASE@
15 | button = KEY_UP
16 | config = LIRC_KEY_UP
17 | end
18 |
19 | begin
20 | prog = @PROJECT_NAME_LOWERCASE@
21 | button = KEY_RIGHT
22 | config = LIRC_KEY_RIGHT
23 | end
24 |
25 | begin
26 | prog = @PROJECT_NAME_LOWERCASE@
27 | button = KEY_DOWN
28 | config = LIRC_KEY_DOWN
29 | end
30 |
31 | begin
32 | prog = @PROJECT_NAME_LOWERCASE@
33 | button = KEY_EXIT
34 | config = LIRC_KEY_EXIT
35 | end
36 |
37 | begin
38 | prog = @PROJECT_NAME_LOWERCASE@
39 | button = KEY_MUTE
40 | config = LIRC_KEY_MUTE
41 | end
42 |
--------------------------------------------------------------------------------
/install/fastotv/linux/gentoo.ebuild.in:
--------------------------------------------------------------------------------
1 | # Copyright 1999-2013 Gentoo Foundation
2 | # Distributed under the terms of the GNU General Public License v3
3 | # $Header: $
4 |
5 | EAPI="6"
6 |
7 | inherit multilib unpacker
8 |
9 | DESCRIPTION="@PROJECT_DESCRIPTION@"
10 | HOMEPAGE="@PROJECT_DOMAIN@"
11 | SRC_URI="@PROJECT_DOWNLOAD_LINK@/@CPACK_PACKAGE_FILE_NAME@.deb"
12 |
13 | LICENSE="GPL-v3"
14 | SLOT="0"
15 | KEYWORDS="~amd64 ~x86"
16 | IUSE=""
17 |
18 | RDEPEND=">=sys-libs/libstdc++-v3-3.3.6-r1"
19 | DEPEND="${RDEPEND}
20 | >=dev-qt/qtcore-5.4.0:5
21 | >=dev-qt/qtgui-5.4.0:5
22 | >=dev-qt/qtwebkit-5.4.0:5"
23 |
24 | ##S=${WORKDIR}/${P}.0
25 | S=${WORKDIR}
26 |
27 | #RESTRICT="strip"
28 |
29 | src_install() {
30 | sed -i '3s|Exec=@PROJECT_NAME_LOWERCASE@|Exec=@PROJECT_NAME_LOWERCASE@.sh|g' "${S}/opt/@PROJECT_NAME_LOWERCASE@/share/applications/@PROJECT_NAME_LOWERCASE@.desktop" || die
31 | sed -i '7s|Icon=@PROJECT_NAME_LOWERCASE@.png|Icon=@PROJECT_NAME_LOWERCASE@|g' "${S}/opt/@PROJECT_NAME_LOWERCASE@/share/applications/@PROJECT_NAME_LOWERCASE@.desktop" || die
32 | sed -i '9s|IDE;redis;|IDE;|g' "${S}/opt/@PROJECT_NAME_LOWERCASE@/share/applications/@PROJECT_NAME_LOWERCASE@.desktop" || die
33 |
34 | dodir /usr/{bin,share}
35 | mv "${S}"/opt/@PROJECT_NAME_LOWERCASE@/{bin,share} "${D}"/usr/
36 |
37 | cp -pPR "${WORKDIR}"/* "${D}"/ || die "copying files failed!"
38 | }
39 |
--------------------------------------------------------------------------------
/install/fastotv/linux/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/linux/icon.png
--------------------------------------------------------------------------------
/install/fastotv/linux/postinst.in:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 | ln -sf @CPACK_PACKAGING_INSTALL_PREFIX@/@TARGET_INSTALL_DESTINATION@/@PROJECT_NAME_LOWERCASE@ @EXECUTABLE_PATH@
4 | chmod +x @EXECUTABLE_PATH@
5 | cp @CPACK_PACKAGING_INSTALL_PREFIX@/@SHARE_INSTALL_DESTINATION@/applications/@PROJECT_NAME_LOWERCASE@.desktop /usr/share/applications/@PROJECT_NAME_LOWERCASE@.desktop
6 | cp @CPACK_PACKAGING_INSTALL_PREFIX@/@SHARE_INSTALL_DESTINATION@/icons/@PROJECT_NAME_LOWERCASE@.png /usr/share/icons/@PROJECT_NAME_LOWERCASE@.png
7 |
--------------------------------------------------------------------------------
/install/fastotv/linux/prerm.in:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | if test -e @EXECUTABLE_PATH@ ; then
5 | rm @EXECUTABLE_PATH@
6 | fi
7 |
8 | if test -e /usr/share/applications/@PROJECT_NAME_LOWERCASE@.desktop ; then
9 | rm /usr/share/applications/@PROJECT_NAME_LOWERCASE@.desktop
10 | fi
11 |
12 | if test -e /usr/share/icons/@PROJECT_NAME_LOWERCASE@.png ; then
13 | rm /usr/share/icons/@PROJECT_NAME_LOWERCASE@.png
14 | fi
15 |
--------------------------------------------------------------------------------
/install/fastotv/linux/xinitrc.in:
--------------------------------------------------------------------------------
1 | # Please add next line into ~/.bash_profile or ~/.bashrc according system
2 | #if [ -z "$DISPLAY" ] && [ -n "$XDG_VTNR" ] && [ "$XDG_VTNR" -eq 1 ]; then
3 | # exec startx
4 | #fi
5 |
6 | exec @EXECUTABLE_PATH@
--------------------------------------------------------------------------------
/install/fastotv/macosx/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/macosx/icon.icns
--------------------------------------------------------------------------------
/install/fastotv/resources/connection_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/resources/connection_error.png
--------------------------------------------------------------------------------
/install/fastotv/resources/down_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/resources/down_arrow.png
--------------------------------------------------------------------------------
/install/fastotv/resources/left_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/resources/left_arrow.png
--------------------------------------------------------------------------------
/install/fastotv/resources/offline_channel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/resources/offline_channel.png
--------------------------------------------------------------------------------
/install/fastotv/resources/right_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/resources/right_arrow.png
--------------------------------------------------------------------------------
/install/fastotv/resources/unknown_channel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/resources/unknown_channel.png
--------------------------------------------------------------------------------
/install/fastotv/resources/up_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/resources/up_arrow.png
--------------------------------------------------------------------------------
/install/fastotv/windows/database.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/windows/database.bmp
--------------------------------------------------------------------------------
/install/fastotv/windows/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/windows/icon.ico
--------------------------------------------------------------------------------
/install/fastotv/windows/nsis-top-logo.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fastogt/fastotv/bf17ee9ac75b30645f6494e7c3df596b6a188ad9/install/fastotv/windows/nsis-top-logo.bmp
--------------------------------------------------------------------------------
/install/fastotv/windows/winres.rc.in:
--------------------------------------------------------------------------------
1 | IDI_ICON1 ICON "@ICON_FILE@"
2 |
3 | #define VOS_NT_WINDOWS32 0x00040004L
4 | #define VFT_APP 0x00000001L
5 |
6 | #define VER_FILEVERSION @MAJOR_VER@,@MINOR_VER1@,@MINOR_VER2@,0
7 | #define VER_FILEVERSION_STR "@MAJOR_VER@.@MINOR_VER1@.@MINOR_VER2@\0"
8 |
9 | #define VER_PRODUCTVERSION @MAJOR_VER@,@MINOR_VER1@,@MINOR_VER2@,0
10 | #define VER_PRODUCTVERSION_STR "@MAJOR_VER@.@MINOR_VER1@.@MINOR_VER2@\0"
11 |
12 | 1 VERSIONINFO
13 | FILEVERSION VER_FILEVERSION
14 | PRODUCTVERSION VER_PRODUCTVERSION
15 | FILEFLAGSMASK 0x3fL
16 | #ifdef _DEBUG
17 | FILEFLAGS 0x1L
18 | #else
19 | FILEFLAGS 0x0L
20 | #endif
21 | FILEOS VOS_NT_WINDOWS32
22 | FILETYPE VFT_APP
23 | FILESUBTYPE 0x0L
24 | BEGIN
25 | BLOCK "StringFileInfo"
26 | BEGIN
27 | BLOCK "040904e4"
28 | BEGIN
29 | VALUE "CompanyName", "@COMPANYNAME@\0"
30 | VALUE "FileDescription", "@PRODUCTNAME@\0"
31 | VALUE "FileVersion", VER_FILEVERSION_STR
32 | VALUE "LegalCopyright", "@PRODUCTCOPYRIGHT@\0"
33 | VALUE "ProductName", "@PRODUCTNAME@\0"
34 | VALUE "ProductVersion", VER_PRODUCTVERSION_STR
35 | VALUE "OriginalFilename", "@SHORTPRODUCTNAME@.exe\0"
36 | VALUE "InternalName", "@SHORTPRODUCTNAME@\0"
37 | END
38 | END
39 | BLOCK "VarFileInfo"
40 | BEGIN
41 | /* The following line should only be modified for localized versions. */
42 | /* It consists of any number of WORD,WORD pairs, with each pair */
43 | /* describing a language,codepage combination supported by the file. */
44 | /* */
45 | /* For example, a file might have values "0x409,1252" indicating that it */
46 | /* supports English language (0x409) in the Windows ANSI codepage (1252). */
47 |
48 | VALUE "Translation", 0x409, 1252
49 | END
50 | END
51 |
--------------------------------------------------------------------------------
/scripts/create_pre_commit_hook.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | HOOKS="pre-commit"
4 | ROOT_DIR=$(git rev-parse --show-toplevel)
5 |
6 | for hook in $HOOKS; do
7 | if [ ! -f $ROOT_DIR/.git/hooks/$hook ]; then
8 | ln -s $ROOT_DIR/scripts/$hook $ROOT_DIR/.git/hooks/$hook
9 | fi
10 | done
11 |
12 |
--------------------------------------------------------------------------------
/scripts/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | TOTAL_ERRORS=0
4 |
5 | for file in `git diff-index --name-only --diff-filter=d HEAD`; do
6 | case "${file#*.}" in
7 | cpp|c|h)
8 | clang-format -i "${file}"
9 | cpplint "${file}"
10 | TOTAL_ERRORS=$(expr $TOTAL_ERRORS + $?);
11 | ;;
12 | esac
13 | done
14 |
15 | exit $TOTAL_ERRORS
16 |
--------------------------------------------------------------------------------
/src/client/cmdutils.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include // for PRIx64
22 | #include // for snprintf
23 | #include // for string
24 |
25 | #include // for CONFIG_AVDEVICE
26 |
27 | extern "C" {
28 | #include // for av_get_media_type_string
29 | #include // for av_get_channel_layout_string
30 | #include // for AVDictionary
31 | #include // for av_get_pix_fmt_name
32 | #include // for av_get_sample_fmt_name
33 | }
34 |
35 | #include // for ConvertFromString
36 | #include // for COMPACT_LOG_WARNING, WARNING_LOG
37 | #include // for DISALLOW_COPY_AND_ASSIGN
38 |
39 | void show_license();
40 | void show_version();
41 | void show_help_tv_player(const std::string& topic);
42 | void show_help_player(const std::string& topic);
43 | void show_buildconf();
44 | void show_formats();
45 | void show_devices();
46 | void show_muxers();
47 | void show_demuxers();
48 | void show_codecs();
49 | void show_hwaccels();
50 | void show_decoders();
51 | void show_encoders();
52 | void show_bsfs();
53 | void show_protocols();
54 | void show_filters();
55 | void show_pix_fmts();
56 | void show_layouts();
57 | void show_sample_fmts();
58 | void show_colors();
59 |
60 | #if CONFIG_AVDEVICE
61 | void show_sinks(const std::string& device);
62 | void show_sources(const std::string& device);
63 | #endif
64 |
65 | bool parse_bool(const std::string& bool_str, bool* result);
66 |
67 | template
68 | bool parse_number(const std::string& number_str, T min, T max, T* result) {
69 | if (number_str.empty() || !result) {
70 | WARNING_LOG() << "Can't parse value(number) invalid arguments!";
71 | return false;
72 | }
73 |
74 | T lresult;
75 | if (!common::ConvertFromString(number_str, &lresult)) {
76 | WARNING_LOG() << "Can't parse value(number) value: " << number_str;
77 | return false;
78 | }
79 |
80 | if (lresult < min || lresult > max) {
81 | WARNING_LOG() << "The value for " << number_str << " was " << lresult << " which is not within " << min << " - "
82 | << max;
83 | return false;
84 | }
85 |
86 | *result = lresult;
87 | return true;
88 | }
89 |
90 | #define media_type_string av_get_media_type_string
91 |
92 | #define GET_PIX_FMT_NAME(pix_fmt) const char* name = av_get_pix_fmt_name(pix_fmt);
93 |
94 | #define GET_SAMPLE_FMT_NAME(sample_fmt) const char* name = av_get_sample_fmt_name(sample_fmt)
95 |
96 | #define GET_SAMPLE_RATE_NAME(rate) \
97 | char name[16]; \
98 | snprintf(name, sizeof(name), "%d", rate);
99 |
100 | #define GET_CH_LAYOUT_NAME(ch_layout) \
101 | char name[16]; \
102 | snprintf(name, sizeof(name), "0x%" PRIx64, ch_layout);
103 |
104 | #define GET_CH_LAYOUT_DESC(ch_layout) \
105 | char name[128]; \
106 | av_get_channel_layout_string(name, sizeof(name), 0, ch_layout);
107 |
--------------------------------------------------------------------------------
/src/client/events/network_events.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/events/network_events.h"
20 |
21 | namespace fastotv {
22 | namespace client {
23 | namespace events {
24 |
25 | ConnectInfo::ConnectInfo() {}
26 |
27 | ConnectInfo::ConnectInfo(const common::net::HostAndPort& host) : host(host) {}
28 |
29 | } // namespace events
30 | } // namespace client
31 | } // namespace fastotv
32 |
--------------------------------------------------------------------------------
/src/client/events/network_events.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include // for HostAndPort
22 |
23 | #include // for EventBase, EventsType::C...
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 |
33 | #define CLIENT_DISCONNECT_EVENT static_cast(USER_EVENTS + 1)
34 | #define CLIENT_CONNECT_EVENT static_cast(USER_EVENTS + 2)
35 | #define CLIENT_AUTHORIZED_EVENT static_cast(USER_EVENTS + 3)
36 | #define CLIENT_UNAUTHORIZED_EVENT static_cast(USER_EVENTS + 4)
37 | #define CLIENT_SERVER_INFO_EVENT static_cast(USER_EVENTS + 5)
38 | #define CLIENT_CONFIG_CHANGE_EVENT static_cast(USER_EVENTS + 6)
39 | #define CLIENT_RECEIVE_CHANNELS_EVENT static_cast(USER_EVENTS + 7)
40 | #define CLIENT_RECEIVE_RUNTIME_CHANNELS_EVENT static_cast(USER_EVENTS + 8)
41 | #define CLIENT_CHAT_MESSAGE_SENT_EVENT static_cast(USER_EVENTS + 9)
42 | #define CLIENT_CHAT_MESSAGE_RECEIVE_EVENT static_cast(USER_EVENTS + 10)
43 | #define CLIENT_NOTIFICATION_TEXT_EVENT static_cast(USER_EVENTS + 11)
44 | #define CLIENT_NOTIFICATION_SHUTDOWN_EVENT static_cast(USER_EVENTS + 12)
45 |
46 | namespace fastotv {
47 | namespace client {
48 | namespace events {
49 |
50 | class TvConfig {};
51 |
52 | struct ConnectInfo {
53 | ConnectInfo();
54 | explicit ConnectInfo(const common::net::HostAndPort& host);
55 |
56 | common::net::HostAndPort host;
57 | };
58 |
59 | struct ChannelsMixInfo {
60 | commands_info::ChannelsInfo channels;
61 | commands_info::VodsInfo vods;
62 | commands_info::ChannelsInfo private_channels;
63 | };
64 |
65 | typedef fastoplayer::gui::events::EventBase ClientDisconnectedEvent;
66 | typedef fastoplayer::gui::events::EventBase ClientConnectedEvent;
67 | typedef fastoplayer::gui::events::EventBase ClientAuthorizedEvent;
68 | typedef fastoplayer::gui::events::EventBase ClientUnAuthorizedEvent;
69 | typedef fastoplayer::gui::events::EventBase ClientServerInfoEvent;
70 | typedef fastoplayer::gui::events::EventBase ClientConfigChangeEvent;
71 | typedef fastoplayer::gui::events::EventBase ReceiveChannelsEvent;
72 | typedef fastoplayer::gui::events::EventBase
73 | ReceiveRuntimeChannelEvent;
74 | typedef fastoplayer::gui::events::EventBase
75 | NotificationTextEvent;
76 | typedef fastoplayer::gui::events::EventBase
77 | NotificationShutdownEvent;
78 |
79 | } // namespace events
80 | } // namespace client
81 | } // namespace fastotv
82 |
--------------------------------------------------------------------------------
/src/client/inner/inner_tcp_handler.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/inner/inner_tcp_handler.h"
20 |
21 | #include
22 | #include
23 |
24 | #include // for fApp
25 | #include // for IoLoop
26 | #include // for connect
27 |
28 | #include "client/events/network_events.h" // for BandwidtInfo, Con...
29 |
30 | #include
31 | #include
32 | #include // for ChannelsInfo
33 | #include // for ServerInfo
34 | #include
35 |
36 | #define CHANNELS_ARRAY_FIELD "channels"
37 | #define VODS_ARRAY_FIELD "vods"
38 | #define PRIVATE_CHANNELS_ARRAY_FIELD "private_channels"
39 |
40 | namespace fastotv {
41 | namespace client {
42 | namespace inner {
43 |
44 | InnerTcpHandler::InnerTcpHandler(const common::net::HostAndPort& server_host, const commands_info::AuthInfo& auth_info)
45 | : common::libev::IoLoopObserver(),
46 | inner_connection_(nullptr),
47 | ping_server_id_timer_(INVALID_TIMER_ID),
48 | server_host_(server_host),
49 | auth_info_(auth_info) {}
50 |
51 | InnerTcpHandler::~InnerTcpHandler() {
52 | CHECK(!inner_connection_);
53 | }
54 |
55 | void InnerTcpHandler::PreLooped(common::libev::IoLoop* server) {
56 | ping_server_id_timer_ = server->CreateTimer(ping_timeout_server, true);
57 |
58 | Connect(server);
59 | }
60 |
61 | void InnerTcpHandler::Accepted(common::libev::IoClient* client) {
62 | UNUSED(client);
63 | }
64 |
65 | void InnerTcpHandler::Moved(common::libev::IoLoop* server, common::libev::IoClient* client) {
66 | UNUSED(server);
67 | UNUSED(client);
68 | }
69 |
70 | void InnerTcpHandler::Closed(common::libev::IoClient* client) {
71 | if (client == inner_connection_) {
72 | Client* iclient = static_cast(client);
73 | common::net::socket_info info = iclient->GetInfo();
74 | common::net::HostAndPort host(info.host(), info.port());
75 | events::ConnectInfo cinf(host);
76 | fApp->PostEvent(new events::ClientDisconnectedEvent(this, cinf));
77 | inner_connection_ = nullptr;
78 | return;
79 | }
80 | }
81 |
82 | void InnerTcpHandler::DataReceived(common::libev::IoClient* client) {
83 | if (client == inner_connection_) {
84 | std::string buff;
85 | Client* iclient = static_cast(client);
86 | common::ErrnoError err = iclient->ReadCommand(&buff);
87 | if (err) {
88 | DEBUG_MSG_ERROR(err, common::logging::LOG_LEVEL_ERR);
89 | ignore_result(client->Close());
90 | delete client;
91 | return;
92 | }
93 |
94 | HandleInnerDataReceived(iclient, buff);
95 | }
96 | }
97 |
98 | void InnerTcpHandler::DataReadyToWrite(common::libev::IoClient* client) {
99 | UNUSED(client);
100 | }
101 |
102 | void InnerTcpHandler::PostLooped(common::libev::IoLoop* server) {
103 | UNUSED(server);
104 | if (ping_server_id_timer_ != INVALID_TIMER_ID) {
105 | server->RemoveTimer(ping_server_id_timer_);
106 | ping_server_id_timer_ = INVALID_TIMER_ID;
107 | }
108 |
109 | CHECK(!inner_connection_);
110 | }
111 |
112 | void InnerTcpHandler::TimerEmited(common::libev::IoLoop* server, common::libev::timer_id_t id) {
113 | UNUSED(server);
114 | if (id == ping_server_id_timer_ && inner_connection_) {
115 | Client* client = inner_connection_;
116 | common::ErrnoError err = client->Ping();
117 | if (err) {
118 | DEBUG_MSG_ERROR(err, common::logging::LOG_LEVEL_ERR);
119 | ignore_result(client->Close());
120 | delete client;
121 | }
122 | }
123 | }
124 |
125 | void InnerTcpHandler::Accepted(common::libev::IoChild* child) {
126 | UNUSED(child);
127 | }
128 |
129 | void InnerTcpHandler::Moved(common::libev::IoLoop* server, common::libev::IoChild* child) {
130 | UNUSED(server);
131 | UNUSED(child);
132 | }
133 |
134 | void InnerTcpHandler::ChildStatusChanged(common::libev::IoChild* child, int status, int signal) {
135 | UNUSED(child);
136 | UNUSED(status);
137 | UNUSED(signal);
138 | }
139 |
140 | void InnerTcpHandler::ActivateRequest() {
141 | if (!inner_connection_) {
142 | return;
143 | }
144 |
145 | Client* client = inner_connection_;
146 | common::ErrnoError err = client->Login(auth_info_);
147 | if (err) {
148 | DEBUG_MSG_ERROR(err, common::logging::LOG_LEVEL_ERR);
149 | ignore_result(client->Close());
150 | delete client;
151 | }
152 | }
153 |
154 | void InnerTcpHandler::RequestServerInfo() {
155 | if (!inner_connection_) {
156 | return;
157 | }
158 |
159 | Client* client = inner_connection_;
160 | common::ErrnoError err = client->GetServerInfo();
161 | if (err) {
162 | DEBUG_MSG_ERROR(err, common::logging::LOG_LEVEL_ERR);
163 | ignore_result(client->Close());
164 | delete client;
165 | }
166 | }
167 |
168 | void InnerTcpHandler::RequestChannels() {
169 | if (!inner_connection_) {
170 | return;
171 | }
172 |
173 | Client* client = inner_connection_;
174 | common::ErrnoError err = client->GetChannels();
175 | if (err) {
176 | DEBUG_MSG_ERROR(err, common::logging::LOG_LEVEL_ERR);
177 | ignore_result(client->Close());
178 | delete client;
179 | }
180 | }
181 |
182 | void InnerTcpHandler::RequesRuntimeChannelInfo(stream_id_t sid) {
183 | if (!inner_connection_) {
184 | return;
185 | }
186 |
187 | Client* client = inner_connection_;
188 | common::ErrnoError err = client->GetRuntimeChannelInfo(sid);
189 | if (err) {
190 | DEBUG_MSG_ERROR(err, common::logging::LOG_LEVEL_ERR);
191 | ignore_result(client->Close());
192 | delete client;
193 | }
194 | }
195 |
196 | void InnerTcpHandler::Connect(common::libev::IoLoop* server) {
197 | if (!server) {
198 | return;
199 | }
200 |
201 | DisConnect(common::make_error("Reconnect"));
202 |
203 | common::net::socket_info client_info;
204 | common::ErrnoError err = common::net::connect(server_host_, common::net::ST_SOCK_STREAM, nullptr, &client_info);
205 | if (err) {
206 | DEBUG_MSG_ERROR(err, common::logging::LOG_LEVEL_ERR);
207 | events::ConnectInfo cinf(server_host_);
208 | auto ex_event =
209 | common::make_exception_event(new events::ClientConnectedEvent(this, cinf), common::make_error_from_errno(err));
210 | fApp->PostEvent(ex_event);
211 | return;
212 | }
213 |
214 | Client* connection = new Client(server, client_info);
215 | inner_connection_ = connection;
216 | if (server->RegisterClient(connection)) {
217 | events::ConnectInfo cinf(server_host_);
218 | fApp->PostEvent(new events::ClientConnectedEvent(this, cinf));
219 | }
220 | }
221 |
222 | void InnerTcpHandler::DisConnect(common::Error err) {
223 | UNUSED(err);
224 | if (inner_connection_) {
225 | Client* connection = inner_connection_;
226 | ignore_result(connection->Close());
227 | delete connection;
228 | }
229 | }
230 |
231 | common::ErrnoError InnerTcpHandler::HandleRequestServerPing(Client* client, const protocol::request_t* req) {
232 | if (req->params) {
233 | const char* params_ptr = req->params->c_str();
234 | json_object* jstop = json_tokener_parse(params_ptr);
235 | if (!jstop) {
236 | return common::make_errno_error_inval();
237 | }
238 |
239 | common::daemon::commands::ServerPingInfo server_ping_info;
240 | common::Error err_des = server_ping_info.DeSerialize(jstop);
241 | json_object_put(jstop);
242 | if (err_des) {
243 | const std::string err_str = err_des->GetDescription();
244 | return common::make_errno_error(err_str, EAGAIN);
245 | }
246 |
247 | return client->Pong(req->id);
248 | }
249 |
250 | return common::make_errno_error_inval();
251 | }
252 |
253 | common::ErrnoError InnerTcpHandler::HandleRequestServerClientInfo(Client* client, const protocol::request_t* req) {
254 | return client->SystemInfo(req->id, auth_info_.GetLogin(), auth_info_.GetDeviceID(),
255 | commands_info::ProjectInfo(PROJECT_NAME_LOWERCASE, PROJECT_VERSION));
256 | }
257 |
258 | common::ErrnoError InnerTcpHandler::HandleRequestServerTextNotification(Client* client,
259 | const protocol::request_t* req) {
260 | if (req->params) {
261 | const char* params_ptr = req->params->c_str();
262 | json_object* jnotify_text = json_tokener_parse(params_ptr);
263 | if (!jnotify_text) {
264 | return common::make_errno_error_inval();
265 | }
266 |
267 | commands_info::NotificationTextInfo notification_text_info;
268 | common::Error err_des = notification_text_info.DeSerialize(jnotify_text);
269 | json_object_put(jnotify_text);
270 | if (err_des) {
271 | const std::string err_str = err_des->GetDescription();
272 | return common::make_errno_error(err_str, EAGAIN);
273 | }
274 |
275 | fApp->PostEvent(new events::NotificationTextEvent(this, notification_text_info));
276 | return client->NotificationTextOK(req->id);
277 | }
278 |
279 | return common::make_errno_error_inval();
280 | }
281 |
282 | common::ErrnoError InnerTcpHandler::HandleRequestServerShutdownNotification(Client* client, const protocol::request_t* req) {
283 | if (req->params) {
284 | const char* params_ptr = req->params->c_str();
285 | json_object* jnotify_text = json_tokener_parse(params_ptr);
286 | if (!jnotify_text) {
287 | return common::make_errno_error_inval();
288 | }
289 |
290 | commands_info::ShutDownInfo shutdown_info;
291 | common::Error err_des = shutdown_info.DeSerialize(jnotify_text);
292 | json_object_put(jnotify_text);
293 | if (err_des) {
294 | const std::string err_str = err_des->GetDescription();
295 | return common::make_errno_error(err_str, EAGAIN);
296 | }
297 |
298 | fApp->PostEvent(new events::NotificationShutdownEvent(this, shutdown_info));
299 | return client->NotificationTextOK(req->id);
300 | }
301 |
302 | return common::make_errno_error_inval();
303 | }
304 |
305 | common::ErrnoError InnerTcpHandler::HandleInnerDataReceived(Client* client, const std::string& input_command) {
306 | protocol::request_t* req = nullptr;
307 | protocol::response_t* resp = nullptr;
308 | common::Error err_parse = common::protocols::json_rpc::ParseJsonRPC(input_command, &req, &resp);
309 | if (err_parse) {
310 | const std::string err_str = err_parse->GetDescription();
311 | return common::make_errno_error(err_str, EAGAIN);
312 | }
313 |
314 | if (req) {
315 | DEBUG_LOG() << "Received request: " << input_command;
316 | common::ErrnoError err = HandleRequestCommand(client, req);
317 | if (err) {
318 | DEBUG_MSG_ERROR(err, common::logging::LOG_LEVEL_ERR);
319 | }
320 | delete req;
321 | } else if (resp) {
322 | DEBUG_LOG() << "Received responce: " << input_command;
323 | common::ErrnoError err = HandleResponceCommand(client, resp);
324 | if (err) {
325 | DEBUG_MSG_ERROR(err, common::logging::LOG_LEVEL_ERR);
326 | }
327 | delete resp;
328 | } else {
329 | DNOTREACHED();
330 | return common::make_errno_error("Invalid command type.", EINVAL);
331 | }
332 |
333 | return common::ErrnoError();
334 | }
335 |
336 | common::ErrnoError InnerTcpHandler::HandleRequestCommand(Client* client, const protocol::request_t* req) {
337 | Client* sclient = static_cast(client);
338 | if (req->method == SERVER_PING) {
339 | return HandleRequestServerPing(sclient, req);
340 | } else if (req->method == SERVER_GET_CLIENT_INFO) {
341 | return HandleRequestServerClientInfo(sclient, req);
342 | } else if (req->method == SERVER_TEXT_NOTIFICATION) {
343 | return HandleRequestServerTextNotification(sclient, req);
344 | } else if (req->method == SERVER_SHUTDOWN_NOTIFICATION) {
345 | return HandleRequestServerShutdownNotification(sclient, req);
346 | }
347 |
348 | WARNING_LOG() << "Received unknown command: " << req->method;
349 | return common::ErrnoError();
350 | }
351 |
352 | common::ErrnoError InnerTcpHandler::HandleResponceClientActivateDevice(Client* client,
353 | const protocol::response_t* resp) {
354 | UNUSED(client);
355 | if (resp->IsMessage()) {
356 | return common::ErrnoError();
357 | }
358 | return common::ErrnoError();
359 | }
360 |
361 | common::ErrnoError InnerTcpHandler::HandleResponceClientLogin(Client* client, const protocol::response_t* resp) {
362 | if (resp->IsMessage()) {
363 | client->SetName(auth_info_.GetLogin());
364 | fApp->PostEvent(new events::ClientAuthorizedEvent(this, auth_info_));
365 | return common::ErrnoError();
366 | }
367 |
368 | common::Error err = common::make_error(resp->error->message);
369 | auto ex_event = common::make_exception_event(new events::ClientAuthorizedEvent(this, auth_info_), err);
370 | fApp->PostEvent(ex_event);
371 | return common::ErrnoError();
372 | }
373 |
374 | common::ErrnoError InnerTcpHandler::HandleResponceClientPing(Client* client, const protocol::response_t* resp) {
375 | UNUSED(client);
376 | if (resp->IsMessage()) {
377 | const char* params_ptr = resp->message->result.c_str();
378 | json_object* jserver_ping = json_tokener_parse(params_ptr);
379 | if (!jserver_ping) {
380 | return common::make_errno_error_inval();
381 | }
382 |
383 | common::daemon::commands::ServerPingInfo server_ping_info;
384 | common::Error err_des = server_ping_info.DeSerialize(jserver_ping);
385 | json_object_put(jserver_ping);
386 | if (err_des) {
387 | const std::string err_str = err_des->GetDescription();
388 | return common::make_errno_error(err_str, EAGAIN);
389 | }
390 | return common::ErrnoError();
391 | }
392 | return common::ErrnoError();
393 | }
394 |
395 | common::ErrnoError InnerTcpHandler::HandleResponceClientGetServerInfo(Client* client,
396 | const protocol::response_t* resp) {
397 | UNUSED(client);
398 |
399 | if (resp->IsMessage()) {
400 | const char* params_ptr = resp->message->result.c_str();
401 | json_object* jserver_info = json_tokener_parse(params_ptr);
402 | if (!jserver_info) {
403 | return common::make_errno_error_inval();
404 | }
405 |
406 | commands_info::ServerInfo sinf;
407 | common::Error err_des = sinf.DeSerialize(jserver_info);
408 | json_object_put(jserver_info);
409 | if (err_des) {
410 | const std::string err_str = err_des->GetDescription();
411 | return common::make_errno_error(err_str, EAGAIN);
412 | }
413 |
414 | fApp->PostEvent(new events::ClientServerInfoEvent(this, sinf));
415 | return common::ErrnoError();
416 | }
417 |
418 | common::Error err = common::make_error(resp->error->message);
419 | auto ex_event =
420 | common::make_exception_event(new events::ClientServerInfoEvent(this, commands_info::ServerInfo()), err);
421 | fApp->PostEvent(ex_event);
422 | return common::ErrnoError();
423 | }
424 |
425 | common::ErrnoError InnerTcpHandler::HandleResponceClientGetChannels(Client* client, const protocol::response_t* resp) {
426 | UNUSED(client);
427 | if (resp->IsMessage()) {
428 | const char* params_ptr = resp->message->result.c_str();
429 | json_object* jchannels_info = json_tokener_parse(params_ptr);
430 | if (!jchannels_info) {
431 | return common::make_errno_error_inval();
432 | }
433 |
434 | json_object* jchannels_array = nullptr;
435 | json_bool jchannels_array_exists =
436 | json_object_object_get_ex(jchannels_info, CHANNELS_ARRAY_FIELD, &jchannels_array);
437 | if (!jchannels_array_exists) {
438 | json_object_put(jchannels_info);
439 | return common::make_errno_error_inval();
440 | }
441 |
442 | json_object* jvods_array = nullptr;
443 | json_bool vods_array_exists = json_object_object_get_ex(jchannels_info, VODS_ARRAY_FIELD, &jvods_array);
444 | if (!vods_array_exists) {
445 | json_object_put(jchannels_info);
446 | return common::make_errno_error_inval();
447 | }
448 |
449 | json_object* jprivate_channels_array = nullptr;
450 | json_bool jprivate_channels_array_exists =
451 | json_object_object_get_ex(jchannels_info, PRIVATE_CHANNELS_ARRAY_FIELD, &jprivate_channels_array);
452 | if (!jprivate_channels_array_exists) {
453 | json_object_put(jchannels_info);
454 | return common::make_errno_error_inval();
455 | }
456 |
457 | commands_info::ChannelsInfo channels;
458 | common::Error err_des = channels.DeSerialize(jchannels_array);
459 | if (err_des) {
460 | json_object_put(jchannels_info);
461 | const std::string err_str = err_des->GetDescription();
462 | return common::make_errno_error(err_str, EAGAIN);
463 | }
464 |
465 | commands_info::VodsInfo vods;
466 | err_des = vods.DeSerialize(jvods_array);
467 | if (err_des) {
468 | json_object_put(jchannels_info);
469 | const std::string err_str = err_des->GetDescription();
470 | return common::make_errno_error(err_str, EAGAIN);
471 | }
472 |
473 | commands_info::ChannelsInfo private_channels;
474 | err_des = private_channels.DeSerialize(jprivate_channels_array);
475 | if (err_des) {
476 | json_object_put(jchannels_info);
477 | const std::string err_str = err_des->GetDescription();
478 | return common::make_errno_error(err_str, EAGAIN);
479 | }
480 |
481 | json_object_put(jchannels_info);
482 | events::ChannelsMixInfo ch = {channels, vods, private_channels};
483 | fApp->PostEvent(new events::ReceiveChannelsEvent(this, ch));
484 | return common::ErrnoError();
485 | }
486 | return common::ErrnoError();
487 | }
488 |
489 | common::ErrnoError InnerTcpHandler::HandleResponceClientGetruntimeChannelInfo(Client* client,
490 | const protocol::response_t* resp) {
491 | UNUSED(client);
492 | if (resp->IsMessage()) {
493 | const char* params_ptr = resp->message->result.c_str();
494 | json_object* jchannels_info = json_tokener_parse(params_ptr);
495 | if (!jchannels_info) {
496 | return common::make_errno_error_inval();
497 | }
498 |
499 | commands_info::RuntimeChannelInfo chan;
500 | common::Error err_des = chan.DeSerialize(jchannels_info);
501 | json_object_put(jchannels_info);
502 | if (err_des) {
503 | const std::string err_str = err_des->GetDescription();
504 | return common::make_errno_error(err_str, EAGAIN);
505 | }
506 |
507 | fApp->PostEvent(new events::ReceiveRuntimeChannelEvent(this, chan));
508 | return common::ErrnoError();
509 | }
510 | return common::ErrnoError();
511 | }
512 |
513 | common::ErrnoError InnerTcpHandler::HandleResponceCommand(Client* client, const protocol::response_t* resp) {
514 | protocol::request_t req;
515 | Client* sclient = static_cast(client);
516 | if (sclient->PopRequestByID(resp->id, &req)) {
517 | if (req.method == CLIENT_ACTIVATE_DEVICE) {
518 | return HandleResponceClientActivateDevice(sclient, resp);
519 | } else if (req.method == CLIENT_LOGIN) {
520 | return HandleResponceClientLogin(sclient, resp);
521 | } else if (req.method == CLIENT_PING) {
522 | return HandleResponceClientPing(sclient, resp);
523 | } else if (req.method == CLIENT_GET_SERVER_INFO) {
524 | return HandleResponceClientGetServerInfo(sclient, resp);
525 | } else if (req.method == CLIENT_GET_CHANNELS) {
526 | return HandleResponceClientGetChannels(sclient, resp);
527 | } else if (req.method == CLIENT_GET_RUNTIME_CHANNEL_INFO) {
528 | return HandleResponceClientGetruntimeChannelInfo(sclient, resp);
529 | } else {
530 | WARNING_LOG() << "HandleResponceServiceCommand not handled command: " << req.method;
531 | }
532 | }
533 |
534 | return common::ErrnoError();
535 | }
536 |
537 | } // namespace inner
538 | } // namespace client
539 | } // namespace fastotv
540 |
--------------------------------------------------------------------------------
/src/client/inner/inner_tcp_handler.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include
23 |
24 | #include // for IoLoopObserver
25 | #include // for HostAndPort
26 |
27 | #include // for AuthInfo
28 | #include
29 | #include // for bandwidth_t
30 |
31 | namespace fastotv {
32 | namespace client {
33 | class Client;
34 | namespace bandwidth {
35 | class TcpBandwidthClient;
36 | }
37 | namespace inner {
38 |
39 | class InnerTcpHandler : public common::libev::IoLoopObserver {
40 | public:
41 | enum {
42 | ping_timeout_server = 30 // sec
43 | };
44 |
45 | explicit InnerTcpHandler(const common::net::HostAndPort& server_host, const commands_info::AuthInfo& auth_info);
46 | ~InnerTcpHandler() override;
47 |
48 | void ActivateRequest(); // should be execute in network thread
49 | void RequestServerInfo(); // should be execute in network thread
50 | void RequestChannels(); // should be execute in network thread
51 | void RequesRuntimeChannelInfo(stream_id_t sid); // should be execute in network thread
52 | void Connect(common::libev::IoLoop* server); // should be execute in network thread
53 | void DisConnect(common::Error err); // should be execute in network thread
54 |
55 | void PreLooped(common::libev::IoLoop* server) override;
56 | void Accepted(common::libev::IoClient* client) override;
57 | void Moved(common::libev::IoLoop* server, common::libev::IoClient* client) override;
58 | void Closed(common::libev::IoClient* client) override;
59 | void DataReceived(common::libev::IoClient* client) override;
60 | void DataReadyToWrite(common::libev::IoClient* client) override;
61 | void PostLooped(common::libev::IoLoop* server) override;
62 | void TimerEmited(common::libev::IoLoop* server, common::libev::timer_id_t id) override;
63 | void Accepted(common::libev::IoChild* child) override;
64 | void Moved(common::libev::IoLoop* server, common::libev::IoChild* child) override;
65 | void ChildStatusChanged(common::libev::IoChild* child, int status, int signal) override;
66 |
67 | protected:
68 | common::ErrnoError HandleInnerDataReceived(Client* client, const std::string& input_command);
69 | common::ErrnoError HandleRequestCommand(Client* client, const protocol::request_t* req);
70 | common::ErrnoError HandleResponceCommand(Client* client, const protocol::response_t* resp);
71 |
72 | private:
73 | common::ErrnoError HandleRequestServerPing(Client* client, const protocol::request_t* req);
74 | common::ErrnoError HandleRequestServerClientInfo(Client* client, const protocol::request_t* req);
75 | common::ErrnoError HandleRequestServerTextNotification(Client* client, const protocol::request_t* req);
76 | common::ErrnoError HandleRequestServerShutdownNotification(Client* client, const protocol::request_t* req);
77 |
78 | common::ErrnoError HandleResponceClientActivateDevice(Client* client, const protocol::response_t* resp);
79 | common::ErrnoError HandleResponceClientLogin(Client* client, const protocol::response_t* resp);
80 | common::ErrnoError HandleResponceClientPing(Client* client, const protocol::response_t* resp);
81 | common::ErrnoError HandleResponceClientGetServerInfo(Client* client, const protocol::response_t* resp);
82 | common::ErrnoError HandleResponceClientGetChannels(Client* client, const protocol::response_t* resp);
83 | common::ErrnoError HandleResponceClientGetruntimeChannelInfo(Client* client, const protocol::response_t* resp);
84 |
85 | Client* inner_connection_;
86 | common::libev::timer_id_t ping_server_id_timer_;
87 |
88 | const common::net::HostAndPort server_host_;
89 | const commands_info::AuthInfo auth_info_;
90 | };
91 |
92 | } // namespace inner
93 | } // namespace client
94 | } // namespace fastotv
95 |
--------------------------------------------------------------------------------
/src/client/inner/inner_tcp_server.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/inner/inner_tcp_server.h"
20 |
21 | namespace fastotv {
22 | namespace client {
23 | namespace inner {
24 |
25 | InnerTcpServer::InnerTcpServer(common::libev::IoLoopObserver* observer)
26 | : IoLoop(new common::libev::LibEvLoop, observer) {}
27 |
28 | const char* InnerTcpServer::ClassName() const {
29 | return "InnerTcpServer";
30 | }
31 |
32 | bool InnerTcpServer::IsCanBeRegistered(common::libev::IoClient* client) const {
33 | if (!client) {
34 | return false;
35 | }
36 | return true;
37 | }
38 |
39 | common::libev::IoChild* InnerTcpServer::CreateChild() {
40 | NOTREACHED();
41 | return nullptr;
42 | }
43 |
44 | } // namespace inner
45 | } // namespace client
46 | } // namespace fastotv
47 |
--------------------------------------------------------------------------------
/src/client/inner/inner_tcp_server.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include // for IoLoop
22 |
23 | namespace fastotv {
24 | namespace client {
25 | namespace inner {
26 |
27 | class InnerTcpServer : public common::libev::IoLoop {
28 | public:
29 | explicit InnerTcpServer(common::libev::IoLoopObserver* observer);
30 | const char* ClassName() const override;
31 |
32 | bool IsCanBeRegistered(common::libev::IoClient* client) const override;
33 |
34 | protected:
35 | common::libev::IoChild* CreateChild() override;
36 | };
37 |
38 | } // namespace inner
39 | } // namespace client
40 | } // namespace fastotv
41 |
--------------------------------------------------------------------------------
/src/client/inputs/lirc_input_client.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2017 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/inputs/lirc_input_client.h"
20 |
21 | #include // for lirc_code2char, lirc_deinit
22 |
23 | #include
24 | #include
25 | #include
26 | #include // for strdup
27 | #include // for freeifnotnull
28 |
29 | namespace fastotv {
30 | namespace client {
31 | namespace inputs {
32 |
33 | common::ErrnoError LircInit(int* fd, struct lirc_config** cfg) {
34 | if (!fd || !cfg) {
35 | return common::make_errno_error_inval();
36 | }
37 |
38 | char* copy = common::strdup(PROJECT_NAME_LOWERCASE); // copy for removing warning
39 | int lfd = lirc_init(copy, 1);
40 | common::utils::freeifnotnull(copy);
41 | if (lfd == -1) {
42 | return common::make_errno_error("Lirc init failed!", EAGAIN);
43 | }
44 |
45 | common::ErrnoError err = common::file_system::set_blocking_descriptor(lfd, false);
46 | if (err) {
47 | return err;
48 | }
49 |
50 | lirc_config* lcfg = nullptr;
51 | const std::string absolute_source_dir = common::file_system::absolute_path_from_relative(RELATIVE_SOURCE_DIR);
52 | const std::string lirc_config_path = common::file_system::make_path(absolute_source_dir, LIRCRC_CONFIG_PATH_RELATIVE);
53 | if (lirc_config_path.empty()) {
54 | return common::make_errno_error("Lirc invalid config path!", EAGAIN);
55 | }
56 |
57 | const char* lirc_config_path_ptr = lirc_config_path.c_str();
58 | char* lirc_config_copy_ptr = common::strdup(lirc_config_path_ptr); // copy for removing warning
59 | int res = lirc_readconfig(lirc_config_copy_ptr, &lcfg, nullptr);
60 | common::utils::freeifnotnull(lirc_config_copy_ptr);
61 | if (res == -1) {
62 | err = LircDeinit(lfd, nullptr);
63 | UNUSED(err);
64 | std::string msg_error = common::MemSPrintf("Could not read LIRC config file: %s", lirc_config_path);
65 | return common::make_errno_error(msg_error, EAGAIN);
66 | }
67 |
68 | *fd = lfd;
69 | *cfg = lcfg;
70 | return common::ErrnoError();
71 | }
72 |
73 | common::ErrnoError LircDeinit(int fd, struct lirc_config** cfg) {
74 | if (fd == -1) {
75 | return common::ErrnoError();
76 | }
77 |
78 | if (lirc_deinit() == -1) {
79 | return common::make_errno_error("Lirc deinit failed!", EAGAIN);
80 | }
81 |
82 | if (cfg) {
83 | *cfg = nullptr;
84 | }
85 | return common::ErrnoError();
86 | }
87 |
88 | LircInputClient::LircInputClient(common::libev::IoLoop* server, int fd, struct lirc_config* cfg)
89 | : base_class(server, fd), cfg_(cfg) {}
90 |
91 | common::Error LircInputClient::ReadWithCallback(read_callback_t cb) {
92 | char* code = nullptr;
93 | int ret;
94 | while ((ret = lirc_nextcode(&code)) == 0 && code != nullptr) {
95 | char* c = nullptr;
96 | while ((ret = lirc_code2char(cfg_, code, &c)) == 0 && c != nullptr) {
97 | if (cb) {
98 | cb(c);
99 | }
100 | }
101 | free(code);
102 | if (ret == -1) {
103 | break;
104 | }
105 | }
106 |
107 | return common::Error();
108 | }
109 |
110 | common::ErrnoError LircInputClient::DoClose() {
111 | return LircDeinit(GetFd(), &cfg_);
112 | }
113 |
114 | } // namespace inputs
115 | } // namespace client
116 | } // namespace fastotv
117 |
--------------------------------------------------------------------------------
/src/client/inputs/lirc_input_client.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include
23 |
24 | #include
25 |
26 | struct lirc_config;
27 |
28 | namespace common {
29 | namespace libev {
30 | class IoLoop;
31 | }
32 | } // namespace common
33 |
34 | namespace fastotv {
35 | namespace client {
36 | namespace inputs {
37 |
38 | common::ErrnoError LircInit(int* fd, struct lirc_config** cfg) WARN_UNUSED_RESULT;
39 | common::ErrnoError LircDeinit(int fd, struct lirc_config** cfg) WARN_UNUSED_RESULT;
40 |
41 | class LircInputClient : public common::libev::DescriptorClient {
42 | public:
43 | typedef common::libev::DescriptorClient base_class;
44 | typedef std::function read_callback_t;
45 | LircInputClient(common::libev::IoLoop* server, int fd, struct lirc_config* cfg);
46 |
47 | common::Error ReadWithCallback(read_callback_t cb) WARN_UNUSED_RESULT;
48 |
49 | private:
50 | common::ErrnoError DoClose() override;
51 |
52 | using base_class::Read;
53 | using base_class::Write;
54 |
55 | struct lirc_config* cfg_;
56 | };
57 | } // namespace inputs
58 | } // namespace client
59 | } // namespace fastotv
60 |
--------------------------------------------------------------------------------
/src/client/ioservice.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/ioservice.h"
20 |
21 | #include // for string
22 |
23 | #include // for fApp
24 | #include // for DEBUG_MSG_ERROR, Error
25 | #include // for COMPACT_LOG_FILE_CRIT
26 | #include // for THREAD_MANAGER
27 |
28 | #include "client/inner/inner_tcp_handler.h" // for InnerTcpHandler, StartC...
29 | #include "client/inner/inner_tcp_server.h" // for InnerTcpServer
30 |
31 | #ifdef HAVE_LIRC
32 | #include // for ConvertFromString, Lirc...
33 | #include "client/inputs/lirc_input_client.h" // for LircInit, LircInputClient
34 | #endif
35 |
36 | namespace common {
37 | namespace libev {
38 | class IoClient;
39 | }
40 | } // namespace common
41 |
42 | namespace fastotv {
43 | namespace client {
44 |
45 | namespace {
46 | class PrivateHandler : public inner::InnerTcpHandler {
47 | public:
48 | typedef inner::InnerTcpHandler base_class;
49 | explicit PrivateHandler(const common::net::HostAndPort& server_host, const commands_info::AuthInfo& auth_info)
50 | : base_class(server_host, auth_info)
51 | #ifdef HAVE_LIRC
52 | ,
53 | client_(nullptr)
54 | #endif
55 | {
56 | }
57 |
58 | ~PrivateHandler() override {}
59 |
60 | void PreLooped(common::libev::IoLoop* server) override {
61 | #ifdef HAVE_LIRC
62 | int fd = INVALID_DESCRIPTOR;
63 | struct lirc_config* lcd = nullptr;
64 | common::ErrnoError err = inputs::LircInit(&fd, &lcd);
65 | if (err) {
66 | DEBUG_MSG_ERROR(err, common::logging::LOG_LEVEL_ERR);
67 | } else {
68 | inputs::LircInputClient* client = new inputs::LircInputClient(server, fd, lcd);
69 | if (server->RegisterClient(client)) {
70 | client_ = client;
71 | }
72 | }
73 | #endif
74 | base_class::PreLooped(server);
75 | }
76 |
77 | void Closed(common::libev::IoClient* client) override {
78 | #ifdef HAVE_LIRC
79 | if (client == client_) {
80 | client_ = nullptr;
81 | return;
82 | }
83 | #endif
84 | base_class::Closed(client);
85 | }
86 |
87 | void DataReceived(common::libev::IoClient* client) override {
88 | #ifdef HAVE_LIRC
89 | if (client == client_) {
90 | auto cb = [this](const std::string& code) {
91 | LircCode lcode;
92 | if (!common::ConvertFromString(code, &lcode)) {
93 | WARNING_LOG() << "Unknown lirc code: " << code;
94 | return;
95 | }
96 |
97 | fastoplayer::gui::events::LircPressInfo linf;
98 | linf.code = lcode;
99 | fastoplayer::gui::events::LircPressEvent* levent = new fastoplayer::gui::events::LircPressEvent(this, linf);
100 | fApp->PostEvent(levent);
101 | };
102 | client_->ReadWithCallback(cb);
103 | return;
104 | }
105 | #endif
106 | base_class::DataReceived(client);
107 | }
108 |
109 | void PostLooped(common::libev::IoLoop* server) override {
110 | UNUSED(server);
111 | #ifdef HAVE_LIRC
112 | if (client_) {
113 | inputs::LircInputClient* connection = client_;
114 | connection->Close();
115 | delete connection;
116 | }
117 | #endif
118 | base_class::PostLooped(server);
119 | }
120 | #ifdef HAVE_LIRC
121 | inputs::LircInputClient* client_;
122 | #endif
123 | };
124 | } // namespace
125 |
126 | IoService::IoService(const commands_info::AuthInfo& ainf, const common::net::HostAndPort& server_host)
127 | : ILoopController(),
128 | ainf_(ainf),
129 | server_host_(server_host),
130 | loop_thread_(THREAD_MANAGER()->CreateThread(&IoService::Exec, this)) {}
131 |
132 | bool IoService::IsRunning() const {
133 | return loop_->IsRunning();
134 | }
135 |
136 | void IoService::Start() {
137 | ILoopController::Start();
138 | }
139 |
140 | void IoService::Stop() {
141 | ILoopController::Stop();
142 | }
143 |
144 | IoService::~IoService() {}
145 |
146 | void IoService::ConnectToServer() const {
147 | PrivateHandler* handler = static_cast(handler_);
148 | client::inner::InnerTcpServer* server = static_cast(loop_);
149 | if (handler) {
150 | auto cb = [handler, server]() { handler->Connect(server); };
151 | ExecInLoopThread(cb);
152 | }
153 | }
154 |
155 | void IoService::ActivateRequest() const {
156 | PrivateHandler* handler = static_cast(handler_);
157 | if (handler) {
158 | auto cb = [handler]() { handler->ActivateRequest(); };
159 | ExecInLoopThread(cb);
160 | }
161 | }
162 |
163 | void IoService::DisconnectFromServer() const {
164 | PrivateHandler* handler = static_cast(handler_);
165 | if (handler) {
166 | auto cb = [handler]() { handler->DisConnect(common::Error()); };
167 | ExecInLoopThread(cb);
168 | }
169 | }
170 |
171 | void IoService::RequestServerInfo() const {
172 | PrivateHandler* handler = static_cast(handler_);
173 | if (handler) {
174 | auto cb = [handler]() { handler->RequestServerInfo(); };
175 | ExecInLoopThread(cb);
176 | }
177 | }
178 |
179 | void IoService::RequestChannels() const {
180 | PrivateHandler* handler = static_cast(handler_);
181 | if (handler) {
182 | auto cb = [handler]() { handler->RequestChannels(); };
183 | ExecInLoopThread(cb);
184 | }
185 | }
186 |
187 | void IoService::RequesRuntimeChannelInfo(stream_id_t sid) const {
188 | PrivateHandler* handler = static_cast(handler_);
189 | if (handler) {
190 | auto cb = [handler, sid]() { handler->RequesRuntimeChannelInfo(sid); };
191 | ExecInLoopThread(cb);
192 | }
193 | }
194 |
195 | common::libev::IoLoopObserver* IoService::CreateHandler() {
196 | return new PrivateHandler(server_host_, ainf_);
197 | }
198 |
199 | common::libev::IoLoop* IoService::CreateServer(common::libev::IoLoopObserver* handler) {
200 | client::inner::InnerTcpServer* serv = new client::inner::InnerTcpServer(handler);
201 | serv->SetName("local_inner_server");
202 | return serv;
203 | }
204 |
205 | void IoService::HandleStarted() {
206 | ignore_result(loop_thread_->Start());
207 | }
208 |
209 | void IoService::HandleStopped() {
210 | loop_thread_->JoinAndGet();
211 | }
212 |
213 | } // namespace client
214 | } // namespace fastotv
215 |
--------------------------------------------------------------------------------
/src/client/ioservice.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 |
23 | #include // for IoLoop
24 | #include // for IoLoopObserver
25 | #include // for ILoopController
26 | #include
27 |
28 | #include
29 | #include
30 |
31 | namespace common {
32 | namespace threads {
33 | template
34 | class Thread;
35 | }
36 | } // namespace common
37 |
38 | namespace fastotv {
39 | namespace client {
40 |
41 | class IoService : public common::libev::ILoopController {
42 | public:
43 | IoService(const commands_info::AuthInfo& ainf, const common::net::HostAndPort& server_host);
44 | ~IoService() override;
45 |
46 | bool IsRunning() const;
47 | void Start();
48 | void Stop();
49 |
50 | void ConnectToServer() const;
51 | void ActivateRequest() const;
52 | void DisconnectFromServer() const;
53 | void RequestServerInfo() const;
54 | void RequestChannels() const;
55 | void RequesRuntimeChannelInfo(stream_id_t sid) const;
56 |
57 | private:
58 | using ILoopController::Exec;
59 |
60 | common::libev::IoLoopObserver* CreateHandler() override;
61 | common::libev::IoLoop* CreateServer(common::libev::IoLoopObserver* handler) override;
62 |
63 | void HandleStarted() override;
64 | void HandleStopped() override;
65 |
66 | const commands_info::AuthInfo ainf_;
67 | const common::net::HostAndPort server_host_;
68 | std::shared_ptr> loop_thread_;
69 | };
70 |
71 | } // namespace client
72 | } // namespace fastotv
73 |
--------------------------------------------------------------------------------
/src/client/live_stream/playlist_entry.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/live_stream/playlist_entry.h"
20 |
21 | #include
22 |
23 | #include
24 | #include
25 |
26 | #define IMG_UNKNOWN_CHANNEL_PATH_RELATIVE "share/resources/unknown_channel.png"
27 |
28 | #define ICON_FILE_NAME "icon"
29 |
30 | namespace fastotv {
31 | namespace client {
32 |
33 | PlaylistEntry::PlaylistEntry() : info_(), icon_(), cache_dir_() {}
34 |
35 | PlaylistEntry::PlaylistEntry(const std::string& cache_root_dir, const commands_info::ChannelInfo& info)
36 | : info_(info), rinfo_(), icon_(), cache_dir_() {
37 | stream_id_t id = info_.GetStreamID();
38 | cache_dir_ = common::file_system::make_path(cache_root_dir, id);
39 | }
40 |
41 | std::string PlaylistEntry::GetCacheDir() const {
42 | return cache_dir_;
43 | }
44 |
45 | std::string PlaylistEntry::GetIconPath() const {
46 | commands_info::EpgInfo epg = info_.GetEpg();
47 | common::uri::GURL uri = epg.GetIconUrl();
48 | bool is_unknown_icon = uri == "https://fastocloud.com/images/unknown_channel.png";
49 | if (is_unknown_icon) {
50 | const std::string absolute_source_dir =
51 | common::file_system::absolute_path_from_relative(RELATIVE_SOURCE_DIR, common::file_system::app_pwd()); // +
52 | return common::file_system::make_path(absolute_source_dir, IMG_UNKNOWN_CHANNEL_PATH_RELATIVE);
53 | }
54 | std::string dir = GetCacheDir();
55 | return common::file_system::make_path(dir, ICON_FILE_NAME);
56 | }
57 |
58 | ChannelDescription PlaylistEntry::GetChannelDescription() const {
59 | std::string decr = "N/A";
60 | commands_info::ChannelInfo url = GetChannelInfo();
61 | commands_info::EpgInfo epg = url.GetEpg();
62 | commands_info::ProgrammeInfo prog;
63 | if (epg.FindProgrammeByTime(common::time::current_utc_mstime(), &prog)) {
64 | decr = prog.GetTitle();
65 | }
66 |
67 | return {epg.GetDisplayName(), decr, GetIcon()};
68 | }
69 |
70 | void PlaylistEntry::SetIcon(channel_icon_t icon) {
71 | icon_ = icon;
72 | }
73 |
74 | channel_icon_t PlaylistEntry::GetIcon() const {
75 | return icon_;
76 | }
77 |
78 | commands_info::ChannelInfo PlaylistEntry::GetChannelInfo() const {
79 | return info_;
80 | }
81 |
82 | void PlaylistEntry::SetRuntimeChannelInfo(const commands_info::RuntimeChannelInfo& rinfo) {
83 | rinfo_ = rinfo;
84 | }
85 |
86 | commands_info::RuntimeChannelInfo PlaylistEntry::GetRuntimeChannelInfo() const {
87 | return rinfo_;
88 | }
89 |
90 | } // namespace client
91 | } // namespace fastotv
92 |
--------------------------------------------------------------------------------
/src/client/live_stream/playlist_entry.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include
23 |
24 | #include
25 | #include
26 |
27 | namespace fastoplayer {
28 | namespace draw {
29 | class SurfaceSaver;
30 | }
31 | } // namespace fastoplayer
32 |
33 | namespace fastotv {
34 | namespace client {
35 |
36 | typedef std::shared_ptr channel_icon_t;
37 |
38 | struct ChannelDescription {
39 | std::string title;
40 | std::string description;
41 | channel_icon_t icon;
42 | };
43 |
44 | class PlaylistEntry {
45 | public:
46 | PlaylistEntry();
47 | PlaylistEntry(const std::string& cache_root_dir, const commands_info::ChannelInfo& info);
48 |
49 | commands_info::ChannelInfo GetChannelInfo() const;
50 |
51 | void SetRuntimeChannelInfo(const commands_info::RuntimeChannelInfo& rinfo);
52 | commands_info::RuntimeChannelInfo GetRuntimeChannelInfo() const;
53 |
54 | void SetIcon(channel_icon_t icon);
55 | channel_icon_t GetIcon() const;
56 |
57 | std::string GetCacheDir() const;
58 | std::string GetIconPath() const;
59 |
60 | ChannelDescription GetChannelDescription() const;
61 |
62 | private:
63 | commands_info::ChannelInfo info_;
64 | commands_info::RuntimeChannelInfo rinfo_;
65 |
66 | channel_icon_t icon_;
67 | std::string cache_dir_;
68 | };
69 |
70 | } // namespace client
71 | } // namespace fastotv
72 |
--------------------------------------------------------------------------------
/src/client/live_stream/playlist_window.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/live_stream/playlist_window.h"
20 |
21 | #include
22 |
23 | #include
24 |
25 | #include
26 | #include
27 |
28 | #include
29 | #include
30 |
31 | namespace fastotv {
32 | namespace client {
33 |
34 | PlaylistWindow::PlaylistWindow(const SDL_Color& back_ground_color, Window* parent)
35 | : base_class(back_ground_color, parent), play_list_(nullptr) {}
36 |
37 | PlaylistWindow::~PlaylistWindow() {}
38 |
39 | void PlaylistWindow::SetPlaylist(const playlist_t* pl) {
40 | play_list_ = pl;
41 | }
42 |
43 | const PlaylistWindow::playlist_t* PlaylistWindow::GetPlaylist() const {
44 | return play_list_;
45 | }
46 |
47 | size_t PlaylistWindow::GetRowCount() const {
48 | if (!play_list_) {
49 | return 0;
50 | }
51 | return play_list_->size();
52 | }
53 |
54 | void PlaylistWindow::DrawRow(SDL_Renderer* render, size_t pos, bool active, bool hover, const SDL_Rect& row_rect) {
55 | UNUSED(active);
56 | UNUSED(hover);
57 |
58 | if (!play_list_) {
59 | return;
60 | }
61 |
62 | SDL_Rect number_rect = {row_rect.x, row_rect.y, channel_number_width, row_rect.h};
63 | std::string number_str = common::ConvertToString(pos + 1);
64 | DrawText(render, number_str, number_rect, PlaylistWindow::CENTER_TEXT);
65 |
66 | ChannelDescription descr = play_list_->operator[](pos).GetChannelDescription();
67 | channel_icon_t icon = descr.icon;
68 | int shift = channel_number_width;
69 | if (icon) {
70 | SDL_Texture* img = icon->GetTexture(render);
71 | if (img) {
72 | SDL_Rect icon_rect = {row_rect.x + shift, row_rect.y, row_rect.h, row_rect.h};
73 | SDL_RenderCopy(render, img, nullptr, &icon_rect);
74 | }
75 | }
76 | shift += row_rect.h + space_width; // in any case shift should be
77 |
78 | int text_width = row_rect.w - shift;
79 | std::string title_line =
80 | fastoplayer::draw::DotText(common::MemSPrintf("Title: %s", descr.title), GetFont(), text_width);
81 | std::string description_line =
82 | fastoplayer::draw::DotText(common::MemSPrintf("Description: %s", descr.description), GetFont(), text_width);
83 |
84 | std::string line_text = common::MemSPrintf(
85 | "%s\n"
86 | "%s",
87 | title_line, description_line);
88 | SDL_Rect text_rect = {row_rect.x + shift, row_rect.y, text_width, row_rect.h};
89 | DrawText(render, line_text, text_rect, GetDrawType());
90 | }
91 |
92 | } // namespace client
93 | } // namespace fastotv
94 |
--------------------------------------------------------------------------------
/src/client/live_stream/playlist_window.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include
23 |
24 | #include
25 |
26 | #include "client/live_stream/playlist_entry.h"
27 |
28 | namespace fastotv {
29 | namespace client {
30 |
31 | class PlaylistWindow : public fastoplayer::gui::IListBox {
32 | public:
33 | typedef fastoplayer::gui::IListBox base_class;
34 | typedef std::vector playlist_t;
35 | enum { channel_number_width = 60, space_width = 10 };
36 | explicit PlaylistWindow(const SDL_Color& back_ground_color, Window* parent = nullptr);
37 | ~PlaylistWindow() override;
38 |
39 | void SetPlaylist(const playlist_t* pl);
40 | const playlist_t* GetPlaylist() const;
41 |
42 | size_t GetRowCount() const override;
43 |
44 | protected:
45 | void DrawRow(SDL_Renderer* render, size_t pos, bool active, bool hover, const SDL_Rect& row_rect) override;
46 |
47 | private:
48 | const playlist_t* play_list_; // pointer
49 | };
50 |
51 | } // namespace client
52 | } // namespace fastotv
53 |
--------------------------------------------------------------------------------
/src/client/load_config.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/load_config.h"
20 |
21 | #include // for strcmp
22 |
23 | #include
24 | #include
25 | #include
26 |
27 | #include
28 | #include
29 | #include
30 |
31 | #include // for HWAccelID
32 |
33 | #include "inih/ini.h" // for ini_parse
34 |
35 | #include "client/cmdutils.h"
36 |
37 | #define CONFIG_USER_OPTIONS "user_options"
38 | #define CONFIG_USER_OPTIONS_LOGIN_FIELD "login"
39 | #define CONFIG_USER_OPTIONS_PASSWORD_FIELD "password"
40 | #define CONFIG_USER_OPTIONS_DEVICE_ID_FIELD "device_id"
41 |
42 | #define CONFIG_SERVER_OPTIONS "server_options"
43 | #define CONFIG_SERVER_OPTIONS_SERVER_FIELD "server"
44 |
45 | #define CONFIG_MAIN_OPTIONS "main_options"
46 | #define CONFIG_MAIN_OPTIONS_LOG_LEVEL_FIELD "loglevel"
47 | #define CONFIG_MAIN_OPTIONS_POWEROFF_ON_EXIT_FIELD "poweroffonexit"
48 |
49 | #define CONFIG_PLAYER_OPTIONS "player_options"
50 | #define CONFIG_PLAYER_OPTIONS_WIDTH_FIELD "width"
51 | #define CONFIG_PLAYER_OPTIONS_HEIGHT_FIELD "height"
52 | #define CONFIG_PLAYER_OPTIONS_FULLSCREEN_FIELD "fullscreen"
53 | #define CONFIG_PLAYER_OPTIONS_VOLUME_FIELD "volume"
54 | #define CONFIG_PLAYER_OPTIONS_LAST_SHOWED_CHANNEL_ID_FIELD "last_showed_channel_id"
55 |
56 | #define CONFIG_APP_OPTIONS "app_options"
57 | #define CONFIG_APP_OPTIONS_AST_FIELD "ast"
58 | #define CONFIG_APP_OPTIONS_VST_FIELD "vst"
59 | #define CONFIG_APP_OPTIONS_FAST_FIELD "fast"
60 | #define CONFIG_APP_OPTIONS_GENPTS_FIELD "genpts"
61 | #define CONFIG_APP_OPTIONS_LOWRES_FIELD "lowres"
62 | #define CONFIG_APP_OPTIONS_SYNC_FIELD "sync"
63 | #define CONFIG_APP_OPTIONS_FRAMEDROP_FIELD "framedrop"
64 | #define CONFIG_APP_OPTIONS_BYTES_FIELD "bytes"
65 | #define CONFIG_APP_OPTIONS_INFBUF_FIELD "infbuf"
66 | #define CONFIG_APP_OPTIONS_VF_FIELD "vf"
67 | #define CONFIG_APP_OPTIONS_AF_FIELD "af"
68 | #define CONFIG_APP_OPTIONS_VN_FIELD "vn"
69 | #define CONFIG_APP_OPTIONS_AN_FIELD "an"
70 | #define CONFIG_APP_OPTIONS_ACODEC_FIELD "acodec"
71 | #define CONFIG_APP_OPTIONS_VCODEC_FIELD "vcodec"
72 | #define CONFIG_APP_OPTIONS_HWACCEL_FIELD "hwaccel"
73 | #define CONFIG_APP_OPTIONS_HWACCEL_DEVICE_FIELD "hwaccel_device"
74 | #define CONFIG_APP_OPTIONS_HWACCEL_OUTPUT_FORMAT_FIELD "hwaccel_output_format"
75 | #define CONFIG_APP_OPTIONS_AUTOROTATE_FIELD "autorotate"
76 |
77 | // vaapi args: -hwaccel vaapi -hwaccel_device /dev/dri/card0
78 | // vdpau args: -hwaccel vdpau
79 | // scale output: -vf scale=1920x1080
80 | // deinterlace output: -vf yadif
81 |
82 | /*
83 | [server_options]
84 | server=fastotv.com:6000
85 |
86 | [user_options]
87 | login=anon@fastogt.com
88 | password=md5_hash
89 | device_id=unique_id
90 |
91 | [main_options]
92 | loglevel=INFO ["EMERG", "ALLERT", "CRITICAL", "ERROR", "WARNING", "NOTICE", "INFO", "DEBUG"]
93 | poweroffonexit=false [true,false]
94 |
95 | [app_options]
96 | ast=0 [0, INT_MAX]
97 | vst=0 [0, INT_MAX]
98 | stats=true [true,false]
99 | fast=false [true,false]
100 | genpts=false [true,false]
101 | lowres=0 [0, INT_MAX]
102 | sync=audio [audio, video]
103 | framedrop=-1 [-1, 0, 1]
104 | infbuf=-1 [-1, 0, 1]
105 | vf=std::string() []
106 | af=std::string() []
107 | acodec=std::string() []
108 | vcodec=std::string() []
109 | hwaccel=none [none, auto, vdpau, dxva2, vda,
110 | videotoolbox, qsv, vaapi, cuvid]
111 | hwaccel_device=std::string() []
112 | hwaccel_output_format=std::string() []
113 | autorotate=false [true,false]
114 |
115 | [player_options]
116 | width=0 [0, INT_MAX]
117 | height=0 [0, INT_MAX]
118 | fullscreen=false [true,false]
119 | volume=100 [0,100]
120 | exitonkeydown=false [true,false]
121 | exitonmousedown=false [true,false]
122 | */
123 |
124 | namespace fastotv {
125 | namespace client {
126 |
127 | namespace {
128 |
129 | int ini_handler_fasto(void* user, const char* section, const char* name, const char* value) {
130 | FastoTVConfig* pconfig = reinterpret_cast(user);
131 | size_t value_len = strlen(value);
132 | if (value_len == 0) { // skip empty fields
133 | return 0;
134 | }
135 |
136 | #define MATCH(s, n) strcmp(section, s) == 0 && strcmp(name, n) == 0
137 | if (MATCH(CONFIG_SERVER_OPTIONS, CONFIG_SERVER_OPTIONS_SERVER_FIELD)) {
138 | common::net::HostAndPort hs;
139 | if (common::ConvertFromString(value, &hs)) {
140 | pconfig->server = hs;
141 | }
142 | return 1;
143 | } else if (MATCH(CONFIG_USER_OPTIONS, CONFIG_USER_OPTIONS_LOGIN_FIELD)) {
144 | pconfig->auth_options.SetLogin(value);
145 | return 1;
146 | } else if (MATCH(CONFIG_USER_OPTIONS, CONFIG_USER_OPTIONS_PASSWORD_FIELD)) {
147 | pconfig->auth_options.SetPassword(value);
148 | return 1;
149 | } else if (MATCH(CONFIG_USER_OPTIONS, CONFIG_USER_OPTIONS_DEVICE_ID_FIELD)) {
150 | pconfig->auth_options.SetDeviceID(value);
151 | return 1;
152 | } else if (MATCH(CONFIG_MAIN_OPTIONS, CONFIG_MAIN_OPTIONS_LOG_LEVEL_FIELD)) {
153 | common::logging::LOG_LEVEL lg;
154 | if (common::logging::text_to_log_level(value, &lg)) {
155 | pconfig->loglevel = lg;
156 | }
157 | return 1;
158 | } else if (MATCH(CONFIG_MAIN_OPTIONS, CONFIG_MAIN_OPTIONS_POWEROFF_ON_EXIT_FIELD)) {
159 | bool exit;
160 | if (parse_bool(value, &exit)) {
161 | pconfig->power_off_on_exit = exit;
162 | }
163 | return 1;
164 | } else if (MATCH(CONFIG_PLAYER_OPTIONS, CONFIG_PLAYER_OPTIONS_WIDTH_FIELD)) {
165 | int width;
166 | if (parse_number(value, -1, std::numeric_limits::max(), &width)) {
167 | pconfig->player_options.screen_size.set_width(width);
168 | }
169 | return 1;
170 | } else if (MATCH(CONFIG_PLAYER_OPTIONS, CONFIG_PLAYER_OPTIONS_HEIGHT_FIELD)) {
171 | int height;
172 | if (parse_number(value, -1, std::numeric_limits::max(), &height)) {
173 | pconfig->player_options.screen_size.set_width(height);
174 | }
175 | return 1;
176 | } else if (MATCH(CONFIG_PLAYER_OPTIONS, CONFIG_PLAYER_OPTIONS_FULLSCREEN_FIELD)) {
177 | bool is_full_screen;
178 | if (parse_bool(value, &is_full_screen)) {
179 | pconfig->player_options.is_full_screen = is_full_screen;
180 | }
181 | return 1;
182 | } else if (MATCH(CONFIG_PLAYER_OPTIONS, CONFIG_PLAYER_OPTIONS_VOLUME_FIELD)) {
183 | int volume;
184 | if (parse_number(value, 0, 100, &volume)) {
185 | pconfig->player_options.audio_volume = static_cast(volume);
186 | }
187 | return 1;
188 | } else if (MATCH(CONFIG_PLAYER_OPTIONS, CONFIG_PLAYER_OPTIONS_LAST_SHOWED_CHANNEL_ID_FIELD)) {
189 | pconfig->player_options.last_showed_channel_id = value;
190 | return 1;
191 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_AST_FIELD)) {
192 | pconfig->app_options.wanted_stream_spec[AVMEDIA_TYPE_AUDIO] = value;
193 | return 1;
194 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_VST_FIELD)) {
195 | pconfig->app_options.wanted_stream_spec[AVMEDIA_TYPE_VIDEO] = value;
196 | return 1;
197 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_FAST_FIELD)) {
198 | bool fast;
199 | if (parse_bool(value, &fast)) {
200 | pconfig->app_options.fast = fast;
201 | }
202 | return 1;
203 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_GENPTS_FIELD)) {
204 | bool genpts;
205 | if (parse_bool(value, &genpts)) {
206 | pconfig->app_options.genpts = genpts;
207 | }
208 | return 1;
209 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_LOWRES_FIELD)) {
210 | int lowres;
211 | if (parse_number(value, std::numeric_limits::min(), std::numeric_limits::max(), &lowres)) {
212 | pconfig->app_options.lowres = lowres;
213 | }
214 | return 1;
215 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_SYNC_FIELD)) {
216 | if (strcmp(value, "audio") == 0) {
217 | pconfig->app_options.av_sync_type = fastoplayer::media::AV_SYNC_AUDIO_MASTER;
218 | } else if (strcmp(value, "video") == 0) {
219 | pconfig->app_options.av_sync_type = fastoplayer::media::AV_SYNC_VIDEO_MASTER;
220 | } else {
221 | return 0;
222 | }
223 | return 1;
224 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_FRAMEDROP_FIELD)) {
225 | if (strcmp(value, "auto") == 0) {
226 | pconfig->app_options.framedrop = fastoplayer::media::FRAME_DROP_AUTO;
227 | } else if (strcmp(value, "off") == 0) {
228 | pconfig->app_options.framedrop = fastoplayer::media::FRAME_DROP_OFF;
229 | } else if (strcmp(value, "on") == 0) {
230 | pconfig->app_options.framedrop = fastoplayer::media::FRAME_DROP_ON;
231 | } else {
232 | return 0;
233 | }
234 |
235 | return 1;
236 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_BYTES_FIELD)) {
237 | if (strcmp(value, "auto") == 0) {
238 | pconfig->app_options.seek_by_bytes = fastoplayer::media::SEEK_AUTO;
239 | } else if (strcmp(value, "off") == 0) {
240 | pconfig->app_options.seek_by_bytes = fastoplayer::media::SEEK_BY_BYTES_OFF;
241 | } else if (strcmp(value, "on") == 0) {
242 | pconfig->app_options.seek_by_bytes = fastoplayer::media::SEEK_BY_BYTES_ON;
243 | } else {
244 | return 0;
245 | }
246 |
247 | return 1;
248 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_INFBUF_FIELD)) {
249 | int inf;
250 | if (parse_number(value, -1, 1, &inf)) {
251 | pconfig->app_options.infinite_buffer = inf;
252 | }
253 | return 1;
254 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_VN_FIELD)) {
255 | bool disable_video;
256 | if (parse_bool(value, &disable_video)) {
257 | pconfig->app_options.enable_video = !disable_video;
258 | }
259 | return 1;
260 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_AN_FIELD)) {
261 | bool disable_audio;
262 | if (parse_bool(value, &disable_audio)) {
263 | pconfig->app_options.enable_audio = !disable_audio;
264 | }
265 | return 1;
266 | #if CONFIG_AVFILTER
267 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_VF_FIELD)) {
268 | std::vector tokens;
269 | size_t vf_count = common::Tokenize(value, ",", &tokens);
270 | for (size_t i = 0; i < vf_count; ++i) {
271 | std::string arg_copy = tokens[i];
272 | size_t del = arg_copy.find_first_of('=');
273 | if (del != std::string::npos) {
274 | std::string key = arg_copy.substr(0, del);
275 | std::string value = arg_copy.substr(del + 1);
276 | if (key == "scale") {
277 | common::draw::Size sz;
278 | if (common::ConvertFromString(value, &sz)) {
279 | pconfig->player_options.screen_size = sz;
280 | }
281 | }
282 | }
283 | }
284 | pconfig->app_options.vfilters = value;
285 | return 1;
286 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_AF_FIELD)) {
287 | pconfig->app_options.afilters = value;
288 | return 1;
289 | #endif
290 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_ACODEC_FIELD)) {
291 | pconfig->app_options.audio_codec_name = value;
292 | return 1;
293 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_VCODEC_FIELD)) {
294 | pconfig->app_options.video_codec_name = value;
295 | return 1;
296 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_HWACCEL_FIELD)) {
297 | fastoplayer::media::HWAccelID hwid;
298 | fastoplayer::media::HWDeviceType dtype;
299 | if (fastoplayer::media::HWAccelIDFromString(value, &hwid, &dtype)) {
300 | pconfig->app_options.hwaccel_id = hwid;
301 | pconfig->app_options.hwaccel_device_type = dtype;
302 | }
303 | return 1;
304 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_HWACCEL_DEVICE_FIELD)) {
305 | pconfig->app_options.hwaccel_device = value;
306 | return 1;
307 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_HWACCEL_OUTPUT_FORMAT_FIELD)) {
308 | pconfig->app_options.hwaccel_output_format = value;
309 | return 1;
310 | } else if (MATCH(CONFIG_APP_OPTIONS, CONFIG_APP_OPTIONS_AUTOROTATE_FIELD)) {
311 | bool autorotate;
312 | if (parse_bool(value, &autorotate)) {
313 | pconfig->app_options.autorotate = autorotate;
314 | }
315 | return 1;
316 | } else {
317 | return 0; /* unknown section/name, error */
318 | }
319 | }
320 | } // namespace
321 |
322 | common::ErrnoError load_config_file(const std::string& config_absolute_path, FastoTVConfig* options) {
323 | if (!options) {
324 | return common::make_errno_error_inval();
325 | }
326 |
327 | std::string copy_config_absolute_path = config_absolute_path;
328 | if (!common::file_system::is_file_exist(config_absolute_path)) {
329 | const std::string absolute_source_dir =
330 | common::file_system::absolute_path_from_relative(RELATIVE_SOURCE_DIR, common::file_system::app_pwd()); // +
331 | copy_config_absolute_path = common::file_system::make_path(absolute_source_dir, CONFIG_FILE_PATH_RELATIVE);
332 | }
333 |
334 | if (!copy_config_absolute_path.empty()) {
335 | int res = ini_parse(copy_config_absolute_path.c_str(), ini_handler_fasto, options);
336 | if (res == -1) {
337 | WARNING_LOG() << "Can't open config file path: " << copy_config_absolute_path;
338 | }
339 | }
340 | return common::ErrnoError();
341 | }
342 |
343 | common::ErrnoError save_config_file(const std::string& config_absolute_path, FastoTVConfig* options) {
344 | if (!options || config_absolute_path.empty()) {
345 | return common::make_errno_error_inval();
346 | }
347 |
348 | common::file_system::FileGuard config_save_file;
349 | common::ErrnoError err = config_save_file.Open(config_absolute_path, "w");
350 | if (err) {
351 | return err;
352 | }
353 |
354 | config_save_file.Write("[" CONFIG_SERVER_OPTIONS "]\n");
355 | const std::string host_and_port_str = common::ConvertToString(options->server);
356 | config_save_file.WriteFormated(CONFIG_SERVER_OPTIONS_SERVER_FIELD "=%s\n", host_and_port_str);
357 |
358 | config_save_file.Write("[" CONFIG_USER_OPTIONS "]\n");
359 | config_save_file.WriteFormated(CONFIG_USER_OPTIONS_LOGIN_FIELD "=%s\n", options->auth_options.GetLogin());
360 | config_save_file.WriteFormated(CONFIG_USER_OPTIONS_PASSWORD_FIELD "=%s\n", options->auth_options.GetPassword());
361 | config_save_file.WriteFormated(CONFIG_USER_OPTIONS_DEVICE_ID_FIELD "=%s\n", options->auth_options.GetDeviceID());
362 |
363 | config_save_file.Write("[" CONFIG_MAIN_OPTIONS "]\n");
364 | config_save_file.WriteFormated(CONFIG_MAIN_OPTIONS_LOG_LEVEL_FIELD "=%s\n",
365 | common::logging::log_level_to_text(options->loglevel));
366 | config_save_file.WriteFormated(CONFIG_MAIN_OPTIONS_POWEROFF_ON_EXIT_FIELD "=%s\n",
367 | common::ConvertToString(options->power_off_on_exit));
368 |
369 | config_save_file.Write("[" CONFIG_APP_OPTIONS "]\n");
370 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_AST_FIELD "=%s\n",
371 | options->app_options.wanted_stream_spec[AVMEDIA_TYPE_AUDIO]);
372 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_VST_FIELD "=%s\n",
373 | options->app_options.wanted_stream_spec[AVMEDIA_TYPE_VIDEO]);
374 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_FAST_FIELD "=%s\n",
375 | common::ConvertToString(options->app_options.fast));
376 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_GENPTS_FIELD "=%s\n",
377 | common::ConvertToString(options->app_options.genpts));
378 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_LOWRES_FIELD "=%d\n", options->app_options.lowres);
379 | config_save_file.WriteFormated(
380 | CONFIG_APP_OPTIONS_SYNC_FIELD "=%s\n",
381 | options->app_options.av_sync_type == fastoplayer::media::AV_SYNC_AUDIO_MASTER ? "audio" : "video");
382 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_FRAMEDROP_FIELD "=%d\n",
383 | static_cast(options->app_options.framedrop));
384 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_BYTES_FIELD "=%d\n",
385 | static_cast(options->app_options.seek_by_bytes));
386 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_INFBUF_FIELD "=%d\n", options->app_options.infinite_buffer);
387 |
388 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_VN_FIELD "=%s\n",
389 | common::ConvertToString(!options->app_options.enable_video));
390 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_AN_FIELD "=%s\n",
391 | common::ConvertToString(!options->app_options.enable_audio));
392 | #if CONFIG_AVFILTER
393 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_VF_FIELD "=%s\n", options->app_options.vfilters);
394 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_AF_FIELD "=%s\n", options->app_options.afilters);
395 | #endif
396 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_ACODEC_FIELD "=%s\n", options->app_options.audio_codec_name);
397 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_VCODEC_FIELD "=%s\n", options->app_options.video_codec_name);
398 | config_save_file.WriteFormated(
399 | CONFIG_APP_OPTIONS_HWACCEL_FIELD "=%s\n",
400 | fastoplayer::media::HWAccelIDToString(options->app_options.hwaccel_id, options->app_options.hwaccel_device_type));
401 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_HWACCEL_DEVICE_FIELD "=%s\n", options->app_options.hwaccel_device);
402 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_HWACCEL_OUTPUT_FORMAT_FIELD "=%s\n",
403 | options->app_options.hwaccel_output_format);
404 | config_save_file.WriteFormated(CONFIG_APP_OPTIONS_AUTOROTATE_FIELD "=%s\n",
405 | common::ConvertToString(options->app_options.autorotate));
406 |
407 | config_save_file.Write("[" CONFIG_PLAYER_OPTIONS "]\n");
408 | config_save_file.WriteFormated(CONFIG_PLAYER_OPTIONS_WIDTH_FIELD "=%d\n",
409 | options->player_options.screen_size.width());
410 | config_save_file.WriteFormated(CONFIG_PLAYER_OPTIONS_HEIGHT_FIELD "=%d\n",
411 | options->player_options.screen_size.height());
412 | config_save_file.WriteFormated(CONFIG_PLAYER_OPTIONS_FULLSCREEN_FIELD "=%s\n",
413 | common::ConvertToString(options->player_options.is_full_screen));
414 | config_save_file.WriteFormated(CONFIG_PLAYER_OPTIONS_VOLUME_FIELD "=%d\n", options->player_options.audio_volume);
415 | config_save_file.WriteFormated(CONFIG_PLAYER_OPTIONS_LAST_SHOWED_CHANNEL_ID_FIELD "=%s\n",
416 | options->player_options.last_showed_channel_id);
417 | return common::ErrnoError();
418 | }
419 | } // namespace client
420 | } // namespace fastotv
421 |
--------------------------------------------------------------------------------
/src/client/load_config.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 |
23 | #include // for Error
24 | #include
25 |
26 | #include
27 |
28 | #include
29 |
30 | namespace fastotv {
31 | namespace client {
32 |
33 | struct FastoTVConfig : public fastoplayer::TVConfig {
34 | commands_info::AuthInfo auth_options;
35 | common::net::HostAndPort server;
36 | };
37 |
38 | common::ErrnoError load_config_file(const std::string& config_absolute_path, FastoTVConfig* options) WARN_UNUSED_RESULT;
39 | common::ErrnoError save_config_file(const std::string& config_absolute_path, FastoTVConfig* options) WARN_UNUSED_RESULT;
40 |
41 | } // namespace client
42 | } // namespace fastotv
43 |
--------------------------------------------------------------------------------
/src/client/player.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include
23 |
24 | #include
25 |
26 | #include "client/events/network_events.h" // for BandwidthEstimationEvent
27 | #include "client/live_stream/playlist_entry.h"
28 |
29 | namespace fastoplayer {
30 | namespace gui {
31 | class IconLabel;
32 | class Button;
33 | } // namespace gui
34 | } // namespace fastoplayer
35 |
36 | namespace fastotv {
37 | namespace client {
38 |
39 | class IoService;
40 | class ChatWindow;
41 | class ProgramsWindow;
42 |
43 | class Player : public fastoplayer::ISimplePlayer {
44 | public:
45 | static const SDL_Color failed_color;
46 | static const SDL_Color playlist_color;
47 | static const SDL_Color info_channel_color;
48 | static const SDL_Color chat_color;
49 | static const SDL_Color keypad_color;
50 | static const SDL_Color playlist_item_preselect_color;
51 |
52 | typedef fastoplayer::ISimplePlayer base_class;
53 | enum { footer_height = 60, keypad_height = 30, keypad_width = 60, min_key_pad_size = 0, max_keypad_size = 999 };
54 | Player(const std::string& app_directory_absolute_path, // for runtime data (cache)
55 | const common::net::HostAndPort& server,
56 | const commands_info::AuthInfo& ainf,
57 | const fastoplayer::PlayerOptions& options,
58 | const fastoplayer::media::AppOptions& opt,
59 | const fastoplayer::media::ComplexOptions& copt);
60 |
61 | ~Player() override;
62 |
63 | std::string GetCurrentUrlName() const override; // return Unknown if not found
64 | fastoplayer::media::AppOptions GetStreamOptions() const;
65 |
66 | protected:
67 | void HandleEvent(event_t* event) override;
68 | void HandleExceptionEvent(event_t* event, common::Error err) override;
69 |
70 | void HandlePreExecEvent(fastoplayer::gui::events::PreExecEvent* event) override;
71 | void HandlePostExecEvent(fastoplayer::gui::events::PostExecEvent* event) override;
72 |
73 | void HandleTimerEvent(fastoplayer::gui::events::TimerEvent* event) override;
74 |
75 | virtual void HandleClientServerInfoEvent(events::ClientServerInfoEvent* event);
76 | virtual void HandleClientConnectedEvent(events::ClientConnectedEvent* event);
77 | virtual void HandleClientDisconnectedEvent(events::ClientDisconnectedEvent* event);
78 | virtual void HandleClientAuthorizedEvent(events::ClientAuthorizedEvent* event);
79 | virtual void HandleClientUnAuthorizedEvent(events::ClientUnAuthorizedEvent* event);
80 | virtual void HandleClientConfigChangeEvent(events::ClientConfigChangeEvent* event);
81 | virtual void HandleReceiveChannelsEvent(events::ReceiveChannelsEvent* event);
82 | virtual void HandleReceiveRuntimeChannelEvent(events::ReceiveRuntimeChannelEvent* event);
83 | virtual void HandleNotificationTextEvent(events::NotificationTextEvent* event);
84 | virtual void HandleNotificationShutdownEvent(events::NotificationShutdownEvent *event);
85 |
86 | void HandleKeyPressEvent(fastoplayer::gui::events::KeyPressEvent* event) override;
87 | void HandleLircPressEvent(fastoplayer::gui::events::LircPressEvent* event) override;
88 |
89 | void DrawInfo() override;
90 | void DrawFailedStatus() override;
91 | void DrawInitStatus() override;
92 |
93 | void InitWindow(const std::string& title, States status) override;
94 | void SetStatus(States new_state) override;
95 |
96 | fastoplayer::media::VideoState* CreateStream(stream_id_t sid,
97 | const common::uri::GURL& uri,
98 | fastoplayer::media::AppOptions opt,
99 | fastoplayer::media::ComplexOptions copt) override;
100 |
101 | void OnWindowCreated(SDL_Window* window, SDL_Renderer* render) override;
102 |
103 | private:
104 | void LoadChannelIcon(const PlaylistEntry& entry);
105 |
106 | typedef fastotv::commands_info::NotificationTextInfo::MessageType admin_message_type_t;
107 | void SetVisiblePlaylist(bool visible);
108 |
109 | bool GetChannelDescription(size_t pos, ChannelDescription* descr) const;
110 | bool GetChannelWatchers(size_t* watchers) const;
111 |
112 | void HandleKeyPad(uint8_t key);
113 | void FinishKeyPadInput();
114 | void RemoveLastSymbolInKeypad();
115 | void CreateStreamPosAfterKeypad(size_t pos);
116 | void ResetKeyPad();
117 | SDL_Rect GetKeyPadRect() const;
118 |
119 | void DrawFooter();
120 | void DrawKeyPad();
121 | void DrawProgramsList();
122 | void DrawWatchers();
123 | void DrawAdminMessage();
124 |
125 | void StartShowFooter();
126 | SDL_Rect GetFooterRect() const;
127 |
128 | void StartShowAdminMessage(const std::string& text, admin_message_type_t type, fastoplayer::media::msec_t ttl);
129 | SDL_Rect GetAdminRect() const;
130 |
131 | SDL_Rect GetWatcherRect() const;
132 |
133 | void ToggleShowProgramsList();
134 | SDL_Rect GetProgramsListRect() const;
135 | SDL_Rect GetHideButtonPlayListRect() const;
136 | SDL_Rect GetShowButtonPlayListRect() const;
137 |
138 | bool GetCurrentUrl(PlaylistEntry* url) const;
139 |
140 | void SwitchToPlayingMode();
141 | void SwitchToConnectMode();
142 | void SwitchToDisconnectMode();
143 | void SwitchToDisconnectModeCheckConfig();
144 | void SwitchToAuthorizeMode();
145 | void SwitchToUnAuthorizeMode();
146 |
147 | fastoplayer::media::VideoState* CreateNextStream();
148 | fastoplayer::media::VideoState* CreatePrevStream();
149 | fastoplayer::media::VideoState* CreateStreamPos(size_t pos);
150 |
151 | size_t GenerateNextPosition() const;
152 | size_t GeneratePrevPosition() const;
153 |
154 | void MoveToNextStream();
155 | void MoveToPreviousStream();
156 |
157 | fastoplayer::draw::SurfaceSaver* offline_channel_texture_;
158 | fastoplayer::draw::SurfaceSaver* connection_error_texture_;
159 |
160 | fastoplayer::draw::SurfaceSaver* right_arrow_button_texture_;
161 | fastoplayer::draw::SurfaceSaver* left_arrow_button_texture_;
162 |
163 | fastoplayer::gui::Button* show_playlist_button_;
164 | fastoplayer::gui::Button* hide_playlist_button_;
165 |
166 | IoService* controller_;
167 |
168 | size_t current_stream_pos_;
169 | std::vector play_list_;
170 |
171 | fastoplayer::gui::IconLabel* description_label_;
172 | fastoplayer::media::msec_t footer_last_shown_;
173 |
174 | fastoplayer::gui::IconLabel* admin_label_;
175 | admin_message_type_t admin_label_type_;
176 | fastoplayer::media::msec_t admin_last_shown_;
177 | fastoplayer::media::msec_t admin_show_time_;
178 |
179 | const fastoplayer::media::AppOptions opt_;
180 | const fastoplayer::media::ComplexOptions copt_;
181 |
182 | const std::string app_directory_absolute_path_;
183 |
184 | fastoplayer::gui::Label* keypad_label_;
185 | fastoplayer::media::msec_t keypad_last_shown_;
186 |
187 | ProgramsWindow* programs_window_;
188 |
189 | commands_info::AuthInfo auth_;
190 | };
191 |
192 | } // namespace client
193 | } // namespace fastotv
194 |
--------------------------------------------------------------------------------
/src/client/programs_window.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/programs_window.h"
20 |
21 | #include
22 |
23 | #include
24 |
25 | #include "client/live_stream/playlist_window.h"
26 |
27 | #define SEARCH_PLACEHOLDER "Search..."
28 |
29 | namespace fastotv {
30 | namespace client {
31 |
32 | const SDL_Color ProgramsWindow::text_background_color = fastoplayer::draw::white_color;
33 |
34 | ProgramsWindow::ProgramsWindow(const SDL_Color& back_ground_color)
35 | : base_class(),
36 | plailist_window_(nullptr),
37 | text_input_box_(nullptr),
38 | font_(nullptr),
39 | text_color_(),
40 | proxy_clicked_cb_(),
41 | origin_(nullptr),
42 | filtered_origin_() {
43 | SetTransparent(true);
44 |
45 | // playlist window
46 | plailist_window_ = new PlaylistWindow(back_ground_color, this);
47 | plailist_window_->SetVisible(true);
48 | plailist_window_->SetPlaylist(&filtered_origin_);
49 |
50 | text_input_box_ = new fastoplayer::gui::LineEdit(text_background_color, this);
51 | text_input_box_->SetTextColor(fastoplayer::draw::black_color);
52 | text_input_box_->SetDrawType(fastoplayer::gui::Label::WRAPPED_TEXT);
53 | text_input_box_->SetVisible(true);
54 | text_input_box_->SetBorderColor(fastoplayer::draw::black_color);
55 | text_input_box_->SetBordered(true);
56 | text_input_box_->SetEnabled(true);
57 | text_input_box_->SetPlaceHolder(SEARCH_PLACEHOLDER);
58 | auto search_text_changed_cb = [this](const std::string& text) {
59 | filtered_origin_.clear();
60 | if (!origin_) {
61 | return;
62 | }
63 |
64 | for (size_t i = 0; i < origin_->size(); ++i) {
65 | PlaylistEntry ent = origin_->operator[](i);
66 | commands_info::ChannelInfo cinf = ent.GetChannelInfo();
67 | const commands_info::EpgInfo epg = cinf.GetEpg();
68 | std::string name = epg.GetDisplayName();
69 | if (text.empty() || name.find(text) != std::string::npos) {
70 | filtered_origin_.push_back(ent);
71 | }
72 | }
73 | };
74 | text_input_box_->SetTextChangedCallback(search_text_changed_cb);
75 |
76 | auto mouse_clicked_cb = [this](Uint8 button, size_t row) {
77 | if (proxy_clicked_cb_) {
78 | if (!origin_) {
79 | return;
80 | }
81 |
82 | PlaylistEntry ent = filtered_origin_[row];
83 | commands_info::ChannelInfo ent_inf = ent.GetChannelInfo();
84 | for (size_t i = 0; i < origin_->size(); ++i) {
85 | PlaylistEntry cent = origin_->operator[](i);
86 | if (cent.GetChannelInfo() == ent_inf) {
87 | proxy_clicked_cb_(button, i);
88 | return;
89 | }
90 | }
91 | }
92 | };
93 | plailist_window_->SetMouseClickedRowCallback(mouse_clicked_cb);
94 | }
95 |
96 | ProgramsWindow::~ProgramsWindow() {
97 | destroy(&text_input_box_);
98 | destroy(&plailist_window_);
99 | }
100 |
101 | bool ProgramsWindow::IsActived() const {
102 | return text_input_box_->IsActived();
103 | }
104 |
105 | void ProgramsWindow::SetPlaylist(const PlaylistWindow::playlist_t* pl) {
106 | origin_ = pl;
107 | text_input_box_->ClearText();
108 | }
109 |
110 | void ProgramsWindow::SetTextColor(const SDL_Color& color) {
111 | plailist_window_->SetTextColor(color);
112 | text_color_ = color;
113 | }
114 |
115 | void ProgramsWindow::SetSelection(PlaylistWindow::Selection sel) {
116 | plailist_window_->SetSelection(sel);
117 | }
118 |
119 | void ProgramsWindow::SetFont(TTF_Font* font) {
120 | plailist_window_->SetFont(font);
121 | text_input_box_->SetFont(font);
122 | font_ = font;
123 | }
124 |
125 | void ProgramsWindow::SetRowHeight(int row_height) {
126 | plailist_window_->SetRowHeight(row_height);
127 | }
128 |
129 | void ProgramsWindow::SetSelectionColor(const SDL_Color& sel) {
130 | plailist_window_->SetSelectionColor(sel);
131 | }
132 |
133 | void ProgramsWindow::SetDrawType(fastoplayer::gui::FontWindow::DrawType dt) {
134 | plailist_window_->SetDrawType(dt);
135 | }
136 |
137 | void ProgramsWindow::SetCurrentPositionSelectionColor(const SDL_Color& sel) {
138 | plailist_window_->SetActiveRowColor(sel);
139 | }
140 |
141 | void ProgramsWindow::SetCurrentPositionInPlaylist(size_t pos) {
142 | plailist_window_->SetActiveRow(pos);
143 | }
144 |
145 | void ProgramsWindow::SetMouseClickedRowCallback(PlaylistWindow::mouse_clicked_row_callback_t cb) {
146 | proxy_clicked_cb_ = cb;
147 | }
148 |
149 | void ProgramsWindow::Draw(SDL_Renderer* render) {
150 | if (!IsCanDraw()) {
151 | base_class::Draw(render);
152 | return;
153 | }
154 |
155 | base_class::Draw(render);
156 |
157 | plailist_window_->SetRect(GetPlaylistRect());
158 | plailist_window_->Draw(render);
159 |
160 | text_input_box_->SetRect(GetTextInputRect());
161 | text_input_box_->Draw(render);
162 | }
163 |
164 | SDL_Rect ProgramsWindow::GetPlaylistRect() const {
165 | if (!font_) {
166 | return fastoplayer::draw::empty_rect;
167 | }
168 |
169 | int font_height_2line = fastoplayer::draw::CalcHeightFontPlaceByRowCount(font_, 1);
170 | SDL_Rect chat_rect = GetRect();
171 | int button_height = font_height_2line;
172 | SDL_Rect chat_rect_without_filter_rect = {chat_rect.x, chat_rect.y, chat_rect.w, chat_rect.h - button_height};
173 | return chat_rect_without_filter_rect;
174 | }
175 |
176 | SDL_Rect ProgramsWindow::GetTextInputRect() const {
177 | if (!font_) {
178 | return fastoplayer::draw::empty_rect;
179 | }
180 |
181 | int font_height_2line = fastoplayer::draw::CalcHeightFontPlaceByRowCount(font_, 1);
182 | SDL_Rect chat_rect = GetRect();
183 | SDL_Rect text_input_rect = {chat_rect.x, chat_rect.y + chat_rect.h - font_height_2line, chat_rect.w,
184 | font_height_2line};
185 | return text_input_rect;
186 | }
187 |
188 | } // namespace client
189 | } // namespace fastotv
190 |
--------------------------------------------------------------------------------
/src/client/programs_window.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 |
23 | #include "client/live_stream/playlist_window.h"
24 |
25 | namespace fastoplayer {
26 | namespace gui {
27 | class Button;
28 | class LineEdit;
29 | } // namespace gui
30 | } // namespace fastoplayer
31 |
32 | namespace fastotv {
33 | namespace client {
34 |
35 | class ProgramsWindow : public fastoplayer::gui::Window {
36 | public:
37 | typedef fastoplayer::gui::Window base_class;
38 | static const SDL_Color text_background_color;
39 |
40 | explicit ProgramsWindow(const SDL_Color& back_ground_color);
41 | ~ProgramsWindow() override;
42 |
43 | bool IsActived() const;
44 |
45 | void SetMouseClickedRowCallback(PlaylistWindow::mouse_clicked_row_callback_t cb);
46 |
47 | void SetPlaylist(const PlaylistWindow::playlist_t* pl);
48 |
49 | void SetTextColor(const SDL_Color& color);
50 |
51 | void SetSelection(PlaylistWindow::Selection sel);
52 |
53 | void SetFont(TTF_Font* font);
54 |
55 | void SetRowHeight(int row_height);
56 |
57 | void SetSelectionColor(const SDL_Color& sel);
58 |
59 | void SetDrawType(fastoplayer::gui::FontWindow::DrawType dt);
60 |
61 | void SetCurrentPositionSelectionColor(const SDL_Color& sel);
62 |
63 | void SetCurrentPositionInPlaylist(size_t pos);
64 |
65 | void Draw(SDL_Renderer* render) override;
66 |
67 | private:
68 | SDL_Rect GetPlaylistRect() const;
69 | SDL_Rect GetTextInputRect() const;
70 |
71 | PlaylistWindow* plailist_window_;
72 | fastoplayer::gui::LineEdit* text_input_box_;
73 |
74 | TTF_Font* font_;
75 | SDL_Color text_color_;
76 | // filters
77 | PlaylistWindow::mouse_clicked_row_callback_t proxy_clicked_cb_;
78 | const PlaylistWindow::playlist_t* origin_;
79 | PlaylistWindow::playlist_t filtered_origin_;
80 | };
81 |
82 | } // namespace client
83 | } // namespace fastotv
84 |
--------------------------------------------------------------------------------
/src/client/tv_player_main.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include
20 |
21 | #include
22 |
23 | extern "C" {
24 | #include // for avdevice_register_all
25 | #include // for avfilter_register_all
26 | }
27 |
28 | #include // for File, create_directory
29 | #include // for File, create_directory
30 | #include
31 |
32 | #include
33 |
34 | #include "client/cmdutils.h" // for DictionaryOptions, show_...
35 | #include "client/load_config.h"
36 | #include "client/player.h" // for Player
37 |
38 | void init_ffmpeg() {
39 | /* register all codecs, demux and protocols */
40 | #if CONFIG_AVDEVICE
41 | avdevice_register_all();
42 | #endif
43 | avformat_network_init();
44 | }
45 |
46 | int main_application(int argc, char** argv, const std::string& app_directory_absolute_path) {
47 | int res = fastoplayer::prepare_to_start(app_directory_absolute_path);
48 | if (res == EXIT_FAILURE) {
49 | return EXIT_FAILURE;
50 | }
51 |
52 | const std::string config_absolute_path =
53 | common::file_system::make_path(app_directory_absolute_path, CONFIG_FILE_NAME);
54 | if (!common::file_system::is_valid_path(config_absolute_path)) {
55 | std::cout << "Invalid config file path: " << config_absolute_path << std::endl;
56 | return EXIT_FAILURE;
57 | }
58 |
59 | fastotv::client::FastoTVConfig main_options;
60 | common::ErrnoError err = fastotv::client::load_config_file(config_absolute_path, &main_options);
61 | if (err) {
62 | return EXIT_FAILURE;
63 | }
64 |
65 | #if defined(LOG_TO_FILE)
66 | const std::string log_path = common::file_system::make_path(app_directory_absolute_path, std::string(LOG_FILE_NAME));
67 | INIT_LOGGER(PROJECT_NAME_TITLE, log_path, main_options.loglevel);
68 | #else
69 | INIT_LOGGER(PROJECT_NAME_TITLE, main_options.loglevel);
70 | #endif
71 |
72 | fastoplayer::FFmpegApplication app(argc, argv);
73 |
74 | AVDictionary* sws_dict = nullptr;
75 | AVDictionary* swr_opts = nullptr;
76 | AVDictionary* format_opts = nullptr;
77 | AVDictionary* codec_opts = nullptr;
78 | av_dict_set(&sws_dict, "flags", "bicubic", 0);
79 |
80 | fastoplayer::media::ComplexOptions copt(swr_opts, sws_dict, format_opts, codec_opts);
81 | auto player = new fastotv::client::Player(app_directory_absolute_path, main_options.server, main_options.auth_options,
82 | main_options.player_options, main_options.app_options, copt);
83 | res = app.Exec();
84 | main_options.player_options = player->GetOptions();
85 | destroy(&player);
86 |
87 | av_dict_free(&swr_opts);
88 | av_dict_free(&sws_dict);
89 | av_dict_free(&format_opts);
90 | av_dict_free(&codec_opts);
91 |
92 | // save config file
93 | err = fastotv::client::save_config_file(config_absolute_path, &main_options);
94 | if (main_options.power_off_on_exit) {
95 | common::ErrnoError err_shut = common::system::Shutdown(common::system::SHUTDOWN);
96 | if (err_shut) {
97 | WARNING_LOG() << "Can't shutdown error: " << err_shut->GetDescription();
98 | }
99 | }
100 | return res;
101 | }
102 |
103 | /* Called from the main */
104 | int main(int argc, char** argv) {
105 | init_ffmpeg();
106 |
107 | for (int i = 1; i < argc; ++i) {
108 | const bool lastarg = i == argc - 1;
109 | if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) {
110 | show_version();
111 | return EXIT_SUCCESS;
112 | } else if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0) {
113 | std::string topic;
114 | if (!lastarg) {
115 | topic = argv[++i];
116 | }
117 | show_help_tv_player(topic);
118 | return EXIT_SUCCESS;
119 | } else if (strcmp(argv[i], "-license") == 0 || strcmp(argv[i], "-l") == 0) {
120 | show_license();
121 | return EXIT_SUCCESS;
122 | } else if (strcmp(argv[i], "-buildconf") == 0) {
123 | show_buildconf();
124 | return EXIT_SUCCESS;
125 | } else if (strcmp(argv[i], "-formats") == 0) {
126 | show_formats();
127 | return EXIT_SUCCESS;
128 | } else if (strcmp(argv[i], "-devices") == 0) {
129 | show_devices();
130 | return EXIT_SUCCESS;
131 | } else if (strcmp(argv[i], "-muxers") == 0) {
132 | show_muxers();
133 | return EXIT_SUCCESS;
134 | } else if (strcmp(argv[i], "-demuxers") == 0) {
135 | show_demuxers();
136 | return EXIT_SUCCESS;
137 | } else if (strcmp(argv[i], "-codecs") == 0) {
138 | show_codecs();
139 | return EXIT_SUCCESS;
140 | } else if (strcmp(argv[i], "-hwaccels") == 0) {
141 | show_hwaccels();
142 | return EXIT_SUCCESS;
143 | } else if (strcmp(argv[i], "-decoders") == 0) {
144 | show_decoders();
145 | return EXIT_SUCCESS;
146 | } else if (strcmp(argv[i], "-encoders") == 0) {
147 | show_encoders();
148 | return EXIT_SUCCESS;
149 | } else if (strcmp(argv[i], "-bsfs") == 0) {
150 | show_bsfs();
151 | return EXIT_SUCCESS;
152 | } else if (strcmp(argv[i], "-protocols") == 0) {
153 | show_protocols();
154 | return EXIT_SUCCESS;
155 | } else if (strcmp(argv[i], "-filters") == 0) {
156 | show_filters();
157 | return EXIT_SUCCESS;
158 | } else if (strcmp(argv[i], "-pix_fmts") == 0) {
159 | show_pix_fmts();
160 | return EXIT_SUCCESS;
161 | } else if (strcmp(argv[i], "-layouts") == 0) {
162 | show_layouts();
163 | return EXIT_SUCCESS;
164 | } else if (strcmp(argv[i], "-sample_fmts") == 0) {
165 | show_sample_fmts();
166 | return EXIT_SUCCESS;
167 | } else if (strcmp(argv[i], "-colors") == 0) {
168 | show_colors();
169 | return EXIT_SUCCESS;
170 | }
171 | #if CONFIG_AVDEVICE
172 | else if (strcmp(argv[i], "-sources") == 0) {
173 | std::string device;
174 | if (!lastarg) {
175 | device = argv[++i];
176 | }
177 | show_sources(device);
178 | return EXIT_SUCCESS;
179 | } else if (strcmp(argv[i], "-sinks") == 0) {
180 | std::string device;
181 | if (!lastarg) {
182 | device = argv[++i];
183 | }
184 | show_sinks(device);
185 | return EXIT_SUCCESS;
186 | }
187 | #endif
188 | else {
189 | show_help_tv_player(std::string());
190 | return EXIT_SUCCESS;
191 | }
192 | }
193 |
194 | const std::string app_directory_path = APPLICATION_DIR;
195 | const bool is_abs = common::file_system::is_absolute_path(app_directory_path);
196 | const std::string app_directory_absolute_path =
197 | is_abs ? app_directory_path : common::file_system::absolute_path_from_relative(app_directory_path);
198 | return main_application(argc, argv, app_directory_absolute_path);
199 | }
200 |
--------------------------------------------------------------------------------
/src/client/utils.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/utils.h"
20 |
21 | #include
22 |
23 | extern "C" {
24 | #include
25 | }
26 |
27 | #include
28 |
29 | namespace fastotv {
30 | namespace client {
31 | namespace {
32 | class CallbackHolder {
33 | public:
34 | explicit CallbackHolder(quit_callback_t cb) : is_quit(cb) {}
35 | static int download_interrupt_callback(void* user_data) {
36 | CallbackHolder* holder = static_cast(user_data);
37 | if (holder->is_quit()) {
38 | return 1;
39 | }
40 |
41 | return 0;
42 | }
43 |
44 | private:
45 | const quit_callback_t is_quit;
46 | };
47 | } // namespace
48 |
49 | bool DownloadFileToBuffer(const common::uri::GURL& uri, common::char_buffer_t* buff, quit_callback_t cb) {
50 | if (!uri.is_valid() || !buff || !cb) {
51 | return false;
52 | }
53 |
54 | const std::string url_str = fastoplayer::media::make_url(uri);
55 | if (url_str.empty()) {
56 | return false;
57 | }
58 |
59 | AVFormatContext* ic = avformat_alloc_context();
60 | if (!ic) {
61 | return false;
62 | }
63 |
64 | const char* in_filename = url_str.c_str();
65 | CallbackHolder holder(cb);
66 | ic->interrupt_callback.callback = CallbackHolder::download_interrupt_callback;
67 | ic->interrupt_callback.opaque = &holder;
68 | int open_result = avformat_open_input(&ic, in_filename, nullptr, nullptr);
69 | if (open_result < 0) {
70 | avformat_free_context(ic);
71 | ic = nullptr;
72 | return false;
73 | }
74 | AVPacket pkt;
75 | int ret = av_read_frame(ic, &pkt);
76 | if (ret < 0) {
77 | avformat_free_context(ic);
78 | ic = nullptr;
79 | return false;
80 | }
81 |
82 | *buff = common::char_buffer_t(pkt.data, pkt.data + pkt.size);
83 | av_packet_unref(&pkt);
84 | avformat_free_context(ic);
85 | ic = nullptr;
86 | return true;
87 | }
88 |
89 | } // namespace client
90 | } // namespace fastotv
91 |
--------------------------------------------------------------------------------
/src/client/utils.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 |
23 | #include
24 | #include
25 |
26 | namespace fastotv {
27 | namespace client {
28 |
29 | typedef std::function quit_callback_t;
30 | bool DownloadFileToBuffer(const common::uri::GURL& uri, common::char_buffer_t* buff, quit_callback_t cb);
31 |
32 | } // namespace client
33 | } // namespace fastotv
34 |
--------------------------------------------------------------------------------
/src/client/vod/vod_entry.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/vod/vod_entry.h"
20 |
21 | #include
22 |
23 | #include
24 | #include
25 |
26 | #define IMG_UNKNOWN_CHANNEL_PATH_RELATIVE "share/resources/unknown_channel.png"
27 |
28 | #define ICON_FILE_NAME "icon"
29 |
30 | namespace fastotv {
31 | namespace client {
32 |
33 | VodEntry::VodEntry() : info_(), icon_(), cache_dir_() {}
34 |
35 | VodEntry::VodEntry(const std::string& cache_root_dir, const commands_info::VodInfo& info)
36 | : info_(info), rinfo_(), icon_(), cache_dir_() {
37 | stream_id_t id = info_.GetStreamID();
38 | cache_dir_ = common::file_system::make_path(cache_root_dir, id);
39 | }
40 |
41 | std::string VodEntry::GetCacheDir() const {
42 | return cache_dir_;
43 | }
44 |
45 | std::string VodEntry::GetIconPath() const {
46 | commands_info::MovieInfo movie = info_.GetMovieInfo();
47 | common::uri::GURL uri = movie.GetPreviewIcon();
48 | bool is_unknown_icon = uri == "https://fastocloud.com/images/unknown_channel.png";
49 | if (is_unknown_icon) {
50 | const std::string absolute_source_dir =
51 | common::file_system::absolute_path_from_relative(RELATIVE_SOURCE_DIR, common::file_system::app_pwd()); // +
52 | return common::file_system::make_path(absolute_source_dir, IMG_UNKNOWN_CHANNEL_PATH_RELATIVE);
53 | }
54 | std::string dir = GetCacheDir();
55 | return common::file_system::make_path(dir, ICON_FILE_NAME);
56 | }
57 |
58 | VodDescription VodEntry::GetChannelDescription() const {
59 | std::string decr = "N/A";
60 | commands_info::VodInfo url = GetVodInfo();
61 | commands_info::MovieInfo movie = url.GetMovieInfo();
62 | std::string descr_str = movie.GetDescription();
63 | if (!descr_str.empty()) {
64 | decr = descr_str;
65 | }
66 |
67 | return {movie.GetName(), decr, GetIcon()};
68 | }
69 |
70 | void VodEntry::SetIcon(channel_icon_t icon) {
71 | icon_ = icon;
72 | }
73 |
74 | channel_icon_t VodEntry::GetIcon() const {
75 | return icon_;
76 | }
77 |
78 | commands_info::VodInfo VodEntry::GetVodInfo() const {
79 | return info_;
80 | }
81 |
82 | void VodEntry::SetRuntimeChannelInfo(const commands_info::RuntimeChannelInfo& rinfo) {
83 | rinfo_ = rinfo;
84 | }
85 |
86 | commands_info::RuntimeChannelInfo VodEntry::GetRuntimeChannelInfo() const {
87 | return rinfo_;
88 | }
89 |
90 | } // namespace client
91 | } // namespace fastotv
92 |
--------------------------------------------------------------------------------
/src/client/vod/vod_entry.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include
23 |
24 | #include
25 | #include
26 |
27 | namespace fastoplayer {
28 | namespace draw {
29 | class SurfaceSaver;
30 | }
31 | } // namespace fastoplayer
32 |
33 | namespace fastotv {
34 | namespace client {
35 |
36 | typedef std::shared_ptr channel_icon_t;
37 |
38 | struct VodDescription {
39 | std::string title;
40 | std::string description;
41 | channel_icon_t icon;
42 | };
43 |
44 | class VodEntry {
45 | public:
46 | VodEntry();
47 | VodEntry(const std::string& cache_root_dir, const commands_info::VodInfo& info);
48 |
49 | commands_info::VodInfo GetVodInfo() const;
50 |
51 | void SetRuntimeChannelInfo(const commands_info::RuntimeChannelInfo& rinfo);
52 | commands_info::RuntimeChannelInfo GetRuntimeChannelInfo() const;
53 |
54 | void SetIcon(channel_icon_t icon);
55 | channel_icon_t GetIcon() const;
56 |
57 | std::string GetCacheDir() const;
58 | std::string GetIconPath() const;
59 |
60 | VodDescription GetChannelDescription() const;
61 |
62 | private:
63 | commands_info::VodInfo info_;
64 | commands_info::RuntimeChannelInfo rinfo_;
65 |
66 | channel_icon_t icon_;
67 | std::string cache_dir_;
68 | };
69 |
70 | } // namespace client
71 | } // namespace fastotv
72 |
--------------------------------------------------------------------------------
/src/client/vod/vods_window.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/vod/vods_window.h"
20 |
21 | #include
22 |
23 | #include
24 |
25 | #include
26 | #include
27 |
28 | #include
29 | #include
30 |
31 | namespace fastotv {
32 | namespace client {
33 |
34 | VodsWindow::VodsWindow(const SDL_Color& back_ground_color, Window* parent)
35 | : base_class(back_ground_color, parent), play_list_(nullptr) {}
36 |
37 | VodsWindow::~VodsWindow() {}
38 |
39 | void VodsWindow::SetPlaylist(const playlist_t* pl) {
40 | play_list_ = pl;
41 | }
42 |
43 | const VodsWindow::playlist_t* VodsWindow::GetPlaylist() const {
44 | return play_list_;
45 | }
46 |
47 | size_t VodsWindow::GetRowCount() const {
48 | if (!play_list_) {
49 | return 0;
50 | }
51 | return play_list_->size();
52 | }
53 |
54 | void VodsWindow::DrawRow(SDL_Renderer* render, size_t pos, bool active, bool hover, const SDL_Rect& row_rect) {
55 | UNUSED(active);
56 | UNUSED(hover);
57 |
58 | if (!play_list_) {
59 | return;
60 | }
61 |
62 | SDL_Rect number_rect = {row_rect.x, row_rect.y, channel_number_width, row_rect.h};
63 | std::string number_str = common::ConvertToString(pos + 1);
64 | DrawText(render, number_str, number_rect, VodsWindow::CENTER_TEXT);
65 |
66 | VodDescription descr = play_list_->operator[](pos).GetChannelDescription();
67 | channel_icon_t icon = descr.icon;
68 | int shift = channel_number_width;
69 | if (icon) {
70 | SDL_Texture* img = icon->GetTexture(render);
71 | if (img) {
72 | SDL_Rect icon_rect = {row_rect.x + shift, row_rect.y, row_rect.h, row_rect.h};
73 | SDL_RenderCopy(render, img, nullptr, &icon_rect);
74 | }
75 | }
76 | shift += row_rect.h + space_width; // in any case shift should be
77 |
78 | int text_width = row_rect.w - shift;
79 | std::string title_line =
80 | fastoplayer::draw::DotText(common::MemSPrintf("Title: %s", descr.title), GetFont(), text_width);
81 | std::string description_line =
82 | fastoplayer::draw::DotText(common::MemSPrintf("Description: %s", descr.description), GetFont(), text_width);
83 |
84 | std::string line_text = common::MemSPrintf(
85 | "%s\n"
86 | "%s",
87 | title_line, description_line);
88 | SDL_Rect text_rect = {row_rect.x + shift, row_rect.y, text_width, row_rect.h};
89 | DrawText(render, line_text, text_rect, GetDrawType());
90 | }
91 |
92 | } // namespace client
93 | } // namespace fastotv
94 |
--------------------------------------------------------------------------------
/src/client/vod/vods_window.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 | #include
23 |
24 | #include
25 |
26 | #include "client/vod/vod_entry.h"
27 |
28 | namespace fastotv {
29 | namespace client {
30 |
31 | class VodsWindow : public fastoplayer::gui::IListBox {
32 | public:
33 | typedef fastoplayer::gui::IListBox base_class;
34 | typedef std::vector playlist_t;
35 | enum { channel_number_width = 60, space_width = 10 };
36 | explicit VodsWindow(const SDL_Color& back_ground_color, Window* parent = nullptr);
37 | ~VodsWindow() override;
38 |
39 | void SetPlaylist(const playlist_t* pl);
40 | const playlist_t* GetPlaylist() const;
41 |
42 | size_t GetRowCount() const override;
43 |
44 | protected:
45 | void DrawRow(SDL_Renderer* render, size_t pos, bool active, bool hover, const SDL_Rect& row_rect) override;
46 |
47 | private:
48 | const playlist_t* play_list_; // pointer
49 | };
50 |
51 | } // namespace client
52 | } // namespace fastotv
53 |
--------------------------------------------------------------------------------
/src/client/vods_window.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include "client/vods_window.h"
20 |
21 | #include
22 |
23 | #include
24 |
25 | #include "client/live_stream/playlist_window.h"
26 |
27 | #define SEARCH_PLACEHOLDER "Search..."
28 |
29 | namespace fastotv {
30 | namespace client {
31 |
32 | const SDL_Color VodsListWindow::text_background_color = fastoplayer::draw::white_color;
33 |
34 | VodsListWindow::VodsListWindow(const SDL_Color& back_ground_color)
35 | : base_class(),
36 | plailist_window_(nullptr),
37 | text_input_box_(nullptr),
38 | font_(nullptr),
39 | text_color_(),
40 | proxy_clicked_cb_(),
41 | origin_(nullptr),
42 | filtered_origin_() {
43 | SetTransparent(true);
44 |
45 | // playlist window
46 | plailist_window_ = new VodsWindow(back_ground_color, this);
47 | plailist_window_->SetVisible(true);
48 | plailist_window_->SetPlaylist(&filtered_origin_);
49 |
50 | text_input_box_ = new fastoplayer::gui::LineEdit(text_background_color, this);
51 | text_input_box_->SetTextColor(fastoplayer::draw::black_color);
52 | text_input_box_->SetDrawType(fastoplayer::gui::Label::WRAPPED_TEXT);
53 | text_input_box_->SetVisible(true);
54 | text_input_box_->SetBorderColor(fastoplayer::draw::black_color);
55 | text_input_box_->SetBordered(true);
56 | text_input_box_->SetEnabled(true);
57 | text_input_box_->SetPlaceHolder(SEARCH_PLACEHOLDER);
58 | auto search_text_changed_cb = [this](const std::string& text) {
59 | filtered_origin_.clear();
60 | if (!origin_) {
61 | return;
62 | }
63 |
64 | for (size_t i = 0; i < origin_->size(); ++i) {
65 | VodEntry ent = origin_->operator[](i);
66 | commands_info::VodInfo cinf = ent.GetVodInfo();
67 | const commands_info::MovieInfo epg = cinf.GetMovieInfo();
68 | std::string name = epg.GetName();
69 | if (text.empty() || name.find(text) != std::string::npos) {
70 | filtered_origin_.push_back(ent);
71 | }
72 | }
73 | };
74 | text_input_box_->SetTextChangedCallback(search_text_changed_cb);
75 |
76 | auto mouse_clicked_cb = [this](Uint8 button, size_t row) {
77 | if (proxy_clicked_cb_) {
78 | if (!origin_) {
79 | return;
80 | }
81 |
82 | VodEntry ent = filtered_origin_[row];
83 | commands_info::VodInfo ent_inf = ent.GetVodInfo();
84 | for (size_t i = 0; i < origin_->size(); ++i) {
85 | VodEntry cent = origin_->operator[](i);
86 | if (cent.GetVodInfo() == ent_inf) {
87 | proxy_clicked_cb_(button, i);
88 | return;
89 | }
90 | }
91 | }
92 | };
93 | plailist_window_->SetMouseClickedRowCallback(mouse_clicked_cb);
94 | }
95 |
96 | VodsListWindow::~VodsListWindow() {
97 | destroy(&text_input_box_);
98 | destroy(&plailist_window_);
99 | }
100 |
101 | bool VodsListWindow::IsActived() const {
102 | return text_input_box_->IsActived();
103 | }
104 |
105 | void VodsListWindow::SetPlaylist(const VodsWindow::playlist_t* pl) {
106 | origin_ = pl;
107 | text_input_box_->ClearText();
108 | }
109 |
110 | void VodsListWindow::SetTextColor(const SDL_Color& color) {
111 | plailist_window_->SetTextColor(color);
112 | text_color_ = color;
113 | }
114 |
115 | void VodsListWindow::SetSelection(VodsWindow::Selection sel) {
116 | plailist_window_->SetSelection(sel);
117 | }
118 |
119 | void VodsListWindow::SetFont(TTF_Font* font) {
120 | plailist_window_->SetFont(font);
121 | text_input_box_->SetFont(font);
122 | font_ = font;
123 | }
124 |
125 | void VodsListWindow::SetRowHeight(int row_height) {
126 | plailist_window_->SetRowHeight(row_height);
127 | }
128 |
129 | void VodsListWindow::SetSelectionColor(const SDL_Color& sel) {
130 | plailist_window_->SetSelectionColor(sel);
131 | }
132 |
133 | void VodsListWindow::SetDrawType(fastoplayer::gui::FontWindow::DrawType dt) {
134 | plailist_window_->SetDrawType(dt);
135 | }
136 |
137 | void VodsListWindow::SetCurrentPositionSelectionColor(const SDL_Color& sel) {
138 | plailist_window_->SetActiveRowColor(sel);
139 | }
140 |
141 | void VodsListWindow::SetCurrentPositionInPlaylist(size_t pos) {
142 | plailist_window_->SetActiveRow(pos);
143 | }
144 |
145 | void VodsListWindow::SetMouseClickedRowCallback(VodsWindow::mouse_clicked_row_callback_t cb) {
146 | proxy_clicked_cb_ = cb;
147 | }
148 |
149 | void VodsListWindow::Draw(SDL_Renderer* render) {
150 | if (!IsCanDraw()) {
151 | base_class::Draw(render);
152 | return;
153 | }
154 |
155 | base_class::Draw(render);
156 |
157 | plailist_window_->SetRect(GetPlaylistRect());
158 | plailist_window_->Draw(render);
159 |
160 | text_input_box_->SetRect(GetTextInputRect());
161 | text_input_box_->Draw(render);
162 | }
163 |
164 | SDL_Rect VodsListWindow::GetPlaylistRect() const {
165 | if (!font_) {
166 | return fastoplayer::draw::empty_rect;
167 | }
168 |
169 | int font_height_2line = fastoplayer::draw::CalcHeightFontPlaceByRowCount(font_, 1);
170 | SDL_Rect chat_rect = GetRect();
171 | int button_height = font_height_2line;
172 | SDL_Rect chat_rect_without_filter_rect = {chat_rect.x, chat_rect.y, chat_rect.w, chat_rect.h - button_height};
173 | return chat_rect_without_filter_rect;
174 | }
175 |
176 | SDL_Rect VodsListWindow::GetTextInputRect() const {
177 | if (!font_) {
178 | return fastoplayer::draw::empty_rect;
179 | }
180 |
181 | int font_height_2line = fastoplayer::draw::CalcHeightFontPlaceByRowCount(font_, 1);
182 | SDL_Rect chat_rect = GetRect();
183 | SDL_Rect text_input_rect = {chat_rect.x, chat_rect.y + chat_rect.h - font_height_2line, chat_rect.w,
184 | font_height_2line};
185 | return text_input_rect;
186 | }
187 |
188 | } // namespace client
189 | } // namespace fastotv
190 |
--------------------------------------------------------------------------------
/src/client/vods_window.h:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2022 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #pragma once
20 |
21 | #include
22 |
23 | #include "client/vod/vods_window.h"
24 |
25 | namespace fastoplayer {
26 | namespace gui {
27 | class Button;
28 | class LineEdit;
29 | } // namespace gui
30 | } // namespace fastoplayer
31 |
32 | namespace fastotv {
33 | namespace client {
34 |
35 | class VodsListWindow : public fastoplayer::gui::Window {
36 | public:
37 | typedef fastoplayer::gui::Window base_class;
38 | static const SDL_Color text_background_color;
39 |
40 | explicit VodsListWindow(const SDL_Color& back_ground_color);
41 | ~VodsListWindow() override;
42 |
43 | bool IsActived() const;
44 |
45 | void SetMouseClickedRowCallback(VodsWindow::mouse_clicked_row_callback_t cb);
46 |
47 | void SetPlaylist(const VodsWindow::playlist_t* pl);
48 |
49 | void SetTextColor(const SDL_Color& color);
50 |
51 | void SetSelection(VodsWindow::Selection sel);
52 |
53 | void SetFont(TTF_Font* font);
54 |
55 | void SetRowHeight(int row_height);
56 |
57 | void SetSelectionColor(const SDL_Color& sel);
58 |
59 | void SetDrawType(fastoplayer::gui::FontWindow::DrawType dt);
60 |
61 | void SetCurrentPositionSelectionColor(const SDL_Color& sel);
62 |
63 | void SetCurrentPositionInPlaylist(size_t pos);
64 |
65 | void Draw(SDL_Renderer* render) override;
66 |
67 | private:
68 | SDL_Rect GetPlaylistRect() const;
69 | SDL_Rect GetTextInputRect() const;
70 |
71 | VodsWindow* plailist_window_;
72 | fastoplayer::gui::LineEdit* text_input_box_;
73 |
74 | TTF_Font* font_;
75 | SDL_Color text_color_;
76 | // filters
77 | VodsWindow::mouse_clicked_row_callback_t proxy_clicked_cb_;
78 | const VodsWindow::playlist_t* origin_;
79 | VodsWindow::playlist_t filtered_origin_;
80 | };
81 |
82 | } // namespace client
83 | } // namespace fastotv
84 |
--------------------------------------------------------------------------------
/src/third-party/ini/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.3.0)
2 | PROJECT(inih C)
3 |
4 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_LIST_DIR}/inih)
5 |
6 | SET(HEADERS_INIH
7 | inih/ini.h
8 | )
9 |
10 | SET(SOURCES_INIH
11 | inih/ini.c
12 | )
13 |
14 | SET(LIBS_INIH)
15 |
16 | ADD_LIBRARY(${PROJECT_NAME} STATIC ${HEADERS_INIH} ${SOURCES_INIH})
17 |
--------------------------------------------------------------------------------
/tests/unit_tests/test_commands.cpp:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2014-2019 FastoGT. All right reserved.
2 |
3 | This file is part of FastoTV.
4 |
5 | FastoTV is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | FastoTV is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with FastoTV. If not, see .
17 | */
18 |
19 | #include
20 |
21 | #include "client/commands.h"
22 |
23 | TEST(Client, TestCommands) {
24 | const auto req = fastotv::client::GetChannelsRequest(std::string("11"));
25 | ASSERT_TRUE(req.IsValid());
26 | }
27 |
--------------------------------------------------------------------------------