Add genereate prview of podcast. Add preview creator dialog. Add video dialog. Add icons. Fixes and more fixes. Refactoring. Update ui.
2
Pipfile
@ -12,6 +12,8 @@ ffmpeg = "*"
|
|||||||
pip = "*"
|
pip = "*"
|
||||||
ffmpeg-python = "*"
|
ffmpeg-python = "*"
|
||||||
pydub = "*"
|
pydub = "*"
|
||||||
|
sound = "*"
|
||||||
|
pysignal = "*"
|
||||||
|
|
||||||
[dev-packages]
|
[dev-packages]
|
||||||
|
|
||||||
|
116
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "b9153460b4a961fc9063b87ddac6e4c7bf8748bfaefcefc26f2401e340ae7b1e"
|
"sha256": "97d779996cd5a22333bb688b9bf3ef013963d64876f4def420e6651d98165e23"
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -16,6 +16,47 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"default": {
|
"default": {
|
||||||
|
"cffi": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e",
|
||||||
|
"sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d",
|
||||||
|
"sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a",
|
||||||
|
"sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec",
|
||||||
|
"sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362",
|
||||||
|
"sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668",
|
||||||
|
"sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c",
|
||||||
|
"sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b",
|
||||||
|
"sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06",
|
||||||
|
"sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698",
|
||||||
|
"sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2",
|
||||||
|
"sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c",
|
||||||
|
"sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7",
|
||||||
|
"sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009",
|
||||||
|
"sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03",
|
||||||
|
"sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b",
|
||||||
|
"sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909",
|
||||||
|
"sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53",
|
||||||
|
"sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35",
|
||||||
|
"sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26",
|
||||||
|
"sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b",
|
||||||
|
"sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01",
|
||||||
|
"sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb",
|
||||||
|
"sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293",
|
||||||
|
"sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd",
|
||||||
|
"sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d",
|
||||||
|
"sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3",
|
||||||
|
"sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d",
|
||||||
|
"sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e",
|
||||||
|
"sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca",
|
||||||
|
"sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d",
|
||||||
|
"sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775",
|
||||||
|
"sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375",
|
||||||
|
"sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b",
|
||||||
|
"sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b",
|
||||||
|
"sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f"
|
||||||
|
],
|
||||||
|
"version": "==1.14.4"
|
||||||
|
},
|
||||||
"click": {
|
"click": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
|
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
|
||||||
@ -24,6 +65,14 @@
|
|||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
|
||||||
"version": "==7.1.2"
|
"version": "==7.1.2"
|
||||||
},
|
},
|
||||||
|
"darr": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:2fdcfbfb23d9b78cdbdc8eacaf53b2fbc80f4aa398c96fa279c4b2676fe25e6d",
|
||||||
|
"sha256:3a57cdf75f0deba2ae03820f4f01747925bf8dac100a3fd9c3c90c56dfad2261"
|
||||||
|
],
|
||||||
|
"markers": "python_version >= '3.6'",
|
||||||
|
"version": "==0.2.2"
|
||||||
|
},
|
||||||
"ffmpeg": {
|
"ffmpeg": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:6931692c890ff21d39938433c2189747815dca0c60ddc7f9bb97f199dba0b5b9"
|
"sha256:6931692c890ff21d39938433c2189747815dca0c60ddc7f9bb97f199dba0b5b9"
|
||||||
@ -116,6 +165,46 @@
|
|||||||
],
|
],
|
||||||
"version": "==0.6.1"
|
"version": "==0.6.1"
|
||||||
},
|
},
|
||||||
|
"numpy": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:012426a41bc9ab63bb158635aecccc7610e3eff5d31d1eb43bc099debc979d94",
|
||||||
|
"sha256:06fab248a088e439402141ea04f0fffb203723148f6ee791e9c75b3e9e82f080",
|
||||||
|
"sha256:0eef32ca3132a48e43f6a0f5a82cb508f22ce5a3d6f67a8329c81c8e226d3f6e",
|
||||||
|
"sha256:1ded4fce9cfaaf24e7a0ab51b7a87be9038ea1ace7f34b841fe3b6894c721d1c",
|
||||||
|
"sha256:2e55195bc1c6b705bfd8ad6f288b38b11b1af32f3c8289d6c50d47f950c12e76",
|
||||||
|
"sha256:2ea52bd92ab9f768cc64a4c3ef8f4b2580a17af0a5436f6126b08efbd1838371",
|
||||||
|
"sha256:36674959eed6957e61f11c912f71e78857a8d0604171dfd9ce9ad5cbf41c511c",
|
||||||
|
"sha256:384ec0463d1c2671170901994aeb6dce126de0a95ccc3976c43b0038a37329c2",
|
||||||
|
"sha256:39b70c19ec771805081578cc936bbe95336798b7edf4732ed102e7a43ec5c07a",
|
||||||
|
"sha256:400580cbd3cff6ffa6293df2278c75aef2d58d8d93d3c5614cd67981dae68ceb",
|
||||||
|
"sha256:43d4c81d5ffdff6bae58d66a3cd7f54a7acd9a0e7b18d97abb255defc09e3140",
|
||||||
|
"sha256:50a4a0ad0111cc1b71fa32dedd05fa239f7fb5a43a40663269bb5dc7877cfd28",
|
||||||
|
"sha256:603aa0706be710eea8884af807b1b3bc9fb2e49b9f4da439e76000f3b3c6ff0f",
|
||||||
|
"sha256:6149a185cece5ee78d1d196938b2a8f9d09f5a5ebfbba66969302a778d5ddd1d",
|
||||||
|
"sha256:759e4095edc3c1b3ac031f34d9459fa781777a93ccc633a472a5468587a190ff",
|
||||||
|
"sha256:7fb43004bce0ca31d8f13a6eb5e943fa73371381e53f7074ed21a4cb786c32f8",
|
||||||
|
"sha256:811daee36a58dc79cf3d8bdd4a490e4277d0e4b7d103a001a4e73ddb48e7e6aa",
|
||||||
|
"sha256:8b5e972b43c8fc27d56550b4120fe6257fdc15f9301914380b27f74856299fea",
|
||||||
|
"sha256:99abf4f353c3d1a0c7a5f27699482c987cf663b1eac20db59b8c7b061eabd7fc",
|
||||||
|
"sha256:a0d53e51a6cb6f0d9082decb7a4cb6dfb33055308c4c44f53103c073f649af73",
|
||||||
|
"sha256:a12ff4c8ddfee61f90a1633a4c4afd3f7bcb32b11c52026c92a12e1325922d0d",
|
||||||
|
"sha256:a4646724fba402aa7504cd48b4b50e783296b5e10a524c7a6da62e4a8ac9698d",
|
||||||
|
"sha256:a76f502430dd98d7546e1ea2250a7360c065a5fdea52b2dffe8ae7180909b6f4",
|
||||||
|
"sha256:a9d17f2be3b427fbb2bce61e596cf555d6f8a56c222bd2ca148baeeb5e5c783c",
|
||||||
|
"sha256:ab83f24d5c52d60dbc8cd0528759532736b56db58adaa7b5f1f76ad551416a1e",
|
||||||
|
"sha256:aeb9ed923be74e659984e321f609b9ba54a48354bfd168d21a2b072ed1e833ea",
|
||||||
|
"sha256:c843b3f50d1ab7361ca4f0b3639bf691569493a56808a0b0c54a051d260b7dbd",
|
||||||
|
"sha256:cae865b1cae1ec2663d8ea56ef6ff185bad091a5e33ebbadd98de2cfa3fa668f",
|
||||||
|
"sha256:cc6bd4fd593cb261332568485e20a0712883cf631f6f5e8e86a52caa8b2b50ff",
|
||||||
|
"sha256:cf2402002d3d9f91c8b01e66fbb436a4ed01c6498fffed0e4c7566da1d40ee1e",
|
||||||
|
"sha256:d051ec1c64b85ecc69531e1137bb9751c6830772ee5c1c426dbcfe98ef5788d7",
|
||||||
|
"sha256:d6631f2e867676b13026e2846180e2c13c1e11289d67da08d71cacb2cd93d4aa",
|
||||||
|
"sha256:dbd18bcf4889b720ba13a27ec2f2aac1981bd41203b3a3b27ba7a33f88ae4827",
|
||||||
|
"sha256:df609c82f18c5b9f6cb97271f03315ff0dbe481a2a02e56aeb1b1a985ce38e60"
|
||||||
|
],
|
||||||
|
"markers": "python_version >= '3.6'",
|
||||||
|
"version": "==1.19.5"
|
||||||
|
},
|
||||||
"packaging": {
|
"packaging": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858",
|
"sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858",
|
||||||
@ -140,6 +229,14 @@
|
|||||||
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||||
"version": "==2.6.0"
|
"version": "==2.6.0"
|
||||||
},
|
},
|
||||||
|
"pycparser": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0",
|
||||||
|
"sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"
|
||||||
|
],
|
||||||
|
"markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
|
||||||
|
"version": "==2.20"
|
||||||
|
},
|
||||||
"pydocstyle": {
|
"pydocstyle": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:19b86fa8617ed916776a11cd8bc0197e5b9856d5433b777f51a3defe13075325",
|
"sha256:19b86fa8617ed916776a11cd8bc0197e5b9856d5433b777f51a3defe13075325",
|
||||||
@ -225,6 +322,23 @@
|
|||||||
],
|
],
|
||||||
"version": "==2.0.0"
|
"version": "==2.0.0"
|
||||||
},
|
},
|
||||||
|
"sound": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:bc5baa8cf11152bdeda1197b6390608d874d8c917f7542b7c06485a952340ee3"
|
||||||
|
],
|
||||||
|
"index": "pypi",
|
||||||
|
"version": "==0.1.0"
|
||||||
|
},
|
||||||
|
"soundfile": {
|
||||||
|
"hashes": [
|
||||||
|
"sha256:2d17e0a6fc2af0d6c1d868bafa5ec80aae6e186a97fec8db07ad6af29842fbc7",
|
||||||
|
"sha256:4555438c2c4f02b39fea2ed40f6ddeda88a80cd1ee9dd129be4d5f5134698cc2",
|
||||||
|
"sha256:490cff42650733d1832728b937fe99fa1802896f5ef4d61bcf78cf7ebecb107b",
|
||||||
|
"sha256:5e342ee293b896d31da67617fe65d0bdca217af193991b0cb6052353b1e0e506",
|
||||||
|
"sha256:b361d4ac1519a2e516cabafa6bf7e93492f999f35d7d25350cd87fdc3e5cb27e"
|
||||||
|
],
|
||||||
|
"version": "==0.10.3.post1"
|
||||||
|
},
|
||||||
"toml": {
|
"toml": {
|
||||||
"hashes": [
|
"hashes": [
|
||||||
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
"sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b",
|
||||||
|
@ -1,13 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
tmp_dir=$1
|
tmp_video_dir=$1
|
||||||
number_of_files=$2
|
audio=$2
|
||||||
audio=$3
|
output_dir=$3
|
||||||
audio2=$4
|
output_file=$4
|
||||||
|
|
||||||
if [ $number_of_files != "2" ]
|
ffmpeg -y -i $tmp_video_dir/video.mp4 -i $audio -ac 1 -tune stillimage "$output_dir$output_file"
|
||||||
then
|
|
||||||
ffmpeg -i $tmp_dir/video/video.mp4 -i $audio -ac 1 -tune stillimage ./out/video-and-audio.mp4 -y
|
|
||||||
else
|
|
||||||
ffmpeg -i $tmp_dir/video/video.mp4 -i $audio -ac 1 -tune stillimage $tmp_dir/video/video_sound_one.mp4 -y
|
|
||||||
ffmpeg -i $tmp_dir/video/video_sound_one.mp4 -i $audio2 -ac 1 -tune stillimage ./out/video-and-audio.mp4 -y
|
|
||||||
fi
|
|
@ -1,5 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
tmp_dir=$1
|
tmp_video_dir=$1
|
||||||
tmp_video_dir=$2
|
|
||||||
|
|
||||||
ffmpeg -y -f concat -safe 0 -i demuxer.txt -r 30 -tune stillimage -vsync vfr -pix_fmt yuv420p $tmp_video_dir/video.mp4
|
ffmpeg -y -f concat -safe 0 -i demuxer.txt -r 30 -tune stillimage -vsync vfr -pix_fmt yuv420p $tmp_video_dir/video.mp4
|
@ -6,9 +6,9 @@ file_2=$4
|
|||||||
|
|
||||||
if [ $number_of_files != "2" ]
|
if [ $number_of_files != "2" ]
|
||||||
then
|
then
|
||||||
ffmpeg -i $file_1 -map_channel 0.0.0 $tmp_dir/left.wav -map_channel 0.0.1 $tmp_dir/right.wav
|
ffmpeg -i $file_1 -map_channel 0.0.0 $tmp_dir/left.wav -map_channel 0.0.1 $tmp_dir/right.wav -y
|
||||||
else
|
else
|
||||||
ffmpeg -i $file_1 -map_channel 0.0.0 $tmp_dir/left.wav
|
ffmpeg -i $file_1 -map_channel 0.0.0 $tmp_dir/left.wav -y
|
||||||
ffmpeg -i $file_2 -map_channel 0.0.1 $tmp_dir/right.wav
|
ffmpeg -i $file_2 -map_channel 0.0.1 $tmp_dir/right.wav -y
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import math
|
import math
|
||||||
from find_loudness import process_find_loudness
|
from find_loudness import process_find_loudness
|
||||||
|
|
||||||
graph_density = 8000
|
graph_density = 44100
|
||||||
threshold_at_point = 1
|
threshold_at_point = 1
|
||||||
inertia_s = 0.3
|
inertia_s = 0.3
|
||||||
inertia_samples = inertia_s * graph_density
|
inertia_samples = inertia_s * graph_density
|
||||||
|
out_demuxer = 'demuxer.txt'
|
||||||
|
|
||||||
|
|
||||||
def set_up_threshold(new_value: int):
|
def set_up_threshold(new_value: int):
|
||||||
@ -64,8 +65,7 @@ def mode_to_string(mode):
|
|||||||
|
|
||||||
def run(tmp_dir):
|
def run(tmp_dir):
|
||||||
"""Main method to run generating demuxer.txt"""
|
"""Main method to run generating demuxer.txt"""
|
||||||
global inertia_samples
|
global inertia_samples, out_demuxer
|
||||||
out_demuxer = 'demuxer.txt'
|
|
||||||
|
|
||||||
with open(out_demuxer, 'w') as demuxer:
|
with open(out_demuxer, 'w') as demuxer:
|
||||||
# Execute process_find_loudness for left and right side
|
# Execute process_find_loudness for left and right side
|
||||||
@ -84,9 +84,9 @@ def run(tmp_dir):
|
|||||||
print("RIGHT:", right_loudness)
|
print("RIGHT:", right_loudness)
|
||||||
|
|
||||||
merged = [*left_loudness, *right_loudness]
|
merged = [*left_loudness, *right_loudness]
|
||||||
print(merged)
|
# print(merged)
|
||||||
sorted_list = sorted(merged, key=lambda x: x['position_start'])
|
sorted_list = sorted(merged, key=lambda x: x['position_start'])
|
||||||
print(sorted_list)
|
# print(sorted_list)
|
||||||
demuxer.write(F"file {tmp_dir}/pics/none.png\n")
|
demuxer.write(F"file {tmp_dir}/pics/none.png\n")
|
||||||
|
|
||||||
last_point = 0
|
last_point = 0
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
|
<qresource prefix="font">
|
||||||
|
<file>src/gui/fonts/Raleway/Raleway-Medium.ttf</file>
|
||||||
|
</qresource>
|
||||||
|
|
||||||
<qresource prefix="left">
|
<qresource prefix="left">
|
||||||
<file>src/gui/images/left.png</file>
|
<file>src/gui/images/left.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
@ -33,6 +37,15 @@
|
|||||||
<file>src/gui/images/icons/import.png</file>
|
<file>src/gui/images/icons/import.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
|
||||||
|
<qresource prefix="video-icons">
|
||||||
|
<file>src/gui/images/icons/control.png</file>
|
||||||
|
<file>src/gui/images/icons/control-pause.png</file>
|
||||||
|
<file>src/gui/images/icons/control-skip.png</file>
|
||||||
|
<file>src/gui/images/icons/control-skip-180.png</file>
|
||||||
|
<file>src/gui/images/icons/control-stop-square.png</file>
|
||||||
|
<file>src/gui/images/icons/speaker-volume.png</file>
|
||||||
|
</qresource>
|
||||||
|
|
||||||
<qresource prefix="favicon">
|
<qresource prefix="favicon">
|
||||||
<file>src/gui/images/icons/32x32.png</file>
|
<file>src/gui/images/icons/32x32.png</file>
|
||||||
<file>src/gui/images/icons/45x45.png</file>
|
<file>src/gui/images/icons/45x45.png</file>
|
||||||
|
178615
resources_rc.py
93
src/gui/fonts/Raleway/OFL.txt
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
Copyright 2010 The Raleway Project Authors (impallari@gmail.com), with Reserved Font Name "Raleway".
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
81
src/gui/fonts/Raleway/README.txt
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
Raleway Variable Font
|
||||||
|
=====================
|
||||||
|
|
||||||
|
This download contains Raleway as both variable fonts and static fonts.
|
||||||
|
|
||||||
|
Raleway is a variable font with this axis:
|
||||||
|
wght
|
||||||
|
|
||||||
|
This means all the styles are contained in these files:
|
||||||
|
Raleway-VariableFont_wght.ttf
|
||||||
|
Raleway-Italic-VariableFont_wght.ttf
|
||||||
|
|
||||||
|
If your app fully supports variable fonts, you can now pick intermediate styles
|
||||||
|
that aren’t available as static fonts. Not all apps support variable fonts, and
|
||||||
|
in those cases you can use the static font files for Raleway:
|
||||||
|
static/Raleway-Thin.ttf
|
||||||
|
static/Raleway-ExtraLight.ttf
|
||||||
|
static/Raleway-Light.ttf
|
||||||
|
static/Raleway-Regular.ttf
|
||||||
|
static/Raleway-Medium.ttf
|
||||||
|
static/Raleway-SemiBold.ttf
|
||||||
|
static/Raleway-Bold.ttf
|
||||||
|
static/Raleway-ExtraBold.ttf
|
||||||
|
static/Raleway-Black.ttf
|
||||||
|
static/Raleway-ThinItalic.ttf
|
||||||
|
static/Raleway-ExtraLightItalic.ttf
|
||||||
|
static/Raleway-LightItalic.ttf
|
||||||
|
static/Raleway-Italic.ttf
|
||||||
|
static/Raleway-MediumItalic.ttf
|
||||||
|
static/Raleway-SemiBoldItalic.ttf
|
||||||
|
static/Raleway-BoldItalic.ttf
|
||||||
|
static/Raleway-ExtraBoldItalic.ttf
|
||||||
|
static/Raleway-BlackItalic.ttf
|
||||||
|
|
||||||
|
Get started
|
||||||
|
-----------
|
||||||
|
|
||||||
|
1. Install the font files you want to use
|
||||||
|
|
||||||
|
2. Use your app's font picker to view the font family and all the
|
||||||
|
available styles
|
||||||
|
|
||||||
|
Learn more about variable fonts
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
|
||||||
|
https://variablefonts.typenetwork.com
|
||||||
|
https://medium.com/variable-fonts
|
||||||
|
|
||||||
|
In desktop apps
|
||||||
|
|
||||||
|
https://theblog.adobe.com/can-variable-fonts-illustrator-cc
|
||||||
|
https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
|
||||||
|
|
||||||
|
Online
|
||||||
|
|
||||||
|
https://developers.google.com/fonts/docs/getting_started
|
||||||
|
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
|
||||||
|
https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
|
||||||
|
|
||||||
|
Installing fonts
|
||||||
|
|
||||||
|
MacOS: https://support.apple.com/en-us/HT201749
|
||||||
|
Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
|
||||||
|
Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
|
||||||
|
|
||||||
|
Android Apps
|
||||||
|
|
||||||
|
https://developers.google.com/fonts/docs/android
|
||||||
|
https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
Please read the full license text (OFL.txt) to understand the permissions,
|
||||||
|
restrictions and requirements for usage, redistribution, and modification.
|
||||||
|
|
||||||
|
You can use them freely in your products & projects - print or digital,
|
||||||
|
commercial or otherwise. However, you can't sell the fonts on their own.
|
||||||
|
|
||||||
|
This isn't legal advice, please consider consulting a lawyer and see the full
|
||||||
|
license for all details.
|
BIN
src/gui/fonts/Raleway/Raleway-Italic-VariableFont_wght.ttf
Normal file
BIN
src/gui/fonts/Raleway/Raleway-Medium.ttf
Normal file
BIN
src/gui/fonts/Raleway/Raleway-VariableFont_wght.ttf
Normal file
BIN
src/gui/images/icons/application-image.png
Executable file
After Width: | Height: | Size: 544 B |
BIN
src/gui/images/icons/control-pause.png
Executable file
After Width: | Height: | Size: 427 B |
BIN
src/gui/images/icons/control-skip-180.png
Executable file
After Width: | Height: | Size: 577 B |
BIN
src/gui/images/icons/control-skip.png
Executable file
After Width: | Height: | Size: 572 B |
BIN
src/gui/images/icons/control-stop-square.png
Executable file
After Width: | Height: | Size: 411 B |
BIN
src/gui/images/icons/control.png
Executable file
After Width: | Height: | Size: 470 B |
BIN
src/gui/images/icons/speaker-volume.png
Executable file
After Width: | Height: | Size: 566 B |
@ -10,6 +10,12 @@
|
|||||||
<height>807</height>
|
<height>807</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>800</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>MagicPodcast</string>
|
<string>MagicPodcast</string>
|
||||||
</property>
|
</property>
|
||||||
@ -185,8 +191,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>300</width>
|
<width>400</width>
|
||||||
<height>150</height>
|
<height>16777215</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="frameShape">
|
<property name="frameShape">
|
||||||
@ -222,7 +228,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>16777215</width>
|
<width>400</width>
|
||||||
<height>35</height>
|
<height>35</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
@ -271,8 +277,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>300</width>
|
<width>400</width>
|
||||||
<height>150</height>
|
<height>16777215</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="frameShape">
|
<property name="frameShape">
|
||||||
@ -308,7 +314,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>16777215</width>
|
<width>400</width>
|
||||||
<height>35</height>
|
<height>35</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
@ -361,8 +367,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>300</width>
|
<width>400</width>
|
||||||
<height>150</height>
|
<height>16777215</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="frameShape">
|
<property name="frameShape">
|
||||||
@ -401,7 +407,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>16777215</width>
|
<width>400</width>
|
||||||
<height>35</height>
|
<height>35</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
@ -450,8 +456,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>300</width>
|
<width>400</width>
|
||||||
<height>150</height>
|
<height>16777215</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="frameShape">
|
<property name="frameShape">
|
||||||
@ -487,7 +493,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>16777215</width>
|
<width>400</width>
|
||||||
<height>35</height>
|
<height>35</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>PreviewDialog</class>
|
<class>PreviewCreatorDialog</class>
|
||||||
<widget class="QDialog" name="PreviewDialog">
|
<widget class="QDialog" name="PreviewCreatorDialog">
|
||||||
<property name="windowModality">
|
<property name="windowModality">
|
||||||
<enum>Qt::NonModal</enum>
|
<enum>Qt::NonModal</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -9,8 +9,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>779</width>
|
<width>584</width>
|
||||||
<height>356</height>
|
<height>422</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -22,17 +22,40 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="v_layout_1"/>
|
<layout class="QVBoxLayout" name="playlist_v_layout">
|
||||||
|
<item>
|
||||||
|
<widget class="QListView" name="playlistView">
|
||||||
|
<property name="acceptDrops">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="showDropIndicator" stdset="0">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="dragDropMode">
|
||||||
|
<enum>QAbstractItemView::DropOnly</enum>
|
||||||
|
</property>
|
||||||
|
<property name="defaultDropAction">
|
||||||
|
<enum>Qt::CopyAction</enum>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="uniformItemSizes">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line_2">
|
<widget class="Line" name="line">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="h_layout_range_values">
|
<layout class="QHBoxLayout" name="range_values_h_layout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="left_label">
|
<widget class="QLabel" name="left_label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -41,7 +64,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="left_range">
|
<widget class="QLineEdit" name="left_range_line_edit">
|
||||||
<property name="inputMethodHints">
|
<property name="inputMethodHints">
|
||||||
<set>Qt::ImhPreferNumbers|Qt::ImhTime</set>
|
<set>Qt::ImhPreferNumbers|Qt::ImhTime</set>
|
||||||
</property>
|
</property>
|
||||||
@ -55,7 +78,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="right_range">
|
<widget class="QLineEdit" name="right_range_line_edit">
|
||||||
<property name="inputMethodHints">
|
<property name="inputMethodHints">
|
||||||
<set>Qt::ImhPreferNumbers|Qt::ImhTime</set>
|
<set>Qt::ImhPreferNumbers|Qt::ImhTime</set>
|
||||||
</property>
|
</property>
|
||||||
@ -71,29 +94,18 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line">
|
<widget class="QLabel" name="log_label">
|
||||||
<property name="orientation">
|
<property name="text">
|
||||||
<enum>Qt::Horizontal</enum>
|
<string>TextLabel</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<widget class="QProgressBar" name="progress_bar">
|
||||||
<item>
|
<property name="value">
|
||||||
<widget class="QPushButton" name="play_button">
|
<number>0</number>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Start</string>
|
</widget>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="stop_button">
|
|
||||||
<property name="text">
|
|
||||||
<string>Stop</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
164
src/gui/ui/video_player_dialog.ui
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>VideoPlayerDialog</class>
|
||||||
|
<widget class="QDialog" name="VideoPlayerDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>640</width>
|
||||||
|
<height>480</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="video_v_layout"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="time_h_layout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="current_time_label">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>0:00</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="time_slider">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="total_time_label">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>0:00</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="buttons_h_layout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="previous_button">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../resources.qrc">
|
||||||
|
<normaloff>:/video-icons/src/gui/images/icons/control-skip-180.png</normaloff>:/video-icons/src/gui/images/icons/control-skip-180.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="play_button">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../resources.qrc">
|
||||||
|
<normaloff>:/video-icons/src/gui/images/icons/control.png</normaloff>:/video-icons/src/gui/images/icons/control.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pause_button">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../resources.qrc">
|
||||||
|
<normaloff>:/video-icons/src/gui/images/icons/control-pause.png</normaloff>:/video-icons/src/gui/images/icons/control-pause.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="stop_button">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../resources.qrc">
|
||||||
|
<normaloff>:/video-icons/src/gui/images/icons/control-stop-square.png</normaloff>:/video-icons/src/gui/images/icons/control-stop-square.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="next_button">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="../../../resources.qrc">
|
||||||
|
<normaloff>:/video-icons/src/gui/images/icons/control-skip.png</normaloff>:/video-icons/src/gui/images/icons/control-skip.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="h_spacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="volume_label">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../../../resources.qrc">:/video-icons/src/gui/images/icons/speaker-volume.png</pixmap>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="volume_slider">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="../../../resources.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -2,21 +2,24 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pydub.utils import mediainfo
|
from pydub.utils import mediainfo
|
||||||
from pydub.audio_segment import AudioSegment
|
from pydub.audio_segment import AudioSegment
|
||||||
|
|
||||||
# import resources_rc
|
# import resources_rc
|
||||||
from PyQt5.QtCore import Qt
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtGui import QPixmap
|
from PyQt5.QtGui import QPixmap
|
||||||
from PyQt5.QtWidgets import QMainWindow, QLabel, QFileDialog, QDialog, QDialogButtonBox, QVBoxLayout, QApplication
|
from PyQt5.QtWidgets import QMainWindow, QLabel, QFileDialog, QDialog, QDialogButtonBox,\
|
||||||
|
QVBoxLayout, QApplication
|
||||||
|
|
||||||
|
|
||||||
from src.python.classes.settings_dialog import SettingsDialog
|
from src.python.classes.settings_dialog import SettingsDialog
|
||||||
from src.python.ui.mainwindow_ui import Ui_MainWindow
|
from src.python.ui.mainwindow_ui import Ui_MainWindow
|
||||||
|
|
||||||
from src.python.classes.translate import Translator
|
from src.python.classes.translate import Translator
|
||||||
from src.python.classes.preview_dialog import PreviewDialog
|
from src.python.classes.preview_creator_dialog import PreviewCreatorDialog
|
||||||
|
|
||||||
import generate_demuxer
|
import generate_demuxer
|
||||||
|
|
||||||
@ -25,6 +28,7 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
|
|||||||
"""
|
"""
|
||||||
MainWindow Class
|
MainWindow Class
|
||||||
"""
|
"""
|
||||||
|
podcast_preview_crated_signal = pyqtSignal(str)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super(MainWindow, self).__init__(parent=parent)
|
super(MainWindow, self).__init__(parent=parent)
|
||||||
@ -34,10 +38,11 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
|
|||||||
self.lang = 'pl'
|
self.lang = 'pl'
|
||||||
self.translator.load_lang(self.lang)
|
self.translator.load_lang(self.lang)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.setup_logic()
|
|
||||||
self.setup_detail()
|
self.setup_detail()
|
||||||
|
self.output_dir = './out/'
|
||||||
self.retranslateUi(self.window())
|
self.retranslateUi(self.window())
|
||||||
self.aresample = "8000"
|
self.aresample = "44100"
|
||||||
|
|
||||||
self.image_extensions = ['.jpg', '.png']
|
self.image_extensions = ['.jpg', '.png']
|
||||||
self.audio_extensions = ['.mp3', '.wav']
|
self.audio_extensions = ['.mp3', '.wav']
|
||||||
@ -48,15 +53,18 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
|
|||||||
title='Process generowania podcastu',
|
title='Process generowania podcastu',
|
||||||
msg='Sprawdzanie poprawności danych'
|
msg='Sprawdzanie poprawności danych'
|
||||||
)
|
)
|
||||||
|
self.preview_creator_dialog = PreviewCreatorDialog(self)
|
||||||
|
self.tmp_working_directory = tempfile.TemporaryDirectory()
|
||||||
self.log_label.hide()
|
self.log_label.hide()
|
||||||
|
self.setup_detail()
|
||||||
|
self.setup_logic()
|
||||||
self.test_data(option=2)
|
self.test_data(option=2)
|
||||||
|
|
||||||
def setup_logic(self):
|
def setup_logic(self):
|
||||||
"""Connect ui elements with methods."""
|
"""Connect ui elements with methods."""
|
||||||
self.action_settings.triggered.connect(self.open_setting_dialog)
|
self.action_settings.triggered.connect(self.open_setting_dialog)
|
||||||
self.button_generate.clicked.connect(self.generate_video_podcast)
|
self.button_generate.clicked.connect(self.generate_video_podcast)
|
||||||
self.button_preview.clicked.connect(self.preview_video_podcast)
|
self.button_preview.clicked.connect(self.show_preview_creator_dialog)
|
||||||
self.button_audio_1.clicked.connect(lambda: self.open_audio_import(audio_number=1))
|
self.button_audio_1.clicked.connect(lambda: self.open_audio_import(audio_number=1))
|
||||||
self.button_audio_2.clicked.connect(lambda: self.open_audio_import(audio_number=2))
|
self.button_audio_2.clicked.connect(lambda: self.open_audio_import(audio_number=2))
|
||||||
self.button_select_avatar_1.clicked.connect(lambda: self.open_image_import(image_number=1))
|
self.button_select_avatar_1.clicked.connect(lambda: self.open_image_import(image_number=1))
|
||||||
@ -67,6 +75,8 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
|
|||||||
self.connected_channels_status = self.check_box_connected_channels.checkState()
|
self.connected_channels_status = self.check_box_connected_channels.checkState()
|
||||||
self.check_box_connected_channels.stateChanged.connect(self.channels_connected)
|
self.check_box_connected_channels.stateChanged.connect(self.channels_connected)
|
||||||
self.threshold_slider.valueChanged.connect(self.update_lcd_threshold)
|
self.threshold_slider.valueChanged.connect(self.update_lcd_threshold)
|
||||||
|
self.preview_creator_dialog.preview_generate_signal.connect(self.generate_video_podcast)
|
||||||
|
self.podcast_preview_crated_signal.connect(self.preview_creator_dialog.add_element_to_list)
|
||||||
|
|
||||||
def on_progress_change(self, value):
|
def on_progress_change(self, value):
|
||||||
"""Update progress bar value"""
|
"""Update progress bar value"""
|
||||||
@ -247,50 +257,30 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
|
|||||||
self.line_edit_audio_2.setDisabled(False)
|
self.line_edit_audio_2.setDisabled(False)
|
||||||
self.line_edit_audio_1.setPlaceholderText("Plik audio 1 rozmówcy")
|
self.line_edit_audio_1.setPlaceholderText("Plik audio 1 rozmówcy")
|
||||||
|
|
||||||
def preview_video_podcast(self):
|
def show_preview_creator_dialog(self):
|
||||||
"""Preview Video Podcast"""
|
"""Preview Podcast Creator"""
|
||||||
|
total_time = 0
|
||||||
|
try:
|
||||||
|
threshold_value, connected_channels, audio_files, image_files, total_time = self.collect_data_files()
|
||||||
|
|
||||||
if not self.check_box_connected_channels.isChecked():
|
print(f"End time: {total_time}")
|
||||||
audio_files = [self.line_edit_audio_1.text(), self.line_edit_audio_2.text()]
|
|
||||||
|
|
||||||
if not all(self.check_file(x, self.audio_extensions) for x in audio_files):
|
self.preview_creator_dialog.total_time_changed(total_time=int(total_time))
|
||||||
return -1
|
self.preview_creator_dialog.show()
|
||||||
|
|
||||||
self.line_edit_audio_1.setProperty(
|
except Exception as err:
|
||||||
'duration', mediainfo(self.line_edit_audio_1.text())['duration'])
|
print(err)
|
||||||
|
return -1
|
||||||
|
|
||||||
self.line_edit_audio_2.setProperty(
|
def collect_data_files(self):
|
||||||
'duration', mediainfo(self.line_edit_audio_2.text())['duration'])
|
""" Collect data from ui."""
|
||||||
|
demuxer_file = Path('./demuxer.txt')
|
||||||
|
if demuxer_file.is_file():
|
||||||
|
shutil.rmtree(demuxer_file, ignore_errors=True)
|
||||||
|
if not Path(self.tmp_working_directory.name).is_dir():
|
||||||
|
self.tmp_working_directory = tempfile.TemporaryDirectory()
|
||||||
|
|
||||||
audio_1 = float(self.line_edit_audio_1.property('duration'))
|
|
||||||
print(audio_1)
|
|
||||||
audio_2 = float(self.line_edit_audio_2.property('duration'))
|
|
||||||
|
|
||||||
print(f"[*] File duration audio_1: {audio_1}")
|
|
||||||
print(f"[*] File duration audio_2: {audio_2}")
|
|
||||||
|
|
||||||
end_time = audio_1 if audio_1 >= audio_2 else audio_2
|
|
||||||
preview_dialog = PreviewDialog(parent=self, start_time=0, end_time=end_time)
|
|
||||||
else:
|
|
||||||
audio_files = [self.line_edit_audio_1.text()]
|
|
||||||
if not all(self.check_file(x, self.audio_extensions) for x in audio_files):
|
|
||||||
return -1
|
|
||||||
|
|
||||||
self.line_edit_audio_1.setProperty(
|
|
||||||
'duration', mediainfo(self.line_edit_audio_1.text())['duration'])
|
|
||||||
|
|
||||||
end_time = float(self.line_edit_audio_1.property('duration'))
|
|
||||||
print(f"[*] File duration audio_2: {end_time}")
|
|
||||||
preview_dialog = PreviewDialog(parent=self, start_time=0, end_time=end_time)
|
|
||||||
|
|
||||||
preview_dialog.exec_()
|
|
||||||
|
|
||||||
def generate_video_podcast(self, start=None, end=None):
|
|
||||||
"""Generate podcast based on values from UI."""
|
|
||||||
self.progress_bar.setValue(0)
|
|
||||||
threshold_value = int(self.threshold_lcd.value())
|
threshold_value = int(self.threshold_lcd.value())
|
||||||
generate_demuxer.set_up_threshold(threshold_value)
|
|
||||||
|
|
||||||
connected_channels = self.check_box_connected_channels.isChecked()
|
connected_channels = self.check_box_connected_channels.isChecked()
|
||||||
print(F"Channels connected: {connected_channels}")
|
print(F"Channels connected: {connected_channels}")
|
||||||
# Setup images
|
# Setup images
|
||||||
@ -304,7 +294,7 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
|
|||||||
for image_path in image_files.values():
|
for image_path in image_files.values():
|
||||||
if not self.check_file(image_path, self.image_extensions):
|
if not self.check_file(image_path, self.image_extensions):
|
||||||
self.create_custom_dialog(title='Błąd!', msg="Tworzenie podcastu zostało przerwane.")
|
self.create_custom_dialog(title='Błąd!', msg="Tworzenie podcastu zostało przerwane.")
|
||||||
return -1
|
raise FileNotFoundError
|
||||||
|
|
||||||
audio_files = []
|
audio_files = []
|
||||||
if not connected_channels:
|
if not connected_channels:
|
||||||
@ -315,121 +305,192 @@ class MainWindow(QMainWindow, QApplication, Ui_MainWindow):
|
|||||||
audio_files.append({'file': self.line_edit_audio_1.text()})
|
audio_files.append({'file': self.line_edit_audio_1.text()})
|
||||||
|
|
||||||
for audio_path in audio_files:
|
for audio_path in audio_files:
|
||||||
|
print(audio_path)
|
||||||
if not Path(audio_path['file']).is_file():
|
if not Path(audio_path['file']).is_file():
|
||||||
if not self.check_file(audio_path['file'], self.audio_extensions):
|
if not self.check_file(audio_path['file'], self.audio_extensions):
|
||||||
self.create_custom_dialog(title='Błąd!', msg="Tworzenie podcastu zostało przerwane.")
|
self.create_custom_dialog(title='Błąd!', msg="Tworzenie podcastu zostało przerwane.")
|
||||||
return -1
|
raise FileNotFoundError
|
||||||
|
|
||||||
# Split name and extension of the file
|
# Split name and extension of the file
|
||||||
for dictionary in audio_files:
|
for dictionary in audio_files:
|
||||||
dictionary['ext'] = dictionary['file'].rsplit('.')[-1]
|
dictionary['ext'] = dictionary['file'].rsplit('.')[-1]
|
||||||
|
|
||||||
self.progress_bar.setValue(10)
|
self.preview_creator_dialog.log_label.show()
|
||||||
with tempfile.TemporaryDirectory() as tmp_dir_name:
|
self.log_label.setText(f'[*] Create temporary directory: {self.tmp_working_directory}')
|
||||||
tmp_dir_name = './tmp_dir' + tmp_dir_name
|
|
||||||
#os.mkdir('./tmp_dir/tmp')
|
|
||||||
os.mkdir(tmp_dir_name)
|
|
||||||
self.log_label.show()
|
|
||||||
self.log_label.setText(f'[*] Create temporary directory: {tmp_dir_name}')
|
|
||||||
tmp_out_dir = tmp_dir_name + "/out"
|
|
||||||
pics_dir = tmp_dir_name + "/pics"
|
|
||||||
audio_dir = tmp_dir_name + "/audio"
|
|
||||||
video_dir = tmp_dir_name + "/video"
|
|
||||||
|
|
||||||
self.progress_bar.setValue(15)
|
self.tmp_out_dir = self.tmp_working_directory.name + "/out"
|
||||||
self.log_label.setText(f"[!] Create tmp out dir: {tmp_out_dir}")
|
self.pics_dir = self.tmp_working_directory.name + "/pics"
|
||||||
os.mkdir(tmp_out_dir)
|
self.audio_dir = self.tmp_working_directory.name + "/audio"
|
||||||
|
self.video_dir = self.tmp_working_directory.name + "/video"
|
||||||
|
|
||||||
self.log_label.setText(f"[*] Create pics dir: {pics_dir}")
|
# self.progress_bar.setValue(15)
|
||||||
os.mkdir(pics_dir)
|
self.log_label.setText(f"[!] Create tmp out dir: {self.tmp_out_dir}")
|
||||||
|
|
||||||
self.log_label.setText(f"[*] Create audio dir: {audio_dir}")
|
if not Path(self.tmp_out_dir).is_dir():
|
||||||
os.mkdir(audio_dir)
|
os.mkdir(self.tmp_out_dir)
|
||||||
|
|
||||||
self.log_label.setText(f"[*] Create video dir: {video_dir}")
|
self.log_label.setText(f"[*] Create pics dir: {self.pics_dir}")
|
||||||
os.mkdir(video_dir)
|
if not Path(self.pics_dir).is_dir():
|
||||||
|
os.mkdir(self.pics_dir)
|
||||||
|
|
||||||
self.log_label.setText(f"[*] Copy images to {pics_dir}")
|
self.log_label.setText(f"[*] Create audio dir: {self.audio_dir}")
|
||||||
shutil.copy(image_files['both'], pics_dir + "/both.png")
|
if not Path(self.audio_dir).is_dir():
|
||||||
shutil.copy(image_files['none'], pics_dir + "/none.png")
|
os.mkdir(self.audio_dir)
|
||||||
shutil.copy(image_files['left'], pics_dir + "/left.png")
|
|
||||||
shutil.copy(image_files['right'], pics_dir + "/right.png")
|
|
||||||
|
|
||||||
self.progress_bar.setValue(20)
|
self.log_label.setText(f"[*] Create video dir: {self.video_dir}")
|
||||||
self.log_label.setText(f"[*] Copy audio to {audio_dir}")
|
if not Path(self.video_dir).is_dir():
|
||||||
if not connected_channels:
|
os.mkdir(self.video_dir)
|
||||||
audio_files[0]['tmp'] = audio_dir + "/left_channel" + "." + audio_files[0]['ext']
|
|
||||||
audio_files[1]['tmp'] = audio_dir + "/right_channel" + "." + audio_files[1]['ext']
|
|
||||||
|
|
||||||
audio_files[0]['duration'] = mediainfo(audio_files[0]['file'])['duration']
|
self.log_label.setText(f"[*] Copy images to {self.pics_dir}")
|
||||||
audio_files[1]['duration'] = mediainfo(audio_files[1]['file'])['duration']
|
shutil.copy(image_files['both'], self.pics_dir + "/both.png")
|
||||||
|
shutil.copy(image_files['none'], self.pics_dir + "/none.png")
|
||||||
|
shutil.copy(image_files['left'], self.pics_dir + "/left.png")
|
||||||
|
shutil.copy(image_files['right'], self.pics_dir + "/right.png")
|
||||||
|
|
||||||
shutil.copy(audio_files[0]['file'], audio_files[0]['tmp'])
|
# self.progress_bar.setValue(20)
|
||||||
shutil.copy(audio_files[1]['file'], audio_files[1]['tmp'])
|
self.log_label.setText(f"[*] Copy audio to {self.audio_dir}")
|
||||||
|
|
||||||
else:
|
total_time = 0
|
||||||
audio_files[0]['tmp'] = audio_dir + "/both_channel" + "." + audio_files[0]['ext']
|
if not connected_channels:
|
||||||
audio_files[0]['duration'] = mediainfo(audio_files[0]['file'])['duration']
|
audio_files[0]['tmp'] = self.audio_dir + "/left_channel" + "." + audio_files[0]['ext']
|
||||||
shutil.copy(audio_files[0]['file'], audio_files[0]['tmp'])
|
audio_files[1]['tmp'] = self.audio_dir + "/right_channel" + "." + audio_files[1]['ext']
|
||||||
|
|
||||||
print(f'[*] Images in {pics_dir}: {os.listdir(pics_dir)}')
|
for num, audio in enumerate(audio_files):
|
||||||
print(f'[*] Audo files in {audio_dir}: {os.listdir(audio_dir)}')
|
audio['duration'] = float(mediainfo(audio['file'])['duration'])
|
||||||
|
shutil.copy(audio['file'], audio['tmp'])
|
||||||
|
total_time = audio['duration'] if total_time < audio['duration'] else total_time
|
||||||
|
print(f"[*] File duration audio {num}: {audio['duration']}")
|
||||||
|
|
||||||
self.progress_bar.setValue(25)
|
else:
|
||||||
subprocess.check_output(["echo", tmp_dir_name]).decode('utf-8')
|
for num, audio in enumerate(audio_files):
|
||||||
|
audio['duration'] = float(mediainfo(audio['file'])['duration'])
|
||||||
|
audio['tmp'] = self.audio_dir + "/both_channel" + "." + audio['ext']
|
||||||
|
shutil.copy(audio['file'], audio['tmp'])
|
||||||
|
total_time = audio['duration'] if total_time < audio['duration'] else total_time
|
||||||
|
print(f"[*] File duration audio {num}: {audio['duration']}")
|
||||||
|
|
||||||
if connected_channels:
|
print(f'[*] Images in {self.pics_dir}: {os.listdir(self.pics_dir)}')
|
||||||
# Split channels
|
print(f'[*] Audo files in {self.audio_dir}: {os.listdir(self.audio_dir)}')
|
||||||
number_of_files = "1"
|
|
||||||
self.log_label.setText("Split audio file 1/5")
|
|
||||||
print(subprocess.check_output([
|
|
||||||
"bash", "bash_commands/split_channels_to_two_ways.sh",
|
|
||||||
audio_dir, number_of_files, audio_files[0]['tmp']
|
|
||||||
]))
|
|
||||||
else:
|
|
||||||
print(F"DUARTION {audio_files[0]['duration'], audio_files[1]['duration']}")
|
|
||||||
if float(audio_files[0]['duration']) > float(audio_files[1]['duration']):
|
|
||||||
print("LEFT")
|
|
||||||
|
|
||||||
else:
|
# self.progress_bar.setValue(25)
|
||||||
print("RIGHT")
|
|
||||||
|
|
||||||
number_of_files = "2"
|
return threshold_value, connected_channels, audio_files, image_files, total_time
|
||||||
self.log_label.setText("Copy audio files 1/5")
|
|
||||||
print(subprocess.check_output([
|
|
||||||
"bash", "bash_commands/split_channels_to_two_ways.sh",
|
|
||||||
audio_dir, number_of_files, audio_files[0]['tmp'], audio_files[1]['tmp']
|
|
||||||
]))
|
|
||||||
|
|
||||||
self.progress_bar.setValue(30)
|
def generate_video_podcast(self, output_file_name="video-and-audio.mp4", start=None, end=None):
|
||||||
self.log_label.setText(f"Create raw files 2/5")
|
"""
|
||||||
subprocess.check_output(['bash',
|
Method to generate video podcast based on collected data from ui.
|
||||||
'bash_commands/create_raw_files.sh',
|
|
||||||
audio_dir, self.aresample])
|
|
||||||
|
|
||||||
self.progress_bar.setValue(60)
|
:param start: Sets the start of the recording to the set second.
|
||||||
self.log_label.setText(f"Create demuxer 3/5")
|
:param end: Sets the end of the recording to the set second.
|
||||||
generate_demuxer.run(tmp_dir=tmp_dir_name)
|
:param output_file_name: Output name of podcast (default = video-and-audio.mp4)
|
||||||
|
If you are generating an entire podcast leave the default value in start and end arg,
|
||||||
|
otherwise the recording will be cut to the set values.
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if not output_file_name:
|
||||||
|
output_file_name = str(datetime.timestamp(datetime.utcnow())) + '_output.mp4'
|
||||||
|
|
||||||
|
threshold_value = None
|
||||||
|
connected_channels = None
|
||||||
|
audio_files = None
|
||||||
|
image_files = None
|
||||||
|
total_time = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
threshold_value, connected_channels, audio_files, image_files, total_time = self.collect_data_files()
|
||||||
|
print(audio_files)
|
||||||
|
except FileNotFoundError:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
"""Generate podcast based on values from UI."""
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
self.progress_bar.show()
|
||||||
|
|
||||||
|
if start is not None and end is not None:
|
||||||
|
for audio in audio_files:
|
||||||
|
print("Get fragment of audio files")
|
||||||
|
|
||||||
|
data = AudioSegment.from_file(audio['tmp'], format=audio['ext'])[start*1000:end*1000]
|
||||||
|
print(F"Frame rate of data:", data.frame_rate)
|
||||||
|
total_time = int(end)
|
||||||
|
data.export(out_f=audio['tmp'], format=audio['ext'])
|
||||||
|
audio['duration'] = float(mediainfo(audio['tmp'])['duration'])
|
||||||
|
|
||||||
|
if connected_channels:
|
||||||
|
# Split channels
|
||||||
|
number_of_files = "1"
|
||||||
|
self.log_label.setText("Split audio file 1/5")
|
||||||
|
subprocess.check_output([
|
||||||
|
"bash", "bash_commands/split_channels_to_two_ways.sh",
|
||||||
|
self.audio_dir, number_of_files, audio_files[0]['tmp']
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
print(F"DUARTION {audio_files[0]['duration'], audio_files[1]['duration']}")
|
||||||
|
|
||||||
|
number_of_files = "2"
|
||||||
|
self.log_label.setText("Copy audio files 1/5")
|
||||||
|
subprocess.check_output([
|
||||||
|
"bash", "bash_commands/split_channels_to_two_ways.sh",
|
||||||
|
self.audio_dir, number_of_files, audio_files[0]['tmp'], audio_files[1]['tmp']
|
||||||
|
])
|
||||||
|
|
||||||
|
self.progress_bar.setValue(30)
|
||||||
|
self.log_label.setText(f"Create raw files 2/5")
|
||||||
|
subprocess.check_output(['bash',
|
||||||
|
'bash_commands/create_raw_files.sh',
|
||||||
|
self.audio_dir, self.aresample])
|
||||||
|
|
||||||
|
self.progress_bar.setValue(60)
|
||||||
|
self.log_label.setText(f"Create demuxer 3/5")
|
||||||
|
generate_demuxer.run(tmp_dir=self.tmp_working_directory.name)
|
||||||
|
|
||||||
|
self.log_label.setText(f"Create video 4/5")
|
||||||
|
|
||||||
|
subprocess.check_output(
|
||||||
|
['bash', 'bash_commands/generate_video_by_demuxer.sh', self.video_dir])
|
||||||
|
|
||||||
|
self.progress_bar.setValue(75)
|
||||||
|
self.log_label.setText(f"Create final podcast 5/5")
|
||||||
|
|
||||||
|
if connected_channels:
|
||||||
|
|
||||||
self.log_label.setText(f"Create video 4/5")
|
|
||||||
subprocess.check_output(
|
subprocess.check_output(
|
||||||
['bash', 'bash_commands/generate_video_by_demuxer.sh', tmp_dir_name, video_dir])
|
['bash', 'bash_commands/connect_sound.sh', self.video_dir, audio_files[0]['tmp'], self.output_dir, output_file_name])
|
||||||
|
self.progress_bar.setValue(100)
|
||||||
|
else:
|
||||||
|
left_channel = None
|
||||||
|
right_channel = None
|
||||||
|
stereo = None
|
||||||
|
|
||||||
self.progress_bar.setValue(75)
|
if audio_files[0]['tmp'].endswith('.mp3'):
|
||||||
self.log_label.setText(f"Create final podcast 5/5")
|
print(1)
|
||||||
if connected_channels:
|
left_channel = AudioSegment.from_mp3(audio_files[0]['tmp']).set_channels(1)
|
||||||
subprocess.check_output(
|
|
||||||
['bash', 'bash_commands/connect_sound.sh', tmp_dir_name, "1", audio_files[0]['file']])
|
|
||||||
self.progress_bar.setValue(100)
|
|
||||||
else:
|
else:
|
||||||
print("IAM HEEEEERERERERERER")
|
left_channel = AudioSegment.from_wav(audio_files[0]['tmp']).set_channels(1)
|
||||||
subprocess.check_output(
|
|
||||||
['bash', 'bash_commands/connect_sound.sh', tmp_dir_name, "2", audio_files[0]['file'], audio_files[1]['file']])
|
|
||||||
self.progress_bar.setValue(100)
|
|
||||||
|
|
||||||
dialog_done = self.create_custom_dialog(title="Informacja", msg="Zakończono generowanie podcastu.")
|
if audio_files[1]['tmp'].endswith('.mp3'):
|
||||||
dialog_done.exec_()
|
print(3)
|
||||||
self.progress_bar.setValue(0)
|
right_channel = AudioSegment.from_mp3(audio_files[1]['tmp']).set_channels(1)
|
||||||
self.log_label.setText("")
|
|
||||||
self.log_label.hide()
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(4)
|
||||||
|
right_channel = AudioSegment.from_wav(audio_files[1]['tmp']).set_channels(1)
|
||||||
|
|
||||||
|
stereo = AudioSegment.from_mono_audiosegments(left_channel, right_channel)
|
||||||
|
stereo.export(self.audio_dir + '/channels.wav', format="wav")
|
||||||
|
|
||||||
|
print(F"{['bash', 'bash_commands/connect_sound.sh', self.video_dir, self.audio_dir + '/channels.wav', self.output_dir, output_file_name]}")
|
||||||
|
subprocess.check_output(
|
||||||
|
['bash', 'bash_commands/connect_sound.sh', self.video_dir, self.audio_dir + '/channels.wav', self.output_dir, output_file_name])
|
||||||
|
|
||||||
|
self.progress_bar.setValue(100)
|
||||||
|
|
||||||
|
if start is not None:
|
||||||
|
print(F"Emit signal podcast_preview_created with path: {self.output_dir + output_file_name}")
|
||||||
|
self.podcast_preview_crated_signal.emit(self.output_dir + output_file_name)
|
||||||
|
|
||||||
|
dialog_done = self.create_custom_dialog(title="Informacja", msg=F"Zakończono generowanie podcastu:\n{self.output_dir + output_file_name}")
|
||||||
|
dialog_done.exec_()
|
||||||
|
self.progress_bar.setValue(0)
|
||||||
|
self.log_label.setText("")
|
||||||
|
self.log_label.hide()
|
||||||
|
164
src/python/classes/preview_creator_dialog.py
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from PyQt5.QtCore import pyqtSignal, QUrl, QAbstractListModel, Qt, QFile, QFileInfo
|
||||||
|
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QMediaPlaylist
|
||||||
|
|
||||||
|
from src.python.classes.range_slider import QRangeSlider
|
||||||
|
from src.python.classes.video_player_dialog import VideoPlayerDialog, hhmmss
|
||||||
|
from src.python.ui.preview_creator_dialog_ui import Ui_PreviewCreatorDialog
|
||||||
|
from PyQt5.QtWidgets import QDialog
|
||||||
|
|
||||||
|
|
||||||
|
class PlaylistModel(QAbstractListModel):
|
||||||
|
"""
|
||||||
|
PlayListModel
|
||||||
|
"""
|
||||||
|
def __init__(self, playlist, *args, **kwargs):
|
||||||
|
super(PlaylistModel, self).__init__(*args, **kwargs)
|
||||||
|
self.playlist = playlist
|
||||||
|
|
||||||
|
def data(self, index, role):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:param index:
|
||||||
|
:param role:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if role == Qt.DisplayRole:
|
||||||
|
media = self.playlist.media(index.row())
|
||||||
|
return media.canonicalUrl().fileName()
|
||||||
|
|
||||||
|
def rowCount(self, index):
|
||||||
|
"""
|
||||||
|
Count number of rows
|
||||||
|
:param index:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
return self.playlist.mediaCount()
|
||||||
|
|
||||||
|
|
||||||
|
class PreviewCreatorDialog(QDialog, Ui_PreviewCreatorDialog):
|
||||||
|
"""
|
||||||
|
Dialog to show preview of podcast.
|
||||||
|
"""
|
||||||
|
preview_generate_signal = pyqtSignal(str, int, int)
|
||||||
|
play_signal = pyqtSignal(str)
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super(PreviewCreatorDialog, self).__init__(parent=parent)
|
||||||
|
self.setupUi(self)
|
||||||
|
|
||||||
|
# Create range slider
|
||||||
|
self.range_slider = QRangeSlider()
|
||||||
|
self.playlist_v_layout.addWidget(self.range_slider)
|
||||||
|
self.range_slider.c.range_changed.connect(self.update_line_edit_range_values)
|
||||||
|
|
||||||
|
self.left_range_line_edit.setText(str(self.range_slider.first_position))
|
||||||
|
self.right_range_line_edit.setText(str(self.range_slider.second_position))
|
||||||
|
self.create_preview_button.clicked.connect(self.generate_preview)
|
||||||
|
|
||||||
|
# Video dialog with video output
|
||||||
|
self.video_dialog = VideoPlayerDialog()
|
||||||
|
|
||||||
|
# Create playlist
|
||||||
|
self.playlist = QMediaPlaylist()
|
||||||
|
|
||||||
|
# Assignment list to player
|
||||||
|
self.video_dialog.player.setPlaylist(self.playlist)
|
||||||
|
|
||||||
|
# Create model of list from list
|
||||||
|
self.model = PlaylistModel(self.playlist)
|
||||||
|
self.playlistView.setModel(self.model)
|
||||||
|
self.playlist.currentIndexChanged.connect(self.playlist_position_changed)
|
||||||
|
selection_model = self.playlistView.selectionModel()
|
||||||
|
selection_model.selectionChanged.connect(self.playlist_selection_changed)
|
||||||
|
self.playlistView.doubleClicked.connect(self.open_dialog)
|
||||||
|
|
||||||
|
self.play_signal.connect(self.video_dialog.player.play)
|
||||||
|
self.setAcceptDrops(True)
|
||||||
|
|
||||||
|
def open_dialog(self):
|
||||||
|
""" Open video dialog """
|
||||||
|
if self.video_dialog.isHidden():
|
||||||
|
self.video_dialog.show()
|
||||||
|
self.video_dialog.player.setPlaylist(self.playlist)
|
||||||
|
|
||||||
|
def playlist_selection_changed(self, ix):
|
||||||
|
"""
|
||||||
|
Change selection on playlist in player
|
||||||
|
:param ix: index
|
||||||
|
"""
|
||||||
|
# We receive a QItemSelection from selectionChanged.
|
||||||
|
i = ix.indexes()[0].row()
|
||||||
|
self.playlist.setCurrentIndex(i)
|
||||||
|
self.video_dialog.player.playlist().setCurrentIndex(i)
|
||||||
|
|
||||||
|
def playlist_position_changed(self, i):
|
||||||
|
"""
|
||||||
|
Change podcast preview on playlist in playlistView
|
||||||
|
:param i: index
|
||||||
|
"""
|
||||||
|
if i > -1:
|
||||||
|
ix = self.model.index(i)
|
||||||
|
self.playlistView.setCurrentIndex(ix)
|
||||||
|
|
||||||
|
def add_element_to_list(self, path):
|
||||||
|
"""
|
||||||
|
Put items to playlist widget.
|
||||||
|
:param path:
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.playlist.addMedia(QMediaContent(
|
||||||
|
QUrl.fromLocalFile(QFileInfo(path).absoluteFilePath()))
|
||||||
|
)
|
||||||
|
|
||||||
|
self.model.layoutChanged.emit()
|
||||||
|
# self.play_signal.emit(path)
|
||||||
|
|
||||||
|
def dragEnterEvent(self, e):
|
||||||
|
if e.mimeData().hasUrls():
|
||||||
|
e.acceptProposedAction()
|
||||||
|
|
||||||
|
def dropEvent(self, e):
|
||||||
|
"""
|
||||||
|
:param e: DropEvent from playlist
|
||||||
|
"""
|
||||||
|
for url in e.mimeData().urls():
|
||||||
|
self.playlist.addMedia(
|
||||||
|
QMediaContent(url)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.model.layoutChanged.emit()
|
||||||
|
|
||||||
|
# If not playing, seeking to first of newly added + play.
|
||||||
|
if self.video_dialog.player.state() != QMediaPlayer.PlayingState:
|
||||||
|
i = self.playlist.mediaCount() - len(e.mimeData().urls())
|
||||||
|
self.playlist.setCurrentIndex(i)
|
||||||
|
|
||||||
|
# self.video_dialog.player.play()
|
||||||
|
|
||||||
|
def generate_preview(self):
|
||||||
|
"""Send singal to generate preview"""
|
||||||
|
generated_name = 'previews/' + str(datetime.timestamp(datetime.utcnow())) + '_preview.mp4'
|
||||||
|
print(F"signal emit {generated_name, int(self.range_slider.first_position), int(self.range_slider.second_position)}")
|
||||||
|
self.preview_generate_signal.emit(
|
||||||
|
generated_name, int(self.range_slider.first_position), int(self.range_slider.second_position))
|
||||||
|
|
||||||
|
def update_line_edit_range_values(self, x, y):
|
||||||
|
"""Update values."""
|
||||||
|
if x == 1:
|
||||||
|
self.left_range_line_edit.setText(str(y))
|
||||||
|
elif x == 2:
|
||||||
|
self.right_range_line_edit.setText(str(y))
|
||||||
|
|
||||||
|
def total_time_changed(self, total_time):
|
||||||
|
"""
|
||||||
|
:param total_time: time of fragment podcast
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
self.range_slider.setRange(0, total_time)
|
||||||
|
self.range_slider.setRangeLimit(0, total_time)
|
||||||
|
self.left_range_line_edit.setText(str(self.range_slider.first_position))
|
||||||
|
self.right_range_line_edit.setText(str(self.range_slider.second_position))
|
@ -1,106 +0,0 @@
|
|||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from PyQt5.QtMultimedia import QMediaPlayer
|
|
||||||
from PyQt5.QtMultimediaWidgets import QVideoWidget
|
|
||||||
|
|
||||||
|
|
||||||
from src.python.classes.range_slider import QRangeSlider
|
|
||||||
from src.python.ui.preview_dialog_ui import Ui_PreviewDialog
|
|
||||||
from PyQt5.QtWidgets import QDialog, QStyle
|
|
||||||
|
|
||||||
|
|
||||||
class PreviewDialog(QDialog, Ui_PreviewDialog):
|
|
||||||
"""
|
|
||||||
Dialog to show preview of podcast.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, start_time=0, end_time=15):
|
|
||||||
super(PreviewDialog, self).__init__(parent=parent)
|
|
||||||
|
|
||||||
self.setupUi(self)
|
|
||||||
self.mediaPlayer = QMediaPlayer(parent=self, flags=QMediaPlayer.VideoSurface)
|
|
||||||
|
|
||||||
self.video_widget = QVideoWidget()
|
|
||||||
self.range_slider = QRangeSlider()
|
|
||||||
self.v_layout_1.addWidget(self.video_widget)
|
|
||||||
self.v_layout_1.addWidget(self.range_slider)
|
|
||||||
|
|
||||||
self.range_slider.setRangeLimit(minimum=int(start_time), maximum=int(end_time))
|
|
||||||
self.range_slider.setRange(start=int(start_time), end=int(end_time))
|
|
||||||
|
|
||||||
self.range_slider.c.range_changed.connect(self.update_line_edit_values)
|
|
||||||
|
|
||||||
self.left_range.setText(str(self.range_slider.first_position))
|
|
||||||
self.right_range.setText(str(self.range_slider.second_position))
|
|
||||||
|
|
||||||
def update_line_edit_values(self, x, y):
|
|
||||||
"""Update values."""
|
|
||||||
if x == 1:
|
|
||||||
self.left_range.setText(str(y))
|
|
||||||
elif x == 2:
|
|
||||||
self.right_range.setText(str(y))
|
|
||||||
|
|
||||||
def get_audio_files(self):
|
|
||||||
"""Load time of audio files"""
|
|
||||||
audio_files = []
|
|
||||||
if not self.connected_channels_status:
|
|
||||||
audio_files.append({'file': self.line_edit_audio_1.text()})
|
|
||||||
audio_files.append({'file': self.line_edit_audio_2.text()})
|
|
||||||
|
|
||||||
else:
|
|
||||||
audio_files.append({'file': self.line_edit_audio_1.text()})
|
|
||||||
|
|
||||||
for audio_path in audio_files:
|
|
||||||
if not Path(audio_path['file']).is_file():
|
|
||||||
if not self.check_file(audio_path['file'], self.audio_extensions):
|
|
||||||
self.create_custom_dialog(title='Błąd!', msg="Tworzenie podcastu zostało przerwane.")
|
|
||||||
return -1
|
|
||||||
|
|
||||||
return audio_files
|
|
||||||
|
|
||||||
def setup_video_logic(self):
|
|
||||||
"""
|
|
||||||
Setup connections to events
|
|
||||||
"""
|
|
||||||
self.mediaPlayer.setVideoOutput(self.video_widget)
|
|
||||||
self.mediaPlayer.stateChanged.connect(self.media_state_changed)
|
|
||||||
self.mediaPlayer.positionChanged.connect(self.position_changed)
|
|
||||||
self.mediaPlayer.durationChanged.connect(self.duration_changed)
|
|
||||||
self.create_preview_button.connect(self.generate_podcast_preview)
|
|
||||||
|
|
||||||
def media_state_changed(self, state):
|
|
||||||
"""
|
|
||||||
:param state:
|
|
||||||
"""
|
|
||||||
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
|
|
||||||
self.playButton.setIcon(
|
|
||||||
self.style().standardIcon(QStyle.SP_MediaPause))
|
|
||||||
else:
|
|
||||||
self.playButton.setIcon(
|
|
||||||
self.style().standardIcon(QStyle.SP_MediaPlay))
|
|
||||||
|
|
||||||
def position_changed(self):
|
|
||||||
"""
|
|
||||||
Position Changed
|
|
||||||
"""
|
|
||||||
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
|
|
||||||
self.mediaPlayer.pause()
|
|
||||||
else:
|
|
||||||
self.mediaPlayer.play()
|
|
||||||
|
|
||||||
def play(self):
|
|
||||||
"""
|
|
||||||
Play
|
|
||||||
"""
|
|
||||||
if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
|
|
||||||
self.mediaPlayer.pause()
|
|
||||||
else:
|
|
||||||
self.mediaPlayer.play()
|
|
||||||
|
|
||||||
def duration_changed(self, duration):
|
|
||||||
"""
|
|
||||||
|
|
||||||
:param duration:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
self.positionSlider.setRange(0, duration)
|
|
@ -23,6 +23,8 @@ class QRangeSlider(QAbstractSlider):
|
|||||||
self.opt = QStyleOptionSlider()
|
self.opt = QStyleOptionSlider()
|
||||||
self.opt.minimum = 0
|
self.opt.minimum = 0
|
||||||
self.opt.maximum = 100
|
self.opt.maximum = 100
|
||||||
|
self.opt.singleStep = 0.1
|
||||||
|
self.minimum_between = 1
|
||||||
|
|
||||||
self.setTickPosition(QSlider.TicksAbove)
|
self.setTickPosition(QSlider.TicksAbove)
|
||||||
self.setTickInterval(1)
|
self.setTickInterval(1)
|
||||||
@ -30,10 +32,6 @@ class QRangeSlider(QAbstractSlider):
|
|||||||
self.setSizePolicy(
|
self.setSizePolicy(
|
||||||
QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed, QSizePolicy.Slider)
|
QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed, QSizePolicy.Slider)
|
||||||
)
|
)
|
||||||
self.c.range_changed.connect(self.handle_emit)
|
|
||||||
|
|
||||||
def handle_emit(self, x, y):
|
|
||||||
print(x, y)
|
|
||||||
|
|
||||||
def setRangeLimit(self, minimum: int, maximum: int):
|
def setRangeLimit(self, minimum: int, maximum: int):
|
||||||
"""Set new range limit."""
|
"""Set new range limit."""
|
||||||
@ -49,6 +47,10 @@ class QRangeSlider(QAbstractSlider):
|
|||||||
"""Get selected current range."""
|
"""Get selected current range."""
|
||||||
return self.first_position, self.second_position
|
return self.first_position, self.second_position
|
||||||
|
|
||||||
|
def checkMinBetweenRange(self, first_position: int, second_position: int):
|
||||||
|
"""Check min.range between first and last handler higher than minimal."""
|
||||||
|
return True if int(second_position) - int(first_position) >= self.minimum_between else False
|
||||||
|
|
||||||
def setTickPosition(self, position: QSlider.TickPosition):
|
def setTickPosition(self, position: QSlider.TickPosition):
|
||||||
"""Set tick position."""
|
"""Set tick position."""
|
||||||
self.opt.tickPosition = position
|
self.opt.tickPosition = position
|
||||||
@ -71,7 +73,6 @@ class QRangeSlider(QAbstractSlider):
|
|||||||
self.style().drawComplexControl(QStyle.CC_Slider, self.opt, painter)
|
self.style().drawComplexControl(QStyle.CC_Slider, self.opt, painter)
|
||||||
|
|
||||||
# Draw INTERVAL
|
# Draw INTERVAL
|
||||||
|
|
||||||
color = self.palette().color(QPalette.Highlight)
|
color = self.palette().color(QPalette.Highlight)
|
||||||
color.setAlpha(160)
|
color.setAlpha(160)
|
||||||
painter.setBrush(QBrush(color))
|
painter.setBrush(QBrush(color))
|
||||||
@ -105,7 +106,6 @@ class QRangeSlider(QAbstractSlider):
|
|||||||
painter.drawRect(selection)
|
painter.drawRect(selection)
|
||||||
|
|
||||||
# Draw first handle
|
# Draw first handle
|
||||||
|
|
||||||
self.opt.subControls = QStyle.SC_SliderHandle
|
self.opt.subControls = QStyle.SC_SliderHandle
|
||||||
self.opt.sliderPosition = self.first_position
|
self.opt.sliderPosition = self.first_position
|
||||||
self.style().drawComplexControl(QStyle.CC_Slider, self.opt, painter)
|
self.style().drawComplexControl(QStyle.CC_Slider, self.opt, painter)
|
||||||
@ -116,6 +116,7 @@ class QRangeSlider(QAbstractSlider):
|
|||||||
|
|
||||||
def mousePressEvent(self, event: QMouseEvent):
|
def mousePressEvent(self, event: QMouseEvent):
|
||||||
"""Handle mouse press event."""
|
"""Handle mouse press event."""
|
||||||
|
# print(self.first_position, self.second_position)
|
||||||
self.opt.sliderPosition = self.first_position
|
self.opt.sliderPosition = self.first_position
|
||||||
self._first_sc = self.style().hitTestComplexControl(
|
self._first_sc = self.style().hitTestComplexControl(
|
||||||
QStyle.CC_Slider, self.opt, event.pos(), self
|
QStyle.CC_Slider, self.opt, event.pos(), self
|
||||||
@ -134,15 +135,17 @@ class QRangeSlider(QAbstractSlider):
|
|||||||
0, distance, event.pos().x(), self.rect().width()
|
0, distance, event.pos().x(), self.rect().width()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Set position of first handler
|
||||||
if self._first_sc == QStyle.SC_SliderHandle:
|
if self._first_sc == QStyle.SC_SliderHandle:
|
||||||
if pos <= self.second_position:
|
if pos <= self.second_position and self.checkMinBetweenRange(pos, self.second_position):
|
||||||
self.first_position = pos
|
self.first_position = pos
|
||||||
self.c.range_changed.emit(1, pos)
|
self.c.range_changed.emit(1, pos)
|
||||||
self.update()
|
self.update()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Set position of secound handler
|
||||||
if self._second_sc == QStyle.SC_SliderHandle:
|
if self._second_sc == QStyle.SC_SliderHandle:
|
||||||
if pos >= self.first_position:
|
if pos >= self.first_position and self.checkMinBetweenRange(self.first_position, pos):
|
||||||
self.second_position = pos
|
self.second_position = pos
|
||||||
self.c.range_changed.emit(2, pos)
|
self.c.range_changed.emit(2, pos)
|
||||||
self.update()
|
self.update()
|
||||||
@ -150,17 +153,17 @@ class QRangeSlider(QAbstractSlider):
|
|||||||
|
|
||||||
def sizeHint(self):
|
def sizeHint(self):
|
||||||
""" Override sizeHint """
|
""" Override sizeHint """
|
||||||
SliderLength = 84
|
slider_length = 84
|
||||||
TickSpace = 5
|
tick_space = 5
|
||||||
|
|
||||||
w = SliderLength
|
w = slider_length
|
||||||
h = self.style().pixelMetric(QStyle.PM_SliderThickness, self.opt, self)
|
h = self.style().pixelMetric(QStyle.PM_SliderThickness, self.opt, self)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.opt.tickPosition & QSlider.TicksAbove
|
self.opt.tickPosition & QSlider.TicksAbove
|
||||||
or self.opt.tickPosition & QSlider.TicksBelow
|
or self.opt.tickPosition & QSlider.TicksBelow
|
||||||
):
|
):
|
||||||
h += TickSpace
|
h += tick_space
|
||||||
|
|
||||||
return (
|
return (
|
||||||
self.style()
|
self.style()
|
||||||
|
87
src/python/classes/video_player_dialog.py
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
from PyQt5.QtCore import QUrl
|
||||||
|
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
|
||||||
|
from PyQt5.QtMultimediaWidgets import QVideoWidget
|
||||||
|
from PyQt5.QtWidgets import QDialog, QFileDialog
|
||||||
|
from src.python.ui.video_player_dialog_ui import Ui_VideoPlayerDialog
|
||||||
|
|
||||||
|
|
||||||
|
def hhmmss(ms):
|
||||||
|
"""
|
||||||
|
:param ms: milliseconds
|
||||||
|
:return: time
|
||||||
|
"""
|
||||||
|
# s = 1000
|
||||||
|
# m = 60000
|
||||||
|
# h = 360000
|
||||||
|
h, r = divmod(ms, 36000)
|
||||||
|
m, r = divmod(r, 60000)
|
||||||
|
s, _ = divmod(r, 1000)
|
||||||
|
return ("%d:%02d:%02d" % (h, m, s)) if h else ("%d:%02d" % (m, s))
|
||||||
|
|
||||||
|
|
||||||
|
class VideoPlayerDialog(QDialog, Ui_VideoPlayerDialog):
|
||||||
|
"""
|
||||||
|
Class to create Video Player in Dialog window.
|
||||||
|
"""
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super(VideoPlayerDialog, self).__init__(parent=parent)
|
||||||
|
self.setupUi(self)
|
||||||
|
|
||||||
|
# Media player
|
||||||
|
self.player = QMediaPlayer()
|
||||||
|
# self.player.error.connect(self.error_alert)
|
||||||
|
# self.open_button.clicked.connect(self.open_file)
|
||||||
|
|
||||||
|
self.videoWidget = QVideoWidget()
|
||||||
|
self.player.setVideoOutput(self.videoWidget)
|
||||||
|
self.video_v_layout.addWidget(self.videoWidget)
|
||||||
|
|
||||||
|
self.player.durationChanged.connect(self.update_duration)
|
||||||
|
self.player.positionChanged.connect(self.update_position)
|
||||||
|
|
||||||
|
# Connect control buttons/slides for media player.
|
||||||
|
self.play_button.pressed.connect(self.player.play)
|
||||||
|
self.pause_button.pressed.connect(self.player.pause)
|
||||||
|
self.stop_button.pressed.connect(self.stop_event)
|
||||||
|
self.volume_slider.valueChanged.connect(self.player.setVolume)
|
||||||
|
self.time_slider.valueChanged.connect(self.player.setPosition)
|
||||||
|
|
||||||
|
# self.previous_button.pressed.connect(self.player.playlist().previous)
|
||||||
|
# self.next_button.pressed.connect(self.player.playlist().next)
|
||||||
|
|
||||||
|
def update_duration(self, duration):
|
||||||
|
"""
|
||||||
|
:param duration:
|
||||||
|
"""
|
||||||
|
print("[VideoPlayer] Update duration")
|
||||||
|
print("!", duration)
|
||||||
|
print("?", self.player.duration())
|
||||||
|
|
||||||
|
self.time_slider.setMaximum(duration)
|
||||||
|
|
||||||
|
if duration >= 0:
|
||||||
|
self.total_time_label.setText(hhmmss(duration))
|
||||||
|
|
||||||
|
def stop_event(self):
|
||||||
|
self.update_position(0)
|
||||||
|
self.player.stop()
|
||||||
|
|
||||||
|
def update_position(self, position):
|
||||||
|
"""
|
||||||
|
:param position:
|
||||||
|
"""
|
||||||
|
print("[VideoPlayer] Update position")
|
||||||
|
if position >= 0:
|
||||||
|
self.current_time_label.setText(hhmmss(position))
|
||||||
|
|
||||||
|
# Disable the events to prevent updating triggering a setPosition event (can cause stuttering).
|
||||||
|
self.time_slider.blockSignals(True)
|
||||||
|
self.time_slider.setValue(position)
|
||||||
|
self.time_slider.blockSignals(False)
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
print("[VideoPlayer] Hide")
|
||||||
|
self.hide()
|
||||||
|
self.update_position(0)
|
||||||
|
self.player.stop()
|
||||||
|
event.ignore()
|
@ -15,6 +15,7 @@ class Ui_MainWindow(object):
|
|||||||
def setupUi(self, MainWindow):
|
def setupUi(self, MainWindow):
|
||||||
MainWindow.setObjectName("MainWindow")
|
MainWindow.setObjectName("MainWindow")
|
||||||
MainWindow.resize(554, 807)
|
MainWindow.resize(554, 807)
|
||||||
|
MainWindow.setMaximumSize(QtCore.QSize(800, 16777215))
|
||||||
self.central_widget = QtWidgets.QWidget(MainWindow)
|
self.central_widget = QtWidgets.QWidget(MainWindow)
|
||||||
self.central_widget.setMinimumSize(QtCore.QSize(0, 0))
|
self.central_widget.setMinimumSize(QtCore.QSize(0, 0))
|
||||||
self.central_widget.setObjectName("central_widget")
|
self.central_widget.setObjectName("central_widget")
|
||||||
@ -97,7 +98,7 @@ class Ui_MainWindow(object):
|
|||||||
sizePolicy.setHeightForWidth(self.preview_label_avatar_1.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.preview_label_avatar_1.sizePolicy().hasHeightForWidth())
|
||||||
self.preview_label_avatar_1.setSizePolicy(sizePolicy)
|
self.preview_label_avatar_1.setSizePolicy(sizePolicy)
|
||||||
self.preview_label_avatar_1.setMinimumSize(QtCore.QSize(0, 150))
|
self.preview_label_avatar_1.setMinimumSize(QtCore.QSize(0, 150))
|
||||||
self.preview_label_avatar_1.setMaximumSize(QtCore.QSize(300, 150))
|
self.preview_label_avatar_1.setMaximumSize(QtCore.QSize(400, 16777215))
|
||||||
self.preview_label_avatar_1.setFrameShape(QtWidgets.QFrame.Box)
|
self.preview_label_avatar_1.setFrameShape(QtWidgets.QFrame.Box)
|
||||||
self.preview_label_avatar_1.setScaledContents(True)
|
self.preview_label_avatar_1.setScaledContents(True)
|
||||||
self.preview_label_avatar_1.setAlignment(QtCore.Qt.AlignCenter)
|
self.preview_label_avatar_1.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
@ -111,7 +112,7 @@ class Ui_MainWindow(object):
|
|||||||
sizePolicy.setHeightForWidth(self.button_select_avatar_1.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.button_select_avatar_1.sizePolicy().hasHeightForWidth())
|
||||||
self.button_select_avatar_1.setSizePolicy(sizePolicy)
|
self.button_select_avatar_1.setSizePolicy(sizePolicy)
|
||||||
self.button_select_avatar_1.setMinimumSize(QtCore.QSize(200, 35))
|
self.button_select_avatar_1.setMinimumSize(QtCore.QSize(200, 35))
|
||||||
self.button_select_avatar_1.setMaximumSize(QtCore.QSize(16777215, 35))
|
self.button_select_avatar_1.setMaximumSize(QtCore.QSize(400, 35))
|
||||||
self.button_select_avatar_1.setIcon(icon)
|
self.button_select_avatar_1.setIcon(icon)
|
||||||
self.button_select_avatar_1.setObjectName("button_select_avatar_1")
|
self.button_select_avatar_1.setObjectName("button_select_avatar_1")
|
||||||
self.w_layout_avatar_1.addWidget(self.button_select_avatar_1)
|
self.w_layout_avatar_1.addWidget(self.button_select_avatar_1)
|
||||||
@ -127,7 +128,7 @@ class Ui_MainWindow(object):
|
|||||||
sizePolicy.setHeightForWidth(self.preview_label_avatar_2.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.preview_label_avatar_2.sizePolicy().hasHeightForWidth())
|
||||||
self.preview_label_avatar_2.setSizePolicy(sizePolicy)
|
self.preview_label_avatar_2.setSizePolicy(sizePolicy)
|
||||||
self.preview_label_avatar_2.setMinimumSize(QtCore.QSize(0, 150))
|
self.preview_label_avatar_2.setMinimumSize(QtCore.QSize(0, 150))
|
||||||
self.preview_label_avatar_2.setMaximumSize(QtCore.QSize(300, 150))
|
self.preview_label_avatar_2.setMaximumSize(QtCore.QSize(400, 16777215))
|
||||||
self.preview_label_avatar_2.setFrameShape(QtWidgets.QFrame.Box)
|
self.preview_label_avatar_2.setFrameShape(QtWidgets.QFrame.Box)
|
||||||
self.preview_label_avatar_2.setScaledContents(True)
|
self.preview_label_avatar_2.setScaledContents(True)
|
||||||
self.preview_label_avatar_2.setAlignment(QtCore.Qt.AlignCenter)
|
self.preview_label_avatar_2.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
@ -141,7 +142,7 @@ class Ui_MainWindow(object):
|
|||||||
sizePolicy.setHeightForWidth(self.button_select_avatar_2.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.button_select_avatar_2.sizePolicy().hasHeightForWidth())
|
||||||
self.button_select_avatar_2.setSizePolicy(sizePolicy)
|
self.button_select_avatar_2.setSizePolicy(sizePolicy)
|
||||||
self.button_select_avatar_2.setMinimumSize(QtCore.QSize(200, 35))
|
self.button_select_avatar_2.setMinimumSize(QtCore.QSize(200, 35))
|
||||||
self.button_select_avatar_2.setMaximumSize(QtCore.QSize(16777215, 35))
|
self.button_select_avatar_2.setMaximumSize(QtCore.QSize(400, 35))
|
||||||
self.button_select_avatar_2.setIcon(icon)
|
self.button_select_avatar_2.setIcon(icon)
|
||||||
self.button_select_avatar_2.setObjectName("button_select_avatar_2")
|
self.button_select_avatar_2.setObjectName("button_select_avatar_2")
|
||||||
self.w_layout_avatar_2.addWidget(self.button_select_avatar_2)
|
self.w_layout_avatar_2.addWidget(self.button_select_avatar_2)
|
||||||
@ -160,7 +161,7 @@ class Ui_MainWindow(object):
|
|||||||
sizePolicy.setHeightForWidth(self.preview_label_avatar_3.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.preview_label_avatar_3.sizePolicy().hasHeightForWidth())
|
||||||
self.preview_label_avatar_3.setSizePolicy(sizePolicy)
|
self.preview_label_avatar_3.setSizePolicy(sizePolicy)
|
||||||
self.preview_label_avatar_3.setMinimumSize(QtCore.QSize(0, 150))
|
self.preview_label_avatar_3.setMinimumSize(QtCore.QSize(0, 150))
|
||||||
self.preview_label_avatar_3.setMaximumSize(QtCore.QSize(300, 150))
|
self.preview_label_avatar_3.setMaximumSize(QtCore.QSize(400, 16777215))
|
||||||
self.preview_label_avatar_3.setFrameShape(QtWidgets.QFrame.Box)
|
self.preview_label_avatar_3.setFrameShape(QtWidgets.QFrame.Box)
|
||||||
self.preview_label_avatar_3.setTextFormat(QtCore.Qt.RichText)
|
self.preview_label_avatar_3.setTextFormat(QtCore.Qt.RichText)
|
||||||
self.preview_label_avatar_3.setScaledContents(True)
|
self.preview_label_avatar_3.setScaledContents(True)
|
||||||
@ -175,7 +176,7 @@ class Ui_MainWindow(object):
|
|||||||
sizePolicy.setHeightForWidth(self.button_select_avatar_3.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.button_select_avatar_3.sizePolicy().hasHeightForWidth())
|
||||||
self.button_select_avatar_3.setSizePolicy(sizePolicy)
|
self.button_select_avatar_3.setSizePolicy(sizePolicy)
|
||||||
self.button_select_avatar_3.setMinimumSize(QtCore.QSize(200, 35))
|
self.button_select_avatar_3.setMinimumSize(QtCore.QSize(200, 35))
|
||||||
self.button_select_avatar_3.setMaximumSize(QtCore.QSize(16777215, 35))
|
self.button_select_avatar_3.setMaximumSize(QtCore.QSize(400, 35))
|
||||||
self.button_select_avatar_3.setIcon(icon)
|
self.button_select_avatar_3.setIcon(icon)
|
||||||
self.button_select_avatar_3.setObjectName("button_select_avatar_3")
|
self.button_select_avatar_3.setObjectName("button_select_avatar_3")
|
||||||
self.w_layout_avatar_3.addWidget(self.button_select_avatar_3)
|
self.w_layout_avatar_3.addWidget(self.button_select_avatar_3)
|
||||||
@ -191,7 +192,7 @@ class Ui_MainWindow(object):
|
|||||||
sizePolicy.setHeightForWidth(self.preview_label_avatar_4.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.preview_label_avatar_4.sizePolicy().hasHeightForWidth())
|
||||||
self.preview_label_avatar_4.setSizePolicy(sizePolicy)
|
self.preview_label_avatar_4.setSizePolicy(sizePolicy)
|
||||||
self.preview_label_avatar_4.setMinimumSize(QtCore.QSize(0, 150))
|
self.preview_label_avatar_4.setMinimumSize(QtCore.QSize(0, 150))
|
||||||
self.preview_label_avatar_4.setMaximumSize(QtCore.QSize(300, 150))
|
self.preview_label_avatar_4.setMaximumSize(QtCore.QSize(400, 16777215))
|
||||||
self.preview_label_avatar_4.setFrameShape(QtWidgets.QFrame.Box)
|
self.preview_label_avatar_4.setFrameShape(QtWidgets.QFrame.Box)
|
||||||
self.preview_label_avatar_4.setScaledContents(True)
|
self.preview_label_avatar_4.setScaledContents(True)
|
||||||
self.preview_label_avatar_4.setAlignment(QtCore.Qt.AlignCenter)
|
self.preview_label_avatar_4.setAlignment(QtCore.Qt.AlignCenter)
|
||||||
@ -205,7 +206,7 @@ class Ui_MainWindow(object):
|
|||||||
sizePolicy.setHeightForWidth(self.button_select_avatar_4.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.button_select_avatar_4.sizePolicy().hasHeightForWidth())
|
||||||
self.button_select_avatar_4.setSizePolicy(sizePolicy)
|
self.button_select_avatar_4.setSizePolicy(sizePolicy)
|
||||||
self.button_select_avatar_4.setMinimumSize(QtCore.QSize(200, 35))
|
self.button_select_avatar_4.setMinimumSize(QtCore.QSize(200, 35))
|
||||||
self.button_select_avatar_4.setMaximumSize(QtCore.QSize(16777215, 35))
|
self.button_select_avatar_4.setMaximumSize(QtCore.QSize(400, 35))
|
||||||
self.button_select_avatar_4.setIcon(icon)
|
self.button_select_avatar_4.setIcon(icon)
|
||||||
self.button_select_avatar_4.setObjectName("button_select_avatar_4")
|
self.button_select_avatar_4.setObjectName("button_select_avatar_4")
|
||||||
self.w_layout_avatar_4.addWidget(self.button_select_avatar_4)
|
self.w_layout_avatar_4.addWidget(self.button_select_avatar_4)
|
||||||
|
89
src/python/ui/preview_creator_dialog_ui.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file './src/gui/ui/preview_creator_dialog.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.2
|
||||||
|
#
|
||||||
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||||
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
|
class Ui_PreviewCreatorDialog(object):
|
||||||
|
def setupUi(self, PreviewCreatorDialog):
|
||||||
|
PreviewCreatorDialog.setObjectName("PreviewCreatorDialog")
|
||||||
|
PreviewCreatorDialog.setWindowModality(QtCore.Qt.NonModal)
|
||||||
|
PreviewCreatorDialog.resize(584, 422)
|
||||||
|
icon = QtGui.QIcon()
|
||||||
|
icon.addPixmap(QtGui.QPixmap(":/icons/src/gui/images/icons/preview.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
PreviewCreatorDialog.setWindowIcon(icon)
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(PreviewCreatorDialog)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.playlist_v_layout = QtWidgets.QVBoxLayout()
|
||||||
|
self.playlist_v_layout.setObjectName("playlist_v_layout")
|
||||||
|
self.playlistView = QtWidgets.QListView(PreviewCreatorDialog)
|
||||||
|
self.playlistView.setAcceptDrops(True)
|
||||||
|
self.playlistView.setProperty("showDropIndicator", True)
|
||||||
|
self.playlistView.setDragDropMode(QtWidgets.QAbstractItemView.DropOnly)
|
||||||
|
self.playlistView.setDefaultDropAction(QtCore.Qt.CopyAction)
|
||||||
|
self.playlistView.setAlternatingRowColors(True)
|
||||||
|
self.playlistView.setUniformItemSizes(True)
|
||||||
|
self.playlistView.setObjectName("playlistView")
|
||||||
|
self.playlist_v_layout.addWidget(self.playlistView)
|
||||||
|
self.verticalLayout.addLayout(self.playlist_v_layout)
|
||||||
|
self.line = QtWidgets.QFrame(PreviewCreatorDialog)
|
||||||
|
self.line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||||
|
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||||
|
self.line.setObjectName("line")
|
||||||
|
self.verticalLayout.addWidget(self.line)
|
||||||
|
self.range_values_h_layout = QtWidgets.QHBoxLayout()
|
||||||
|
self.range_values_h_layout.setObjectName("range_values_h_layout")
|
||||||
|
self.left_label = QtWidgets.QLabel(PreviewCreatorDialog)
|
||||||
|
self.left_label.setObjectName("left_label")
|
||||||
|
self.range_values_h_layout.addWidget(self.left_label)
|
||||||
|
self.left_range_line_edit = QtWidgets.QLineEdit(PreviewCreatorDialog)
|
||||||
|
self.left_range_line_edit.setInputMethodHints(QtCore.Qt.ImhPreferNumbers|QtCore.Qt.ImhTime)
|
||||||
|
self.left_range_line_edit.setObjectName("left_range_line_edit")
|
||||||
|
self.range_values_h_layout.addWidget(self.left_range_line_edit)
|
||||||
|
self.right_label = QtWidgets.QLabel(PreviewCreatorDialog)
|
||||||
|
self.right_label.setObjectName("right_label")
|
||||||
|
self.range_values_h_layout.addWidget(self.right_label)
|
||||||
|
self.right_range_line_edit = QtWidgets.QLineEdit(PreviewCreatorDialog)
|
||||||
|
self.right_range_line_edit.setInputMethodHints(QtCore.Qt.ImhPreferNumbers|QtCore.Qt.ImhTime)
|
||||||
|
self.right_range_line_edit.setObjectName("right_range_line_edit")
|
||||||
|
self.range_values_h_layout.addWidget(self.right_range_line_edit)
|
||||||
|
self.create_preview_button = QtWidgets.QPushButton(PreviewCreatorDialog)
|
||||||
|
self.create_preview_button.setObjectName("create_preview_button")
|
||||||
|
self.range_values_h_layout.addWidget(self.create_preview_button)
|
||||||
|
self.verticalLayout.addLayout(self.range_values_h_layout)
|
||||||
|
self.log_label = QtWidgets.QLabel(PreviewCreatorDialog)
|
||||||
|
self.log_label.setObjectName("log_label")
|
||||||
|
self.verticalLayout.addWidget(self.log_label)
|
||||||
|
self.progress_bar = QtWidgets.QProgressBar(PreviewCreatorDialog)
|
||||||
|
self.progress_bar.setProperty("value", 0)
|
||||||
|
self.progress_bar.setObjectName("progress_bar")
|
||||||
|
self.verticalLayout.addWidget(self.progress_bar)
|
||||||
|
|
||||||
|
self.retranslateUi(PreviewCreatorDialog)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(PreviewCreatorDialog)
|
||||||
|
|
||||||
|
def retranslateUi(self, PreviewCreatorDialog):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
PreviewCreatorDialog.setWindowTitle(_translate("PreviewCreatorDialog", "MagicPodcast - preview podcast"))
|
||||||
|
self.left_label.setText(_translate("PreviewCreatorDialog", "Czas rozpoczęcia:"))
|
||||||
|
self.right_label.setText(_translate("PreviewCreatorDialog", "Czas zakończenia:"))
|
||||||
|
self.create_preview_button.setText(_translate("PreviewCreatorDialog", "Utwórz podgląd"))
|
||||||
|
self.log_label.setText(_translate("PreviewCreatorDialog", "TextLabel"))
|
||||||
|
import resources_rc
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
app = QtWidgets.QApplication(sys.argv)
|
||||||
|
PreviewCreatorDialog = QtWidgets.QDialog()
|
||||||
|
ui = Ui_PreviewCreatorDialog()
|
||||||
|
ui.setupUi(PreviewCreatorDialog)
|
||||||
|
PreviewCreatorDialog.show()
|
||||||
|
sys.exit(app.exec_())
|
@ -1,88 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Form implementation generated from reading ui file './src/gui/ui/preview_dialog.ui'
|
|
||||||
#
|
|
||||||
# Created by: PyQt5 UI code generator 5.15.2
|
|
||||||
#
|
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
|
||||||
# run again. Do not edit this file unless you know what you are doing.
|
|
||||||
|
|
||||||
|
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
|
||||||
|
|
||||||
|
|
||||||
class Ui_PreviewDialog(object):
|
|
||||||
def setupUi(self, PreviewDialog):
|
|
||||||
PreviewDialog.setObjectName("PreviewDialog")
|
|
||||||
PreviewDialog.setWindowModality(QtCore.Qt.NonModal)
|
|
||||||
PreviewDialog.resize(779, 356)
|
|
||||||
icon = QtGui.QIcon()
|
|
||||||
icon.addPixmap(QtGui.QPixmap(":/icons/src/gui/images/icons/preview.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
|
||||||
PreviewDialog.setWindowIcon(icon)
|
|
||||||
self.verticalLayout = QtWidgets.QVBoxLayout(PreviewDialog)
|
|
||||||
self.verticalLayout.setObjectName("verticalLayout")
|
|
||||||
self.v_layout_1 = QtWidgets.QVBoxLayout()
|
|
||||||
self.v_layout_1.setObjectName("v_layout_1")
|
|
||||||
self.verticalLayout.addLayout(self.v_layout_1)
|
|
||||||
self.line_2 = QtWidgets.QFrame(PreviewDialog)
|
|
||||||
self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
|
|
||||||
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
|
|
||||||
self.line_2.setObjectName("line_2")
|
|
||||||
self.verticalLayout.addWidget(self.line_2)
|
|
||||||
self.h_layout_range_values = QtWidgets.QHBoxLayout()
|
|
||||||
self.h_layout_range_values.setObjectName("h_layout_range_values")
|
|
||||||
self.left_label = QtWidgets.QLabel(PreviewDialog)
|
|
||||||
self.left_label.setObjectName("left_label")
|
|
||||||
self.h_layout_range_values.addWidget(self.left_label)
|
|
||||||
self.left_range = QtWidgets.QLineEdit(PreviewDialog)
|
|
||||||
self.left_range.setInputMethodHints(QtCore.Qt.ImhPreferNumbers|QtCore.Qt.ImhTime)
|
|
||||||
self.left_range.setObjectName("left_range")
|
|
||||||
self.h_layout_range_values.addWidget(self.left_range)
|
|
||||||
self.right_label = QtWidgets.QLabel(PreviewDialog)
|
|
||||||
self.right_label.setObjectName("right_label")
|
|
||||||
self.h_layout_range_values.addWidget(self.right_label)
|
|
||||||
self.right_range = QtWidgets.QLineEdit(PreviewDialog)
|
|
||||||
self.right_range.setInputMethodHints(QtCore.Qt.ImhPreferNumbers|QtCore.Qt.ImhTime)
|
|
||||||
self.right_range.setObjectName("right_range")
|
|
||||||
self.h_layout_range_values.addWidget(self.right_range)
|
|
||||||
self.create_preview_button = QtWidgets.QPushButton(PreviewDialog)
|
|
||||||
self.create_preview_button.setObjectName("create_preview_button")
|
|
||||||
self.h_layout_range_values.addWidget(self.create_preview_button)
|
|
||||||
self.verticalLayout.addLayout(self.h_layout_range_values)
|
|
||||||
self.line = QtWidgets.QFrame(PreviewDialog)
|
|
||||||
self.line.setFrameShape(QtWidgets.QFrame.HLine)
|
|
||||||
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
|
||||||
self.line.setObjectName("line")
|
|
||||||
self.verticalLayout.addWidget(self.line)
|
|
||||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
|
||||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
|
||||||
self.play_button = QtWidgets.QPushButton(PreviewDialog)
|
|
||||||
self.play_button.setObjectName("play_button")
|
|
||||||
self.horizontalLayout.addWidget(self.play_button)
|
|
||||||
self.stop_button = QtWidgets.QPushButton(PreviewDialog)
|
|
||||||
self.stop_button.setObjectName("stop_button")
|
|
||||||
self.horizontalLayout.addWidget(self.stop_button)
|
|
||||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
|
||||||
|
|
||||||
self.retranslateUi(PreviewDialog)
|
|
||||||
QtCore.QMetaObject.connectSlotsByName(PreviewDialog)
|
|
||||||
|
|
||||||
def retranslateUi(self, PreviewDialog):
|
|
||||||
_translate = QtCore.QCoreApplication.translate
|
|
||||||
PreviewDialog.setWindowTitle(_translate("PreviewDialog", "MagicPodcast - preview podcast"))
|
|
||||||
self.left_label.setText(_translate("PreviewDialog", "Czas rozpoczęcia:"))
|
|
||||||
self.right_label.setText(_translate("PreviewDialog", "Czas zakończenia:"))
|
|
||||||
self.create_preview_button.setText(_translate("PreviewDialog", "Utwórz podgląd"))
|
|
||||||
self.play_button.setText(_translate("PreviewDialog", "Start"))
|
|
||||||
self.stop_button.setText(_translate("PreviewDialog", "Stop"))
|
|
||||||
import resources_rc
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
import sys
|
|
||||||
app = QtWidgets.QApplication(sys.argv)
|
|
||||||
PreviewDialog = QtWidgets.QDialog()
|
|
||||||
ui = Ui_PreviewDialog()
|
|
||||||
ui.setupUi(PreviewDialog)
|
|
||||||
PreviewDialog.show()
|
|
||||||
sys.exit(app.exec_())
|
|
110
src/python/ui/video_player_dialog_ui.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file './src/gui/ui/video_player_dialog.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.2
|
||||||
|
#
|
||||||
|
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||||
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
|
class Ui_VideoPlayerDialog(object):
|
||||||
|
def setupUi(self, VideoPlayerDialog):
|
||||||
|
VideoPlayerDialog.setObjectName("VideoPlayerDialog")
|
||||||
|
VideoPlayerDialog.resize(640, 480)
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(VideoPlayerDialog)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.video_v_layout = QtWidgets.QVBoxLayout()
|
||||||
|
self.video_v_layout.setObjectName("video_v_layout")
|
||||||
|
self.verticalLayout.addLayout(self.video_v_layout)
|
||||||
|
self.time_h_layout = QtWidgets.QHBoxLayout()
|
||||||
|
self.time_h_layout.setObjectName("time_h_layout")
|
||||||
|
self.current_time_label = QtWidgets.QLabel(VideoPlayerDialog)
|
||||||
|
self.current_time_label.setMinimumSize(QtCore.QSize(80, 0))
|
||||||
|
self.current_time_label.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
|
||||||
|
self.current_time_label.setObjectName("current_time_label")
|
||||||
|
self.time_h_layout.addWidget(self.current_time_label)
|
||||||
|
self.time_slider = QtWidgets.QSlider(VideoPlayerDialog)
|
||||||
|
self.time_slider.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.time_slider.setObjectName("time_slider")
|
||||||
|
self.time_h_layout.addWidget(self.time_slider)
|
||||||
|
self.total_time_label = QtWidgets.QLabel(VideoPlayerDialog)
|
||||||
|
self.total_time_label.setMinimumSize(QtCore.QSize(80, 0))
|
||||||
|
self.total_time_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
|
||||||
|
self.total_time_label.setObjectName("total_time_label")
|
||||||
|
self.time_h_layout.addWidget(self.total_time_label)
|
||||||
|
self.verticalLayout.addLayout(self.time_h_layout)
|
||||||
|
self.buttons_h_layout = QtWidgets.QHBoxLayout()
|
||||||
|
self.buttons_h_layout.setObjectName("buttons_h_layout")
|
||||||
|
self.previous_button = QtWidgets.QPushButton(VideoPlayerDialog)
|
||||||
|
self.previous_button.setText("")
|
||||||
|
icon = QtGui.QIcon()
|
||||||
|
icon.addPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/control-skip-180.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.previous_button.setIcon(icon)
|
||||||
|
self.previous_button.setObjectName("previous_button")
|
||||||
|
self.buttons_h_layout.addWidget(self.previous_button)
|
||||||
|
self.play_button = QtWidgets.QPushButton(VideoPlayerDialog)
|
||||||
|
self.play_button.setText("")
|
||||||
|
icon1 = QtGui.QIcon()
|
||||||
|
icon1.addPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/control.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.play_button.setIcon(icon1)
|
||||||
|
self.play_button.setObjectName("play_button")
|
||||||
|
self.buttons_h_layout.addWidget(self.play_button)
|
||||||
|
self.pause_button = QtWidgets.QPushButton(VideoPlayerDialog)
|
||||||
|
self.pause_button.setText("")
|
||||||
|
icon2 = QtGui.QIcon()
|
||||||
|
icon2.addPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/control-pause.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.pause_button.setIcon(icon2)
|
||||||
|
self.pause_button.setObjectName("pause_button")
|
||||||
|
self.buttons_h_layout.addWidget(self.pause_button)
|
||||||
|
self.stop_button = QtWidgets.QPushButton(VideoPlayerDialog)
|
||||||
|
self.stop_button.setText("")
|
||||||
|
icon3 = QtGui.QIcon()
|
||||||
|
icon3.addPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/control-stop-square.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.stop_button.setIcon(icon3)
|
||||||
|
self.stop_button.setObjectName("stop_button")
|
||||||
|
self.buttons_h_layout.addWidget(self.stop_button)
|
||||||
|
self.next_button = QtWidgets.QPushButton(VideoPlayerDialog)
|
||||||
|
self.next_button.setText("")
|
||||||
|
icon4 = QtGui.QIcon()
|
||||||
|
icon4.addPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/control-skip.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||||
|
self.next_button.setIcon(icon4)
|
||||||
|
self.next_button.setObjectName("next_button")
|
||||||
|
self.buttons_h_layout.addWidget(self.next_button)
|
||||||
|
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
|
self.buttons_h_layout.addItem(spacerItem)
|
||||||
|
self.volume_label = QtWidgets.QLabel(VideoPlayerDialog)
|
||||||
|
self.volume_label.setText("")
|
||||||
|
self.volume_label.setPixmap(QtGui.QPixmap(":/video-icons/src/gui/images/icons/speaker-volume.png"))
|
||||||
|
self.volume_label.setObjectName("volume_label")
|
||||||
|
self.buttons_h_layout.addWidget(self.volume_label)
|
||||||
|
self.volume_slider = QtWidgets.QSlider(VideoPlayerDialog)
|
||||||
|
self.volume_slider.setMaximum(100)
|
||||||
|
self.volume_slider.setProperty("value", 100)
|
||||||
|
self.volume_slider.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.volume_slider.setObjectName("volume_slider")
|
||||||
|
self.buttons_h_layout.addWidget(self.volume_slider)
|
||||||
|
self.verticalLayout.addLayout(self.buttons_h_layout)
|
||||||
|
|
||||||
|
self.retranslateUi(VideoPlayerDialog)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(VideoPlayerDialog)
|
||||||
|
|
||||||
|
def retranslateUi(self, VideoPlayerDialog):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
VideoPlayerDialog.setWindowTitle(_translate("VideoPlayerDialog", "Dialog"))
|
||||||
|
self.current_time_label.setText(_translate("VideoPlayerDialog", "0:00"))
|
||||||
|
self.total_time_label.setText(_translate("VideoPlayerDialog", "0:00"))
|
||||||
|
import resources_rc
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
app = QtWidgets.QApplication(sys.argv)
|
||||||
|
VideoPlayerDialog = QtWidgets.QDialog()
|
||||||
|
ui = Ui_VideoPlayerDialog()
|
||||||
|
ui.setupUi(VideoPlayerDialog)
|
||||||
|
VideoPlayerDialog.show()
|
||||||
|
sys.exit(app.exec_())
|