mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-14 19:24:29 +02:00
Compare commits
3180 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d2202a4e33 | |||
| 9b1163f959 | |||
| 5b5edc506d | |||
| b30b4375e7 | |||
| 1b0c03d892 | |||
| bca49184e7 | |||
| 26d6c33163 | |||
| 9420615317 | |||
| 7198c6b8c6 | |||
| 9513864851 | |||
| f9b8aa1862 | |||
| 34371c070c | |||
| d6099dd263 | |||
| a1bc39141e | |||
| 13ed41d077 | |||
| 8a0a8f718f | |||
| 7d08a54ad9 | |||
| b9b47e3ec7 | |||
| 16989f2122 | |||
| 892d3a370d | |||
| 6af7ca9867 | |||
| c3c354f794 | |||
| 43572a1560 | |||
| 79daed63ee | |||
| 21d3ad86d4 | |||
| 31ebe842e8 | |||
| 88487de72f | |||
| 616da8c99d | |||
| ec8712cceb | |||
| 3d6923b2a1 | |||
| f04337becf | |||
| 9a5dd4c19d | |||
| 643e0b1039 | |||
| 330061a6e7 | |||
| 0a292715cf | |||
| 52f034a513 | |||
| 25e05388ba | |||
| 7ad9a1af03 | |||
| 9346c69343 | |||
| 4a3f0ccf96 | |||
| 52a1396e29 | |||
| f556dd2584 | |||
| aea5c09825 | |||
| 8c3c9a1219 | |||
| a4f1f383a7 | |||
| ee73c5c1b5 | |||
| c2904a4633 | |||
| 6faa2249f9 | |||
| 119c3acfe7 | |||
| 138a2683f2 | |||
| 463637fa10 | |||
| d5aab926bf | |||
| 37ba04b770 | |||
| 3d0b7dee71 | |||
| a287c2caac | |||
| 1b673d9dd0 | |||
| d10621c201 | |||
| e1d6dfc324 | |||
| 130ea2a7ca | |||
| c8d53253d2 | |||
| 5c67438925 | |||
| 1012dba8d7 | |||
| e8d43f53d9 | |||
| a0e8ce4b13 | |||
| 0e35b3edcb | |||
| 25bb5851ec | |||
| 80b0bc0869 | |||
| c05743b7b9 | |||
| 7c2a1f0f37 | |||
| 0b8b9e75d1 | |||
| d65c343e91 | |||
| cd8e7cc947 | |||
| 0df5cf2e91 | |||
| 412275e40d | |||
| 4c7ad66bd7 | |||
| 8ac21357c3 | |||
| 2fd88b901b | |||
| 5697759d9e | |||
| ee0042c768 | |||
| a6212f1388 | |||
| 7bfea60b35 | |||
| beee740dc8 | |||
| e31387b8bc | |||
| 3586a12c46 | |||
| bf21254b13 | |||
| dc9f61e70a | |||
| 3028998a43 | |||
| 42511ce8d8 | |||
| c245d2134f | |||
| f01884537d | |||
| b48fb0d4da | |||
| 7a6470a19d | |||
| bfd8fc771a | |||
| f96ca4ac1f | |||
| 937bfce68e | |||
| 5869d35d85 | |||
| 8d3325e6cd | |||
| 4badb5b975 | |||
| 7e4ff233ec | |||
| 0e3397239d | |||
| 08bae3da2e | |||
| 4b49c8bd6e | |||
| c1bd1fcbd4 | |||
| 1c3379f082 | |||
| 86c97a8ba3 | |||
| 8e6c18d3f4 | |||
| f1e80c466d | |||
| 9a542bcb20 | |||
| 290c8ec420 | |||
| 517ccd5e40 | |||
| bb7bbe0a60 | |||
| ca25a31d79 | |||
| e804e99013 | |||
| f447aded57 | |||
| c596a51593 | |||
| ed26368a3a | |||
| 1b40e4aaca | |||
| 84d7fe550b | |||
| e68d507659 | |||
| 2db1e8fb81 | |||
| df674d4056 | |||
| 21dcda147c | |||
| 201d5ba219 | |||
| 2728462d77 | |||
| f73b497b67 | |||
| d2bdb85dc8 | |||
| 3572b4752e | |||
| 20de162a55 | |||
| 64a8e66bac | |||
| ccc1874a4b | |||
| 4fec896378 | |||
| d485fcb3ee | |||
| c9498c3cec | |||
| 62fffaf56f | |||
| 553a5cc455 | |||
| 957ec1d3d3 | |||
| 00c158387b | |||
| d12fa690c0 | |||
| 94226e83ba | |||
| 4cf041f6cb | |||
| 1b86a6e6f8 | |||
| 6e907ae618 | |||
| 39dde85d03 | |||
| 8bb9170865 | |||
| 2cd5ce6aea | |||
| 64fbaff82b | |||
| 15a38f5f9d | |||
| 4c1d93a322 | |||
| 6a40959f3a | |||
| c4bf297f42 | |||
| da1b408f97 | |||
| 91c3e3b684 | |||
| 609a44aaf2 | |||
| 3d84443bcf | |||
| 56046d4db8 | |||
| 90fc037833 | |||
| ee4eadf7a6 | |||
| 3292121e67 | |||
| c8416b820b | |||
| c9d229e336 | |||
| bfbcd7a949 | |||
| bf2ba3c4d1 | |||
| 9d50d44c99 | |||
| e76afee12d | |||
| 06ef51db2e | |||
| a85a2a3cc5 | |||
| 8fbecbcdd7 | |||
| b386f78d68 | |||
| 095757044a | |||
| 9b3b8aa4de | |||
| 4932834441 | |||
| 8773ebf64b | |||
| f628795b3f | |||
| 0c78bda328 | |||
| d9f4bc70fb | |||
| ddd2ea5f4d | |||
| a326303956 | |||
| ba1eba98ea | |||
| 8282ebce40 | |||
| 4c3b7c45cf | |||
| 668251274a | |||
| e79fc72950 | |||
| bcda41120e | |||
| 80fc00bb05 | |||
| f71ccab811 | |||
| 795951a2e8 | |||
| d62999ed16 | |||
| 9b1699a5a4 | |||
| 88c1f00b62 | |||
| 6834367a3e | |||
| dedcf21a37 | |||
| a747a5f9fa | |||
| fcfb9865df | |||
| aa1e9cc9fa | |||
| 9b7d21891d | |||
| df19baed37 | |||
| 7848f6a1c5 | |||
| 14e128337d | |||
| cb314f0a0b | |||
| ddb313fd2b | |||
| 8f183955a0 | |||
| 536a4162c4 | |||
| 41a47f99f7 | |||
| 31fa1ea21e | |||
| fb49c71118 | |||
| 0b87cfc7d4 | |||
| 76fa37019e | |||
| d94e861a78 | |||
| d9b537d334 | |||
| 93c2081d3f | |||
| 5ad8ed43fd | |||
| 1f4416a77a | |||
| e9d4dba64b | |||
| 3a2307a5c6 | |||
| d6c1af1a0c | |||
| f6cb7ca01d | |||
| bc0fdc49e0 | |||
| 43ccb63eb5 | |||
| a0000a8547 | |||
| a37ff0c4f2 | |||
| e449ad7472 | |||
| a718a785b3 | |||
| ea7cc08832 | |||
| a342f4c7e9 | |||
| 0af2657bbc | |||
| 451c2a244f | |||
| a603aed7db | |||
| f6bbf410f1 | |||
| 018692edd0 | |||
| 2740785df5 | |||
| 613a9964a1 | |||
| 2ef2f5db1d | |||
| 577e15a949 | |||
| 58ff3e6c0d | |||
| 80c471a939 | |||
| b78fca7b91 | |||
| be76092195 | |||
| 771d3c3c9d | |||
| 8c21765c0f | |||
| a2e3522862 | |||
| e20c2210f5 | |||
| 11f3fecd11 | |||
| 1a5d7c1c5d | |||
| 0bca1aab74 | |||
| 95fa15f902 | |||
| d586582489 | |||
| 7ef46eaa29 | |||
| 38957625ad | |||
| d30e076dbd | |||
| 0619555232 | |||
| 3ffa5eb613 | |||
| c60583c6bb | |||
| 4cf7a1086d | |||
| fa75006ca9 | |||
| d28b2fa057 | |||
| 0a90765ed0 | |||
| 2892f629f0 | |||
| 5be05853c6 | |||
| 0f569ac5cb | |||
| b725c1e8e0 | |||
| 4d418d1bb5 | |||
| 752594f69a | |||
| b6125e97e9 | |||
| c00caa886e | |||
| 37540d1c68 | |||
| 8fca67f0d6 | |||
| 13f891c34f | |||
| f924ab721a | |||
| ae3708edc6 | |||
| 4ef2574ae3 | |||
| 154171e01e | |||
| 17732a0b8a | |||
| b6906d1edc | |||
| 26329765d1 | |||
| fab7424ebb | |||
| e4c9416c4a | |||
| 72c661e8f5 | |||
| d5acd98eb3 | |||
| 849c754ca2 | |||
| e6f6385173 | |||
| d3ca2bf58f | |||
| 82f1dbca89 | |||
| c85b826978 | |||
| f28c40aa8e | |||
| 3fa3bc1719 | |||
| 93bd95f4bd | |||
| 7d572ff794 | |||
| 693278a87b | |||
| b6bcbcac96 | |||
| 4cfea01aa8 | |||
| 9e301e1aec | |||
| 8502acffb7 | |||
| 580b7c94fb | |||
| fe1e432f9e | |||
| 904ccc7a91 | |||
| 069196704e | |||
| 2db6bf399e | |||
| a5bc49ee4a | |||
| 949d455d2f | |||
| 3254d27fc2 | |||
| 4921afdb51 | |||
| 54b653cc00 | |||
| 3066ab0d06 | |||
| 17c5acda3c | |||
| ee3cacffd7 | |||
| 0cd5b9072c | |||
| 987fdd32fb | |||
| 314143db7a | |||
| 10f468dd3f | |||
| c66881d4a6 | |||
| 45d42da528 | |||
| c50e1800ec | |||
| 06aa051162 | |||
| 33e7bcbdb8 | |||
| c44266eb82 | |||
| dcbb1483b9 | |||
| 4620b566b9 | |||
| 076b11a735 | |||
| 246f783a64 | |||
| ac3e7fbf44 | |||
| dda1665b9c | |||
| db4d721b93 | |||
| f48824dec0 | |||
| eac90c6b42 | |||
| ec5a91b89a | |||
| a9a3342519 | |||
| 51f3e1b684 | |||
| 2459145dbf | |||
| d48abe03b0 | |||
| 1e4e54eca0 | |||
| 9d23da226f | |||
| c911738b5c | |||
| 574e0a10e2 | |||
| f240660a6e | |||
| b2416c6466 | |||
| 3ed489f35c | |||
| f96ad8ff6e | |||
| 2d7289a248 | |||
| 2de6a5029f | |||
| bed3cae6df | |||
| b3bf3e46be | |||
| 336ef58f61 | |||
| f3e7491c3a | |||
| 48b9d2f53e | |||
| 1dff9897c9 | |||
| b5a61d2915 | |||
| 0c5b43bcdd | |||
| fe8ebe3f79 | |||
| 265afcec7e | |||
| 26d5ee0c93 | |||
| 6e1011f18a | |||
| 9bca1946ed | |||
| 0c8beedb94 | |||
| c274e447dd | |||
| 2bc2891c73 | |||
| fe1bebc12d | |||
| 339c483a4b | |||
| 73f1f0e1d6 | |||
| f83fc9ba27 | |||
| 4e5692e935 | |||
| 2bb707299a | |||
| 9aa46e8543 | |||
| 4831e51cb4 | |||
| 4ea331ecf2 | |||
| 79764430d8 | |||
| 51107ee9dd | |||
| d359e8420b | |||
| ea11bb61e3 | |||
| 4a90a3e1c9 | |||
| 8f73e93205 | |||
| 1a7263cb9f | |||
| d6332e796e | |||
| ebcb3b413c | |||
| 2a92edd7ed | |||
| 9584672051 | |||
| 6018936dc2 | |||
| d00da31e60 | |||
| afd8ff1435 | |||
| 4f65ef4d33 | |||
| cdadad5689 | |||
| 00d768a6bf | |||
| 08faba5455 | |||
| c1e92b594e | |||
| d38147bcf2 | |||
| 8681eb0251 | |||
| 72ecb0fce3 | |||
| 17b052430b | |||
| 94d52d9ddb | |||
| 9ecaa46eb8 | |||
| a10b0c5dc5 | |||
| 4242201777 | |||
| ff82232e27 | |||
| 5ee0565342 | |||
| 483e2236ca | |||
| 7ee62b8222 | |||
| 74c14fdf66 | |||
| 8a34c4b2e2 | |||
| b1dcd53212 | |||
| 4d1671f147 | |||
| deedc5d79f | |||
| 02dc164611 | |||
| de7bbd6c37 | |||
| ddf66056ec | |||
| f0a7c41b81 | |||
| cb200f6e9e | |||
| 78a66147f1 | |||
| 5999a1a62e | |||
| ab56cfe762 | |||
| 654c501fb8 | |||
| 227c2563c5 | |||
| 4b270e703e | |||
| 5bc3b4bf7d | |||
| 353124d82d | |||
| 15a82e2324 | |||
| 2b85f96406 | |||
| 8d408eaadb | |||
| 51f29f40ee | |||
| 72d6ff625c | |||
| b1766779ee | |||
| a42143690c | |||
| c21df3b7f0 | |||
| a8faf2eb6e | |||
| 8abe5b42e5 | |||
| 3cfc4cd5be | |||
| 661d22f46c | |||
| 1f40302b36 | |||
| dff6d1843a | |||
| 07b7420ba5 | |||
| 43afeb205f | |||
| 6aeca2c1e3 | |||
| 30b1129d60 | |||
| 8e0e4cf25d | |||
| 7aa3322a04 | |||
| 07789f5dad | |||
| a1ffe4deff | |||
| f407bc12df | |||
| 4df5c9e1e1 | |||
| a2abe49d3f | |||
| b0e911ad7f | |||
| 3bb6eb16de | |||
| a978abb523 | |||
| c4345f9a85 | |||
| ca92d4ea3d | |||
| 5c95a6f4fa | |||
| dfb0246826 | |||
| 791bf2c52e | |||
| 18bdf4a8d0 | |||
| af789a4f8d | |||
| 30a2675972 | |||
| 5539fe0b73 | |||
| 30504660fa | |||
| 00d06db90e | |||
| 108a0d0ce6 | |||
| 1bff48cbf9 | |||
| c91cbebc9f | |||
| 305df89438 | |||
| 42eb289d97 | |||
| b8596c6f2a | |||
| 8696812d23 | |||
| 70cd26ce6a | |||
| 2b99f3c753 | |||
| 96a1c77577 | |||
| 9a3e7eecd9 | |||
| 7cb22815e6 | |||
| da2efd88f2 | |||
| 2f0b244f48 | |||
| 78c9b7f33e | |||
| 9f461253a8 | |||
| a3d02b8702 | |||
| 8dcda63c85 | |||
| 35e28fc0d0 | |||
| 72fd5211f0 | |||
| 690d4fa4b1 | |||
| c477ea1628 | |||
| 9837dc88a0 | |||
| 23f1c1a149 | |||
| d9cf8a474a | |||
| 5bec0e510d | |||
| 14f443124a | |||
| 9d968e7906 | |||
| bc7ffe4720 | |||
| 29f0090417 | |||
| 509be0b3f8 | |||
| b1b3f0dbac | |||
| 269d3d22b5 | |||
| 78c05b263f | |||
| a0b6290a4d | |||
| 059ce3b7f0 | |||
| 699c3d80b7 | |||
| e5009398e0 | |||
| 899eef18ec | |||
| 3210f24293 | |||
| cc391e1a9e | |||
| 70982f6969 | |||
| 2abbda924b | |||
| b3179f75f4 | |||
| c0934d141f | |||
| 1e0b9bb51e | |||
| 9143d47bd2 | |||
| 6df0a315a9 | |||
| 3f4f9ad5f1 | |||
| 749f225562 | |||
| 2e065b128a | |||
| d60ae20839 | |||
| 441b23bce5 | |||
| 44c01dd73e | |||
| 01ca4e25ae | |||
| 3c39a9ab22 | |||
| 74808095b9 | |||
| 09f2d4f546 | |||
| 1480d9ac20 | |||
| c00c125191 | |||
| 7ac0e38f35 | |||
| 59b870d3dc | |||
| d2dd796cb9 | |||
| ccadf5d09c | |||
| dbe078c8b3 | |||
| 129bc0819b | |||
| 3f5dc4e182 | |||
| 4de0fbe6b0 | |||
| c46d316e95 | |||
| 8cf430ef7e | |||
| e2c3a8b1e1 | |||
| 1b50fb982a | |||
| ff4c741f4b | |||
| 1a015089ed | |||
| ef70aa410e | |||
| 636e0de5aa | |||
| 8925da94e1 | |||
| d7ef8a48fe | |||
| bf32cdd683 | |||
| 6b3a8066e3 | |||
| fddef65a58 | |||
| 9388c483ec | |||
| 7cbede9190 | |||
| fc14b8f0da | |||
| 4ebb5a87b2 | |||
| 8dba6a186f | |||
| b1ff979171 | |||
| ebeb88d425 | |||
| d7c7aa2215 | |||
| 6f407b2080 | |||
| 59e10bcac6 | |||
| 256f7b9b0f | |||
| f2ca07033c | |||
| e233f1dded | |||
| 07c09f255d | |||
| 774d0326c7 | |||
| ce412686b9 | |||
| dfcf9fa6aa | |||
| 6a548440ea | |||
| eba2273cd1 | |||
| 3f1fb1fc3c | |||
| 35cbfb3fb0 | |||
| 6bf8f43ab1 | |||
| 3204b98aaf | |||
| f29c2a5805 | |||
| facbfa479b | |||
| 555b8efcad | |||
| 0e268864e2 | |||
| a7687947e6 | |||
| 8254ff078e | |||
| f8d90d68a3 | |||
| 60fe05bc63 | |||
| fa2db10e44 | |||
| 06081ca18b | |||
| 34fad0bf98 | |||
| 78ad2cfb88 | |||
| 9da8e9280f | |||
| 8ac0bd452e | |||
| 98038201b3 | |||
| 62b1688856 | |||
| 2dd9741102 | |||
| 6d5c05fba3 | |||
| d93b49cc4f | |||
| 6ccb55d6f7 | |||
| a1fb735fde | |||
| 066cf42338 | |||
| 5c952fbbd6 | |||
| 60b92ba775 | |||
| 1242f6c942 | |||
| 1920bff007 | |||
| 05c12e2505 | |||
| 354951f1d6 | |||
| a67d3e9aee | |||
| b706c25b68 | |||
| 4dbe17eaf9 | |||
| a4b598aa15 | |||
| 05a9a71f4a | |||
| 9b2caa6fdd | |||
| bebb748546 | |||
| b509a849a1 | |||
| 20602650c4 | |||
| a2d0b8b452 | |||
| 1fa7526036 | |||
| 1033726d65 | |||
| e5c3f82dd9 | |||
| 2c21dddea9 | |||
| 208812347f | |||
| 8c8a8f9994 | |||
| 77e9938f0f | |||
| aea6a9f534 | |||
| a346cff472 | |||
| 1b3c3efcd5 | |||
| 898055a3c2 | |||
| f2030d9957 | |||
| a5f323e4e3 | |||
| bdb1fd517b | |||
| 6ce75453fe | |||
| 80aed98e97 | |||
| 7e939b7535 | |||
| 57f0ebbff9 | |||
| a426df9c65 | |||
| 2584835176 | |||
| 40cb41399f | |||
| eedea5cbf7 | |||
| bd97a7a216 | |||
| d1891fc31c | |||
| 20193eae36 | |||
| 1cb10eb889 | |||
| d52352966e | |||
| a8382ceb50 | |||
| d47c9b0773 | |||
| 1a383de5c4 | |||
| 44e69a9603 | |||
| 91cba0ec45 | |||
| e0a0e0b00c | |||
| 22f214c8e1 | |||
| 9ff2dd6be1 | |||
| 4e09f903ca | |||
| a45f674bc1 | |||
| 75da9809e9 | |||
| 561fb7a4be | |||
| b0da6361cb | |||
| bc74c9064a | |||
| 66133b8b21 | |||
| b69c270c31 | |||
| d56e6427a9 | |||
| 0692a9ff51 | |||
| 4bf6b1df5e | |||
| bb7ab5690c | |||
| c12422b2cd | |||
| be6598e224 | |||
| faf750a544 | |||
| ab7105ffa0 | |||
| e4da6829d3 | |||
| 1c1d494913 | |||
| a22b34ed25 | |||
| 31c045fdb5 | |||
| 887a1685dd | |||
| ec887d5aaf | |||
| 08f503748e | |||
| 656f0f7b16 | |||
| 410378dccd | |||
| ff22a32a61 | |||
| 5cdf0552ac | |||
| d4cd8442c4 | |||
| b0430af217 | |||
| a6c22731ba | |||
| 61b562fcaa | |||
| 3d551e384a | |||
| 4cf9b7adac | |||
| f76559b791 | |||
| ea6d276a46 | |||
| a323145344 | |||
| 26aa7ef09f | |||
| 4a5f9df7bf | |||
| f2a9c8558b | |||
| 07c3b6ad04 | |||
| 8cbdd61f98 | |||
| 276b1b5539 | |||
| fbc4a5cac2 | |||
| 8b01fb0bcf | |||
| f565014203 | |||
| 3a048dafab | |||
| 7383bc3f44 | |||
| 96d9eadb4b | |||
| 199db12565 | |||
| f66ea63b7e | |||
| bed53be218 | |||
| af1e41681c | |||
| 7987430825 | |||
| 592395d15c | |||
| 5cd243f2c1 | |||
| f699807cae | |||
| 31b7ec7308 | |||
| 5ea882dae3 | |||
| 1628237ba7 | |||
| b86241695d | |||
| 7bab2d197e | |||
| 6288f945cd | |||
| 1356171af5 | |||
| 409c285f36 | |||
| 844ff5bb04 | |||
| 6ae9e7edb5 | |||
| a38fbb157d | |||
| b4db00b979 | |||
| 142a1a392f | |||
| c98b90a4e2 | |||
| c5298cf12d | |||
| 9e30fa81de | |||
| 8f5458f3ae | |||
| 0a8f5e97e4 | |||
| 92bec955a8 | |||
| 89c0d95a94 | |||
| 2c88cd7ac0 | |||
| 0440079a24 | |||
| 5fbf21c1bd | |||
| e4cc0e04e8 | |||
| 01179c69ec | |||
| 038e22e5db | |||
| ebeba2ba17 | |||
| daebb5753a | |||
| bb2016889a | |||
| 470bbc9899 | |||
| 527fa587ce | |||
| 8a22e44f3b | |||
| ad7736f90d | |||
| 2ab27ef42a | |||
| 314c840293 | |||
| ee451fe345 | |||
| 50f90aee79 | |||
| 31c02e5915 | |||
| d08f4df146 | |||
| e17f592602 | |||
| 50bb362dc9 | |||
| 1d1ee314ca | |||
| db8fb7f5a3 | |||
| 498fe48255 | |||
| 2b75f9638d | |||
| f159d1de55 | |||
| eb67c87e20 | |||
| 95953c86ae | |||
| f8bd4d7155 | |||
| 4d73147121 | |||
| 0466114f67 | |||
| 0a585e00e5 | |||
| 5048f1c21b | |||
| 486c823111 | |||
| 7e66eb856c | |||
| edb9a5ba3c | |||
| 6f354c6c02 | |||
| 2fb8ecbf02 | |||
| f7c79fe3cc | |||
| 5363a90c6b | |||
| d132ddefef | |||
| 46db4077b8 | |||
| 344d27ea5a | |||
| 2dfb819d35 | |||
| cef8d03d49 | |||
| 4177b090b2 | |||
| 26075a9520 | |||
| 76b88ebdbf | |||
| bae4a2df7e | |||
| e8ce1e3445 | |||
| 90a4025bcc | |||
| f66797c5cf | |||
| bd22d29d58 | |||
| 5026dda9ca | |||
| b30e93389c | |||
| a2a635a141 | |||
| 05dd0831c1 | |||
| db788452bd | |||
| 5c5fdcf14d | |||
| b96a252a61 | |||
| 793aa7fd7f | |||
| d0673f9133 | |||
| 4b4b82bd5f | |||
| dda0b6c296 | |||
| e212c611be | |||
| a95492f7a0 | |||
| ff3c22fc2b | |||
| 59e8a2dfae | |||
| d44e215e5e | |||
| 129fddf07c | |||
| 0dd766cec8 | |||
| f79b57d0cf | |||
| 226b188eaf | |||
| 8f4e01e004 | |||
| d54dab87ef | |||
| ef8e35032e | |||
| 599e291824 | |||
| 3d8fe01bc6 | |||
| a72cecd235 | |||
| 02a2e8a7f1 | |||
| 38c1b031c2 | |||
| 3ba72e8728 | |||
| 5286b19af5 | |||
| 5c104f8e1d | |||
| 0988b08f7a | |||
| bfcd5c84ca | |||
| 93b24f98a6 | |||
| 32d52cb0dd | |||
| 552d5d8928 | |||
| 5b583fefbc | |||
| 3c4d48f45d | |||
| f6b8b6cb9b | |||
| 78cf98dcb7 | |||
| 13e95ad5cb | |||
| 5ab4263c0a | |||
| 77ea599e36 | |||
| 6793a84f9b | |||
| 9ab449dcf3 | |||
| c883e9d792 | |||
| 0e73bf1e6d | |||
| 1ccddb92d4 | |||
| 56501e0811 | |||
| 3d6a550f23 | |||
| 8de4e190dc | |||
| d17ceec14b | |||
| 741ddaf384 | |||
| 76b03a8a88 | |||
| fd194124a9 | |||
| ff7053c566 | |||
| be438587c7 | |||
| 1146175648 | |||
| 3f99d1d3cc | |||
| af58273c4c | |||
| 93abf66240 | |||
| 6924249bcf | |||
| 21fa2ee87b | |||
| 50861dc5c1 | |||
| 64f6bf52b0 | |||
| e9d256aa74 | |||
| 79b5f2154f | |||
| 0f42eab7a4 | |||
| f10e7f4ab7 | |||
| e1f7fe5700 | |||
| ebfd656c54 | |||
| 630ebb0583 | |||
| 748dcbd989 | |||
| c0b4ceef0b | |||
| 8ba768ecec | |||
| cfb5e203b3 | |||
| 433e42e3e4 | |||
| 1519a6b1da | |||
| 87abacc632 | |||
| e5bc1defa2 | |||
| c975a78ed7 | |||
| 4537342ec2 | |||
| ee80bca994 | |||
| 55c1012d1c | |||
| df5a7d4fb1 | |||
| fba0e5932f | |||
| 28c2c8d179 | |||
| d1459650e1 | |||
| 6138ac009f | |||
| aa4a9cdad7 | |||
| a7af3cd483 | |||
| a12accf3fa | |||
| ffe669137b | |||
| a874c5455d | |||
| d70b7e5bc7 | |||
| 8e80662bb0 | |||
| dbd7d2e290 | |||
| 93d948ac57 | |||
| c69c7ce59c | |||
| 79c79b06ca | |||
| b922667fbd | |||
| 9bfe89f115 | |||
| 4975f7f098 | |||
| 4db49038c8 | |||
| 4cc7ec5a02 | |||
| 930de813f7 | |||
| e9ec9e79ac | |||
| 212b2aea16 | |||
| 06a0dc374f | |||
| 1cc63412ec | |||
| 39c35d4430 | |||
| 10699b7c09 | |||
| 25c807965c | |||
| 5321ca913e | |||
| b8c7ac4529 | |||
| 5b98c0b7ff | |||
| 7ed4e3ae35 | |||
| 250b266321 | |||
| 682797c54b | |||
| 2221a12950 | |||
| e2cdcd094a | |||
| 71b0d9cc38 | |||
| 808fadd061 | |||
| 760d349af1 | |||
| 6b2a20231d | |||
| 975aac5a00 | |||
| f6909d0ea9 | |||
| 88ee6659b2 | |||
| 3e878f5124 | |||
| c32c4c1e46 | |||
| 1e526097f6 | |||
| 7c728c4ae1 | |||
| 87aa7bbb76 | |||
| 729fd3cebf | |||
| a9d7164b58 | |||
| 8a9a7f0858 | |||
| f02aa252b7 | |||
| 6103d07d07 | |||
| 66f166909e | |||
| 03f7002711 | |||
| ff58de2d8c | |||
| 9a4585d438 | |||
| 81800c5a4d | |||
| e2e9249d40 | |||
| 9cc852a097 | |||
| 0b98c7a352 | |||
| 4463531f1e | |||
| 61ed160881 | |||
| fd6b0d07fb | |||
| d92b6648ac | |||
| ae71427b91 | |||
| 08a9c052d5 | |||
| 865c103d42 | |||
| fc87b54439 | |||
| fe53a3f52c | |||
| 72e8c66879 | |||
| bc2f576b30 | |||
| 614c535f5e | |||
| 92b5a6e381 | |||
| c6924ccaeb | |||
| aa59547af7 | |||
| 67f1cd4e15 | |||
| 6ad98e2c70 | |||
| 0ee28f3433 | |||
| 25107bd2db | |||
| 304f260cff | |||
| 9bcf4d2571 | |||
| e129a06436 | |||
| c99714dbb2 | |||
| 8771d3bc19 | |||
| e5964ae35b | |||
| 218b792e73 | |||
| 0b253b07b2 | |||
| be85ed3645 | |||
| 9868abe1b1 | |||
| cdb886a454 | |||
| ac1f31f2cd | |||
| 89dd7f19ef | |||
| 923b0817ce | |||
| 4c9981f3c8 | |||
| 0ef469f3b5 | |||
| 73044dffed | |||
| ea35619a78 | |||
| 8280292fb4 | |||
| dc8cdc95d0 | |||
| 5e9710a8c6 | |||
| c404bd9f17 | |||
| 61de98d651 | |||
| bf2575c3c9 | |||
| f5e64232c9 | |||
| 9daedf6f09 | |||
| dad1e659a5 | |||
| 0a8547a692 | |||
| 5647ca7f08 | |||
| a3b3edb565 | |||
| fb9c9cb172 | |||
| 2815bd177c | |||
| 7aa05c08f1 | |||
| 112ba57729 | |||
| bdac7672b7 | |||
| 09a49cfaa0 | |||
| 08cac6affd | |||
| ade8517429 | |||
| c9826cb26a | |||
| 3f764e3122 | |||
| 9d29287c02 | |||
| b9cdd452df | |||
| 32d1105833 | |||
| d84d4cec4f | |||
| e9a61c24df | |||
| 5ffcbad18b | |||
| e7c4894833 | |||
| 3289cd1e2b | |||
| 4127253650 | |||
| 2c55cce6ba | |||
| 633eb45011 | |||
| 65aeeba567 | |||
| f37fd29fd0 | |||
| 310ed9af0d | |||
| 4e4ffa6526 | |||
| 8975f2d92c | |||
| ddf839beb0 | |||
| 53bd98394b | |||
| 84bea96941 | |||
| 4470379dfb | |||
| f727561553 | |||
| e6dbd55644 | |||
| 0df6fda9e8 | |||
| 1d58f59190 | |||
| a30a41c2cc | |||
| 7a82b941cb | |||
| 480e126437 | |||
| 92d43d042d | |||
| f2b172738f | |||
| 4fe1217a69 | |||
| fa82fc49bb | |||
| 5d1e340cbb | |||
| abcbdc4a25 | |||
| 8fbb1e5565 | |||
| 149a08914e | |||
| f5c51f7cf7 | |||
| 280b3c66eb | |||
| 3a3732a6c6 | |||
| 2093c19127 | |||
| c2823aae39 | |||
| ec1a896795 | |||
| a46964a258 | |||
| b4036f44f1 | |||
| 1ad6605dfb | |||
| c6add663f8 | |||
| 1ac081ef4c | |||
| 074e90d046 | |||
| a2c3050c51 | |||
| de60209e2b | |||
| d385480b52 | |||
| 6b1cea6c91 | |||
| d2b5f86639 | |||
| e8877daca3 | |||
| b9dffcb069 | |||
| bcd19dd0f5 | |||
| 48926a7ec4 | |||
| 8981572674 | |||
| f836fe2056 | |||
| 1067714c2c | |||
| 6b0564d6e4 | |||
| 6c17f7ad49 | |||
| 44bad588b4 | |||
| 44c8974aba | |||
| 6a1eb231dd | |||
| 39ab409970 | |||
| cb1817f440 | |||
| 0b09c259aa | |||
| d446e40741 | |||
| 00bcb4cf02 | |||
| 92ad6f3baf | |||
| fb9c38b75f | |||
| ab295f0f10 | |||
| 197d4d1c81 | |||
| bf95193d5b | |||
| 375c0a02bb | |||
| ac10e00d7c | |||
| f5498a4660 | |||
| 95968c7e0e | |||
| f59030ecaf | |||
| da7f068d5d | |||
| e845c59229 | |||
| c391e84451 | |||
| 9b5dd92dad | |||
| 4a7539cd06 | |||
| e8a021e1b0 | |||
| 8b92872c1f | |||
| 6f99ac676e | |||
| 7433cec2c4 | |||
| a1e5ce246b | |||
| 97ba76ab47 | |||
| 866dee7cc2 | |||
| 4f1143420c | |||
| 702aefa43e | |||
| 86ca20403e | |||
| 356b5c1750 | |||
| 37c89ffba3 | |||
| 4a83efcd61 | |||
| 871308cf25 | |||
| 90f1ea7896 | |||
| 1c308b2710 | |||
| 5227bc9167 | |||
| 4f93ee29e6 | |||
| 07a51589cb | |||
| 67847c9485 | |||
| 96071e157a | |||
| f70da4b33e | |||
| 92cd6e8435 | |||
| 0637682eb0 | |||
| af1888b21a | |||
| fca61d68b0 | |||
| 954e9fc7c1 | |||
| 9750cfe6bf | |||
| 1910c8fc0f | |||
| 7f9932129d | |||
| 8947c0d2e7 | |||
| 48015d3f43 | |||
| 74ffdca614 | |||
| 2ae3c6bf29 | |||
| 28e33e1883 | |||
| 9615120586 | |||
| 3d557be918 | |||
| b166b1a383 | |||
| 905e573520 | |||
| 15b91fb6a4 | |||
| 2c64c729bf | |||
| 2ddc7897e0 | |||
| e359cc5da9 | |||
| 73ae9f8879 | |||
| 7ea8b983d4 | |||
| 4b652e6878 | |||
| 90c541d117 | |||
| 540cd272e0 | |||
| 0cc665a26b | |||
| c0965f7205 | |||
| e092726070 | |||
| 08bf7acb29 | |||
| 2f7d45db09 | |||
| 7c3aa65166 | |||
| 5637ff4228 | |||
| 7f47ce268f | |||
| 0af2e4af03 | |||
| c379c833e4 | |||
| f63e1b3760 | |||
| 16f7bdcd33 | |||
| bebad5127c | |||
| 4907003d3c | |||
| cac62b31b1 | |||
| 5d3b3319ad | |||
| 736b5a2a06 | |||
| 92a9aa6d3c | |||
| d908fa5e38 | |||
| aafb7e22df | |||
| 2c1f0d248c | |||
| e744fe666b | |||
| ea45025bf9 | |||
| ea19514b53 | |||
| 1186025c89 | |||
| 85b6842557 | |||
| 86685a9db4 | |||
| 256a5b94c5 | |||
| d1021749bc | |||
| 27229da36f | |||
| 44d969c0d2 | |||
| 9170a5abc1 | |||
| 1aa734cb83 | |||
| 3695ae07d5 | |||
| fea6e1b236 | |||
| 2ff72867e3 | |||
| 0419de4baf | |||
| 843b0b3eb1 | |||
| 9f2c4c6b59 | |||
| 9c64193434 | |||
| 99fbe4e9ff | |||
| ffa014f910 | |||
| 1edb856214 | |||
| c2cafd1a80 | |||
| da8a79a857 | |||
| cb73017fbe | |||
| 56d6014626 | |||
| 3bbb510b7a | |||
| f2e6c61bfa | |||
| f1cb13fd94 | |||
| 7d1e7f2b58 | |||
| 6229148307 | |||
| 18288544a5 | |||
| de5f310011 | |||
| 7ef998e438 | |||
| 0b7c36c456 | |||
| bf8d3a044f | |||
| 000de4c72e | |||
| 5d7ab54340 | |||
| d5e8fadc64 | |||
| 5db2bef7b0 | |||
| 41a03c98f3 | |||
| af646e4496 | |||
| b3590430c9 | |||
| 0aea2bac74 | |||
| 2915a1a145 | |||
| 14e0aeb4f3 | |||
| 638f2e09ed | |||
| 880e2f0d30 | |||
| e5698e6c8f | |||
| aa075bdf6b | |||
| 96b00e95f5 | |||
| 9394e3ec42 | |||
| 435b5a2b27 | |||
| 4ad563f8fc | |||
| e94f56a185 | |||
| a2c140c87f | |||
| 1a979a8498 | |||
| a020e985f2 | |||
| f8d9e6eeb8 | |||
| 564c81575f | |||
| 8b16a7a8c7 | |||
| 6b245f34a2 | |||
| f17a77c18e | |||
| 17ac5ffe99 | |||
| 2b04f0b585 | |||
| 22ed71cef4 | |||
| 1f5d672cbf | |||
| c136bb4ea8 | |||
| e28a3ac945 | |||
| 3829f574ca | |||
| d8ac919543 | |||
| 97e4f39492 | |||
| 9d58a1be8b | |||
| 4be34d3cf1 | |||
| 6ef57bf7d6 | |||
| c70d833a5e | |||
| 7b10240297 | |||
| 0f0543d3f6 | |||
| 738c8cb630 | |||
| 09c41b6e20 | |||
| 324eb4d4bf | |||
| 0f24048cd5 | |||
| 0ffdc485d7 | |||
| 6810a9d593 | |||
| c96f1d28e6 | |||
| f2d86f2782 | |||
| ee88ea90ee | |||
| 7c1bf15618 | |||
| fdb170b443 | |||
| 1fa7ae4f0d | |||
| 7641890910 | |||
| 72c78fc163 | |||
| 8d8c076931 | |||
| f3f495d23b | |||
| bc3729c930 | |||
| 5a0c8c9f32 | |||
| 367a69cdfe | |||
| e8230ee01f | |||
| 99f1ad0ea6 | |||
| 11d3326d73 | |||
| 7dd88213b1 | |||
| e0cb165927 | |||
| 1e660c8e85 | |||
| e8704adc67 | |||
| 43d6ddd7cf | |||
| 6e0ac7fa75 | |||
| 800aca6f0f | |||
| a228582984 | |||
| 9f9f8e0e39 | |||
| 3d6f4629e9 | |||
| 6fca0dac0e | |||
| 22e9aea827 | |||
| e064e96c96 | |||
| b667236c92 | |||
| e4df563811 | |||
| d86abebb50 | |||
| 1b3bf89ee8 | |||
| 291063bd98 | |||
| 4c298ca484 | |||
| 650dc8bc6a | |||
| 2ee8236365 | |||
| 4707c02a34 | |||
| d0faa14760 | |||
| 19725deb7e | |||
| 81cafd21d0 | |||
| 365c1c3f3e | |||
| fbc3120c47 | |||
| 66093c3278 | |||
| 7d4ca441d5 | |||
| cee8598b3f | |||
| 256e845e7a | |||
| f39ac6f58b | |||
| a397de448b | |||
| 62adad0739 | |||
| 3d647fe55a | |||
| 65b0511d9e | |||
| 16a33e42e2 | |||
| 81c0e000e7 | |||
| d4a5a714fb | |||
| e60e0c02c0 | |||
| 5fa35c5273 | |||
| 95ad6b8ab4 | |||
| 1b34eb14f8 | |||
| 412480b326 | |||
| 0500824e57 | |||
| 3e0f3d05e2 | |||
| 62f9b16139 | |||
| 80523828c7 | |||
| 979a105071 | |||
| ea81b74e3b | |||
| 1864440f5c | |||
| b96594b17c | |||
| 97960a2232 | |||
| 5fc73f87f4 | |||
| 8ca5cb18a3 | |||
| 517f3b7709 | |||
| 603f863b71 | |||
| e40a93e389 | |||
| 6279ae63ce | |||
| cb2a21ef19 | |||
| edc82d77a5 | |||
| e89612e5b9 | |||
| 9150e69783 | |||
| 4b95112724 | |||
| b45748fead | |||
| 0b3052ced2 | |||
| aae53fb9da | |||
| 291d32bd35 | |||
| 6386be09c2 | |||
| 05bed05afe | |||
| 5b9d197b7d | |||
| 9cce6945e6 | |||
| 33f1e51ebc | |||
| d466184a02 | |||
| be3f120548 | |||
| 2e303da384 | |||
| dfc3fd8e58 | |||
| 51e3ec27d8 | |||
| 1ec76ce248 | |||
| 9012afc534 | |||
| a19045f9d6 | |||
| d18c8976b9 | |||
| 5485ef4f50 | |||
| f4a56ae106 | |||
| 280316dceb | |||
| 9094ee0dc6 | |||
| cad489480c | |||
| 9655d28a23 | |||
| 76d3299690 | |||
| 7b846b42e3 | |||
| b8ca60ebd5 | |||
| ddb9f0b95d | |||
| 93f4277b3c | |||
| f841a8ba58 | |||
| 4d4825de75 | |||
| a71bac037c | |||
| 02e4e4da01 | |||
| 0bf6f9d596 | |||
| 472c6efc12 | |||
| 66d88ed10b | |||
| 4439b3ad22 | |||
| 7c6a838d7f | |||
| 5c951afa64 | |||
| 878e06cd36 | |||
| 4ef879d1f2 | |||
| b74f91b868 | |||
| 693790a19f | |||
| 98724979cb | |||
| ab430355ec | |||
| 060a8f6345 | |||
| 97aaf3ef9b | |||
| 6eb7f5f962 | |||
| 313fe1ca2c | |||
| ce34fbe502 | |||
| 562e9bfebb | |||
| c2fbe5c606 | |||
| f53cb0fae7 | |||
| 9d8b93a269 | |||
| e65ef95027 | |||
| 3455c2955f | |||
| 4abd395efa | |||
| c332bd198a | |||
| 6c395cc07d | |||
| 7eea2fba9b | |||
| e89115a027 | |||
| 00ffa42f50 | |||
| e55825fd88 | |||
| a50a9fcf9a | |||
| ce8679a978 | |||
| 5d6348fbf9 | |||
| 63e9d47f09 | |||
| 8cc7343201 | |||
| 2aabd54e6a | |||
| bb56f274c8 | |||
| 241d7335e4 | |||
| bc7037bb52 | |||
| e7e5814214 | |||
| 4c9fbd3fba | |||
| 566d397bd1 | |||
| 2da65cdd5f | |||
| e3eae7fbe8 | |||
| 91601e5647 | |||
| 882c09b870 | |||
| 1d7a130bd1 | |||
| 202fb5fef3 | |||
| f73d7b4cb9 | |||
| 48d3d38e84 | |||
| 11c903a3e9 | |||
| 4992659b46 | |||
| 7285eca249 | |||
| dc8021e952 | |||
| fb18143791 | |||
| 475551b0d9 | |||
| 5447da0588 | |||
| 1b18e02fe0 | |||
| 2e63a4c037 | |||
| 2d0e0c8fcc | |||
| 2b61e10d91 | |||
| 97ce72ed07 | |||
| fcbf9f7d8f | |||
| c2a68aa0b8 | |||
| 080c70e8a8 | |||
| c11030dde5 | |||
| a2e6a8e41f | |||
| ec5f614a25 | |||
| 23338319a0 | |||
| 191c7fdf30 | |||
| 1342ed2afe | |||
| 69b0193535 | |||
| db2489a555 | |||
| b191126f36 | |||
| ef0de38624 | |||
| 3d0a43d0e7 | |||
| 874be7ea8b | |||
| a93034ad59 | |||
| 134cee6adc | |||
| cb64e8d504 | |||
| 35a6dfb52a | |||
| 1c276db76f | |||
| 400e0f1dd4 | |||
| 9a7ed81759 | |||
| 6f40cf9beb | |||
| 307028734f | |||
| cd2d7c91c3 | |||
| 8b375d66fa | |||
| 8f367abe0b | |||
| fdc84be0d9 | |||
| edfceaad14 | |||
| 40fda5067d | |||
| 573706e5e4 | |||
| 1ef4acc2af | |||
| 6035db3231 | |||
| 2cd44412f6 | |||
| c149fe31fb | |||
| 0e24d638c9 | |||
| 5c056f0c4d | |||
| 62b838427f | |||
| ad529c10ab | |||
| 8ef7399612 | |||
| 939c1f0f29 | |||
| 6b48cf574d | |||
| 1478819258 | |||
| f53fbd6282 | |||
| 60e6e1f242 | |||
| 7a5f63e0f5 | |||
| c0e325dfbf | |||
| 62e775b7c2 | |||
| 37676a296a | |||
| bcc4548f7b | |||
| 60714b5ca4 | |||
| d632634e56 | |||
| bec8b40edb | |||
| ab361eef72 | |||
| 1f16adbca7 | |||
| 1677ef3189 | |||
| 36defdfbe9 | |||
| 7ba6e4adc3 | |||
| ee2cbc80b8 | |||
| b4d960e795 | |||
| 0f716d9053 | |||
| cdbfd22296 | |||
| de801a4f23 | |||
| 1376a615b7 | |||
| 1fbc9ab85e | |||
| 9a8a3601a7 | |||
| f1e68e9bd0 | |||
| 5228e6e6c7 | |||
| 5b977cef54 | |||
| a802deeb51 | |||
| eaf6375410 | |||
| d1daf21a3f | |||
| 98c83c8509 | |||
| b25731f621 | |||
| 563f5ec713 | |||
| ad25ae43d5 | |||
| b058e72fdd | |||
| 38ee8ccfe3 | |||
| 53161f76a6 | |||
| 742a929966 | |||
| 63b3646e73 | |||
| 794c73a613 | |||
| 59fc2a4c15 | |||
| 6a144f86cf | |||
| f218e11d78 | |||
| f6bcd8a2c2 | |||
| bf0cd5a6cd | |||
| fc1504f2e5 | |||
| 7b4d545dca | |||
| 89f27d0b2d | |||
| 3728f42185 | |||
| 2d6c4c6aee | |||
| 83b8ec6a99 | |||
| 5e87f6d806 | |||
| f2da932777 | |||
| 4b3e6d7a58 | |||
| c50d671bdb | |||
| 5290cbea94 | |||
| f6b55a4e19 | |||
| 4e0d2207a3 | |||
| f089d5714f | |||
| be26c04dd1 | |||
| cbcfe37e28 | |||
| ef0fde8615 | |||
| cc728642ed | |||
| d9360a66af | |||
| 4040f7afca | |||
| 758c347258 | |||
| cf76a605d2 | |||
| 1cfcfc465e | |||
| fc611dee57 | |||
| de8b23db4e | |||
| b036dcece6 | |||
| 94c83245db | |||
| c14146926a | |||
| 29dffd06b3 | |||
| 9646d18624 | |||
| 170d9a27ff | |||
| 4d43374b31 | |||
| 085332da27 | |||
| 4dae3ee33b | |||
| dd729ec649 | |||
| 9ef582bd6f | |||
| a4fec6323c | |||
| 4e9d56441a | |||
| af71ae9dd9 | |||
| 305563e44f | |||
| f042fd2e88 | |||
| 5a13932dd9 | |||
| 06c9967971 | |||
| 6e8d667c6a | |||
| 0529ce2bc4 | |||
| 639552ae8f | |||
| 0d1cc8581a | |||
| ed54b55a63 | |||
| 12d8a1f92e | |||
| ed76e54904 | |||
| c2bb936586 | |||
| 42b334efcd | |||
| 56367f257a | |||
| 55db243362 | |||
| 395f4e904c | |||
| 3c5a39a99a | |||
| 572c3be647 | |||
| 06e7d6c3df | |||
| bcde888257 | |||
| 1767213321 | |||
| b36b4e4ad1 | |||
| 8857eb4e78 | |||
| fce3414c65 | |||
| f0f23a2c61 | |||
| a77f78f08f | |||
| 9269792a8c | |||
| e87d507c0c | |||
| 5fc07180dd | |||
| a35990ee4c | |||
| 7d71954674 | |||
| 1cee55bf45 | |||
| c11ca2ff64 | |||
| f88756cb53 | |||
| 54d284cdac | |||
| 011d6bebfa | |||
| 447dc54710 | |||
| e2ff6327eb | |||
| a293b6fc77 | |||
| e56ffc689d | |||
| 4cca6a72d8 | |||
| 6e79b29678 | |||
| a432ffc0ce | |||
| 205cb2c29d | |||
| 1594b46f68 | |||
| e1e7791dff | |||
| d3accbc085 | |||
| 69cc5a559e | |||
| 9f8f2f6730 | |||
| 498eb9330b | |||
| 6047322f0c | |||
| 2ce6a031a4 | |||
| 323bab7d4a | |||
| 73f45b8772 | |||
| a9407f055c | |||
| 2eb1134828 | |||
| 7e35571b94 | |||
| 19f7e3631a | |||
| 094f2da774 | |||
| 1b9d22a491 | |||
| df1e19dd47 | |||
| 8c4fa838fe | |||
| 2f6df2f9af | |||
| 446b0c2dfa | |||
| 0eb963d491 | |||
| 156484ac80 | |||
| 6511d4c21c | |||
| e2a8c70f3d | |||
| 53386e4d42 | |||
| d82d25cc10 | |||
| d79b4b2352 | |||
| a206187802 | |||
| e48e810005 | |||
| fbac3ebad1 | |||
| c88a042c8b | |||
| a78d76d143 | |||
| 33ea0af06f | |||
| 55a15f5a21 | |||
| 3dd5a32cc0 | |||
| 0df86c6aaf | |||
| 383ff6c234 | |||
| 2cf920a1d4 | |||
| dc8bb7cc2f | |||
| cfe51035fb | |||
| a2afbd3080 | |||
| dcb17243f8 | |||
| 6e706b3a8c | |||
| f5e3d79cc7 | |||
| 1febfa4f4e | |||
| 9601d0fc45 | |||
| 9f8f0262c7 | |||
| e718a4f843 | |||
| 2257103ee6 | |||
| 9e58aafa4a | |||
| a13096bdfe | |||
| 53c3958b2b | |||
| bbc0bcae1e | |||
| 2b52bf4539 | |||
| 40f315a259 | |||
| f191915b53 | |||
| cb0e79972d | |||
| 2a980d9fc0 | |||
| 6daeb56550 | |||
| 65ae3e1d8d | |||
| 403b93daf6 | |||
| ff0380b456 | |||
| e7bb6c8767 | |||
| f9c7b4e441 | |||
| 0540b8e1ad | |||
| fcde6f686e | |||
| 444dce4aeb | |||
| 1a0b8fb37f | |||
| 4fcc8abf55 | |||
| 131b92e9fe | |||
| 5391b529b6 | |||
| 92aea38230 | |||
| 590ca98463 | |||
| 16936aa452 | |||
| dedb1e0c80 | |||
| 63163737c2 | |||
| 9f99e88c92 | |||
| b6f748ad8f | |||
| 1f3f70a642 | |||
| edfb59a87d | |||
| 999b01c814 | |||
| e7f52cbf98 | |||
| 311d1c805d | |||
| 2908c97432 | |||
| 122423e535 | |||
| 639865f3e2 | |||
| 42e214eb17 | |||
| 73c29d44c3 | |||
| ab6148f0b4 | |||
| bf0243c253 | |||
| b53c9daf50 | |||
| 7fa482e5c6 | |||
| 391bd119b8 | |||
| cdd9b1fa3b | |||
| 99487d0e2b | |||
| 5ff98258df | |||
| 41bc4832f3 | |||
| 69dbb2e17c | |||
| 3dbaf96a9a | |||
| 15d8b891d6 | |||
| efc09a7b47 | |||
| 6e84e5ce9c | |||
| 7d5d2b86cf | |||
| e887600c7e | |||
| 8216faae6e | |||
| 8c1b9e1557 | |||
| 57595c70b0 | |||
| cf568d2782 | |||
| ba07e46cf8 | |||
| f19ba1b0db | |||
| 51887f1cbc | |||
| 539e285f86 | |||
| 75d57640eb | |||
| 56316ffcca | |||
| 580dbd0905 | |||
| 42a394628e | |||
| 0233845994 | |||
| f42647426b | |||
| b54521de51 | |||
| d7e09167fa | |||
| 26d20e458c | |||
| 3099d55b40 | |||
| 72218929b9 | |||
| f99106ccb1 | |||
| dd6f9c5ad3 | |||
| 7d2209860e | |||
| c82a927556 | |||
| 59e9d80b18 | |||
| 732d30c919 | |||
| 8586490162 | |||
| f8a3cf2d3d | |||
| 826ca5ece5 | |||
| 73a3542ab2 | |||
| dfbe243b4c | |||
| f7d76ebf1d | |||
| 34c36c09ff | |||
| 765dab5d8d | |||
| 063d02a9cb | |||
| 6e5e9ab7bc | |||
| c8c7ac45d1 | |||
| 14181ec70d | |||
| b20e5a1e01 | |||
| 64d222a1e4 | |||
| e4554fe9ca | |||
| 8ec736789c | |||
| 9a323a9a8d | |||
| 298e626b6e | |||
| af7308e395 | |||
| 7c80fcacba | |||
| beb23efa88 | |||
| 1b65f5f164 | |||
| bb336f1bc7 | |||
| 36d386b451 | |||
| 9199f48a3c | |||
| 5c88c585a0 | |||
| 771b1490d2 | |||
| 4bbdbf6332 | |||
| 7dc10fbe46 | |||
| 90ca83bd96 | |||
| 4ee92fc637 | |||
| 1d39488061 | |||
| d87cd32ff4 | |||
| 2a50ae905d | |||
| f536584d7a | |||
| fa3bd58b7f | |||
| 1f5d2c49fc | |||
| 3e585c3438 | |||
| c23e792f68 | |||
| 02d3c93c2c | |||
| a07ef0f5ee | |||
| e415251f30 | |||
| ddbc143178 | |||
| d54715a9c3 | |||
| eb9507707d | |||
| 3377de1fe3 | |||
| b5807e0788 | |||
| c86e82039a | |||
| 999b2267c0 | |||
| fbf9585b5a | |||
| 470365644f | |||
| 7b3847cc5c | |||
| 2b0e1a1dec | |||
| 316e140329 | |||
| 02c4c3b03d | |||
| e5405e191b | |||
| 839ea61d55 | |||
| 02f27f8cbc | |||
| 35b5138593 | |||
| 809c5ed051 | |||
| 412451f9d6 | |||
| 35802f2089 | |||
| 8f6f0f8401 | |||
| 44d95badc4 | |||
| d622faba17 | |||
| b5945d3d5c | |||
| 52cd6fb1dd | |||
| 04681babf1 | |||
| e63c068720 | |||
| fb5b465a4e | |||
| 59ea3c7949 | |||
| 6f5306dbdc | |||
| b5388fdf2f | |||
| d2904c1fd5 | |||
| 7718feedd5 | |||
| 56add277f9 | |||
| 86f772ad38 | |||
| 24c99551c7 | |||
| 9441d2a33a | |||
| 3922091a58 | |||
| 1107ce8fd8 | |||
| 3d10cd1adf | |||
| 02ac3943f2 | |||
| 44b672b6f5 | |||
| 0239d8350d | |||
| bada5fe941 | |||
| 6db871958e | |||
| 0b557fe265 | |||
| ce08627396 | |||
| 200ec5dcfb | |||
| 8a6f55a63e | |||
| e327f5e6f0 | |||
| 5849726913 | |||
| e063613a7f | |||
| 48d2cb4975 | |||
| 59412b1673 | |||
| d1a235272e | |||
| 7db9627ff6 | |||
| 83550cd153 | |||
| 77471bd9d6 | |||
| 0e94211ff1 | |||
| f6e7bba354 | |||
| b2255e5b27 | |||
| 7b493ff4c8 | |||
| aeef163349 | |||
| 26f2352059 | |||
| 67e38d8de2 | |||
| 2c3a4cbabf | |||
| fed3ea597c | |||
| 547b2fc9e8 | |||
| cf07f4aef1 | |||
| 3dc4aea053 | |||
| afa29facc6 | |||
| 8c0120bdbb | |||
| a3e72c5b43 | |||
| 33efc86788 | |||
| ec6be34c31 | |||
| fd49a1e80a | |||
| d1d6855d58 | |||
| 504b9e7051 | |||
| 9cb64fd087 | |||
| fe9ccf55c1 | |||
| 4840da2c1b | |||
| 543fb282fe | |||
| 9b7ae498d2 | |||
| 5668bcf19b | |||
| 66c25b3cb6 | |||
| e234fb32d9 | |||
| f70c67ad7f | |||
| cf3cfdb2bc | |||
| 394f1f2049 | |||
| a9819542d4 | |||
| d0e3b8c4ee | |||
| e3681cf993 | |||
| 26c717a1bf | |||
| 6efdbf2950 | |||
| b45b082c06 | |||
| da21a649c0 | |||
| 347736f2b4 | |||
| a6649b2d6b | |||
| 33a78c1919 | |||
| 3b4b669038 | |||
| 26b666abcd | |||
| 32e2a8ba2c | |||
| fdc399b44c | |||
| ec43661664 | |||
| a05a655037 | |||
| ca3833e71b | |||
| 3910b047d4 | |||
| 15c1381c1e | |||
| c0e65d9a36 | |||
| 38ff490b60 | |||
| f8fa41d4bf | |||
| b74c65cc7c | |||
| 624e5ae633 | |||
| 71935e7099 | |||
| bb9a551318 | |||
| 457ec7f6f5 | |||
| 433b88c0bf | |||
| 9f8911536a | |||
| eeb09c54d8 | |||
| 52a3777aae | |||
| ea1f451d35 | |||
| 28795e549b | |||
| 0a667bf18a | |||
| 2d8a4e13e6 | |||
| f1702b5693 | |||
| b89d0837a6 | |||
| cba6a6ec51 | |||
| d74623faf9 | |||
| db4bf08475 | |||
| f9c2327bf5 | |||
| beab9870cf | |||
| dbfb93a50f | |||
| 6b66cd7f29 | |||
| 08089e0654 | |||
| b2ef973f16 | |||
| d862f8cd53 | |||
| 9c61e9eda3 | |||
| dc000e08ab | |||
| 5469d59de9 | |||
| 37f640ece2 | |||
| 906898c785 | |||
| 30f6c5f8f1 | |||
| 1a2059c0f1 | |||
| 4fb0050411 | |||
| 5708fb1668 | |||
| 870604d64c | |||
| 9f4bf4267d | |||
| 5c15d57f5f | |||
| 6e1f76185e | |||
| 7fe5ba480c | |||
| 2333ff7b2d | |||
| 5063961748 | |||
| 815c0a394d | |||
| 6d3f42a441 | |||
| 4b76594d8d | |||
| f5144f33da | |||
| 03f7e9e15a | |||
| a8baa4b67c | |||
| f40bebed3b | |||
| 5a036e572b | |||
| cd31f5fceb | |||
| f812174270 | |||
| aeaeb8ba94 | |||
| 2adeb401ff | |||
| 52325cb7dd | |||
| 6265bbf99a | |||
| 8c0c9a5e29 | |||
| 8638c73a4e | |||
| d2d4038357 | |||
| f8fdbaf566 | |||
| 0b2536dd3e | |||
| b2b7d8d64e | |||
| 67c34794e8 | |||
| 30f0cdde6f | |||
| 71637cc282 | |||
| 56402db7ee | |||
| 3e76d380a1 | |||
| 4873165dbc | |||
| 277706505e | |||
| 9f09aa725b | |||
| 06fee385e1 | |||
| dc4ef1163f | |||
| 2928837b76 | |||
| a5124b118b | |||
| e7db878188 | |||
| 0b164a7989 | |||
| a4088685a0 | |||
| fc06963c56 | |||
| 9680e7460c | |||
| 271e53a6bf | |||
| 3888483fb4 | |||
| d67e72912c | |||
| b843989719 | |||
| 7717450044 | |||
| 98947c10bb | |||
| 6aa7266084 | |||
| bd5656bf89 | |||
| 1e4795e653 | |||
| c8e0090870 | |||
| 2dd9d8338b | |||
| 8d3c82de19 | |||
| 3bff10e17d | |||
| 6562a5191a | |||
| 5ef159876a | |||
| 1bb86d8984 | |||
| edd735ce80 | |||
| 4fd06b5ea8 | |||
| f6d997ca87 | |||
| 5963efcec8 | |||
| f8fbfee49d | |||
| 4d7ee63d77 | |||
| 21b97f68fa | |||
| 95c91b4dc6 | |||
| ca1b35a351 | |||
| 84177d38d4 | |||
| e21589da86 | |||
| 0768971f35 | |||
| 6c42a7f6e4 | |||
| a65f3bd116 | |||
| 822e508d13 | |||
| 1611aeedce | |||
| 7c243756bc | |||
| 43b53df0a0 | |||
| 66c6c2400a | |||
| 30096a5ae4 | |||
| c70afc24bd | |||
| ce53b7adb1 | |||
| 25fa70fe9e | |||
| 724957fbec | |||
| 9084ef35b4 | |||
| e58b1054ea | |||
| 24de0866f7 | |||
| 0cec99361b | |||
| 8ba745030a | |||
| 4ddf897719 | |||
| 9be7eb67d8 | |||
| 56bba522ac | |||
| b6c1b3fb96 | |||
| 82de13d95a | |||
| 92dd6fb575 | |||
| ced58a047d | |||
| 2d98b877a2 | |||
| a26b91291c | |||
| 46a649afc1 | |||
| 3ce242886b | |||
| 3b5538a09c | |||
| 796519f6a7 | |||
| 2365a9caab | |||
| 425b5d0478 | |||
| 628560850a | |||
| 69f058e532 | |||
| c66b660c10 | |||
| 4fdb3322cc | |||
| 73122400e3 | |||
| d1cdfafe22 | |||
| 91e8a2cf0e | |||
| b5721a92e9 | |||
| cefe4b773c | |||
| 332346449f | |||
| 2c199e7c42 | |||
| 2a32864856 | |||
| 9481bbd2ef | |||
| 08aad5461e | |||
| 0bab9474ae | |||
| 1f802eca46 | |||
| a02df6c980 | |||
| e0194b2b95 | |||
| 74f4886ea6 | |||
| d9119921de | |||
| 4a12ec6fc0 | |||
| 0c855cdd6d | |||
| 89d44a5f60 | |||
| aa47018197 | |||
| d5cd2446e4 | |||
| eb386fb0fb | |||
| cb24b84bff | |||
| d65522a9b4 | |||
| fa91d0b705 | |||
| ae43cfaaf2 | |||
| 8bbcb05303 | |||
| f2713462cc | |||
| ac9d406862 | |||
| 74738022da | |||
| aae8d5d639 | |||
| 372ee9b6b6 | |||
| 943e21f507 | |||
| b6308bab4f | |||
| 6a4df2a641 | |||
| a92eb4d10a | |||
| c03e52c06f | |||
| 66e663757a | |||
| d279f61d0b | |||
| b59d4791cf | |||
| 680a3802d7 | |||
| c3ee97103f | |||
| 489fbe628a | |||
| 9ba42ec950 | |||
| b54facdbd8 | |||
| 5c790b8540 | |||
| ef32b49e50 | |||
| 8fb09d07ed | |||
| 710d3360ac | |||
| ded036b93e | |||
| 364e6a1341 | |||
| 2aec91d8c0 | |||
| 4f0c880e3e | |||
| 13d623f350 | |||
| 9aecf79d7f | |||
| 2e8076d909 | |||
| 655939147a | |||
| bf899022d7 | |||
| ed5aa4a67d | |||
| 22bf3549b6 | |||
| f260a8be66 | |||
| 068ab8ab36 | |||
| 6fde585504 | |||
| c45cc6928d | |||
| 110b7df4d5 | |||
| 73eea20fcc | |||
| 4f20a68b33 | |||
| dafef46a1b | |||
| e283831841 | |||
| d13c7b6b3e | |||
| e7d1477a7e | |||
| 2810f6afc1 | |||
| 821811cf0c | |||
| fea666bd1e | |||
| 193254de94 | |||
| b919719aeb | |||
| ea051c6d5f | |||
| 893b3c629d | |||
| c07c942659 | |||
| b1d6d84e6f | |||
| 1afb248e4d | |||
| cad85d76a5 | |||
| 29ad851a9c | |||
| cb9eaeeff9 | |||
| 7c9493cbc2 | |||
| d21c01f8d1 | |||
| f4f06c9777 | |||
| 437b6f3f0e | |||
| a163c90f2b | |||
| 9d9d22fcba | |||
| df5e175b86 | |||
| 0f8bbfd64c | |||
| 8c270288de | |||
| 7bd7cdd867 | |||
| f618713551 | |||
| de329e49a8 | |||
| 2aa6f771a9 | |||
| 7787fcff8e | |||
| 6e576d208e | |||
| 00751dc5d3 | |||
| e456fb8f88 | |||
| 9dd579a6d5 | |||
| fbd36a4347 | |||
| 7f8bfb22de | |||
| 943b513a52 | |||
| 221eaf1a81 | |||
| 41f1ec445f | |||
| a289723f66 | |||
| a3f6efecb8 | |||
| 2587cf3b95 | |||
| d535331b4b | |||
| 6d85399ec5 | |||
| 7a113474f0 | |||
| 0bb7cc0a1a | |||
| 322ff3fcb9 | |||
| d329cabf07 | |||
| 38c48e8b6a | |||
| cd0b349496 | |||
| 7f1932e282 | |||
| 17f2fb4471 | |||
| 022a9cc6df | |||
| c88db3221c | |||
| bd3e1299a3 | |||
| 3a97688804 | |||
| 3f027b2698 | |||
| 916754ea6d | |||
| 335633a5e0 | |||
| 925bfc2a99 | |||
| d19c767ad1 | |||
| d2347d9972 | |||
| f8dcff9fc4 | |||
| e5716922a3 | |||
| 65e956a01c | |||
| a93829557b | |||
| c21d475bbd | |||
| 935dd046da | |||
| 1b2d9f0c5d | |||
| 4baea67e75 | |||
| 1e8332f36a | |||
| 096696bed7 | |||
| 756cd1ee47 | |||
| 64534542a9 | |||
| b22e31c302 | |||
| 008beb4896 | |||
| 576bcc6979 | |||
| 4ec345a239 | |||
| 972bfbcccc | |||
| f59fbaf0eb | |||
| 631ed8c0fd | |||
| 41e8a2a7d1 | |||
| 599626b709 | |||
| 0ae17ddb1a | |||
| 7353c26a4f | |||
| b8769e954e | |||
| 81cd2d9be9 | |||
| 90707c453d | |||
| ec0e9f078c | |||
| 98b537575f | |||
| 233195b020 | |||
| 7d71e28bfc | |||
| 13e09953af | |||
| a85ca4108c | |||
| 8620febeb3 | |||
| af4c047c41 | |||
| bec9b34f54 | |||
| 9989daec94 | |||
| c86dd7397d | |||
| eefc81ed8c | |||
| 91c717376f | |||
| 344c918b65 | |||
| deeda519b0 | |||
| 2db12b9d84 | |||
| 378588c67d | |||
| 119b6bdfd5 | |||
| 8751a2d330 | |||
| 4543ddbcc2 | |||
| 77a7b18b29 | |||
| 749aef1a64 | |||
| 8091b6bc1b | |||
| 4efa845580 | |||
| 8c9ae90753 | |||
| d1117aafac | |||
| a565182b2b | |||
| 650b0ae646 | |||
| b677619f32 | |||
| 2fa8f09a21 | |||
| 73c9279907 | |||
| 7d8912f170 | |||
| 2601ba53d4 | |||
| 81baaaa98a | |||
| c2638131b4 | |||
| 586486b81c | |||
| af75ac00e2 | |||
| 67b66c1780 | |||
| b3dce680b0 | |||
| d01a59650f | |||
| 5ae987d48e | |||
| 6a6ecbf826 | |||
| 4bdf180145 | |||
| 6ebb8c2e91 | |||
| 5eae7a6328 | |||
| 7d81c979fe | |||
| c06ac00677 | |||
| 85c754b456 | |||
| 35d3547b62 | |||
| 8661f42fce | |||
| a28098c4f8 | |||
| d45f34ee8b | |||
| d552f8dc43 | |||
| b45360b49e | |||
| fffdf8d671 | |||
| 2634134481 | |||
| c0ac71611b | |||
| 63ecdfefe3 | |||
| 6345e8e467 | |||
| e96545ca29 | |||
| dc08858e0f | |||
| f5787f9ba0 | |||
| a271fe11e9 | |||
| a20a3866d0 | |||
| 28d25fdf33 | |||
| f13ad4fcb3 | |||
| a524410b0a | |||
| 8e23d8d557 | |||
| 59531f005e | |||
| 4c8cba53ef | |||
| 34cd53249d | |||
| 14ce344a3f | |||
| cc5142000b | |||
| 1ad6532f1a | |||
| f136a1a970 | |||
| a959ec7571 | |||
| e1a6304e32 | |||
| be05c95026 | |||
| 3983e542b2 | |||
| 3d76652b5f | |||
| 6532dbced4 | |||
| fe27ebefc8 | |||
| 6e84613a14 | |||
| 568ebc6199 | |||
| cf1d67d927 | |||
| 8181cc8528 | |||
| b344ee094f | |||
| b042aeacf5 | |||
| fea58d2271 | |||
| ca5da27170 | |||
| 11eab828c4 | |||
| 8ca3f9a9c2 | |||
| deb044357b | |||
| 00c07d2dff | |||
| 185ed3ce0b | |||
| 3b043250b6 | |||
| 3359b3c7ab | |||
| 6b1e483d28 | |||
| d3faa05479 | |||
| 73f17be890 | |||
| 9292ceedb1 | |||
| d1470a9935 | |||
| 38fa137cfd | |||
| a7288d8ad8 | |||
| 0692517f13 | |||
| 4f44e3fc46 | |||
| 14398da51f | |||
| 6e8897d62b | |||
| 69da1e4559 | |||
| abde47fa18 | |||
| f46b406cbd | |||
| 48313b42a2 | |||
| 1e06b57f25 | |||
| 8a6c896dde | |||
| b3c7b07813 | |||
| 65072ddbe5 | |||
| d42fb851a2 | |||
| ea0791a3bf | |||
| 8d4df7f74b | |||
| 4b07eae80e | |||
| 77162ff637 | |||
| e10f414724 | |||
| 53c3f253e6 | |||
| b0f20c9973 | |||
| 5c3ae656a0 | |||
| a98efdfedd | |||
| 3b8eb6731c | |||
| 89bc4707ab | |||
| e5a8b01980 | |||
| 7194542029 | |||
| 06beadba74 | |||
| b10249af7d | |||
| 1f04214461 | |||
| 39d611e870 | |||
| b913d39a50 | |||
| eb60e9aa9b | |||
| 53bb0c508f | |||
| 1c50d3e4b3 | |||
| de724d9570 | |||
| e8293b2e06 | |||
| 904345ff82 | |||
| d16592817b | |||
| 14f1a78608 | |||
| 68c2a68087 | |||
| ae83f729db | |||
| c53f4d0d63 | |||
| cbb3134740 | |||
| 9b97c157f2 | |||
| 11cf244e97 | |||
| 6673bd9212 | |||
| 02dfc5d20d | |||
| 565ff86ab4 | |||
| 5a77790859 | |||
| 66101f8628 | |||
| 2f70b153f2 | |||
| 31fe9979dd | |||
| 4fc6e9240c | |||
| 0eae59ee66 | |||
| 8e6cd47f25 | |||
| ecdbe17fba | |||
| 0e9dcf74b2 | |||
| 5297c2a995 | |||
| edf5e2c14e | |||
| 9180adb850 | |||
| 1b080f1777 | |||
| 0a2584172a | |||
| 1993203d26 | |||
| 3c18cdcb1f | |||
| e767fb8d35 | |||
| 3255422836 | |||
| 67fa06b933 | |||
| 398e468c9e | |||
| f7ee35e578 | |||
| 800b458d3d | |||
| 3f31a4d25b | |||
| 0592abd31b | |||
| 55d546b892 | |||
| f28e42c4fe | |||
| 7cdc849ffa | |||
| eed04b3ff3 | |||
| e2044eba66 | |||
| 06e6d12e2f | |||
| 48fd68ca87 | |||
| 7ad59a7af1 | |||
| bae2c9c1d8 | |||
| 3d171686b5 | |||
| f86b3a32cd | |||
| 59d6113ee4 | |||
| f270f34865 | |||
| b2514d49d2 | |||
| 2951068e0c | |||
| a4dcaa7c14 | |||
| b90de6d89f | |||
| 532a7addd4 | |||
| 5389178644 | |||
| 6cbdc8c8b7 | |||
| 6e6a70b8ed | |||
| 1a0a0423e7 | |||
| b28779b0f6 | |||
| 63fd349e3c | |||
| 481c92c1c8 | |||
| d733730950 | |||
| 93a9e5dd83 | |||
| db9672509c | |||
| ffe69d313b | |||
| 502a44e9f5 | |||
| 5e913b0e9e | |||
| 864651ce8d | |||
| 850deed6c1 | |||
| 63424b765d | |||
| a635e84d82 | |||
| 6991f819f3 | |||
| a22c634cd4 | |||
| 80aaa962ec | |||
| 876ea3db52 | |||
| 1bfc0f3138 | |||
| 5fa9427323 | |||
| 29cea58471 | |||
| 4779bc830a | |||
| dd8a645986 | |||
| 9aa2c52b20 | |||
| 0914b2a474 | |||
| d387a1f4dc | |||
| 3488aa54be | |||
| de541aeba9 | |||
| 5fb00bd6c7 | |||
| fdabc82342 | |||
| e5f90f176c | |||
| 6438547edc | |||
| 0f0ab25fe8 | |||
| fc7a20dd0f | |||
| f8c7237bba | |||
| 00af7d6835 | |||
| 86fb8e5809 | |||
| 29964c3f26 | |||
| ec787d090d | |||
| f9707e6809 | |||
| 5665e5e222 | |||
| 336e5c77fe | |||
| d8b107f59c | |||
| 19197fabe8 | |||
| 3801825793 | |||
| 25e15a16b1 | |||
| 5ac9419703 | |||
| 821e15f1ee | |||
| 0efe03e726 | |||
| 577d6e735c | |||
| 7668123aaa | |||
| 0b87d580c3 | |||
| 170a03cac6 | |||
| 70d8acb812 | |||
| 2670d5a9aa | |||
| 44081671ac | |||
| 462b304bea | |||
| 059f58803c | |||
| e170e9281d | |||
| 5987e03463 | |||
| ddbdfd47be | |||
| 1b83e17d60 | |||
| bc7ed4e7d0 | |||
| 283c7fa88c | |||
| d01ee3163d | |||
| 90457e32b6 | |||
| 4cb6c94693 | |||
| 93c78a27b3 | |||
| 50452848e7 | |||
| 4f70fd9583 | |||
| e6c8354ec8 | |||
| a1e77002c3 | |||
| 099cd52381 | |||
| 0d1675fbaa | |||
| f021da5627 | |||
| 906480b8e2 | |||
| 38b83af714 | |||
| 05dab12b7c | |||
| c0628a64a6 | |||
| 5ecaa9459d | |||
| 24b2277206 | |||
| 8e60d2c72e | |||
| cfe2f9e6b4 | |||
| 0a11b5898a | |||
| be49de6fa0 | |||
| 1ad52e918b | |||
| 53388336d2 | |||
| 4e1496e736 | |||
| 216c964d13 | |||
| 6bb828eb8f | |||
| 511845a1c4 | |||
| 89f10e1605 | |||
| 76b4e93604 | |||
| cec089a271 | |||
| b4bd36c4b2 | |||
| 338eb42b04 | |||
| 8e42fce0aa | |||
| a7900b342e | |||
| 506bbe1c08 | |||
| d32d8cc0ec | |||
| 0cb9655523 | |||
| 3067bef82d | |||
| 486764be03 | |||
| 5e336138d0 | |||
| 4a5180bc0a | |||
| dd28e33612 | |||
| b66c0411df | |||
| c59b114a1d | |||
| 352faeddb2 | |||
| 140d44d826 | |||
| db220001f6 | |||
| 5ac9b5576a | |||
| b23873e0ed | |||
| 284ec35699 | |||
| cb0e629dd3 | |||
| 1aaadd6228 | |||
| e20a357340 | |||
| fef2952d47 | |||
| f4b2e0dd7a | |||
| d3aace98ac | |||
| 3a7f82eb66 | |||
| 3e24b678c4 | |||
| 2ab6ca06ed | |||
| 9ac5041b43 | |||
| 9262422d01 | |||
| 9f04becc7a | |||
| 8485af6cac | |||
| 48f7e6c63f | |||
| e1fb84d6a3 | |||
| 5db9a738c5 | |||
| 145e75624d | |||
| d09b49e17c | |||
| fdc3ca1227 | |||
| 51d47a1455 | |||
| 9504671919 | |||
| e5248db844 | |||
| 551d013b63 | |||
| d65950cda2 | |||
| 15c38a0a4e | |||
| 74ed14496b | |||
| 1fa6fb0a8c | |||
| 3dc6ae115f | |||
| fa36b9b5cb | |||
| 47fff9304b | |||
| 29c0d93864 | |||
| 38ff521851 | |||
| 34de1bffc6 | |||
| 8dc1592278 | |||
| 5b86205349 | |||
| 0d4fbd540e | |||
| b9edabc236 | |||
| 180d9ae9c9 | |||
| 80cc2f0cb7 | |||
| 1927896442 | |||
| bf9c1176b6 | |||
| 166156519a | |||
| d89daa1b25 | |||
| efc17f265c | |||
| 8427e6fd3e | |||
| f1ac712eba | |||
| 0d4394a749 | |||
| 9dac598113 | |||
| 6db573d255 | |||
| 9b21f31b0d | |||
| 2fedecb809 | |||
| b24a8c70e3 | |||
| d6684efd26 | |||
| 644241959a | |||
| 273c1b1922 | |||
| 45682c382f | |||
| 4e6b86f8f4 | |||
| a6b4ca69db | |||
| 6b32e00097 | |||
| 19d310475b | |||
| a8b9df3952 | |||
| bb75c78c1a | |||
| 57ea137982 | |||
| 9721ed0fb3 | |||
| 224863fbd5 | |||
| 1d459d8fab | |||
| 33e0ac729e | |||
| 268ecf42c3 | |||
| 708281f00b | |||
| 56b68a50e9 | |||
| e4048dc2dd | |||
| 5949c772d1 | |||
| 63998b64cc | |||
| fbb3ea142a | |||
| 435f760b5d | |||
| f47129bd72 | |||
| aa42acfe22 | |||
| ddfe6ac5c1 | |||
| 624dff1b96 | |||
| 8d498b564d | |||
| 26561261bc | |||
| 44728be719 | |||
| 678bb1218b | |||
| c496e80eac | |||
| 269db188d0 | |||
| f5afbfd4f5 | |||
| ccd86a242c | |||
| 42a5cb7ad2 | |||
| 6977323d88 | |||
| 7b1d03d45a | |||
| 8a4f1ef51a | |||
| 9b50bb2e81 | |||
| 4f27d779a1 | |||
| 73c6353351 | |||
| f571b66a43 | |||
| 901664ba44 | |||
| 02012b5491 | |||
| 4f57e40c91 | |||
| 832e536a9e | |||
| c2316ca5bc | |||
| 3535edcfa1 | |||
| a4932ed0f1 | |||
| 515d9040a1 | |||
| fe3a743814 | |||
| 8e08cd772b | |||
| 206f80c5f4 | |||
| c6ce380042 | |||
| 939d98d660 | |||
| c9a3420f85 | |||
| 9a1a399bac | |||
| c8aac1dca9 | |||
| 14c17916f5 | |||
| 7b0576d7cc | |||
| ecb118d5af | |||
| efbf187b35 | |||
| 2ea3feba90 | |||
| f265257efb | |||
| 13cc0caed7 | |||
| 2068240e1a | |||
| 7f5901f022 | |||
| a022de6225 | |||
| f5570b7f40 | |||
| 7e1c48694a | |||
| a546f61ea8 | |||
| 7ecac10eee | |||
| ee2e10e86b | |||
| 7752f44a90 | |||
| e01fc3eb47 | |||
| 910c8190e0 | |||
| a62ccc0d69 | |||
| 4f47041108 | |||
| 16cfde0538 | |||
| 6a15d46461 | |||
| 4331ae1925 | |||
| 4d85d916b7 | |||
| 4f4b14dd4d | |||
| 444e650711 | |||
| c65ccaa153 | |||
| 6b54db9b75 | |||
| 3bab470db6 | |||
| adf01cb56a | |||
| bbe3af7f61 | |||
| 3e7d32c807 | |||
| 76e25cb738 | |||
| 8f0dc34847 | |||
| fc6ec2cc02 | |||
| 34b7b07ff8 | |||
| 6c33b73cdd | |||
| 1e86ba4120 | |||
| 89c79aa6c3 | |||
| 4ed748fa30 | |||
| 5569e94f41 | |||
| 892eec79ed | |||
| b248b4a8af | |||
| 39fe467b64 | |||
| 1c301ec889 | |||
| de5690ddcb | |||
| f376c8f7ae | |||
| 2e199d47a8 | |||
| 96269db93e | |||
| d35db63d73 | |||
| 9d003486c2 | |||
| 0c4b85980c | |||
| 5961db6b9b | |||
| d0039c2920 | |||
| 5bdec2f532 | |||
| fd758bb307 | |||
| a11d09ebdf | |||
| d294064da6 | |||
| fd4a5acc40 | |||
| 05a7a61257 | |||
| 90a4a11d49 | |||
| d9f914eb7c | |||
| 134242973b | |||
| 92900d8dc8 | |||
| 7a970e1d00 | |||
| e8e0f355fc | |||
| 3202fd88d2 | |||
| 1c66c904ab | |||
| 784e090081 | |||
| 2d08d3dc94 | |||
| 237b9754c6 | |||
| 74bbccdf59 | |||
| 062d625901 | |||
| 3f30c2bda2 | |||
| 0702692746 | |||
| 11a218b1aa | |||
| f4acff1321 | |||
| a8ee746c39 | |||
| ddd5fc7bf3 | |||
| 22dfe05287 | |||
| fa78e1295a | |||
| 4a634ca154 | |||
| bd1f5d0888 | |||
| 2f028c5f40 | |||
| 56c8843406 | |||
| 37c4c596b5 | |||
| 7b0bde4f1f | |||
| 5c5c7d64a8 | |||
| 565189d08c | |||
| 682580e318 | |||
| 74e3d6470a | |||
| b4e6a715fc | |||
| 85f0d44997 | |||
| 294855700d | |||
| 099ddfedc7 | |||
| d9e2bcef6d | |||
| 7a628f1a12 | |||
| 75bc680934 | |||
| 0c98b5ff76 | |||
| 11918e5846 | |||
| 2c33bf8c6f | |||
| e833a67bb7 | |||
| 6dc5087cbd | |||
| eabda670ac | |||
| 845e7930d7 | |||
| d20bfa240d | |||
| ba27a46ac6 | |||
| 866e5bd929 | |||
| 1beb5517a7 | |||
| a12ad1f627 | |||
| c18be9dde7 | |||
| 4eba400170 | |||
| dc376ab161 | |||
| 5ff49a78eb | |||
| 6df50992c4 | |||
| 5d2bcfaa38 | |||
| 990d7ad0f7 | |||
| 510283cd4d | |||
| dcc183179a | |||
| 30bc9b04c5 | |||
| 8aaeb1c7ce | |||
| 1984c68516 | |||
| c81c89d6d9 | |||
| 9ce2405f3f | |||
| 21fba45a3c | |||
| a0bbdcefb3 | |||
| 753da789a0 | |||
| cd5ce6e162 | |||
| 5a25cc171d | |||
| 32dc68f103 | |||
| 69a500d657 | |||
| ed9f34de5f | |||
| d6f1291c0b | |||
| 01079f5162 | |||
| 9b0dc287c1 | |||
| bb92566781 | |||
| 17b1c664a8 | |||
| 2eaba084c7 | |||
| ff75ab73cc | |||
| 3c54593456 | |||
| 39dfb2e606 | |||
| 4e7ade8612 | |||
| 664013e7ad | |||
| 9d51c64d92 | |||
| ee82c7834d | |||
| b389c6e103 | |||
| b3a2d3c1e4 | |||
| 5d33af13ca | |||
| 6b2a851dec | |||
| 3b3072801c | |||
| 9ed33d4337 | |||
| 728b3eb5db | |||
| f73398ea84 | |||
| 2b646c2153 | |||
| f83692c0df | |||
| b8236b1b1c | |||
| 1a3d77b2c0 | |||
| 816ee9e545 | |||
| 06766ddb98 | |||
| 7151848406 | |||
| 45b5347092 | |||
| 5b6986c230 | |||
| de195d9b20 | |||
| b47552c08f | |||
| 48dabd3ca2 | |||
| 91ac0368e3 | |||
| dfe4bc199f | |||
| 1630404621 | |||
| 02c66491e8 | |||
| d4b1d9abe5 | |||
| 6ab77be8fc | |||
| 6cf518e7df | |||
| 8f1745bf44 | |||
| 38f1ae34ad | |||
| ad415945a6 | |||
| a44fe29b8d | |||
| c1d96fc876 | |||
| 65db50df5d | |||
| f009d6f9e7 | |||
| ed8bd18dfb | |||
| af648334d1 | |||
| 8f4ce02d05 | |||
| 9b7e87c043 | |||
| cae8e6ae79 | |||
| 1a2272ad43 | |||
| fede91a98b | |||
| 7e8c6fcc9d | |||
| 0ca3167595 | |||
| c74cc9bc12 | |||
| 061fff6f17 | |||
| 2aaabdd2ea | |||
| 2f06ed2af8 | |||
| 52252de3a6 | |||
| ff725980c3 | |||
| d6d420b1f7 | |||
| 977e8a4c54 | |||
| b8188a7954 | |||
| 8ac57db117 | |||
| 5cc66e4d36 | |||
| d9d2022096 | |||
| 1ea38b1981 | |||
| d63a36216f | |||
| 9ac935ed94 | |||
| 02bb2b7477 | |||
| 9cfce59547 | |||
| 99f0d5c685 | |||
| f84cb1c9cc | |||
| ae4733c59d | |||
| 2629c92a00 | |||
| 4ccb922d1a | |||
| 8113e9a168 | |||
| a632f3c5cb | |||
| e64e2f2c4e | |||
| f6d49eb5b9 | |||
| ee4f498a13 | |||
| 3bdb1f8550 | |||
| 971f060029 | |||
| 2684fd6b62 | |||
| 6085c5bf01 | |||
| 550f0d9936 | |||
| 9c00554118 | |||
| ec7e8989a6 | |||
| 3ca4272230 | |||
| ae14afd5f7 | |||
| 3d40b23496 | |||
| 88c0c41a70 | |||
| 176917caf4 | |||
| e2e8fdafb1 | |||
| aad8b09d81 | |||
| 90e3d9e460 | |||
| baf9e4a9af | |||
| 1b453d0436 | |||
| 49b1a496b1 | |||
| 50afd83bc6 | |||
| 85934dcbe2 | |||
| 095ff20e2b | |||
| 3a91ed2571 | |||
| 20c534fc46 | |||
| 0c0bd8be98 | |||
| ead6f9f4cd | |||
| 2328d9e107 | |||
| 87aa8333a8 | |||
| f1de985304 | |||
| 5d3cbf8d1a | |||
| c24ed8d47b | |||
| cbf4a83b3f | |||
| a6887715c7 | |||
| e2169bc1da | |||
| 89f3b46a9e | |||
| d64e838b6d | |||
| 263e495561 | |||
| 127433628d | |||
| 29e8da0944 | |||
| a2992c86e6 | |||
| 1cc796b1a7 | |||
| 679cc7af38 | |||
| c4b3239e33 | |||
| 4139da82b9 | |||
| bdc7dc2cd8 | |||
| 244a4da28a | |||
| e7e0dbd29a | |||
| 1f6b2e629b | |||
| 793ba944d6 | |||
| 438480517b | |||
| e3b4d13c47 | |||
| 3caebb31ae | |||
| 8b9eee4961 | |||
| 280f5adb22 | |||
| 16cfcad0bf | |||
| 51431d22ba | |||
| ef3bc9202b | |||
| cdae169922 | |||
| c45a7a2ef6 | |||
| ddf16b71c2 | |||
| d29f843525 | |||
| 8ce8ac4404 | |||
| b55e59e665 | |||
| 598a3b5d7b | |||
| 8c16e3231e | |||
| eca5eced63 | |||
| e87d8da1fb | |||
| f5fba1cbd1 | |||
| 06b4c3faab | |||
| 6d0b9b3747 | |||
| 92f2cef4d1 | |||
| 5fdfbd470b | |||
| 75b5f70196 | |||
| b68be77865 | |||
| 105aab0345 | |||
| 9c3270a2de | |||
| 5c33e9666a | |||
| aeb9403b67 | |||
| 50735567c9 | |||
| 0e83c992c3 | |||
| dac7106df8 | |||
| 11b467e455 | |||
| 7cc2437ef7 | |||
| 8d4ffc0713 | |||
| 5ec5fb17ca | |||
| 234d643dd3 | |||
| 7288a1fcb2 | |||
| b8b23cd359 | |||
| c05eaa9382 | |||
| 6d14bda7b0 | |||
| e2fd951ff3 | |||
| bf598d5fe9 | |||
| 32f420dbe5 | |||
| 6d0e35ddcb | |||
| f9f4557841 | |||
| d441cdba71 | |||
| 9f24fb618f | |||
| 9d43641765 | |||
| 93f9ae8a31 | |||
| c2ca0852d9 | |||
| 8bedfc257f | |||
| b709810079 | |||
| d4721d50f7 | |||
| 14b54e554e | |||
| 7555091d56 | |||
| dbc176fe25 | |||
| 0a45385d48 | |||
| f33ee27f56 | |||
| 5444b575f3 | |||
| 6361cd8268 | |||
| 0055fcf489 | |||
| b7899d0c8c | |||
| c1e5e45431 | |||
| 44d0966892 | |||
| be0932f538 | |||
| 6cfa740f90 | |||
| 1bd8ec786b | |||
| 9a276d7289 | |||
| ac63d41daf | |||
| bd0a8a642b | |||
| 3e9b38044f | |||
| d8ca9b5f39 | |||
| e9f8e5eebd | |||
| bf2613ee49 | |||
| 3b691da8d1 | |||
| 4955a4ef98 | |||
| ca55d86187 | |||
| 5974856924 | |||
| bdb7c65ab0 | |||
| 45ba8690a9 | |||
| 7054190832 | |||
| dbd997b551 | |||
| 369bda13f8 | |||
| c9216e5625 | |||
| 93af9656d0 | |||
| bcade5bb9d | |||
| 59ab303c5c | |||
| 4ab9d1a493 | |||
| f1576eeb32 | |||
| 1f851887d9 | |||
| 2a2564cf45 | |||
| b5a78763f8 | |||
| 728e1ffdd0 | |||
| 14c9cfb310 | |||
| b511a54445 | |||
| f446e5ad3d | |||
| c263c12448 | |||
| ed9b6f0d3f | |||
| d3152bee9c | |||
| a504b429bd | |||
| 7b6db5ad7a | |||
| 398f675412 | |||
| d18bf338b6 | |||
| 3091d28615 | |||
| ab2365b475 | |||
| 7d356a2d20 | |||
| e5a4f27e79 | |||
| 9cbcda0f7b | |||
| 93b2cd6002 | |||
| 411ed1e0c7 | |||
| e5c4fe003b | |||
| d6293ab081 | |||
| 38a5431ceb | |||
| 7f2a9f6806 | |||
| 6ab69e5c1c | |||
| cd902a12b3 | |||
| 72809e8724 | |||
| 610cad00bf | |||
| 4f5bbebcd8 | |||
| 33f88039d7 | |||
| 2cf6b5052d | |||
| 8cb680f34e | |||
| f089ef3fbe | |||
| e1d2d4b863 | |||
| d0b34dc04c | |||
| 6a8cffe615 | |||
| d08101a5f4 | |||
| 7b6a26367a | |||
| 08ecf3f582 | |||
| 8d38e97c0b | |||
| 4c167cf528 | |||
| 7d27b675d0 | |||
| 0ef7e82548 | |||
| 8db0b52821 | |||
| 364199916f | |||
| 42066ecaba | |||
| 986b5a2afe | |||
| 921689aa04 | |||
| 283dcaffe2 | |||
| 074ffacf9d | |||
| f1d3177b69 | |||
| fa50e9dd20 | |||
| d4de43a062 | |||
| af795985fc | |||
| 610b19d646 | |||
| 95c8915d78 | |||
| 6bdfec743c | |||
| e270c46703 | |||
| 0c0a866481 | |||
| 28ca0aed48 | |||
| ca9ab100e5 | |||
| 73732bfb29 | |||
| 048e7f4c1b | |||
| d041df8254 | |||
| 8e8b9a3cff | |||
| b7b65d7361 | |||
| 6263c8a0cd | |||
| 3c92054a6e | |||
| cf2b6a895f | |||
| 5bdb34521d | |||
| e1e83c11cc | |||
| 0f5b17de0f | |||
| 568d9a3e30 | |||
| 1518b793dc | |||
| 6182b46033 | |||
| 4194553450 | |||
| 5f5a696717 | |||
| 35d516e140 | |||
| fb5e5cc13f | |||
| aa475a8d2e | |||
| fa5c023d33 | |||
| 22d8e6f79f | |||
| 126ae4a0f0 | |||
| 68f18245a7 | |||
| e2e25b7134 | |||
| 32088647c3 | |||
| baf8df9597 | |||
| 34aa266260 | |||
| 8c887c2eee | |||
| a95250cabb | |||
| 96bc6807ae | |||
| 81a139b875 | |||
| 1a3c20f0f7 | |||
| 4f735d0201 | |||
| ec0543335e | |||
| 0872d024f9 | |||
| 0ce21c91ef | |||
| 220c7c271b | |||
| bf389b94d6 | |||
| 6187f36c33 | |||
| 73df4e4abf | |||
| 1a8a5a5e8e | |||
| c4ab6280c6 | |||
| a27b6a113a | |||
| a60ded5c94 | |||
| 5ff67d4b2d | |||
| 874e3d976f | |||
| 90e1284d83 | |||
| 75518b71ea | |||
| b355efd73a | |||
| 8e920d727f | |||
| 5976be55f4 | |||
| 4c3df1a963 | |||
| 5b44f495ee | |||
| 3951e15446 | |||
| b9da7c6f27 | |||
| c5ae4a6957 | |||
| e40c2f97f0 | |||
| 1dbc11bdd5 | |||
| 299edae7c0 | |||
| 86309bd837 | |||
| 0312e9026d | |||
| a7bafb60e9 | |||
| 602769b9d0 | |||
| e76546f8e4 | |||
| a9ef1680ce | |||
| 670ddef944 | |||
| be6b8dce25 | |||
| 75fd20f5df | |||
| f0509a6631 | |||
| 702319c4ca | |||
| d5bd187930 | |||
| 753036f0c8 | |||
| cfc763b488 | |||
| 7edfeab0b7 | |||
| 226b0540c5 | |||
| 0c36647506 | |||
| 1348c8880e | |||
| 9334285edd | |||
| 2330d3a056 | |||
| bce54a64ff | |||
| bd43400ad8 | |||
| b16c75324e | |||
| 0ddef1169d | |||
| 4da09bd841 | |||
| 6811cd617b | |||
| 4e762c75b0 | |||
| f471c30036 | |||
| aaed932a67 | |||
| 5f168b1a1e | |||
| 5d6f0d7e47 | |||
| cf176f1b99 | |||
| d97e867c07 | |||
| 3d0654dd48 | |||
| e688840703 | |||
| 8bf272e806 | |||
| 0744bc4004 | |||
| 918f8cbe16 | |||
| b6dafff524 | |||
| 34686dc167 | |||
| c0c75bf18e | |||
| 66cfb403c6 | |||
| 0375f9c0ae | |||
| 11ac758d78 | |||
| 9e705b2f53 | |||
| b475108ff3 | |||
| ab34dff152 | |||
| 6a3f093cfa | |||
| 04ef9af703 | |||
| b773ab3fb4 | |||
| 32085dc009 | |||
| 18fdfc26aa | |||
| f50d2fa48e | |||
| e82859c979 | |||
| 99bb35f109 | |||
| 8637f8ee9b | |||
| 1e11d40828 | |||
| 5546b102eb | |||
| 7d9c8c9172 | |||
| 8dd51b7207 | |||
| 746c5b603f | |||
| d0de8d22fe | |||
| 231b8e9481 | |||
| f9f36700bb | |||
| ba9fced3db | |||
| c192ecf6b7 | |||
| 6ee029e14b | |||
| 935f880fa7 | |||
| 47d046c5fe | |||
| 4305e17cbe | |||
| c5c4cdd0b4 | |||
| 252562db90 | |||
| a898682f3e | |||
| 7829094668 | |||
| 042c23a545 | |||
| af2b9e3a4c | |||
| b3b7c55b9a | |||
| 1859ede325 | |||
| 2c32c374fb | |||
| 65d22406a3 | |||
| 92689a60ae | |||
| 1a598ccf0d | |||
| e50feb74fd | |||
| af067a8c84 | |||
| 61a196bc3d | |||
| 6a431daffc | |||
| 1aad3e6cc8 | |||
| c8d42e32ed | |||
| 514cc6edb8 | |||
| 208d3ffa7b | |||
| 25dd92f8c0 | |||
| 3f81b7e56d | |||
| 99b7333991 | |||
| a2ae4ba441 | |||
| 4e1b2792c9 | |||
| 55695bb5bc | |||
| 6e064da536 | |||
| 69ff12645c | |||
| efb93d22d9 | |||
| cdb0068dcc | |||
| b0a0d714c4 | |||
| 7e36ee243c | |||
| 21bc56a8ba | |||
| e920c0fe3e | |||
| 31992fb398 | |||
| dc65599fae | |||
| eb9dc7b70d | |||
| 06bf2502a6 | |||
| 242655bac9 | |||
| 8335b3ee77 | |||
| a0c8ad9511 | |||
| d775a9364b | |||
| 1695124472 | |||
| 70145eb150 | |||
| dacd7d94d9 | |||
| 85bd8555c0 | |||
| 6920b4e366 | |||
| bda3835cb1 | |||
| 83e5aa6137 | |||
| 4719e52c6e | |||
| e313eadcd2 | |||
| be952e40ba | |||
| 4d4b24f8b0 | |||
| 9533fa25c3 | |||
| 013c9072b9 | |||
| bf8dc05fac | |||
| f4b38662fa | |||
| ea41cce5ef | |||
| 013c292ffb | |||
| cb18f11133 | |||
| ea25f49c65 | |||
| 5d15d5958e | |||
| efed92b15c | |||
| 7d39d02e98 | |||
| e006442e4f | |||
| 212848e931 | |||
| 732de53d1b | |||
| 08c00eed1e | |||
| 2a1c3d1f33 | |||
| 5f57084ed9 | |||
| 9368e29d62 | |||
| ae8751e9ca | |||
| a11b8c4750 | |||
| 1e7e23df96 | |||
| 8395e00835 | |||
| 66bc1bdc77 | |||
| b8984661d9 | |||
| ea98a1c9f9 | |||
| 9173b40e2e | |||
| 59e5b1918f | |||
| ab4b7b8ee6 | |||
| 7f0f153ebd | |||
| f3d51a242d | |||
| 88ce192610 | |||
| bd489647e9 | |||
| c36666b4d4 | |||
| 97727cae2c | |||
| f412b6818e | |||
| e8aea86e75 |
@@ -1,3 +1,5 @@
|
||||
---
|
||||
exclude_paths:
|
||||
- '3rdparty/**'
|
||||
- '*.md'
|
||||
- '**/*.md'
|
||||
|
||||
@@ -26,13 +26,17 @@ The following is a list of *general* style recommendations that will make review
|
||||
* Please try to prefix your commit message, indicating what area of the project was modified.
|
||||
* For example `gs: message...`.
|
||||
* Looking at the project's commit history will help with keeping prefixes consistent overtime, *there is no strictly enforced list*.
|
||||
|
||||
* Try to keep messages brief and informative
|
||||
|
||||
* Remove unnecessary commits and squash commits together when appropriate.
|
||||
* If you are not familiar with rebasing with git, check out the following resources:
|
||||
* CLI - https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history
|
||||
* GUI (SourceTree) - https://www.atlassian.com/blog/sourcetree/interactive-rebase-sourcetree
|
||||
|
||||
* Code Styling and Formatting
|
||||
* [Consult the style guide](https://github.com/tadanokojin/pcsx2/blob/coding-guide/pcsx2/Docs/Coding_Guidelines.md)
|
||||
|
||||
* Run `clang-format` using the configuration file in the root of the repository
|
||||
* Visual Studio Setup - https://devblogs.microsoft.com/cppblog/clangformat-support-in-visual-studio-2017-15-7-preview-1/
|
||||
* IMPORTANT - if you are running `clang-format` on unrelated changes (ie. formatting an entire file), please do so in a separate commit.
|
||||
@@ -41,9 +45,9 @@ The following is a list of *general* style recommendations that will make review
|
||||
## General Documentation And Coding Strategies
|
||||
|
||||
* [Commenting Etiquette](https://github.com/PCSX2/pcsx2/wiki/Commenting-Etiquette)
|
||||
|
||||
* [Coding style](https://github.com/PCSX2/pcsx2/wiki/Code-Formatting-Guidelines)
|
||||
* [More comprehensive style-guide (Currently in Draft)](https://github.com/tadanokojin/pcsx2/blob/coding-guide/pcsx2/Docs/Coding_Guidelines.md)
|
||||
* [wxWidgets coding strategies](https://github.com/PCSX2/pcsx2/wiki/wxWidgets-Coding-Strategies)
|
||||
|
||||
## Tasks
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [PCSX2]
|
||||
@@ -60,16 +60,13 @@ body:
|
||||
label: Operating System
|
||||
options:
|
||||
- Windows 11
|
||||
- Windows 10 (32bit)
|
||||
- Windows 10 (64bit)
|
||||
- Windows 8.1 (32bit)
|
||||
- Windows 8.1 (64bit)
|
||||
- Linux (32bit) - Specify Distro Below
|
||||
- Linux (64bit) - Specify Distro Below
|
||||
- macOS (Monteray)
|
||||
- macOS (BigSur)
|
||||
- macOS (Catalina)
|
||||
- macOS (Mojave)
|
||||
- Linux (64bit) - Specify distro below
|
||||
- macOS 13 (Ventura)
|
||||
- macOS 12 (Monterey)
|
||||
- macOS 11 (Big Sur)
|
||||
- macOS 10.15 (Catalina)
|
||||
- macOS 10.14 (Mojave)
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
|
||||
@@ -54,9 +54,6 @@ body:
|
||||
Please make sure your system meets our requirements for OS version, CPU and GPU
|
||||
- [System Requirements](https://github.com/PCSX2/pcsx2#system-requirements)
|
||||
|
||||
We **do not** accept bug reports for **unsupported operating systems**.
|
||||
- [For macOS Support](https://forums.pcsx2.net/Thread-Native-Mac-Testing-Build)
|
||||
|
||||
Performance issues as a result of not meeting our hardware requirements are not valid
|
||||
|
||||
Please read our known issues pages for AMD and Intel drivers.
|
||||
@@ -78,16 +75,13 @@ body:
|
||||
label: Operating System
|
||||
options:
|
||||
- Windows 11
|
||||
- Windows 10 (32bit)
|
||||
- Windows 10 (64bit)
|
||||
- Windows 8.1 (32bit)
|
||||
- Windows 8.1 (64bit)
|
||||
- Linux (32bit) - Specify Distro Below
|
||||
- Linux (64bit) - Specify Distro Below
|
||||
- macOS (Monteray)
|
||||
- macOS (BigSur)
|
||||
- macOS (Catalina)
|
||||
- macOS (Mojave)
|
||||
- Linux (64bit) - Specify distro below
|
||||
- macOS 13 (Ventura)
|
||||
- macOS 12 (Monterey)
|
||||
- macOS 11 (Big Sur)
|
||||
- macOS 10.15 (Catalina)
|
||||
- macOS 10.14 (Mojave)
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
|
||||
+33
-13
@@ -12,7 +12,6 @@
|
||||
- 'cmake/**/*'
|
||||
- 'CMakeLists.txt'
|
||||
- '**/CMakeLists.txt'
|
||||
- 'buildbot.xml'
|
||||
- 'build.sh'
|
||||
'Dependencies':
|
||||
- '3rdparty/*'
|
||||
@@ -24,15 +23,17 @@
|
||||
- '**/*.md'
|
||||
- '*.pdf'
|
||||
- '**/*.pdf'
|
||||
'GUI/WX':
|
||||
- 'pcsx2/gui/*'
|
||||
- 'pcsx2/gui/**/*'
|
||||
'GUI/Qt':
|
||||
- 'pcsx2-qt/*'
|
||||
- 'pcsx2-qt/**/*'
|
||||
- '3rdparty/Qt/*'
|
||||
- '3rdparty/Qt/**/*'
|
||||
'GameDB':
|
||||
- '**/GameIndex.*'
|
||||
'Installer | Package':
|
||||
- 'nsis/*'
|
||||
- 'nsis/**/*'
|
||||
- 'build.sh'
|
||||
'Translations':
|
||||
- 'pcsx2-qt/Translations/*'
|
||||
|
||||
# Tools / Features
|
||||
'Debugger':
|
||||
@@ -46,6 +47,9 @@
|
||||
'TAS Functionality':
|
||||
- 'pcsx2/Recording/*'
|
||||
- 'pcsx2/Recording/**/*'
|
||||
'RetroAchievements':
|
||||
- 'pcsx2/Frontend/Achievements.*'
|
||||
- 'pcsx2/Achievements.*'
|
||||
|
||||
# Emulation Components
|
||||
'Counters':
|
||||
@@ -65,15 +69,34 @@
|
||||
'GS':
|
||||
- 'pcsx2/GS/*'
|
||||
- 'pcsx2/GS/**/*'
|
||||
'GS: Direct3D':
|
||||
- 'bin/resources/shaders/*'
|
||||
- 'bin/resources/shaders/**/*'
|
||||
'GS: Direct3D 11':
|
||||
- 'pcsx2/GS/Renderers/DX11/*'
|
||||
- 'pcsx2/GS/Renderers/DX11/**/*'
|
||||
- 'bin/resources/shaders/dx11/*'
|
||||
- 'bin/resources/shaders/dx11/**/*'
|
||||
'GS: Direct3D 12':
|
||||
- 'pcsx2/GS/Renderers/DX12/*'
|
||||
- 'pcsx2/GS/Renderers/DX12/**/*'
|
||||
- 'bin/resources/shaders/dx11/*'
|
||||
- 'bin/resources/shaders/dx11/**/*'
|
||||
'GS: Hardware':
|
||||
- 'pcsx2/GS/Renderers/HW/*'
|
||||
- 'pcsx2/GS/Renderers/HW/**/*'
|
||||
'GS: OpenGL':
|
||||
- 'pcsx2/GS/Renderers/OpenGL/*'
|
||||
- 'pcsx2/GS/Renderers/OpenGL/**/*'
|
||||
- 'bin/resources/shaders/opengl/*'
|
||||
- 'bin/resources/shaders/opengl/**/*'
|
||||
'GS: Vulkan':
|
||||
- 'pcsx2/GS/Renderers/Vulkan/*'
|
||||
- 'pcsx2/GS/Renderers/Vulkan/**/*'
|
||||
- 'bin/resources/shaders/vulkan/*'
|
||||
- 'bin/resources/shaders/vulkan/**/*'
|
||||
'GS: Metal':
|
||||
- 'pcsx2/GS/Renderers/Metal/*'
|
||||
- 'pcsx2/GS/Renderers/Metal/**/*'
|
||||
'GS: Texture Cache':
|
||||
- 'pcsx2/GS/Renderers/*TextureCache*.*'
|
||||
- 'pcsx2/GS/Renderers/**/*TextureCache*.*'
|
||||
@@ -94,12 +117,9 @@
|
||||
'Memory Card':
|
||||
- 'pcsx2/gui/MemoryCard*'
|
||||
- 'pcsx2/gui/**/MemoryCard*'
|
||||
'PAD: Linux/Mac':
|
||||
- 'pcsx2/PAD/Linux/*'
|
||||
- 'pcsx2/PAD/Linux/**/*'
|
||||
'PAD: Windows':
|
||||
- 'pcsx2/PAD/Windows/*'
|
||||
- 'pcsx2/PAD/Windows/**/*'
|
||||
'PAD':
|
||||
- 'pcsx2/PAD/*'
|
||||
- 'pcsx2/PAD/**/*'
|
||||
'SPU2':
|
||||
- 'pcsx2/SPU2/*'
|
||||
- 'pcsx2/SPU2/**/*'
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# CI Documentation
|
||||
|
||||
## Releases
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
PCSX2 Repo->>Actions: PR is merged or commit is pushed to master
|
||||
Actions->>PCSX2 Repo: Increment latest tag and push, create a draft release
|
||||
Actions->>Actions: Kicked off pipeline on the tag push, build relevant configs
|
||||
Actions->>PCSX2 Repo: Rename and upload artifacts to draft release, publish the release
|
||||
Actions->>Discord: Announce release via a WebHook
|
||||
PCSX2 Repo->>Web API: POST webhook to API informing it that a new release has occurred
|
||||
Web API->>Web API: Update cache with new release
|
||||
```
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 82 KiB |
@@ -1,47 +0,0 @@
|
||||
@startuml
|
||||
participant User as user
|
||||
participant Github as github
|
||||
participant "Create Release WF" as create
|
||||
participant "Build WFs" as build
|
||||
participant "Finalize Release WF" as finalize
|
||||
participant Discord as discord
|
||||
|
||||
==Nightly Release==
|
||||
|
||||
user -> github : New Commit on master (from PR, or directly)
|
||||
...waiting for commit push event to fire...
|
||||
github -> create : Push a new git tag, patch incrementing latest Version
|
||||
alt from-pr? case
|
||||
create -> create : Use links to the PR as a description
|
||||
else was a commit
|
||||
create -> create : Use Commit Message as Description
|
||||
end
|
||||
create -> create : Generate release notes
|
||||
create -> github : Create new draft release, associated with tag and with the notes
|
||||
note right
|
||||
Draft releases are not public facing, only those with write access can see them!
|
||||
end note
|
||||
...waiting for push tag event to fire...
|
||||
loop for all build workflows
|
||||
github -> build : Build the tag commit
|
||||
build -> build : .exe will use the git tag for it's title and such
|
||||
build -> build : Upload the generated artifact to the associated release
|
||||
alt all-artifacts-uploaded? case
|
||||
build -> github : Publish the release
|
||||
user -> github : Can now download the artifacts on the published release
|
||||
end
|
||||
note right
|
||||
This is the only area where an eventual consistency issue is apparent
|
||||
It is because GitHub does not fire events for when draft releases are edited
|
||||
This is glossed over in the initial impl and can be improved and be made eventually consistent as well
|
||||
end note
|
||||
|
||||
|
||||
...waiting for release publish event to fire...
|
||||
github -> finalize : Announce the Release
|
||||
finalize -> github : Gather all asset links, and format message embed.
|
||||
finalize -> discord : Announce new build via a WebHook
|
||||
|
||||
...waiting for announcement...
|
||||
user -> discord : Can download artifacts from links via the discord
|
||||
@enduml
|
||||
@@ -0,0 +1,29 @@
|
||||
name: 🏭 Update Controller Database
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 16 * * 1" # every monday @ 12pm EST - https://crontab.guru/#0_16_*_*_1
|
||||
|
||||
jobs:
|
||||
update-controller-db:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get Latest DB and Prepare DB File
|
||||
run: |
|
||||
cd .github/workflows/scripts/controller-db/
|
||||
wget -O game_controller_db.txt https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt
|
||||
python ./update-db.py
|
||||
mv ./game_controller_db.txt ${{github.workspace}}/bin/resources/game_controller_db.txt
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
title: "PAD: Update to latest controller database"
|
||||
commit-message: "PAD: Update to latest controller database."
|
||||
committer: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
author: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
body: "Weekly automatic update of SDL Controller DB"
|
||||
reviewers: lightningterror
|
||||
@@ -1,27 +0,0 @@
|
||||
name: 📝 Validate GameDB
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/GameIndex.yaml'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/GameIndex.yaml'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Validate GameDB
|
||||
env:
|
||||
SCRIPT_DIR: .github/workflows/scripts/validation/lint-gamedb
|
||||
run: |
|
||||
pip install -r "${SCRIPT_DIR}/requirements.txt"
|
||||
python "${SCRIPT_DIR}/lint-gamedb.py"
|
||||
@@ -0,0 +1,31 @@
|
||||
name: 📝 Validate GameDB
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/GameIndex.yaml'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- '**/GameIndex.yaml'
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint and Validate GameDB
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Validate Contents
|
||||
run: |
|
||||
npm install -g ajv-cli
|
||||
ajv validate -s ./pcsx2/Docs/gamedb-schema.json --spec=draft2020 -d ./bin/resources/GameIndex.yaml
|
||||
|
||||
- name: Check Formatting
|
||||
run: |
|
||||
npm install -g prettier
|
||||
prettier --check ./bin/resources/GameIndex.yaml
|
||||
@@ -1,207 +0,0 @@
|
||||
name: 🐧 Linux Builds
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the master branch
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- v*
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- "**/*.md"
|
||||
- "**/*.bat"
|
||||
- "**/*.cmd"
|
||||
- "**/*.props"
|
||||
- "**/*.sln"
|
||||
- ".clang-format"
|
||||
- ".codacy.yaml"
|
||||
- ".github/*"
|
||||
- ".github/workflows/lint-gamedb.yml"
|
||||
- ".github/workflows/macos-workflow.yml"
|
||||
- ".github/workflows/pr-triage.yml"
|
||||
- ".github/workflows/scripts/windows/**"
|
||||
- ".github/workflows/scripts/validation/**"
|
||||
- ".github/workflows/windows-workflow.yml"
|
||||
- ".gitignore"
|
||||
- "bin/PCSX2_keys.ini.default"
|
||||
- "build.sh"
|
||||
- "buildbot.xml"
|
||||
- "pcsx2/CDVD/Windows/**"
|
||||
- "pcsx2/DEV9/Win32/**"
|
||||
- "pcsx2/PAD/Windows/**"
|
||||
- "pcsx2/SPU2/Windows/**"
|
||||
- "pcsx2/USB/Win32/**"
|
||||
- "pcsx2/windows/**"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
# Prevent one build from failing everything (although maybe those should be included as experimental builds instead)
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-18.04
|
||||
platform: x86
|
||||
compiler: gcc
|
||||
cmakeflags: -DLTO_PCSX2_CORE=ON
|
||||
appimage: true
|
||||
experimental: false
|
||||
- os: ubuntu-18.04
|
||||
platform: x64
|
||||
compiler: gcc
|
||||
cmakeflags: -DLTO_PCSX2_CORE=ON
|
||||
appimage: true
|
||||
experimental: false
|
||||
- os: ubuntu-18.04
|
||||
platform: x86
|
||||
compiler: clang
|
||||
# Need to disable PCH until cmake 3.17
|
||||
# (PCH conflicts with ccache, fixed by https://gitlab.kitware.com/cmake/cmake/-/merge_requests/4400)
|
||||
cmakeflags: -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON
|
||||
detail: " nopch"
|
||||
appimage: false
|
||||
experimental: false
|
||||
- os: ubuntu-18.04
|
||||
platform: x86
|
||||
compiler: gcc
|
||||
cmakeflags: -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON
|
||||
detail: " nopch"
|
||||
appimage: false
|
||||
experimental: false
|
||||
- os: ubuntu-18.04
|
||||
platform: x86
|
||||
compiler: gcc
|
||||
cmakeflags: -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON -DARCH_FLAG=-march=haswell
|
||||
detail: " avx2 nopch"
|
||||
appimage: false
|
||||
experimental: false
|
||||
|
||||
name: ${{ matrix.platform }} | ${{ matrix.compiler }}${{ matrix.detail }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
# Set some sort of timeout in the event of run-away builds. We are limited on concurrent jobs so, get rid of them.
|
||||
timeout-minutes: 60
|
||||
|
||||
env:
|
||||
CCACHE_BASEDIR: ${{ github.workspace }}
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_COMPRESSLEVEL: 9
|
||||
CCACHE_MAXSIZE: 100M
|
||||
|
||||
steps:
|
||||
# NOTE - useful for debugging
|
||||
# - name: Dump GitHub context
|
||||
# env:
|
||||
# GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
# run: |
|
||||
# echo "$GITHUB_CONTEXT"
|
||||
# echo ${{ github.event.pull_request.title }}
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Checkout Submodules
|
||||
if: steps.cache-submodules.outputs.cache-hit != 'true'
|
||||
run: git submodule update --init --recursive -j $(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
# -- SETUP CCACHE - https://cristianadam.eu/20200113/speeding-up-c-plus-plus-github-actions-using-ccache/
|
||||
- name: Prepare ccache timestamp
|
||||
id: ccache_cache_timestamp
|
||||
shell: cmake -P {0}
|
||||
run: |
|
||||
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
|
||||
message("::set-output name=timestamp::${current_date}")
|
||||
|
||||
- name: ccache cache files
|
||||
uses: actions/cache@v2.1.7
|
||||
with:
|
||||
path: .ccache
|
||||
key: ${{ matrix.os }} ${{ matrix.platform }} ${{ matrix.compiler }}${{ matrix.detail }} ccache ${{ steps.ccache_cache_timestamp.outputs.timestamp }}
|
||||
restore-keys: ${{ matrix.os }} ${{ matrix.platform }} ${{ matrix.compiler }}${{ matrix.detail }} ccache
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
run: |
|
||||
ARCH=$([ "${{ matrix.platform }}" == x86 ] && echo "32bit" || echo "64bit")
|
||||
ARTIFACT_NAME=""
|
||||
if [ ${{ github.event_name }} == "pull_request" ]; then
|
||||
PR_SHA=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
|
||||
ARTIFACT_NAME="PCSX2-${ARCH}"
|
||||
if [ ! -z "${{ github.event.pull_request.number }}" ]; then
|
||||
PR_NUM=${{ github.event.pull_request.number }}
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}-pr[${PR_NUM}]"
|
||||
fi
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}-sha[${PR_SHA}]"
|
||||
if [ ! -z "${{ github.event.pull_request.title }}" ]; then
|
||||
PR_TITLE=$(echo "${{ github.event.pull_request.title }}" | tr -cd '[a-zA-Z0-9[:space:]]_-')
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}-title["${PR_TITLE}""
|
||||
fi
|
||||
else
|
||||
SHA=$(git rev-parse --short "$GITHUB_SHA")
|
||||
ARTIFACT_NAME="PCSX2-${ARCH}-sha[${SHA}"
|
||||
fi
|
||||
TRIMMED_ARTIFACT_NAME=$(printf "%.199s]" "$ARTIFACT_NAME")
|
||||
echo "name=$TRIMMED_ARTIFACT_NAME"
|
||||
echo "##[set-output name=name;]${TRIMMED_ARTIFACT_NAME}"
|
||||
echo "##[set-output name=arch;]${ARCH}"
|
||||
|
||||
- name: Install Packages
|
||||
env:
|
||||
PLATFORM: ${{ matrix.platform }}
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
run: .github/workflows/scripts/linux/install-packages.sh
|
||||
|
||||
- name: Generate CMake
|
||||
env:
|
||||
PLATFORM: ${{ matrix.platform }}
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
ADDITIONAL_CMAKE_ARGS: ${{ matrix.cmakeflags }}
|
||||
run: .github/workflows/scripts/linux/generate-cmake.sh
|
||||
|
||||
- name: Build PCSX2
|
||||
working-directory: build
|
||||
run: ../.github/workflows/scripts/linux/compile.sh
|
||||
|
||||
- name: Run Tests
|
||||
working-directory: ./build
|
||||
run: ninja unittests
|
||||
|
||||
- name: Package AppImage
|
||||
if: matrix.appimage == true
|
||||
env:
|
||||
PLATFORM: ${{ matrix.platform }}
|
||||
COMPILER: ${{ matrix.compiler }}
|
||||
name: ${{ steps.artifact-metadata.outputs.name }}
|
||||
run: .github/workflows/scripts/linux/appimage.sh
|
||||
|
||||
- name: Upload artifact
|
||||
if: matrix.appimage == true
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.name }}
|
||||
path: ci-artifacts
|
||||
|
||||
# ---- Release / Tagging related steps ----
|
||||
- name: Prepare Build Artifacts
|
||||
if: github.repository == 'PCSX2/pcsx2' && startsWith(github.ref, 'refs/tags/') && matrix.appimage == true
|
||||
run: |
|
||||
mv ./ci-artifacts/*.AppImage ./ci-artifacts/linux-AppImage-${{ steps.artifact-metadata.outputs.arch }}.AppImage
|
||||
ls ./ci-artifacts/
|
||||
|
||||
- name: Upload Assets and Potential Publish Release
|
||||
if: github.repository == 'PCSX2/pcsx2' && startsWith(github.ref, 'refs/tags/') && matrix.appimage == true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_PAT }}
|
||||
ASSET_DIR: ${{ github.WORKSPACE }}/ci-artifacts
|
||||
ASSET_EXTENSION: AppImage
|
||||
TAG_TO_SEARCH_FOR: ${{ github.REF }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/upload-release-artifacts
|
||||
npm ci
|
||||
node index.js
|
||||
@@ -0,0 +1,20 @@
|
||||
name: 🐧 Linux Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build_linux_qt:
|
||||
name: "AppImage"
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,129 @@
|
||||
name: Linux Build Steps
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
jobName:
|
||||
required: true
|
||||
type: string
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: ubuntu-20.04
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
default: x64
|
||||
compiler:
|
||||
required: true
|
||||
type: string
|
||||
cmakeflags:
|
||||
required: true
|
||||
type: string
|
||||
buildAppImage:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
detail:
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
cheats_url:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
name: ${{ inputs.jobName }}
|
||||
runs-on: ${{ inputs.os }}
|
||||
# Set some sort of timeout in the event of run-away builds. We are limited on concurrent jobs so, get rid of them.
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
CCACHE_BASEDIR: ${{ github.workspace }}
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_COMPRESSLEVEL: 9
|
||||
CCACHE_MAXSIZE: 100M
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
env:
|
||||
OS: linux
|
||||
GUI_FRAMEWORK: QT
|
||||
ARCH: ${{ inputs.platform }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
PR_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: ./.github/workflows/scripts/common/name-artifacts.sh
|
||||
|
||||
# -- SETUP CCACHE - https://cristianadam.eu/20200113/speeding-up-c-plus-plus-github-actions-using-ccache/
|
||||
- name: Prepare ccache timestamp
|
||||
id: ccache_cache_timestamp
|
||||
run: echo "timestamp=$(date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: ccache cache files
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .ccache
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} ${{ inputs.detail }} ccache ${{ steps.ccache_cache_timestamp.outputs.timestamp }}
|
||||
restore-keys: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} ${{ inputs.detail }} ccache
|
||||
|
||||
- name: Install Packages
|
||||
env:
|
||||
COMPILER: ${{ inputs.compiler }}
|
||||
run: .github/workflows/scripts/linux/install-packages-qt.sh
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/deps
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.gui }} deps ${{ hashFiles('.github/workflows/scripts/linux/build-dependencies-qt.sh') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
run: .github/workflows/scripts/linux/build-dependencies-qt.sh
|
||||
|
||||
- name: Download cheats
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.cheats_url }}/cheats_ni.zip" "${{ inputs.cheats_url }}/cheats_ws.zip"
|
||||
|
||||
- name: Generate CMake
|
||||
env:
|
||||
COMPILER: ${{ inputs.compiler }}
|
||||
ADDITIONAL_CMAKE_ARGS: ${{ inputs.cmakeflags }}
|
||||
run: .github/workflows/scripts/linux/generate-cmake-qt.sh
|
||||
|
||||
- name: Build PCSX2
|
||||
working-directory: build
|
||||
run: ../.github/workflows/scripts/linux/compile.sh
|
||||
|
||||
- name: Run Tests
|
||||
working-directory: ./build
|
||||
run: ninja unittests
|
||||
|
||||
- name: Package AppImage
|
||||
if: inputs.buildAppImage == true
|
||||
env:
|
||||
NAME: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
run: |
|
||||
.github/workflows/scripts/linux/appimage-qt.sh "$(realpath .)" "$(realpath ./build)" "$HOME/deps" "$NAME"
|
||||
mkdir -p "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
mv "${NAME}.AppImage" "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
|
||||
- name: Upload artifact
|
||||
if: inputs.buildAppImage == true
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: ci-artifacts
|
||||
@@ -1,118 +0,0 @@
|
||||
name: 🍎 MacOS Builds
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the master branch
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
- '**/*.bat'
|
||||
- '**/*.cmd'
|
||||
- '**/*.props'
|
||||
- '**/*.sln'
|
||||
- '.clang-format'
|
||||
- '.codacy.yaml'
|
||||
- '.github/*'
|
||||
- '.github/workflows/lint-gamedb.yml'
|
||||
- '.github/workflows/linux-workflow.yml'
|
||||
- '.github/workflows/pr-triage.yml'
|
||||
- '.github/workflows/scripts/windows/**'
|
||||
- '.github/workflows/scripts/validation/**'
|
||||
- '.github/workflows/windows-workflow.yml'
|
||||
- '.gitignore'
|
||||
- 'bin/PCSX2_keys.ini.default'
|
||||
- 'build.sh'
|
||||
- 'buildbot.xml'
|
||||
- 'pcsx2/CDVD/Windows/**'
|
||||
- 'pcsx2/DEV9/Win32/**'
|
||||
- 'pcsx2/PAD/Windows/**'
|
||||
- 'pcsx2/SPU2/Windows/**'
|
||||
- 'pcsx2/USB/Win32/**'
|
||||
- 'pcsx2/windows/**'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
- '**/*.bat'
|
||||
- '**/*.cmd'
|
||||
- '**/*.props'
|
||||
- '**/*.sln'
|
||||
- '.clang-format'
|
||||
- '.codacy.yaml'
|
||||
- '.github/*'
|
||||
- '.github/workflows/lint-gamedb.yml'
|
||||
- '.github/workflows/linux-workflow.yml'
|
||||
- '.github/workflows/pr-triage.yml'
|
||||
- '.github/workflows/scripts/windows/**'
|
||||
- '.github/workflows/scripts/validation/**'
|
||||
- '.github/workflows/windows-workflow.yml'
|
||||
- '.gitignore'
|
||||
- 'bin/PCSX2_keys.ini.default'
|
||||
- 'build.sh'
|
||||
- 'buildbot.xml'
|
||||
- 'pcsx2/CDVD/Windows/**'
|
||||
- 'pcsx2/DEV9/Win32/**'
|
||||
- 'pcsx2/PAD/Windows/**'
|
||||
- 'pcsx2/SPU2/Windows/**'
|
||||
- 'pcsx2/USB/Win32/**'
|
||||
- 'pcsx2/windows/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
# Prevent one build from failing everything (although maybe those should be included as experimental builds instead)
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-11.0]
|
||||
platform: [x64]
|
||||
experimental: [false]
|
||||
|
||||
name: ${{ matrix.platform }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
# Set some sort of timeout in the event of run-away builds. We are limited on concurrent jobs so, get rid of them.
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
# NOTE - useful for debugging
|
||||
# - name: Dump GitHub context
|
||||
# env:
|
||||
# GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
# run: |
|
||||
# echo "$GITHUB_CONTEXT"
|
||||
# echo ${{ github.event.pull_request.title }}
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Checkout Submodules
|
||||
run: git submodule update --init --recursive -j $(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
- name: Install Packages
|
||||
env:
|
||||
PLATFORM: ${{ matrix.platform }}
|
||||
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
||||
HOMEBREW_NO_ANALYTICS: 1
|
||||
run: |
|
||||
# To save time, only brew update if running the install without it fails
|
||||
function do-install() {
|
||||
brew install sound-touch portaudio wxwidgets sdl2 libsamplerate
|
||||
}
|
||||
if ! do-install; then
|
||||
brew update
|
||||
do-install
|
||||
fi
|
||||
|
||||
- name: Generate CMake Files
|
||||
run: cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_BUILD_PO=FALSE -DLTO_PCSX2_CORE=ON -B build .
|
||||
|
||||
- name: Build PCSX2
|
||||
working-directory: build
|
||||
run: make -j$(getconf _NPROCESSORS_ONLN) # macOS doesn't use make install
|
||||
|
||||
- name: Run Tests
|
||||
working-directory: build
|
||||
run: make -j$(getconf _NPROCESSORS_ONLN) unittests
|
||||
@@ -0,0 +1,155 @@
|
||||
name: MacOS Build Steps
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
jobName:
|
||||
required: true
|
||||
type: string
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: macos-11.0
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
default: x64
|
||||
gui:
|
||||
required: true
|
||||
type: string
|
||||
cheats_url:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
|
||||
jobs:
|
||||
build_macos:
|
||||
name: ${{ inputs.jobName }}
|
||||
runs-on: ${{ inputs.os }}
|
||||
# Set some sort of timeout in the event of run-away builds. We are limited on concurrent jobs so, get rid of them.
|
||||
timeout-minutes: 90
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
CCACHE_BASEDIR: ${{ github.workspace }}
|
||||
CCACHE_DIR: ${{ github.workspace }}/.ccache
|
||||
CCACHE_COMPRESS: true
|
||||
CCACHE_COMPRESSLEVEL: 9
|
||||
CCACHE_MAXSIZE: 100M
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
env:
|
||||
OS: macos
|
||||
GUI_FRAMEWORK: ${{ inputs.gui }}
|
||||
ARCH: ${{ inputs.platform }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
PR_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: ./.github/workflows/scripts/common/name-artifacts.sh
|
||||
|
||||
- name: Install Packages
|
||||
env:
|
||||
PLATFORM: ${{ inputs.platform }}
|
||||
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
||||
HOMEBREW_NO_ANALYTICS: 1
|
||||
run: |
|
||||
brew unlink libjpeg || true # Conflicts with our self-built dependencies
|
||||
brew unlink libpng || true
|
||||
# Unlike other packages, brew's MoltenVK build uses MoltenVK's minimum macOS version of 10.13 so we can use it
|
||||
if ! brew install molten-vk ccache; then
|
||||
brew update
|
||||
brew install molten-vk ccache
|
||||
fi
|
||||
|
||||
- name: Cache Dependencies
|
||||
id: cache-deps
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/deps
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.gui }} deps ${{ hashFiles('.github/workflows/scripts/macos/build-dependencies.sh') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
GUI: ${{ inputs.gui }}
|
||||
run: .github/workflows/scripts/macos/build-dependencies.sh
|
||||
|
||||
- name: Download cheats
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.cheats_url }}/cheats_ni.zip" "${{ inputs.cheats_url }}/cheats_ws.zip"
|
||||
|
||||
# -- SETUP CCACHE - https://cristianadam.eu/20200113/speeding-up-c-plus-plus-github-actions-using-ccache/
|
||||
- name: Prepare ccache timestamp
|
||||
id: ccache_cache_timestamp
|
||||
run: echo "timestamp=$(date -u "+%Y-%m-%d-%H;%M;%S")" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache ccache cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .ccache
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.gui }} ccache ${{ steps.ccache_cache_timestamp.outputs.timestamp }}
|
||||
restore-keys: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.gui }} ccache
|
||||
|
||||
- name: Generate CMake Files
|
||||
run: |
|
||||
cmake -DCMAKE_PREFIX_PATH="$HOME/deps" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DUSE_OPENGL=OFF \
|
||||
-DDISABLE_ADVANCE_SIMD=ON \
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
||||
-DUSE_SYSTEM_LIBS=OFF \
|
||||
-DUSE_SYSTEM_SDL2=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \
|
||||
-B build .
|
||||
|
||||
- name: Build PCSX2
|
||||
working-directory: build
|
||||
run: |
|
||||
ccache -p
|
||||
ccache -s
|
||||
ccache -z
|
||||
make -j$(getconf _NPROCESSORS_ONLN) # macOS doesn't use make install
|
||||
ccache -s
|
||||
# Ensure there's no global constructors in multi-isa files
|
||||
for dir in */CMakeFiles/GS-{avx,avx2}.dir; do
|
||||
if find "$dir" -name "*.o" | xargs nm | grep _GLOBAL_; then
|
||||
echo "::error::Multi-isa files must not have global constructors!"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Run Tests
|
||||
if: inputs.gui == 'Qt'
|
||||
working-directory: build
|
||||
run: make -j$(getconf _NPROCESSORS_ONLN) unittests
|
||||
|
||||
- name: Prepare Build Artifacts
|
||||
run: |
|
||||
cp /usr/local/lib/libMoltenVK.dylib build/pcsx2*/PCSX2.app/Contents/Frameworks/
|
||||
TAG="$(git tag --points-at HEAD)"
|
||||
if [ -z "$TAG" ]; then
|
||||
APPNAME="${{ steps.artifact-metadata.outputs.artifact-name }}"
|
||||
else
|
||||
APPNAME="PCSX2-$TAG"
|
||||
fi
|
||||
mv build/pcsx2*/PCSX2.app "$APPNAME.app"
|
||||
tar cvzf "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.gz" "$APPNAME.app"
|
||||
mkdir ci-artifacts
|
||||
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.gz" ci-artifacts/macOS-${{ inputs.gui }}.tar.gz
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: "*.tar.gz"
|
||||
@@ -0,0 +1,18 @@
|
||||
name: 🍎 MacOS Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build_macos_qt:
|
||||
name: "Defaults"
|
||||
uses: ./.github/workflows/macos_build.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
gui: "Qt"
|
||||
secrets: inherit
|
||||
@@ -1,24 +0,0 @@
|
||||
name: 📢 Announce Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
announce:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Announce Release
|
||||
env:
|
||||
DISCORD_BUILD_WEBHOOK: ${{ secrets.DISCORD_BUILD_WEBHOOK }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/announce-release
|
||||
npm ci
|
||||
node index.js
|
||||
@@ -1,62 +0,0 @@
|
||||
# Whenever a commit is pushed to master (ideally via a pull-request!)
|
||||
# this action will create the next release, which means:
|
||||
# 1. tag master with the proper version
|
||||
# 2. create a new draft release (pre-released if a nightly build)
|
||||
# 3. add release notes
|
||||
|
||||
name: 🏭 Create Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
# TODO - future work
|
||||
# workflow_dispatch:
|
||||
# inputs:
|
||||
# isStable:
|
||||
# description: 'Should it be a stable release?'
|
||||
# required: true
|
||||
# default: 'false'
|
||||
# versionTag:
|
||||
# description: 'The version to tag with'
|
||||
# required: true
|
||||
|
||||
jobs:
|
||||
cut-release:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
# Docs - https://github.com/mathieudutour/github-tag-action
|
||||
# Workflows cannot trigger other workflows implicitly
|
||||
# - https://github.community/t/github-actions-workflow-not-triggering-with-tag-push/17053/7
|
||||
- name: Bump Version and Push Tag
|
||||
id: tag_version
|
||||
uses: mathieudutour/github-tag-action@v6.0
|
||||
with:
|
||||
github_token: ${{ secrets.BOT_PAT }}
|
||||
tag_prefix: v
|
||||
default_bump: patch
|
||||
|
||||
# Generate the Release Notes
|
||||
- name: Generate Release Notes
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COMMIT_SHA: ${{ github.SHA }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/generate-release-notes
|
||||
npm ci
|
||||
node index.js
|
||||
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
|
||||
ls
|
||||
|
||||
# Docs - https://github.com/softprops/action-gh-release
|
||||
- name: Create a GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: steps.tag_version.outputs.new_tag
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
draft: true
|
||||
prerelease: true
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
@@ -0,0 +1,24 @@
|
||||
name: 📢 Announce Release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
announce:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Announce Release
|
||||
env:
|
||||
DISCORD_BUILD_WEBHOOK: ${{ secrets.DISCORD_BUILD_WEBHOOK }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/announce-release
|
||||
npm ci
|
||||
node index.js
|
||||
@@ -0,0 +1,71 @@
|
||||
# Whenever a commit is pushed to master (ideally via a pull-request!)
|
||||
# this action will create the next release, which means:
|
||||
# 1. tag master with the proper version
|
||||
# 2. create a new draft release (pre-released if a nightly build)
|
||||
# 3. add release notes
|
||||
|
||||
name: 🏭 Create Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
# TODO - future work
|
||||
# workflow_dispatch:
|
||||
# inputs:
|
||||
# isStable:
|
||||
# description: 'Should it be a stable release?'
|
||||
# required: true
|
||||
# default: 'false'
|
||||
# versionTag:
|
||||
# description: 'The version to tag with'
|
||||
# required: true
|
||||
|
||||
jobs:
|
||||
cut-release:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
name: "Create Tag and Release"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Docs - https://github.com/mathieudutour/github-tag-action
|
||||
- name: Bump Version and Push Tag
|
||||
id: tag_version
|
||||
uses: mathieudutour/github-tag-action@v6.1
|
||||
with:
|
||||
# Workflows cannot trigger other workflows implicitly
|
||||
# - https://github.community/t/github-actions-workflow-not-triggering-with-tag-push/17053/7
|
||||
github_token: ${{ secrets.BOT_PAT }}
|
||||
tag_prefix: v
|
||||
default_bump: patch
|
||||
|
||||
# TODO - we could do this and remove the node.js script, but auto-generated notes only work
|
||||
# with PRs -- not commits (determine how much we care).
|
||||
# - name: Create Draft Release
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.BOT_PAT }}
|
||||
# run: |
|
||||
# echo "Creating release with tag - ${{ steps.tag_version.outputs.new_tag }}"
|
||||
# gh release create ${{ steps.tag_version.outputs.new_tag }} --draft --generate-notes -title ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
- name: Generate Release Notes
|
||||
env:
|
||||
OWNER: PCSX2
|
||||
REPO: pcsx2
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COMMIT_SHA: ${{ github.SHA }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/generate-release-notes
|
||||
npm ci
|
||||
node index.js
|
||||
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
|
||||
|
||||
- name: Create a GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: steps.tag_version.outputs.new_tag
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
draft: true
|
||||
prerelease: true
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
@@ -0,0 +1,115 @@
|
||||
name: 🏭 Release Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
# Build Everything
|
||||
# Linux
|
||||
build_linux_qt:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Linux"
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
secrets: inherit
|
||||
|
||||
# Windows
|
||||
build_windows_qt:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Windows"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
secrets: inherit
|
||||
|
||||
build_qt_sse4:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Windows - SSE4"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: Release
|
||||
simd: "SSE4"
|
||||
secrets: inherit
|
||||
|
||||
build_qt_avx2:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Windows - AVX2"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: Release AVX2
|
||||
secrets: inherit
|
||||
|
||||
# MacOS
|
||||
build_macos_qt:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "MacOS"
|
||||
uses: ./.github/workflows/macos_build.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
gui: "Qt"
|
||||
secrets: inherit
|
||||
|
||||
# Upload the Artifacts
|
||||
upload_artifacts:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
needs:
|
||||
- build_linux_qt
|
||||
- build_windows_qt
|
||||
- build_qt_sse4
|
||||
- build_qt_avx2
|
||||
- build_macos_qt
|
||||
name: "Upload Artifacts"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare Artifact Folder
|
||||
run: mkdir ./ci-artifacts/
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
name: Download all Artifacts
|
||||
with:
|
||||
path: ./ci-artifacts/
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls ./ci-artifacts/
|
||||
|
||||
# Prepare artifacts, they are all zips from github!
|
||||
- name: Prepare Artifacts
|
||||
working-directory: ./ci-artifacts/
|
||||
run: for d in *windows*/; do 7z a "${d}asset.7z" ./$d/*; done
|
||||
|
||||
# Artifact Naming:
|
||||
# MacOS: PCSX2-<tag>-macOS-[additional hyphen seperated tags]
|
||||
# Windows|Linux: PCSX2-<tag>-<windows|linux>-<32bit|64bit>--[additional hyphen seperated tags]
|
||||
- name: Name and Upload the Release Assets
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAG: ${{ github.REF }}
|
||||
SCAN_DIR: ${{ github.WORKSPACE }}/ci-artifacts
|
||||
OUT_DIR: ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
run: |
|
||||
gh release list --repo PCSX2/pcsx2
|
||||
mkdir -p ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
python ./.github/workflows/scripts/releases/rename-release-assets.py
|
||||
ls ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
TAG_VAL=$(echo ${{ github.REF }} | awk -F'refs/tags/' '{print $2}')
|
||||
gh release upload "${TAG_VAL}" ${{ github.WORKSPACE }}/ci-artifacts/out/* --repo PCSX2/pcsx2 --clobber
|
||||
|
||||
- name: Publish Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_PAT }}
|
||||
run: |
|
||||
TAG_VAL=$(echo ${{ github.REF }} | awk -F'refs/tags/' '{print $2}')
|
||||
gh release edit ${TAG_VAL} --draft=false --repo PCSX2/pcsx2
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Artifact Naming Scheme:
|
||||
# PCSX2-<OS>-<GUI>-[ARCH]-[SIMD]-[pr\[PR_NUM\]]-[title|sha\[SHA|PR_TITLE\]
|
||||
# -- limited to 200 chars
|
||||
# Outputs:
|
||||
# - artifact-name
|
||||
|
||||
# Inputs as env-vars
|
||||
# OS
|
||||
# BUILD_SYSTEM
|
||||
# GUI_FRAMEWORK
|
||||
# ARCH
|
||||
# SIMD
|
||||
# EVENT_NAME
|
||||
# PR_TITLE
|
||||
# PR_NUM
|
||||
# PR_SHA
|
||||
|
||||
NAME=""
|
||||
|
||||
if [ "${OS}" == "macos" ]; then
|
||||
NAME="PCSX2-${OS}-${GUI_FRAMEWORK}"
|
||||
elif [[ ("${OS}" == "windows" && "$BUILD_SYSTEM" != "cmake") ]]; then
|
||||
NAME="PCSX2-${OS}-${GUI_FRAMEWORK}-${ARCH}-${SIMD}"
|
||||
else
|
||||
NAME="PCSX2-${OS}-${GUI_FRAMEWORK}-${ARCH}"
|
||||
fi
|
||||
|
||||
# Add cmake if used to differentate it from msbuild builds
|
||||
# Else the two artifacts will have the same name and the files will be merged
|
||||
if [[ ! -z "${BUILD_SYSTEM}" ]]; then
|
||||
if [ "${BUILD_SYSTEM}" == "cmake" ]; then
|
||||
NAME="${NAME}-${BUILD_SYSTEM}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Add PR / Commit Metadata
|
||||
if [ "$EVENT_NAME" == "pull_request" ]; then
|
||||
PR_SHA=$(git rev-parse --short "${PR_SHA}")
|
||||
if [ ! -z "${PR_NUM}" ]; then
|
||||
NAME="${NAME}-pr[${PR_NUM}]"
|
||||
fi
|
||||
NAME="${NAME}-sha[${PR_SHA}]"
|
||||
if [ ! -z "${PR_TITLE}" ]; then
|
||||
PR_TITLE=$(echo "${PR_TITLE}" | tr -cd '[a-zA-Z0-9[:space:]]_-')
|
||||
NAME="${NAME}-title[${PR_TITLE}"
|
||||
fi
|
||||
else
|
||||
SHA=$(git rev-parse --short "$GITHUB_SHA")
|
||||
NAME="${NAME}-sha[${SHA}"
|
||||
fi
|
||||
|
||||
# Trim the Name
|
||||
NAME=$(printf "%.199s]" "$NAME")
|
||||
echo "${NAME}"
|
||||
echo "artifact-name=${NAME}" >> "$GITHUB_OUTPUT"
|
||||
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
|
||||
relevant_categories = [
|
||||
"# Windows",
|
||||
"# Mac OS X",
|
||||
"# Linux"
|
||||
]
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
export LD_LIBRARY_PATH="$APPDIR/usr/lib:$LD_LIBRARY_PATH"
|
||||
BINARY_NAME=$(basename "$ARGV0")
|
||||
if [[ ! -e "$PWD/$BINARY_NAME.config" ]]; then
|
||||
mkdir "$PWD/$BINARY_NAME.config"
|
||||
fi
|
||||
export XDG_CONFIG_HOME="$PWD/$BINARY_NAME.config"
|
||||
|
||||
ln -sf $APPDIR/usr/bin/app /tmp/PCSX2
|
||||
mkdir -p $HOME/.local/share/icons/hicolor/scalable/apps && cp $APPDIR/PCSX2.png $HOME/.local/share/icons/hicolor/scalable/apps
|
||||
|
||||
$APPDIR/AppRun-patched
|
||||
|
||||
unlink /tmp/PCSX2
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
APPDIR=$(dirname "$0")
|
||||
exec "$APPDIR/usr/bin/pcsx2-qt" "$@"
|
||||
+290
@@ -0,0 +1,290 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# This is free and unencumbered software released into the public domain.
|
||||
#
|
||||
# Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
# distribute this software, either in source code form or as a compiled
|
||||
# binary, for any purpose, commercial or non-commercial, and by any
|
||||
# means.
|
||||
#
|
||||
# In jurisdictions that recognize copyright laws, the author or authors
|
||||
# of this software dedicate any and all copyright interest in the
|
||||
# software to the public domain. We make this dedication for the benefit
|
||||
# of the public at large and to the detriment of our heirs and
|
||||
# successors. We intend this dedication to be an overt act of
|
||||
# relinquishment in perpetuity of all present and future rights to this
|
||||
# software under copyright law.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
# OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# For more information, please refer to <http://unlicense.org/>
|
||||
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
source "$SCRIPTDIR/functions.sh"
|
||||
|
||||
if [ "$#" -ne 4 ]; then
|
||||
echo "Syntax: $0 <path to pcsx2 directory> <path to build directory> <deps prefix> <output name>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PCSX2DIR=$1
|
||||
BUILDDIR=$2
|
||||
DEPSDIR=$3
|
||||
NAME=$4
|
||||
|
||||
BINARY=pcsx2-qt
|
||||
APPDIRNAME=PCSX2.AppDir
|
||||
STRIP=llvm-strip-12
|
||||
|
||||
declare -a SYSLIBS=(
|
||||
"libaio.so.1"
|
||||
"libz.so.1"
|
||||
"libuuid.so.1"
|
||||
"libapparmor.so.1"
|
||||
"libblkid.so.1"
|
||||
"libbsd.so.0"
|
||||
"libdbus-1.so.3"
|
||||
"libgcrypt.so.20"
|
||||
"liblzma.so.5"
|
||||
"libmount.so.1"
|
||||
"libnsl.so.1"
|
||||
"libpcre.so.3"
|
||||
"libselinux.so.1"
|
||||
"libsystemd.so.0"
|
||||
"libudev.so.1"
|
||||
"libwrap.so.0"
|
||||
"libharfbuzz.so.0"
|
||||
"libFLAC.so.8"
|
||||
"libSoundTouch.so.1"
|
||||
"libXau.so.6"
|
||||
"libXcomposite.so.1"
|
||||
"libXcursor.so.1"
|
||||
"libXdamage.so.1"
|
||||
"libXdmcp.so.6"
|
||||
"libXext.so.6"
|
||||
"libXfixes.so.3"
|
||||
"libXi.so.6"
|
||||
"libXinerama.so.1"
|
||||
"libXrandr.so.2"
|
||||
"libXrender.so.1"
|
||||
"libXxf86vm.so.1"
|
||||
"libasyncns.so.0"
|
||||
"libcrypto.so.1.1"
|
||||
"libjpeg.so.8"
|
||||
"liblz4.so.1"
|
||||
"libogg.so.0"
|
||||
"libpcap.so.0.8"
|
||||
"libpng16.so.16"
|
||||
"libpulse.so.0"
|
||||
"libsamplerate.so.0"
|
||||
"libsndfile.so.1"
|
||||
"libvorbis.so.0"
|
||||
"libvorbisenc.so.2"
|
||||
"libxcb.so.1"
|
||||
"libxcb-render.so.0"
|
||||
"libxcb-shm.so.0"
|
||||
"libxkbcommon.so.0"
|
||||
"libxkbcommon-x11.so.0"
|
||||
"pulseaudio/libpulsecommon-13.99.so"
|
||||
"libasound.so.2"
|
||||
"libfreetype.so.6"
|
||||
"libpcre2-16.so.0"
|
||||
"libexpat.so.1"
|
||||
"libffi.so.7"
|
||||
"libgraphite2.so.3"
|
||||
"libresolv.so.2"
|
||||
"libgpg-error.so.0"
|
||||
"libpcre2-16.so.0"
|
||||
"libpng16.so.16"
|
||||
"libxcb-icccm.so.4"
|
||||
"libxcb-image.so.0"
|
||||
"libxcb-keysyms.so.1"
|
||||
"libxcb-randr.so.0"
|
||||
"libxcb-render.so.0"
|
||||
"libxcb-render-util.so.0"
|
||||
"libxcb-shape.so.0"
|
||||
"libxcb-sync.so.1"
|
||||
"libxcb-util.so.1"
|
||||
"libxcb-xfixes.so.0"
|
||||
"libxcb-xkb.so.1"
|
||||
"libevdev.so.2"
|
||||
"libgudev-1.0.so.0"
|
||||
"libinput.so.10"
|
||||
"libjpeg.so.8"
|
||||
"libmtdev.so.1"
|
||||
"libpng16.so.16"
|
||||
"libudev.so.1"
|
||||
"libuuid.so.1"
|
||||
"libcurl.so.4"
|
||||
"libnghttp2.so.14"
|
||||
"libidn2.so.0"
|
||||
"librtmp.so.1"
|
||||
"libssh.so.4"
|
||||
"libpsl.so.5"
|
||||
"libssl.so.1.1"
|
||||
"libnettle.so.7"
|
||||
"libgnutls.so.30"
|
||||
"libgssapi_krb5.so.2"
|
||||
"libldap_r-2.4.so.2"
|
||||
"liblber-2.4.so.2"
|
||||
"libbrotlidec.so.1"
|
||||
"libunistring.so.2"
|
||||
"libhogweed.so.5"
|
||||
"libgmp.so.10"
|
||||
"libp11-kit.so.0"
|
||||
"libtasn1.so.6"
|
||||
"libkrb5.so.3"
|
||||
"libk5crypto.so.3"
|
||||
"libcom_err.so.2"
|
||||
"libkrb5support.so.0"
|
||||
"libsasl2.so.2"
|
||||
"libgssapi.so.3"
|
||||
"libbrotlicommon.so.1"
|
||||
"libkeyutils.so.1"
|
||||
"libheimntlm.so.0"
|
||||
"libkrb5.so.26"
|
||||
"libasn1.so.8"
|
||||
"libhcrypto.so.4"
|
||||
"libroken.so.18"
|
||||
"libwind.so.0"
|
||||
"libheimbase.so.1"
|
||||
"libhx509.so.5"
|
||||
"libsqlite3.so.0"
|
||||
"libcrypt.so.1"
|
||||
)
|
||||
|
||||
declare -a DEPLIBS=(
|
||||
"libSDL2-2.0.so.0"
|
||||
)
|
||||
|
||||
declare -a QTLIBS=(
|
||||
"libQt6Core.so.6"
|
||||
"libQt6Gui.so.6"
|
||||
"libQt6Network.so.6"
|
||||
"libQt6OpenGL.so.6"
|
||||
"libQt6Svg.so.6"
|
||||
"libQt6WaylandClient.so.6"
|
||||
"libQt6WaylandCompositor.so.6"
|
||||
"libQt6WaylandEglClientHwIntegration.so.6"
|
||||
"libQt6WaylandEglCompositorHwIntegration.so.6"
|
||||
"libQt6Widgets.so.6"
|
||||
"libQt6XcbQpa.so.6"
|
||||
)
|
||||
|
||||
declare -a QTPLUGINS=(
|
||||
"plugins/iconengines"
|
||||
"plugins/imageformats"
|
||||
"plugins/platforms"
|
||||
#"plugins/platformthemes" # Enable this if we want to ship GTK+ themes at any point.
|
||||
"plugins/tls"
|
||||
"plugins/wayland-decoration-client"
|
||||
"plugins/wayland-graphics-integration-client"
|
||||
"plugins/wayland-graphics-integration-server"
|
||||
"plugins/wayland-shell-integration"
|
||||
"plugins/xcbglintegrations"
|
||||
)
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! -f appimagetool-x86_64.AppImage ]; then
|
||||
retry_command wget -O appimagetool-x86_64.AppImage https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
chmod +x appimagetool-x86_64.AppImage
|
||||
fi
|
||||
|
||||
OUTDIR=$(realpath "./$APPDIRNAME")
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
rm -fr "$OUTDIR"
|
||||
mkdir "$OUTDIR"
|
||||
mkdir "$OUTDIR/usr"
|
||||
|
||||
echo "Copying binary and resources..."
|
||||
cp -a "$BUILDDIR/bin" "$OUTDIR/usr"
|
||||
|
||||
# Patch RPATH so the binary goes hunting for shared libraries in the AppDir instead of system.
|
||||
echo "Patching RPATH in ${BINARY}..."
|
||||
patchelf --set-rpath '$ORIGIN/../lib' "$OUTDIR/usr/bin/$BINARY"
|
||||
|
||||
# Currently we leave the main binary unstripped, uncomment if this is not desired.
|
||||
#$STRIP "$OUTDIR/usr/bin/$BINARY"
|
||||
|
||||
# Libraries we pull in from the system.
|
||||
echo "Copying system libraries..."
|
||||
mkdir -p "$OUTDIR/usr/lib" "$OUTDIR/usr/lib/pulseaudio"
|
||||
for lib in "${SYSLIBS[@]}"; do
|
||||
blib=$(basename "$lib")
|
||||
if [ -f "/lib/x86_64-linux-gnu/$lib" ]; then
|
||||
cp "/lib/x86_64-linux-gnu/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
elif [ -f "$CHROOT/usr/lib/x86_64-linux-gnu/$lib" ]; then
|
||||
cp "$CHROOT/usr/lib/x86_64-linux-gnu/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
elif [ -f "$CHROOT/lib/$lib" ]; then
|
||||
cp "$CHROOT/lib/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
elif [ -f "$CHROOT/usr/lib/$lib" ]; then
|
||||
cp "$CHROOT/usr/lib/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
else
|
||||
echo "*** Failed to find '$blib'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$STRIP "$OUTDIR/usr/lib/$blib"
|
||||
done
|
||||
|
||||
# Dependencies we built, at this point it's just SDL.
|
||||
echo "Copying dependency libraries..."
|
||||
for lib in "${DEPLIBS[@]}"; do
|
||||
blib=$(basename "$lib")
|
||||
if [ -f "$DEPSDIR/lib/$lib" ]; then
|
||||
cp "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
else
|
||||
echo "*** Failed to find '$blib'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$STRIP "$OUTDIR/usr/lib/$blib"
|
||||
done
|
||||
|
||||
echo "Copying Qt libraries..."
|
||||
for lib in "${QTLIBS[@]}"; do
|
||||
cp -aL "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib"
|
||||
$STRIP "$OUTDIR/usr/lib/$lib"
|
||||
done
|
||||
|
||||
echo "Copying Qt plugins..."
|
||||
mkdir -p "$OUTDIR/usr/lib/plugins"
|
||||
for plugin in "${QTPLUGINS[@]}"; do
|
||||
mkdir -p "$OUTDIR/usr/lib/$plugin"
|
||||
cp -aL "$DEPSDIR/$plugin"/*.so "$OUTDIR/usr/lib/$plugin/"
|
||||
done
|
||||
|
||||
for so in $(find "$OUTDIR/usr/lib/plugins" -iname '*.so'); do
|
||||
# This is ../../ because it's usually plugins/group/name.so
|
||||
echo "Patching RPATH in ${so}..."
|
||||
patchelf --set-rpath '$ORIGIN/../..' "$so"
|
||||
$STRIP "$so"
|
||||
done
|
||||
|
||||
for so in $(find "$OUTDIR/usr/lib" -maxdepth 1); do
|
||||
if [ -f "$so" ]; then
|
||||
echo "Patching RPATH in ${so}"
|
||||
patchelf --set-rpath '$ORIGIN' "$so"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Creating qt.conf..."
|
||||
cat > "$OUTDIR/usr/bin/qt.conf" << EOF
|
||||
[Paths]
|
||||
Plugins = ../lib/plugins
|
||||
EOF
|
||||
|
||||
echo "Copy desktop/icon..."
|
||||
cp "$PCSX2DIR/pcsx2/Resources/AppIcon64.png" "$OUTDIR/PCSX2.png"
|
||||
cp "$SCRIPTDIR/pcsx2-qt.desktop" "$OUTDIR/PCSX2.desktop"
|
||||
cp "$SCRIPTDIR/AppRun-qt" "$OUTDIR/AppRun"
|
||||
|
||||
echo "Generate AppImage"
|
||||
./appimagetool-x86_64.AppImage -v "$OUTDIR" "$NAME.AppImage"
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
echo "${PLATFORM}"
|
||||
if [ "${PLATFORM}" == "x86" ]; then
|
||||
APPARCH="i686"
|
||||
ARCH="i386"
|
||||
LIBARCH="i386-linux-gnu"
|
||||
else
|
||||
APPARCH="x86_64"
|
||||
ARCH="x86_64"
|
||||
LIBARCH="x86_64-linux-gnu"
|
||||
fi
|
||||
BUILDPATH="$GITHUB_WORKSPACE"/build
|
||||
BUILDBIN="$BUILDPATH"/pcsx2
|
||||
cd /tmp
|
||||
curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-$ARCH.AppImage"
|
||||
chmod a+x linuxdeploy*.AppImage
|
||||
./linuxdeploy-"$ARCH".AppImage --appimage-extract
|
||||
curl -sSfL "https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh" -o /tmp/squashfs-root/usr/bin/linuxdeploy-plugin-gtk.sh
|
||||
chmod a+x /tmp/squashfs-root/usr/bin/linuxdeploy-plugin-gtk.sh
|
||||
mv /tmp/squashfs-root/usr/bin/patchelf /tmp/squashfs-root/usr/bin/patchelf.orig
|
||||
sudo cp /usr/local/bin/patchelf /tmp/squashfs-root/usr/bin/patchelf
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
mkdir -p squashfs-root/usr/bin
|
||||
ls -al "$BUILDBIN"
|
||||
cp -P "$BUILDBIN"/PCSX2 "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/
|
||||
patchelf --set-rpath /tmp/PCSX2 "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/PCSX2
|
||||
cp ./pcsx2/gui/Resources/AppIcon64.png ./squashfs-root/PCSX2.png
|
||||
cp ./linux_various/PCSX2.desktop.in ./squashfs-root/PCSX2.desktop
|
||||
sed -i -e 's|Categories=@PCSX2_MENU_CATEGORIES@|Categories=Game;Emulator;|g' ./squashfs-root/PCSX2.desktop
|
||||
sed -i -e 's|__GL_THREADED_OPTIMIZATIONS=1|__GL_THREADED_OPTIMIZATIONS=0|g' ./squashfs-root/PCSX2.desktop
|
||||
curl -sSfL "https://github.com/AppImage/AppImageKit/releases/download/continuous/runtime-$APPARCH" -o ./squashfs-root/runtime
|
||||
mkdir -p squashfs-root/usr/share/applications && cp ./squashfs-root/PCSX2.desktop ./squashfs-root/usr/share/applications
|
||||
mkdir -p squashfs-root/usr/share/icons && cp ./squashfs-root/PCSX2.png ./squashfs-root/usr/share/icons
|
||||
mkdir -p squashfs-root/usr/share/icons/hicolor/scalable/apps && cp ./squashfs-root/PCSX2.png ./squashfs-root/usr/share/icons/hicolor/scalable/apps
|
||||
mkdir -p squashfs-root/usr/share/pixmaps && cp ./squashfs-root/PCSX2.png ./squashfs-root/usr/share/pixmaps
|
||||
mkdir -p squashfs-root/usr/lib/
|
||||
mkdir -p squashfs-root/usr/optional/libstdc++
|
||||
mkdir -p squashfs-root/usr/optional/libgcc_s
|
||||
cp ./.github/workflows/scripts/linux/AppRun "$GITHUB_WORKSPACE"/squashfs-root/AppRun
|
||||
curl -sSfL "https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/AppRun-patched-$APPARCH" -o "$GITHUB_WORKSPACE"/squashfs-root/AppRun-patched
|
||||
curl -sSfL "https://github.com/darealshinji/AppImageKit-checkrt/releases/download/continuous/exec-$APPARCH.so" -o "$GITHUB_WORKSPACE"/squashfs-root/usr/optional/exec.so
|
||||
chmod a+x ./squashfs-root/AppRun
|
||||
chmod a+x ./squashfs-root/runtime
|
||||
chmod a+x ./squashfs-root/AppRun-patched
|
||||
chmod a+x ./squashfs-root/usr/optional/exec.so
|
||||
echo "$name" > "$GITHUB_WORKSPACE"/squashfs-root/version.txt
|
||||
mkdir -p "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/app
|
||||
cp -r "$GITHUB_WORKSPACE"/bin/Langs "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/
|
||||
cp -r "$GITHUB_WORKSPACE"/bin/resources "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/app/
|
||||
cp "$GITHUB_WORKSPACE"/bin/docs/{Configuration_Guide.pdf,PCSX2_FAQ.pdf} "$GITHUB_WORKSPACE"/squashfs-root/usr/bin/app
|
||||
cp /usr/lib/$LIBARCH/libthai.so.0 "$GITHUB_WORKSPACE"/squashfs-root/usr/lib/
|
||||
cp --dereference /usr/lib/"$LIBARCH"/libstdc++.so.6 "$GITHUB_WORKSPACE"/squashfs-root/usr/optional/libstdc++/libstdc++.so.6
|
||||
cp --dereference /lib/"$LIBARCH"/libgcc_s.so.1 "$GITHUB_WORKSPACE"/squashfs-root/usr/optional/libgcc_s/libgcc_s.so.1
|
||||
export UPD_INFO="gh-releases-zsync|PCSX2|pcsx2|latest|$name.AppImage.zsync"
|
||||
export OUTPUT="$name.AppImage"
|
||||
/tmp/squashfs-root/AppRun --appdir="$GITHUB_WORKSPACE"/squashfs-root/ --plugin gtk -d "$GITHUB_WORKSPACE"/squashfs-root/PCSX2.desktop -i "$GITHUB_WORKSPACE"/squashfs-root/PCSX2.png --output appimage
|
||||
mkdir -p "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
ls -al .
|
||||
mv "$name.AppImage" "$GITHUB_WORKSPACE"/ci-artifacts # && mv "$name.AppImage.zsync" "$GITHUB_WORKSPACE"/ci-artifacts
|
||||
chmod -R 777 ./ci-artifacts
|
||||
cd ./ci-artifacts
|
||||
ls -al .
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
INSTALLDIR="$HOME/deps"
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
SDL=SDL2-2.26.0
|
||||
QT=6.3.1
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
8000d7169febce93c84b6bdf376631f8179132fd69f7015d4dadb8b9c2bdb295 $SDL.tar.gz
|
||||
0a64421d9c2469c2c48490a032ab91d547017c9cc171f3f8070bc31888f24e03 qtbase-everywhere-src-$QT.tar.xz
|
||||
7b19f418e6f7b8e23344082dd04440aacf5da23c5a73980ba22ae4eba4f87df7 qtsvg-everywhere-src-$QT.tar.xz
|
||||
c412750f2aa3beb93fce5f30517c607f55daaeb7d0407af206a8adf917e126c1 qttools-everywhere-src-$QT.tar.xz
|
||||
d7bdd55e2908ded901dcc262157100af2a490bf04d31e32995f6d91d78dfdb97 qttranslations-everywhere-src-$QT.tar.xz
|
||||
6f14fea2d172a5b4170be3efcb0e58535f6605b61bcd823f6d5c9d165bb8c0f0 qtwayland-everywhere-src-$QT.tar.xz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtwayland-everywhere-src-$QT.tar.xz"
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
echo "Building SDL..."
|
||||
tar xf "$SDL.tar.gz"
|
||||
cd "$SDL"
|
||||
./configure --prefix "$INSTALLDIR" --disable-dbus --without-x --disable-video-opengl --disable-video-opengles --disable-video-vulkan --disable-wayland-shared --disable-ime --disable-oss --disable-alsa --disable-jack --disable-esd --disable-pipewire --disable-pulseaudio --disable-arts --disable-nas --disable-sndio --disable-fusionsound --disable-diskaudio
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ..
|
||||
|
||||
# Couple notes:
|
||||
# -fontconfig is needed otherwise Qt Widgets render only boxes.
|
||||
# -qt-doubleconversion avoids a dependency on libdouble-conversion.
|
||||
# ICU avoids pulling in a bunch of large libraries, and hopefully we can get away without it.
|
||||
# OpenGL is needed to render window decorations in Wayland, apparently.
|
||||
echo "Building Qt Base..."
|
||||
tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
cd "qtbase-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
../configure -prefix "$INSTALLDIR" -release -no-dbus -gui -widgets -fontconfig -qt-doubleconversion -ssl -openssl-runtime -opengl desktop -qpa xcb,wayland -xkbcommon -- -DFEATURE_dbus=OFF -DFEATURE_icu=OFF -DFEATURE_printsupport=OFF -DFEATURE_sql=OFF
|
||||
cmake --build . --parallel
|
||||
cmake --install .
|
||||
cd ../../
|
||||
|
||||
echo "Building Qt SVG..."
|
||||
tar xf "qtsvg-everywhere-src-$QT.tar.xz"
|
||||
cd "qtsvg-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --parallel
|
||||
cmake --install .
|
||||
cd ../../
|
||||
|
||||
echo "Building Qt Wayland..."
|
||||
tar xf "qtwayland-everywhere-src-$QT.tar.xz"
|
||||
cd "qtwayland-everywhere-src-$QT"
|
||||
# qtwayland does not build without qml/qtdeclarative in 6.3.1. Work around it.
|
||||
patch -u src/compositor/CMakeLists.txt <<EOF
|
||||
--- src/compositor/CMakeLists.txt 2022-06-08 13:44:30.000000000 +1000
|
||||
+++ src/compositor/CMakeLists.txt 2022-07-17 20:05:25.461881785 +1000
|
||||
@@ -46,7 +46,6 @@
|
||||
global/qtwaylandcompositorglobal.h
|
||||
global/qtwaylandqmlinclude.h
|
||||
global/qwaylandcompositorextension.cpp global/qwaylandcompositorextension.h global/qwaylandcompositorextension_p.h
|
||||
- global/qwaylandquickextension.cpp global/qwaylandquickextension.h
|
||||
global/qwaylandutils_p.h
|
||||
hardware_integration/qwlclientbufferintegration.cpp hardware_integration/qwlclientbufferintegration_p.h
|
||||
wayland_wrapper/qwlbuffermanager.cpp wayland_wrapper/qwlbuffermanager_p.h
|
||||
EOF
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --parallel
|
||||
cmake --install .
|
||||
cd ../../
|
||||
|
||||
echo "Installing Qt Tools..."
|
||||
tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
# From Mac build-dependencies.sh:
|
||||
# Linguist relies on a library in the Designer target, which takes 5-7 minutes to build on the CI
|
||||
# Avoid it by not building Linguist, since we only need the tools that come with it
|
||||
patch -u src/linguist/CMakeLists.txt <<EOF
|
||||
--- src/linguist/CMakeLists.txt
|
||||
+++ src/linguist/CMakeLists.txt
|
||||
@@ -14,7 +14,7 @@
|
||||
add_subdirectory(lrelease-pro)
|
||||
add_subdirectory(lupdate)
|
||||
add_subdirectory(lupdate-pro)
|
||||
-if(QT_FEATURE_process AND QT_FEATURE_pushbutton AND QT_FEATURE_toolbutton AND TARGET Qt::Widgets AND NOT no-png)
|
||||
+if(QT_FEATURE_process AND QT_FEATURE_pushbutton AND QT_FEATURE_toolbutton AND TARGET Qt::Widgets AND TARGET Qt::PrintSupport AND NOT no-png)
|
||||
add_subdirectory(linguist)
|
||||
endif()
|
||||
EOF
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=OFF -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF ..
|
||||
cmake --build . --parallel
|
||||
cmake --install .
|
||||
cd ../../
|
||||
|
||||
echo "Installing Qt Translations..."
|
||||
tar xf "qttranslations-everywhere-src-$QT.tar.xz"
|
||||
cd "qttranslations-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --parallel
|
||||
cmake --install .
|
||||
cd ../../
|
||||
|
||||
echo "Cleaning up..."
|
||||
cd ..
|
||||
rm -r deps-build
|
||||
Executable
+16
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
function retry_command {
|
||||
# Package servers tend to be unreliable at times..
|
||||
# Retry a bunch of times.
|
||||
local RETRIES=10
|
||||
|
||||
for i in $(seq 1 "$RETRIES"); do
|
||||
"$@" && break
|
||||
if [ "$i" == "$RETRIES" ]; then
|
||||
echo "Command \"$@\" failed after ${RETRIES} retries."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "${COMPILER}" = "clang" ]; then
|
||||
echo "Using clang toolchain"
|
||||
cat > "$HOME/clang-toolchain.cmake" << EOF
|
||||
set(CMAKE_C_COMPILER /usr/bin/clang-12)
|
||||
set(CMAKE_CXX_COMPILER /usr/bin/clang++-12)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
|
||||
EOF
|
||||
ADDITIONAL_CMAKE_ARGS="$ADDITIONAL_CMAKE_ARGS -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_TOOLCHAIN_FILE=$HOME/clang-toolchain.cmake"
|
||||
fi
|
||||
|
||||
echo "Additional CMake Args - ${ADDITIONAL_CMAKE_ARGS}"
|
||||
|
||||
# Generate CMake into ./build
|
||||
# DISABLE_ADVANCE_SIMD is needed otherwise we end up doing -march=native.
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
cmake \
|
||||
-B build \
|
||||
-G Ninja \
|
||||
$ADDITIONAL_CMAKE_ARGS \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DQT_BUILD=ON \
|
||||
-DCUBEB_API=ON \
|
||||
-DX11_API=ON \
|
||||
-DWAYLAND_API=ON \
|
||||
-DENABLE_SETCAP=OFF \
|
||||
-DCMAKE_PREFIX_PATH="$HOME/deps" \
|
||||
-DUSE_SYSTEM_SDL2=ON \
|
||||
-DUSE_SYSTEM_ZSTD=OFF \
|
||||
-DDISABLE_ADVANCE_SIMD=TRUE
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "${COMPILER}" = "gcc" ]; then
|
||||
export CC=gcc-10
|
||||
export CXX=g++-10
|
||||
else
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
fi
|
||||
|
||||
if [ "${PLATFORM}" = x86 ]; then
|
||||
ADDITIONAL_CMAKE_ARGS="$ADDITIONAL_CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=cmake/linux-compiler-i386-multilib.cmake"
|
||||
fi
|
||||
echo "Additional CMake Args - ${ADDITIONAL_CMAKE_ARGS}"
|
||||
|
||||
# Generate CMake into ./build
|
||||
cmake \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DPACKAGE_MODE=TRUE \
|
||||
-DWAYLAND_API=TRUE \
|
||||
-DDISABLE_ADVANCE_SIMD=TRUE \
|
||||
-DCMAKE_INSTALL_LIBDIR="/tmp/" \
|
||||
-DCMAKE_INSTALL_DATADIR="/tmp/" \
|
||||
-DCMAKE_INSTALL_DOCDIR="/tmp/PCSX2" \
|
||||
-DOpenGL_GL_PREFERENCE="LEGACY" \
|
||||
-DOPENGL_opengl_LIBRARY="" \
|
||||
-DXDG_STD=TRUE \
|
||||
$ADDITIONAL_CMAKE_ARGS \
|
||||
-GNinja \
|
||||
-B build
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
source "$SCRIPTDIR/functions.sh"
|
||||
|
||||
set -e
|
||||
|
||||
# Packages - Build and Qt
|
||||
declare -a BUILD_PACKAGES=(
|
||||
"build-essential"
|
||||
"git"
|
||||
"cmake"
|
||||
"ccache"
|
||||
"ninja-build"
|
||||
"libclang-dev" # Qt goes hunting for libclang-11 specifically.
|
||||
"libclang-11-dev"
|
||||
"libclang-12-dev"
|
||||
"patchelf"
|
||||
"libglib2.0-dev"
|
||||
"libfontconfig1-dev"
|
||||
"libharfbuzz-dev"
|
||||
"libjpeg-dev"
|
||||
"libpng-dev"
|
||||
"libfreetype-dev"
|
||||
"libinput-dev"
|
||||
"libxcb-*-dev"
|
||||
"libxkbcommon-dev"
|
||||
"libxkbcommon-x11-dev"
|
||||
"libxrender-dev"
|
||||
"libwayland-dev"
|
||||
"libgl1-mesa-dev"
|
||||
"libegl-dev"
|
||||
"libegl1-mesa-dev"
|
||||
"libgl1-mesa-dev"
|
||||
"libssl-dev"
|
||||
)
|
||||
|
||||
# Packages - PCSX2
|
||||
declare -a PCSX2_PACKAGES=(
|
||||
"libaio-dev"
|
||||
"libasound2-dev"
|
||||
"libbz2-dev"
|
||||
"libcurl4-openssl-dev"
|
||||
"libegl1-mesa-dev"
|
||||
"libgl1-mesa-dev"
|
||||
"libgtk-3-dev"
|
||||
"libharfbuzz-dev"
|
||||
"libjpeg-dev"
|
||||
"liblzma-dev"
|
||||
"libpcap0.8-dev"
|
||||
"libpng-dev"
|
||||
"libpulse-dev"
|
||||
"librsvg2-dev"
|
||||
"libsamplerate0-dev"
|
||||
"libsoundtouch-dev"
|
||||
"libudev-dev"
|
||||
"libx11-xcb-dev"
|
||||
"pkg-config"
|
||||
"zlib1g-dev"
|
||||
)
|
||||
|
||||
if [ "${COMPILER}" = "gcc" ]; then
|
||||
BUILD_PACKAGES+=("g++-10")
|
||||
else
|
||||
BUILD_PACKAGES+=("llvm-12" "lld-12" "clang-12")
|
||||
fi
|
||||
|
||||
retry_command sudo apt-get -qq update && break
|
||||
|
||||
# Install packages needed for building
|
||||
echo "Will install the following packages for building - ${BUILD_PACKAGES[*]}"
|
||||
retry_command sudo apt-get -y install "${BUILD_PACKAGES[@]}"
|
||||
|
||||
# Install packages needed by pcsx2
|
||||
PCSX2_PACKAGES=("${PCSX2_PACKAGES[@]}")
|
||||
echo "Will install the following packages for pcsx2 - ${PCSX2_PACKAGES[*]}"
|
||||
retry_command sudo apt-get -y install "${PCSX2_PACKAGES[@]}"
|
||||
@@ -1,70 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Packages - Build Environment
|
||||
declare -a BUILD_PACKAGES=(
|
||||
"ccache"
|
||||
"cmake"
|
||||
"ninja-build"
|
||||
)
|
||||
|
||||
# Packages - PCSX2
|
||||
declare -a PCSX2_PACKAGES=(
|
||||
"libaio-dev"
|
||||
"libbz2-dev"
|
||||
"libegl1-mesa-dev"
|
||||
"libgdk-pixbuf2.0-dev"
|
||||
"libgl1-mesa-dev"
|
||||
"libgtk-3-dev"
|
||||
"libharfbuzz-dev"
|
||||
"libjpeg-dev"
|
||||
"liblzma-dev"
|
||||
"libpcap0.8-dev"
|
||||
"libpng-dev"
|
||||
"libpulse-dev"
|
||||
"librsvg2-dev"
|
||||
"libsdl2-dev"
|
||||
"libsamplerate0-dev"
|
||||
"libsoundtouch-dev"
|
||||
"libwxgtk3.0-gtk3-dev"
|
||||
"libx11-xcb-dev"
|
||||
"libxml2-dev"
|
||||
"pkg-config"
|
||||
"portaudio19-dev"
|
||||
"zlib1g-dev"
|
||||
)
|
||||
|
||||
if [ "${COMPILER}" = "gcc" ]; then
|
||||
BUILD_PACKAGES+=("g++-10-multilib")
|
||||
else
|
||||
BUILD_PACKAGES+=("clang-9")
|
||||
PCSX2_PACKAGES+=("libstdc++-10-dev")
|
||||
fi
|
||||
|
||||
# - https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md
|
||||
ARCH=""
|
||||
echo "${PLATFORM}"
|
||||
if [ "${PLATFORM}" == "x86" ]; then
|
||||
ARCH=":i386"
|
||||
sudo dpkg --add-architecture i386
|
||||
fi
|
||||
|
||||
sudo apt-get -qq update
|
||||
|
||||
# Install packages needed for building
|
||||
echo "Will install the following packages for building - ${BUILD_PACKAGES[*]}"
|
||||
#sudo apt remove gcc-9 g++-9
|
||||
sudo apt-get -y install "${BUILD_PACKAGES[@]}"
|
||||
|
||||
# Install packages needed by pcsx2
|
||||
PCSX2_PACKAGES=("${PCSX2_PACKAGES[@]/%/"${ARCH}"}")
|
||||
echo "Will install the following packages for pcsx2 - ${PCSX2_PACKAGES[*]}"
|
||||
sudo apt-get -y install "${PCSX2_PACKAGES[@]}"
|
||||
|
||||
cd /tmp
|
||||
curl -sSfLO https://github.com/NixOS/patchelf/releases/download/0.12/patchelf-0.12.tar.bz2
|
||||
tar xvf patchelf-0.12.tar.bz2
|
||||
cd patchelf-0.12*/
|
||||
./configure
|
||||
make && sudo make install
|
||||
@@ -0,0 +1,12 @@
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Name=PCSX2
|
||||
StartupWMClass=PCSX2
|
||||
GenericName=PlayStation 2 Emulator
|
||||
Comment=Sony PlayStation 2 emulator
|
||||
Exec=pcsx2-qt
|
||||
Icon=PCSX2
|
||||
Keywords=game;emulator;
|
||||
Categories=Game;Emulator;
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.14
|
||||
|
||||
INSTALLDIR="$HOME/deps"
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
SDL=SDL2-2.26.0
|
||||
PNG=1.6.37
|
||||
JPG=9e
|
||||
SOUNDTOUCH=soundtouch-2.3.1
|
||||
QT=6.3.1
|
||||
|
||||
mkdir deps-build
|
||||
cd deps-build
|
||||
|
||||
export PKG_CONFIG_PATH="$INSTALLDIR/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
export LDFLAGS="-L$INSTALLDIR/lib -dead_strip $LDFLAGS"
|
||||
export CFLAGS="-I$INSTALLDIR/include -Os $CFLAGS"
|
||||
export CXXFLAGS="-I$INSTALLDIR/include -Os $CXXFLAGS"
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
8000d7169febce93c84b6bdf376631f8179132fd69f7015d4dadb8b9c2bdb295 $SDL.tar.gz
|
||||
505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca libpng-$PNG.tar.xz
|
||||
4077d6a6a75aeb01884f708919d25934c93305e49f7e3f36db9129320e6f4f3d jpegsrc.v$JPG.tar.gz
|
||||
6900996607258496ce126924a19fe9d598af9d892cf3f33d1e4daaa9b42ae0b1 $SOUNDTOUCH.tar.gz
|
||||
0a64421d9c2469c2c48490a032ab91d547017c9cc171f3f8070bc31888f24e03 qtbase-everywhere-src-$QT.tar.xz
|
||||
7b19f418e6f7b8e23344082dd04440aacf5da23c5a73980ba22ae4eba4f87df7 qtsvg-everywhere-src-$QT.tar.xz
|
||||
c412750f2aa3beb93fce5f30517c607f55daaeb7d0407af206a8adf917e126c1 qttools-everywhere-src-$QT.tar.xz
|
||||
d7bdd55e2908ded901dcc262157100af2a490bf04d31e32995f6d91d78dfdb97 qttranslations-everywhere-src-$QT.tar.xz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$PNG/libpng-$PNG.tar.xz" \
|
||||
-O "https://www.ijg.org/files/jpegsrc.v$JPG.tar.gz" \
|
||||
-O "https://www.surina.net/soundtouch/$SOUNDTOUCH.tar.gz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
|
||||
shasum -a 256 --check SHASUMS
|
||||
|
||||
echo "Installing SDL..."
|
||||
tar xf "$SDL.tar.gz"
|
||||
cd "$SDL"
|
||||
./configure --prefix "$INSTALLDIR" --without-x
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ..
|
||||
|
||||
echo "Installing libpng..."
|
||||
tar xf "libpng-$PNG.tar.xz"
|
||||
cd "libpng-$PNG"
|
||||
./configure --prefix "$INSTALLDIR" --disable-dependency-tracking
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ..
|
||||
|
||||
echo "Installing libjpeg..."
|
||||
tar xf "jpegsrc.v$JPG.tar.gz"
|
||||
cd "jpeg-$JPG"
|
||||
./configure --prefix "$INSTALLDIR" --disable-dependency-tracking
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ..
|
||||
|
||||
echo "Installing soundtouch..."
|
||||
tar xf "$SOUNDTOUCH.tar.gz"
|
||||
cd "$SOUNDTOUCH"
|
||||
cmake -B build -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=MinSizeRel
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
|
||||
echo "Installing Qt Base..."
|
||||
tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
cd "qtbase-everywhere-src-$QT"
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release -DFEATURE_optimize_size=ON -DFEATURE_dbus=OFF -DFEATURE_framework=OFF -DFEATURE_icu=OFF -DFEATURE_opengl=OFF -DFEATURE_printsupport=OFF -DFEATURE_sql=OFF -DFEATURE_gssapi=OFF
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
echo "Installing Qt SVG..."
|
||||
tar xf "qtsvg-everywhere-src-$QT.tar.xz"
|
||||
cd "qtsvg-everywhere-src-$QT"
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=MinSizeRel
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
echo "Installing Qt Tools..."
|
||||
tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
# Linguist relies on a library in the Designer target, which takes 5-7 minutes to build on the CI
|
||||
# Avoid it by not building Linguist, since we only need the tools that come with it
|
||||
patch -u src/linguist/CMakeLists.txt <<EOF
|
||||
--- src/linguist/CMakeLists.txt
|
||||
+++ src/linguist/CMakeLists.txt
|
||||
@@ -14,7 +14,7 @@
|
||||
add_subdirectory(lrelease-pro)
|
||||
add_subdirectory(lupdate)
|
||||
add_subdirectory(lupdate-pro)
|
||||
-if(QT_FEATURE_process AND QT_FEATURE_pushbutton AND QT_FEATURE_toolbutton AND TARGET Qt::Widgets AND NOT no-png)
|
||||
+if(QT_FEATURE_process AND QT_FEATURE_pushbutton AND QT_FEATURE_toolbutton AND TARGET Qt::Widgets AND TARGET Qt::PrintSupport AND NOT no-png)
|
||||
add_subdirectory(linguist)
|
||||
endif()
|
||||
EOF
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=OFF -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
echo "Installing Qt Translations..."
|
||||
tar xf "qttranslations-everywhere-src-$QT.tar.xz"
|
||||
cd "qttranslations-everywhere-src-$QT"
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Cleaning up..."
|
||||
cd ..
|
||||
rm -r deps-build
|
||||
@@ -8,53 +8,23 @@ if (!releaseInfo.prerelease) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const assets = releaseInfo.assets;
|
||||
let windowsAssetLinks = "";
|
||||
let linuxAssetLinks = "";
|
||||
|
||||
for (var i = 0; i < assets.length; i++) {
|
||||
let asset = assets[i];
|
||||
if (asset.name.includes("symbols")) {
|
||||
continue;
|
||||
}
|
||||
if (asset.name.includes("windows")) {
|
||||
let friendlyName = asset.name;
|
||||
try {
|
||||
friendlyName = asset.name.split("windows-")[1].split(".7z")[0].replace("-", " ");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
windowsAssetLinks += `- [${friendlyName}](${asset.browser_download_url})\n`
|
||||
} else if (asset.name.includes("linux")) {
|
||||
let friendlyName = asset.name;
|
||||
try {
|
||||
friendlyName = asset.name.split("linux-")[1].split(".AppImage")[0].replace("-", " ");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
linuxAssetLinks += `- [${friendlyName}](${asset.browser_download_url})\n`
|
||||
}
|
||||
}
|
||||
|
||||
// Publish Webhook
|
||||
const embed = new MessageEmbed()
|
||||
.setColor('#FF8000')
|
||||
.setTitle('New PCSX2 Nightly Build Available!')
|
||||
.setDescription("To download the latest or previous builds, [visit the official downloads page](https://pcsx2.net/downloads/).")
|
||||
.addFields(
|
||||
{ name: 'Version', value: releaseInfo.tag_name, inline: true },
|
||||
{ name: 'Release Link', value: `[Github Release](${releaseInfo.html_url})`, inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://github.com/PCSX2/pcsx2/wiki/Nightly-Build-Usage-Guide)', inline: true },
|
||||
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
|
||||
);
|
||||
|
||||
if (windowsAssetLinks != "") {
|
||||
embed.addField('Windows Downloads', windowsAssetLinks, false);
|
||||
}
|
||||
if (linuxAssetLinks != "") {
|
||||
embed.addField('Linux Downloads', linuxAssetLinks, false);
|
||||
}
|
||||
// Get all webhooks, simple comma-sep string
|
||||
const webhookUrls = process.env.DISCORD_BUILD_WEBHOOK.split(",");
|
||||
|
||||
const webhookClient = new WebhookClient({ url: process.env.DISCORD_BUILD_WEBHOOK });
|
||||
await webhookClient.send({
|
||||
embeds: [embed],
|
||||
});
|
||||
for (const url of webhookUrls) {
|
||||
const webhookClient = new WebhookClient({ url: url });
|
||||
await webhookClient.send({
|
||||
embeds: [embed],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -328,14 +328,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz",
|
||||
"integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"encoding": "^0.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"encoding": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
@@ -714,9 +722,9 @@
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz",
|
||||
"integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import { throttling } from "@octokit/plugin-throttling";
|
||||
import { retry } from "@octokit/plugin-retry";
|
||||
|
||||
let owner = process.env.OWNER;
|
||||
let repo = process.env.REPO;
|
||||
|
||||
Octokit.plugin(throttling);
|
||||
Octokit.plugin(retry);
|
||||
const octokit = new Octokit({
|
||||
auth: process.env.GITHUB_TOKEN,
|
||||
userAgent: 'PCSX2/pcsx2',
|
||||
userAgent: `${owner}/${repo}`,
|
||||
log: {
|
||||
debug: () => { },
|
||||
info: () => { },
|
||||
@@ -39,14 +43,14 @@ let commitSha = process.env.COMMIT_SHA;
|
||||
console.log(`Searching for Commit - ${commitSha}`);
|
||||
|
||||
const { data: commit } = await octokit.rest.repos.getCommit({
|
||||
owner: "PCSX2",
|
||||
repo: "pcsx2",
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
ref: commitSha,
|
||||
});
|
||||
|
||||
const { data: associatedPulls } = await octokit.rest.repos.listPullRequestsAssociatedWithCommit({
|
||||
owner: "PCSX2",
|
||||
repo: "pcsx2",
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
commit_sha: commit.sha,
|
||||
});
|
||||
|
||||
|
||||
+3
-3
@@ -154,9 +154,9 @@
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz",
|
||||
"integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==",
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
tag = os.environ['TAG'].split("refs/tags/")[1]
|
||||
scan_dir = os.environ['SCAN_DIR']
|
||||
output_dir = os.environ['OUT_DIR']
|
||||
accepted_exts = ["AppImage", "tar.gz", "7z"]
|
||||
|
||||
|
||||
for dir_name in os.listdir(scan_dir):
|
||||
asset_name = "pcsx2-{}".format(tag)
|
||||
if "macos" in dir_name.lower():
|
||||
asset_name += "-macos"
|
||||
elif "linux" in dir_name.lower():
|
||||
asset_name += "-linux-AppImage-64bit"
|
||||
elif "windows" in dir_name.lower():
|
||||
asset_name += "-windows-64bit"
|
||||
else:
|
||||
continue;
|
||||
|
||||
if "avx2" in dir_name.lower():
|
||||
asset_name += "-AVX2"
|
||||
elif "sse4" in dir_name.lower():
|
||||
asset_name += "-SSE4"
|
||||
|
||||
asset_name += "-Qt"
|
||||
|
||||
if "symbols" in dir_name.lower():
|
||||
asset_name += "-symbols"
|
||||
|
||||
print(asset_name)
|
||||
|
||||
dir_handled = False
|
||||
for file in os.listdir(os.path.join(scan_dir, dir_name)):
|
||||
for ext in accepted_exts:
|
||||
if file.endswith(ext):
|
||||
dir_handled = True
|
||||
print("Moving {} to out dir".format(file))
|
||||
shutil.move(os.path.join(scan_dir, dir_name, file), os.path.join(output_dir, asset_name + "." + ext))
|
||||
break
|
||||
if dir_handled:
|
||||
break
|
||||
|
||||
if not dir_handled:
|
||||
print("Could not find asset in directory when one was expected")
|
||||
exit(1)
|
||||
@@ -1,2 +0,0 @@
|
||||
node_modules/
|
||||
*.md
|
||||
@@ -1,145 +0,0 @@
|
||||
import { Octokit } from "@octokit/rest";
|
||||
import { throttling } from "@octokit/plugin-throttling";
|
||||
import { retry } from "@octokit/plugin-retry";
|
||||
Octokit.plugin(throttling);
|
||||
Octokit.plugin(retry);
|
||||
const octokit = new Octokit({
|
||||
auth: process.env.GITHUB_TOKEN,
|
||||
userAgent: 'PCSX2/pcsx2',
|
||||
log: {
|
||||
debug: () => { },
|
||||
info: () => { },
|
||||
warn: console.warn,
|
||||
error: console.error
|
||||
},
|
||||
throttle: {
|
||||
onRateLimit: (retryAfter, options) => {
|
||||
octokit.log.warn(
|
||||
`Request quota exhausted for request ${options.method} ${options.url}`
|
||||
);
|
||||
|
||||
// Retry twice after hitting a rate limit error, then give up
|
||||
if (options.request.retryCount <= 2) {
|
||||
console.log(`Retrying after ${retryAfter} seconds!`);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
onAbuseLimit: (retryAfter, options) => {
|
||||
// does not retry, only logs a warning
|
||||
octokit.log.warn(
|
||||
`Abuse detected for request ${options.method} ${options.url}`
|
||||
);
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
let assetDir = process.env.ASSET_DIR;
|
||||
let tagToSearchFor = process.env.TAG_TO_SEARCH_FOR.split("refs/tags/")[1];
|
||||
|
||||
console.log(`Searching in - ${assetDir}`);
|
||||
console.log(`Searching for tag - ${tagToSearchFor}`);
|
||||
|
||||
const { data: recentReleases } = await octokit.rest.repos.listReleases({
|
||||
owner: "PCSX2",
|
||||
repo: "pcsx2",
|
||||
per_page: 100
|
||||
});
|
||||
|
||||
let release = undefined;
|
||||
for (var i = 0; i < recentReleases.length; i++) {
|
||||
if (recentReleases[i].tag_name == tagToSearchFor) {
|
||||
release = recentReleases[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (release == undefined) {
|
||||
console.log(`Unable to find release with tag - ${tagToSearchFor}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Upload any assets we need to, don't upload assets that are already there!
|
||||
const { data: releaseAssetsPre } = await octokit.rest.repos.listReleaseAssets({
|
||||
owner: "PCSX2",
|
||||
repo: "pcsx2",
|
||||
release_id: release.id,
|
||||
per_page: 100
|
||||
});
|
||||
|
||||
import glob from 'glob';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
glob(assetDir + `/**/*${process.env.ASSET_EXTENSION}`, {}, async (err, files) => {
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
let foundDuplicate = false;
|
||||
for (var j = 0; j < releaseAssetsPre.length; j++) {
|
||||
let existingAsset = releaseAssetsPre[j];
|
||||
if (existingAsset.name == `pcsx2-${release.tag_name}-${path.basename(files[i])}`) {
|
||||
foundDuplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundDuplicate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var assetBytes = fs.readFileSync(files[i], null);
|
||||
const { data: uploadAsset } = await octokit.rest.repos.uploadReleaseAsset({
|
||||
owner: "PCSX2",
|
||||
repo: "pcsx2",
|
||||
release_id: release.id,
|
||||
name: `pcsx2-${release.tag_name}-${path.basename(files[i])}`,
|
||||
data: assetBytes,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Ideally there would be a webhook event for when an artifact is added to a draft release
|
||||
// unfortunately, such a thing does not exist yet. Therefore, we have to wait a bit
|
||||
// for the API to become consistent
|
||||
// TODO - future work - we could check previous draft releases to become eventually consistent as well
|
||||
// - draft releases should only be a temporary state, so anything that remains a draft had a problem
|
||||
await new Promise(resolve => setTimeout(resolve, 10 * 1000));
|
||||
|
||||
// Poll the release, and check to see if it's ready to be published
|
||||
const { data: releaseAssetsPost } = await octokit.rest.repos.listReleaseAssets({
|
||||
owner: "PCSX2",
|
||||
repo: "pcsx2",
|
||||
release_id: release.id,
|
||||
per_page: 100
|
||||
});
|
||||
|
||||
// Expected Assets, if we have all of them, we will publish it
|
||||
let expectedAssets = {
|
||||
"windows-32bit-sse4": false,
|
||||
"windows-32bit-avx2": false,
|
||||
"windows-64bit-sse4": false,
|
||||
"windows-64bit-avx2": false,
|
||||
"linux-appimage-32bit": false,
|
||||
"linux-appimage-64bit": false
|
||||
}
|
||||
|
||||
for (var i = 0; i < releaseAssetsPost.length; i++) {
|
||||
let asset = releaseAssetsPost[i];
|
||||
if (asset.name.includes("symbols")) {
|
||||
continue;
|
||||
}
|
||||
for (var j = 0; j < Object.keys(expectedAssets).length; j++) {
|
||||
let expectedNamePrefix = Object.keys(expectedAssets)[j];
|
||||
if (asset.name.toLowerCase().includes(expectedNamePrefix)) {
|
||||
expectedAssets[expectedNamePrefix] = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(expectedAssets);
|
||||
|
||||
if (Object.values(expectedAssets).every(Boolean)) {
|
||||
await octokit.rest.repos.updateRelease({
|
||||
owner: "PCSX2",
|
||||
repo: "pcsx2",
|
||||
release_id: release.id,
|
||||
draft: false
|
||||
});
|
||||
}
|
||||
-973
@@ -1,973 +0,0 @@
|
||||
{
|
||||
"name": "upload-release-artifacts",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@octokit/plugin-retry": "^3.0.9",
|
||||
"@octokit/plugin-throttling": "^3.5.2",
|
||||
"@octokit/rest": "^18.12.0",
|
||||
"discord.js": "^13.2.0",
|
||||
"glob": "^7.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/builders": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.6.0.tgz",
|
||||
"integrity": "sha512-mH3Gx61LKk2CD05laCI9K5wp+a3NyASHDUGx83DGJFkqJlRlSV5WMJNY6RS37A5SjqDtGMF4wVR9jzFaqShe6Q==",
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^4.0.1",
|
||||
"discord-api-types": "^0.22.0",
|
||||
"ow": "^0.27.0",
|
||||
"ts-mixer": "^6.0.0",
|
||||
"tslib": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0",
|
||||
"npm": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/builders/node_modules/discord-api-types": {
|
||||
"version": "0.22.0",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz",
|
||||
"integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/collection": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz",
|
||||
"integrity": "sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog==",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@discordjs/form-data": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz",
|
||||
"integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
|
||||
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz",
|
||||
"integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^2.4.4",
|
||||
"@octokit/graphql": "^4.5.8",
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/request-error": "^2.0.5",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
|
||||
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
|
||||
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.1.0.tgz",
|
||||
"integrity": "sha512-dWZfYvCCdjZzDYA3lIAMF72Q0jld8xidqCq5Ryw09eBJXZdcM6he0vWBTvw/b5UnGYqexxOyHWgfrsTlUJL3Gw=="
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "2.16.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.9.tgz",
|
||||
"integrity": "sha512-gfSCMgz5scFKsR0dW4jaYsDJVt/UwCHp4dF7sHlmSekZvwzvLiOAGZ4MQkEsL5DW9hIk2W+UQkYZMTA1b6Wsqw==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.33.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA=="
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "5.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.12.1.tgz",
|
||||
"integrity": "sha512-0nY3htfl6x9UkPcqv8pm9vOC/bTA7f4IMDWln13neHRdNWQvOQgZ9fRxK7BAc74rye4yVINEFi9Yb9rnGUvosA==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.33.0",
|
||||
"deprecation": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz",
|
||||
"integrity": "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"bottleneck": "^2.15.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-throttling": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.5.2.tgz",
|
||||
"integrity": "sha512-Eu7kfJxU8vmHqWGNszWpg+GVp2tnAfax3XQV5CkYPEE69C+KvInJXW9WajgSeW+cxYe0UVdouzCtcreGNuJo7A==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.1",
|
||||
"bottleneck": "^2.15.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
|
||||
"integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^6.0.1",
|
||||
"@octokit/request-error": "^2.1.0",
|
||||
"@octokit/types": "^6.16.1",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
|
||||
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/rest": {
|
||||
"version": "18.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
|
||||
"integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
|
||||
"dependencies": {
|
||||
"@octokit/core": "^3.5.1",
|
||||
"@octokit/plugin-paginate-rest": "^2.16.8",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "6.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.33.0.tgz",
|
||||
"integrity": "sha512-0zffZ048M0UhthyPXQHLz4038Ak46nMWZXkzlXvXB/M/L1jYPBceq4iZj4qjKVrvveaJrrgKdJ9+3yUuITfcCw==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^11.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sapphire/async-queue": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.6.tgz",
|
||||
"integrity": "sha512-M5CbgMgesemMUCQo5G/InGHvp+GZx6uuJNV1iwvSWD8EFNVrfxaTcqhcAXM3MPYkjlxvNnoDNk0R1lfzvca6LA==",
|
||||
"engines": {
|
||||
"node": ">=v14.18.0",
|
||||
"npm": ">=7.24.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@sindresorhus/is": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz",
|
||||
"integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/is?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.3.tgz",
|
||||
"integrity": "sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ=="
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.0.tgz",
|
||||
"integrity": "sha512-cyeefcUCgJlEk+hk2h3N+MqKKsPViQgF5boi9TTHSK+PoR9KWBb/C5ccPcDyAqgsbAYHTwulch725DV84+pSpg==",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
|
||||
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
|
||||
},
|
||||
"node_modules/bottleneck": {
|
||||
"version": "2.19.5",
|
||||
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
||||
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"node_modules/discord-api-types": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.23.1.tgz",
|
||||
"integrity": "sha512-igWmn+45mzXRWNEPU25I/pr8MwxHb767wAr51oy3VRLRcTlp5ADBbrBR0lq3SA1Rfw3MtM4TQu1xo3kxscfVdQ==",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/discord.js": {
|
||||
"version": "13.2.0",
|
||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.2.0.tgz",
|
||||
"integrity": "sha512-nyxUvL8wuQG38zx13wUMkpcA8koFszyiXdkSLwwM9opKW2LC2H5gD0cTZxImeJ6GtEnKPWT8xBiE8lLBmbNIhw==",
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^0.6.0",
|
||||
"@discordjs/collection": "^0.2.1",
|
||||
"@discordjs/form-data": "^3.0.1",
|
||||
"@sapphire/async-queue": "^1.1.5",
|
||||
"@types/ws": "^8.2.0",
|
||||
"discord-api-types": "^0.23.1",
|
||||
"node-fetch": "^2.6.1",
|
||||
"ws": "^8.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.6.0",
|
||||
"npm": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-prop": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
|
||||
"integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
|
||||
"dependencies": {
|
||||
"is-obj": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/is-obj": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
|
||||
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.50.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz",
|
||||
"integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.33",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz",
|
||||
"integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.50.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz",
|
||||
"integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/ow": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz",
|
||||
"integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==",
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^4.0.1",
|
||||
"callsites": "^3.1.0",
|
||||
"dot-prop": "^6.0.1",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"type-fest": "^1.2.1",
|
||||
"vali-date": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||
},
|
||||
"node_modules/ts-mixer": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz",
|
||||
"integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ=="
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
|
||||
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
|
||||
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"node_modules/vali-date": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz",
|
||||
"integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||
},
|
||||
"node_modules/whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||
"dependencies": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": "^5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@discordjs/builders": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.6.0.tgz",
|
||||
"integrity": "sha512-mH3Gx61LKk2CD05laCI9K5wp+a3NyASHDUGx83DGJFkqJlRlSV5WMJNY6RS37A5SjqDtGMF4wVR9jzFaqShe6Q==",
|
||||
"requires": {
|
||||
"@sindresorhus/is": "^4.0.1",
|
||||
"discord-api-types": "^0.22.0",
|
||||
"ow": "^0.27.0",
|
||||
"ts-mixer": "^6.0.0",
|
||||
"tslib": "^2.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"discord-api-types": {
|
||||
"version": "0.22.0",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz",
|
||||
"integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@discordjs/collection": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz",
|
||||
"integrity": "sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog=="
|
||||
},
|
||||
"@discordjs/form-data": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz",
|
||||
"integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"@octokit/auth-token": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz",
|
||||
"integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3"
|
||||
}
|
||||
},
|
||||
"@octokit/core": {
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz",
|
||||
"integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==",
|
||||
"requires": {
|
||||
"@octokit/auth-token": "^2.4.4",
|
||||
"@octokit/graphql": "^4.5.8",
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/request-error": "^2.0.5",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/endpoint": {
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz",
|
||||
"integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/graphql": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz",
|
||||
"integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==",
|
||||
"requires": {
|
||||
"@octokit/request": "^5.6.0",
|
||||
"@octokit/types": "^6.0.3",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/openapi-types": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.1.0.tgz",
|
||||
"integrity": "sha512-dWZfYvCCdjZzDYA3lIAMF72Q0jld8xidqCq5Ryw09eBJXZdcM6he0vWBTvw/b5UnGYqexxOyHWgfrsTlUJL3Gw=="
|
||||
},
|
||||
"@octokit/plugin-paginate-rest": {
|
||||
"version": "2.16.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.16.9.tgz",
|
||||
"integrity": "sha512-gfSCMgz5scFKsR0dW4jaYsDJVt/UwCHp4dF7sHlmSekZvwzvLiOAGZ4MQkEsL5DW9hIk2W+UQkYZMTA1b6Wsqw==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.33.0"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA=="
|
||||
},
|
||||
"@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "5.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.12.1.tgz",
|
||||
"integrity": "sha512-0nY3htfl6x9UkPcqv8pm9vOC/bTA7f4IMDWln13neHRdNWQvOQgZ9fRxK7BAc74rye4yVINEFi9Yb9rnGUvosA==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.33.0",
|
||||
"deprecation": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-retry": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz",
|
||||
"integrity": "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"bottleneck": "^2.15.3"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-throttling": {
|
||||
"version": "3.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.5.2.tgz",
|
||||
"integrity": "sha512-Eu7kfJxU8vmHqWGNszWpg+GVp2tnAfax3XQV5CkYPEE69C+KvInJXW9WajgSeW+cxYe0UVdouzCtcreGNuJo7A==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.1",
|
||||
"bottleneck": "^2.15.3"
|
||||
}
|
||||
},
|
||||
"@octokit/request": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
|
||||
"integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==",
|
||||
"requires": {
|
||||
"@octokit/endpoint": "^6.0.1",
|
||||
"@octokit/request-error": "^2.1.0",
|
||||
"@octokit/types": "^6.16.1",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"node-fetch": "^2.6.1",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/request-error": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz",
|
||||
"integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==",
|
||||
"requires": {
|
||||
"@octokit/types": "^6.0.3",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"@octokit/rest": {
|
||||
"version": "18.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
|
||||
"integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
|
||||
"requires": {
|
||||
"@octokit/core": "^3.5.1",
|
||||
"@octokit/plugin-paginate-rest": "^2.16.8",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^5.12.0"
|
||||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "6.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.33.0.tgz",
|
||||
"integrity": "sha512-0zffZ048M0UhthyPXQHLz4038Ak46nMWZXkzlXvXB/M/L1jYPBceq4iZj4qjKVrvveaJrrgKdJ9+3yUuITfcCw==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^11.1.0"
|
||||
}
|
||||
},
|
||||
"@sapphire/async-queue": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.6.tgz",
|
||||
"integrity": "sha512-M5CbgMgesemMUCQo5G/InGHvp+GZx6uuJNV1iwvSWD8EFNVrfxaTcqhcAXM3MPYkjlxvNnoDNk0R1lfzvca6LA=="
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz",
|
||||
"integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.3.tgz",
|
||||
"integrity": "sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ=="
|
||||
},
|
||||
"@types/ws": {
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.0.tgz",
|
||||
"integrity": "sha512-cyeefcUCgJlEk+hk2h3N+MqKKsPViQgF5boi9TTHSK+PoR9KWBb/C5ccPcDyAqgsbAYHTwulch725DV84+pSpg==",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"before-after-hook": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
|
||||
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
|
||||
},
|
||||
"bottleneck": {
|
||||
"version": "2.19.5",
|
||||
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
|
||||
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"callsites": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
|
||||
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"discord-api-types": {
|
||||
"version": "0.23.1",
|
||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.23.1.tgz",
|
||||
"integrity": "sha512-igWmn+45mzXRWNEPU25I/pr8MwxHb767wAr51oy3VRLRcTlp5ADBbrBR0lq3SA1Rfw3MtM4TQu1xo3kxscfVdQ=="
|
||||
},
|
||||
"discord.js": {
|
||||
"version": "13.2.0",
|
||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.2.0.tgz",
|
||||
"integrity": "sha512-nyxUvL8wuQG38zx13wUMkpcA8koFszyiXdkSLwwM9opKW2LC2H5gD0cTZxImeJ6GtEnKPWT8xBiE8lLBmbNIhw==",
|
||||
"requires": {
|
||||
"@discordjs/builders": "^0.6.0",
|
||||
"@discordjs/collection": "^0.2.1",
|
||||
"@discordjs/form-data": "^3.0.1",
|
||||
"@sapphire/async-queue": "^1.1.5",
|
||||
"@types/ws": "^8.2.0",
|
||||
"discord-api-types": "^0.23.1",
|
||||
"node-fetch": "^2.6.1",
|
||||
"ws": "^8.2.3"
|
||||
}
|
||||
},
|
||||
"dot-prop": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
|
||||
"integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
|
||||
"requires": {
|
||||
"is-obj": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"is-obj": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
|
||||
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="
|
||||
},
|
||||
"is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
|
||||
},
|
||||
"lodash.isequal": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
|
||||
"integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.50.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz",
|
||||
"integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.33",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz",
|
||||
"integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==",
|
||||
"requires": {
|
||||
"mime-db": "1.50.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz",
|
||||
"integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"ow": {
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz",
|
||||
"integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==",
|
||||
"requires": {
|
||||
"@sindresorhus/is": "^4.0.1",
|
||||
"callsites": "^3.1.0",
|
||||
"dot-prop": "^6.0.1",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"type-fest": "^1.2.1",
|
||||
"vali-date": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
|
||||
},
|
||||
"ts-mixer": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz",
|
||||
"integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ=="
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
|
||||
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
|
||||
},
|
||||
"type-fest": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
|
||||
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA=="
|
||||
},
|
||||
"universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"vali-date": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz",
|
||||
"integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY="
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
|
||||
"requires": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
|
||||
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "upload-release-artifacts",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@octokit/plugin-retry": "^3.0.9",
|
||||
"@octokit/plugin-throttling": "^3.5.2",
|
||||
"@octokit/rest": "^18.12.0",
|
||||
"glob": "^7.2.0"
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
import yaml
|
||||
|
||||
# Assumes this is ran from the root of the repository
|
||||
file_path = "./bin/resources/GameIndex.yaml"
|
||||
|
||||
# These settings have to be manually kept in sync with the emulator code unfortunately.
|
||||
# up to date validation should ALWAYS be provided via the application!
|
||||
allowed_game_options = [
|
||||
"name",
|
||||
"region",
|
||||
"compat",
|
||||
"roundModes",
|
||||
"clampModes",
|
||||
"gameFixes",
|
||||
"speedHacks",
|
||||
"memcardFilters",
|
||||
"patches",
|
||||
]
|
||||
allowed_round_modes = ["eeRoundMode", "vuRoundMode"]
|
||||
allowed_clamp_modes = ["eeClampMode", "vuClampMode"]
|
||||
allowed_game_fixes = [
|
||||
"VuAddSubHack",
|
||||
"FpuCompareHack",
|
||||
"FpuMulHack",
|
||||
"FpuNegDivHack",
|
||||
"XGKickHack",
|
||||
"EETimingHack",
|
||||
"SkipMPEGHack",
|
||||
"OPHFlagHack",
|
||||
"DMABusyHack",
|
||||
"VIFFIFOHack",
|
||||
"VIF1StallHack",
|
||||
"GIFFIFOHack",
|
||||
"GoemonTlbHack",
|
||||
"VUKickstartHack",
|
||||
"IbitHack",
|
||||
"VUOverflowHack",
|
||||
]
|
||||
allowed_speed_hacks = ["mvuFlagSpeedHack", "InstantVU1SpeedHack"]
|
||||
# Patches are allowed to have a 'default' key or a crc-32 key, followed by
|
||||
allowed_patch_options = ["author", "content"]
|
||||
|
||||
issue_list = []
|
||||
|
||||
|
||||
def is_hex_number(string):
|
||||
try:
|
||||
int(string, 16)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def validate_string_option(serial, key, value):
|
||||
if not isinstance(value, str):
|
||||
issue_list.append("[{}]: '{}' must be a string".format(serial, key))
|
||||
|
||||
|
||||
def validate_int_option(serial, key, value, low, high):
|
||||
if not isinstance(value, int) or (value < low or value > high):
|
||||
issue_list.append(
|
||||
"[{}]: '{}' must be an int and between {}-{} (inclusive)".format(
|
||||
serial, key, low, high
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def validate_list_of_strings(serial, key, value):
|
||||
if not isinstance(value, list) or not all(isinstance(item, str) for item in value):
|
||||
issue_list.append("[{}]: '{}' must be a list of strings".format(serial, key))
|
||||
|
||||
|
||||
def validate_valid_options(serial, key, value, allowed_values):
|
||||
if value not in allowed_values:
|
||||
issue_list.append("[{}]: Invalid '{}' option [{}]".format(serial, key, value))
|
||||
|
||||
|
||||
def validate_clamp_round_modes(serial, key, value, allowed_values):
|
||||
if not isinstance(value, dict):
|
||||
issue_list.append("[{}]: '{}' must be a valid object".format(serial, key))
|
||||
return
|
||||
for mode_key, mode_value in value.items():
|
||||
validate_valid_options(serial, key, mode_key, allowed_values)
|
||||
validate_int_option(serial, key, mode_value, 0, 3)
|
||||
|
||||
|
||||
def validate_game_fixes(serial, key, value):
|
||||
if not isinstance(value, list):
|
||||
issue_list.append(
|
||||
"[{}]: 'gameFixes' must be a list of valid gameFixes".format(serial)
|
||||
)
|
||||
return
|
||||
for gamefix in value:
|
||||
validate_valid_options(serial, key, gamefix, allowed_game_fixes)
|
||||
|
||||
|
||||
def validate_speed_hacks(serial, key, value):
|
||||
if not isinstance(value, dict):
|
||||
issue_list.append("[{}]: 'speedHacks' must be a valid object".format(serial))
|
||||
return
|
||||
for speedhack, speedhack_value in value.items():
|
||||
validate_valid_options(serial, key, speedhack, allowed_speed_hacks)
|
||||
validate_int_option(serial, speedhack, speedhack_value, 0, 1)
|
||||
|
||||
|
||||
def validate_patches(serial, key, value):
|
||||
if not isinstance(value, dict):
|
||||
issue_list.append(
|
||||
"[{}]: 'patches' must be valid mapping of CRC32 -> Patch Objects".format(
|
||||
serial
|
||||
)
|
||||
)
|
||||
return
|
||||
for crc, patch in value.items():
|
||||
if crc != "default" and not is_hex_number(str(crc)):
|
||||
issue_list.append(
|
||||
"[{}]: Patches must either be key'd with 'default' or a valid CRC-32 Hex String".format(
|
||||
serial
|
||||
)
|
||||
)
|
||||
continue
|
||||
for patch_option, option_value in patch.items():
|
||||
validate_valid_options(serial, key, patch_option, allowed_patch_options)
|
||||
if patch_option == "author":
|
||||
validate_string_option(serial, patch_option, option_value)
|
||||
if patch_option == "content":
|
||||
validate_string_option(serial, patch_option, option_value)
|
||||
|
||||
|
||||
# pylint:disable=unnecessary-lambda
|
||||
option_validation_handlers = {
|
||||
"name": (lambda serial, key, value: validate_string_option(serial, key, value)),
|
||||
"region": (lambda serial, key, value: validate_string_option(serial, key, value)),
|
||||
"compat": (
|
||||
lambda serial, key, value: validate_int_option(serial, key, value, 0, 6)
|
||||
),
|
||||
"roundModes": (
|
||||
lambda serial, key, value: validate_clamp_round_modes(
|
||||
serial, key, value, allowed_round_modes
|
||||
)
|
||||
),
|
||||
"clampModes": (
|
||||
lambda serial, key, value: validate_clamp_round_modes(
|
||||
serial, key, value, allowed_clamp_modes
|
||||
)
|
||||
),
|
||||
"gameFixes": (lambda serial, key, value: validate_game_fixes(serial, key, value)),
|
||||
"speedHacks": (lambda serial, key, value: validate_speed_hacks(serial, key, value)),
|
||||
"memcardFilters": (
|
||||
lambda serial, key, value: validate_list_of_strings(serial, key, value)
|
||||
),
|
||||
"patches": (lambda serial, key, value: validate_patches(serial, key, value)),
|
||||
}
|
||||
|
||||
print("Opening {}...".format(file_path))
|
||||
with open(file_path) as f:
|
||||
try:
|
||||
print("Attempting to parse GameDB file...")
|
||||
gamedb = yaml.load(f, Loader=yaml.FullLoader)
|
||||
except Exception as err:
|
||||
print(err)
|
||||
print(
|
||||
"Unable to parse GameDB. Exiting, verify that the file indeed is valid YAML."
|
||||
)
|
||||
exit(1)
|
||||
|
||||
print("File loaded successfully, validating schema...")
|
||||
progress_counter = 0
|
||||
for serial, game_options in gamedb.items():
|
||||
progress_counter = progress_counter + 1
|
||||
if progress_counter % 500 == 0 or progress_counter >= len(gamedb.items()):
|
||||
print(
|
||||
"[{}/{}] Processing GameDB Entries...".format(
|
||||
progress_counter, len(gamedb.items())
|
||||
)
|
||||
)
|
||||
|
||||
# Check for required values
|
||||
if not "name" in game_options.keys():
|
||||
issue_list.append("[{}]: 'name' is a required value".format(serial))
|
||||
if not "region" in game_options.keys():
|
||||
issue_list.append("[{}]: 'region' is a required value".format(serial))
|
||||
|
||||
# Check the options
|
||||
for key, value in game_options.items():
|
||||
if key not in allowed_game_options:
|
||||
issue_list.append("[{}]: Invalid option [{}]".format(serial, key))
|
||||
continue
|
||||
|
||||
if key in option_validation_handlers:
|
||||
option_validation_handlers[key](serial, key, value)
|
||||
|
||||
if len(issue_list) > 0:
|
||||
print("Issues found during validation:")
|
||||
print(*issue_list, sep="\n")
|
||||
exit(1)
|
||||
else:
|
||||
print("GameDB Validated Successfully!")
|
||||
exit(0)
|
||||
@@ -1 +0,0 @@
|
||||
PyYAML==5.4.1
|
||||
@@ -1,29 +0,0 @@
|
||||
name: 🏭 Update Controller Database
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 16 * * 1" # every monday @ 12pm EST - https://crontab.guru/#0_16_*_*_1
|
||||
|
||||
jobs:
|
||||
update-controller-db:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Get Latest DB and Prepare DB File
|
||||
run: |
|
||||
cd .github/workflows/scripts/controller-db/
|
||||
wget -O game_controller_db.txt https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/master/gamecontrollerdb.txt
|
||||
python ./update-db.py
|
||||
mv ./game_controller_db.txt ${{github.workspace}}/pcsx2/PAD/Linux/res/game_controller_db.txt
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
title: "pad-linux: Update to latest controller database"
|
||||
commit-message: "pad-linux: Update to latest controller database."
|
||||
committer: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
author: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
body: "Weekly automatic update of SDL Controller DB for Linux / Mac OS"
|
||||
reviewers: lightningterror
|
||||
@@ -1,191 +0,0 @@
|
||||
name: 🖥️ Windows Builds
|
||||
|
||||
# Controls when the action will run. Triggers the workflow on push or pull request
|
||||
# events but only for the master branch
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- v*
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
paths-ignore:
|
||||
- '**/*.md'
|
||||
- '.clang-format'
|
||||
- '.codacy.yaml'
|
||||
- '.github/*'
|
||||
- '.github/workflows/lint-gamedb.yml'
|
||||
- '.github/workflows/linux-workflow.yml'
|
||||
- '.github/workflows/macos-workflow.yml'
|
||||
- '.github/workflows/scripts/linux/**'
|
||||
- '.github/workflows/scripts/validation/**'
|
||||
- '.gitignore'
|
||||
- 'bin/PCSX2_keys.ini.default'
|
||||
- 'build.sh'
|
||||
- 'buildbot.xml'
|
||||
- 'linux_various/**'
|
||||
- 'mscompile.cmd'
|
||||
- 'pcsx2/CDVD/Linux/**'
|
||||
- 'pcsx2/DEV9/Linux/**'
|
||||
- 'pcsx2/Linux/**'
|
||||
- 'pcsx2/PAD/Linux/**'
|
||||
- 'pcsx2/SPU2/Linux/**'
|
||||
- 'pcsx2/USB/linux/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
# Prevent one build from failing everything (although maybe those should be included as experimental builds instead)
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-2019]
|
||||
platform: [Win32, x64]
|
||||
configuration: [Release, Release AVX2, CMake]
|
||||
experimental: [false]
|
||||
|
||||
name: ${{ matrix.platform }} | ${{ matrix.configuration }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
continue-on-error: ${{ matrix.experimental }}
|
||||
# Set some sort of timeout in the event of run-away builds. We are limited on concurrent jobs so, get rid of them.
|
||||
timeout-minutes: 60
|
||||
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
BUILDCACHE_COMPRESS_FORMAT: ZSTD
|
||||
BUILDCACHE_COMPRESS_LEVEL: 9
|
||||
BUILDCACHE_MAX_CACHE_SIZE: 536870912 # 512MB
|
||||
BUILDCACHE_DIRECT_MODE: true
|
||||
BUILDCACHE_LOG_FILE: ${{ github.workspace }}\buildcache.log
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Checkout Submodules
|
||||
run: git submodule update --init --recursive -j $env:NUMBER_OF_PROCESSORS
|
||||
|
||||
- name: Setup Buildcache
|
||||
uses: mikehardy/buildcache-action@v1.2.2
|
||||
with:
|
||||
cache_key: ${{ matrix.os }} ${{ matrix.platform }} ${{ matrix.configuration }}
|
||||
if: matrix.configuration == 'CMake' # TODO: buildcache on VS
|
||||
|
||||
- name: Verify VS Project Files
|
||||
run: .github\workflows\scripts\windows\validate-vs-filters.ps1
|
||||
if: matrix.configuration != 'CMake'
|
||||
|
||||
- name: Setup msbuild
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
if: matrix.configuration != 'CMake'
|
||||
|
||||
- name: Generate CMake
|
||||
id: cmake
|
||||
shell: cmd
|
||||
run: |
|
||||
if "${{ github.event.inputs.retainDebugArtifacts }}"=="true" (SET type=RelWithDebInfo) else (SET type=Release)
|
||||
if "${{ matrix.platform }}"=="Win32" (SET vcvars=vcvarsamd64_x86.bat) else (SET vcvars=vcvars64.bat)
|
||||
call "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\%vcvars%"
|
||||
echo ::set-output name=buildtype::%type%
|
||||
echo ::set-output name=vcvars::%vcvars%
|
||||
cmake . -B build -DCMAKE_BUILD_TYPE=%type% -DLTO_PCSX2_CORE=ON -G Ninja -DCMAKE_C_COMPILER_LAUNCHER=..\buildcache\bin\buildcache.exe -DCMAKE_CXX_COMPILER_LAUNCHER=..\buildcache\bin\buildcache.exe -DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON
|
||||
if: matrix.configuration == 'CMake'
|
||||
|
||||
- name: Build PCSX2
|
||||
shell: cmd
|
||||
env:
|
||||
# Set to 'true' to retain the .pdb / .exp / .lib, etc files which can be useful for repro'ing issues that only occur in the compiled .exe
|
||||
RetainDebuggingArtifacts: ${{ github.event.inputs.retainDebugArtifacts == 'true' }}
|
||||
run: |
|
||||
if "${{ matrix.configuration }}"=="CMake" (
|
||||
call "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\${{ steps.cmake.outputs.vcvars }}"
|
||||
cmake --build build --config ${{ steps.cmake.outputs.buildtype }}
|
||||
) else (
|
||||
msbuild "PCSX2_suite.sln" /m /v:m /p:Configuration="${{ matrix.configuration }}" /p:Platform="${{ matrix.platform }}"
|
||||
)
|
||||
|
||||
- name: Run Tests
|
||||
shell: cmd
|
||||
run: |
|
||||
call "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\${{ steps.cmake.outputs.vcvars }}"
|
||||
cmake --build build --config ${{ steps.cmake.outputs.buildtype }} --target unittests
|
||||
if: matrix.configuration == 'CMake'
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
run: |
|
||||
ARCH=$([ "${{ matrix.platform }}" == Win32 ] && echo "32bit" || echo "64bit")
|
||||
case "${{ matrix.configuration }}" in
|
||||
Release) SIMD="SSE4";;
|
||||
*AVX2) SIMD="AVX2";;
|
||||
CMake) SIMD="CMake"
|
||||
cp build/pcsx2/PCSX2* bin/ ;;
|
||||
*) SIMD="UNKNOWN";;
|
||||
esac
|
||||
if [ ${{ github.event_name }} == "pull_request" ]; then
|
||||
PR_SHA=$(git rev-parse --short "${{ github.event.pull_request.head.sha }}")
|
||||
ARTIFACT_NAME="PCSX2-${ARCH}-${SIMD}"
|
||||
if [ ! -z "${{ github.event.pull_request.number }}" ]; then
|
||||
PR_NUM=${{ github.event.pull_request.number }}
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}-pr[${PR_NUM}]"
|
||||
fi
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}-sha[${PR_SHA}]"
|
||||
if [ ! -z "${{ github.event.pull_request.title }}" ]; then
|
||||
PR_TITLE=$(echo "${{ github.event.pull_request.title }}" | tr -cd '[a-zA-Z0-9[:space:]]_-')
|
||||
ARTIFACT_NAME="${ARTIFACT_NAME}-title["${PR_TITLE}""
|
||||
fi
|
||||
else
|
||||
SHA=$(git rev-parse --short "$GITHUB_SHA")
|
||||
ARTIFACT_NAME="PCSX2-${ARCH}-${SIMD}-sha[${SHA}"
|
||||
fi
|
||||
TRIMMED_ARTIFACT_NAME=$(printf "%.199s]" "$ARTIFACT_NAME")
|
||||
echo "name=$TRIMMED_ARTIFACT_NAME"
|
||||
echo "##[set-output name=name;]${TRIMMED_ARTIFACT_NAME}"
|
||||
echo "##[set-output name=arch;]${ARCH}"
|
||||
echo "##[set-output name=simd;]${SIMD}"
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
continue-on-error: true
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.name }}
|
||||
path: |
|
||||
./bin
|
||||
!./bin/**/*.bsc
|
||||
!./bin/**/*.exp
|
||||
!./bin/**/*.ilk
|
||||
!./bin/**/*.iobj
|
||||
!./bin/**/*.ipdb
|
||||
!./bin/**/*.pdb
|
||||
!./bin/**/*.lib
|
||||
|
||||
- name: Upload artifact - with symbols
|
||||
if: matrix.configuration != 'CMake'
|
||||
uses: actions/upload-artifact@v2
|
||||
continue-on-error: true
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.name }}-symbols
|
||||
path: ./bin/**/*.pdb
|
||||
|
||||
# ---- Release / Tagging related steps ----
|
||||
- name: Prepare Build Artifacts
|
||||
if: github.repository == 'PCSX2/pcsx2' && startsWith(github.ref, 'refs/tags/') && matrix.configuration != 'CMake'
|
||||
run: |
|
||||
mkdir -p ./ci-artifacts/
|
||||
7z a ./ci-artifacts/windows-${{ steps.artifact-metadata.outputs.arch }}-${{ steps.artifact-metadata.outputs.simd }}.7z ./bin/* '-xr!*bsc' '-xr!*.exp' '-xr!*.ilk' '-xr!*.iobj' '-xr!*.ipdb' '-xr!*.pdb' '-xr!*.lib'
|
||||
7z a ./ci-artifacts/windows-${{ steps.artifact-metadata.outputs.arch }}-${{ steps.artifact-metadata.outputs.simd }}-symbols.7z ./bin/*.pdb
|
||||
ls ./ci-artifacts/
|
||||
|
||||
- name: Upload Assets and Potential Publish Release
|
||||
if: github.repository == 'PCSX2/pcsx2' && startsWith(github.ref, 'refs/tags/') && matrix.configuration != 'CMake'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_PAT }}
|
||||
ASSET_DIR: ${{ github.WORKSPACE }}/ci-artifacts
|
||||
ASSET_EXTENSION: 7z
|
||||
TAG_TO_SEARCH_FOR: ${{ github.REF }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/upload-release-artifacts
|
||||
npm ci
|
||||
node index.js
|
||||
@@ -0,0 +1,67 @@
|
||||
name: 🖥️ Windows Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
# MSBUILD
|
||||
lint_vs_proj_files:
|
||||
name: Lint VS Project Files
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Verify VS Project Files
|
||||
run: .github\workflows\scripts\windows\validate-vs-filters.ps1
|
||||
|
||||
build_qt_sse4:
|
||||
needs: lint_vs_proj_files
|
||||
name: "SSE4"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: Release
|
||||
simd: "SSE4"
|
||||
secrets: inherit
|
||||
|
||||
build_qt_avx2:
|
||||
needs: lint_vs_proj_files
|
||||
name: "AVX2"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: Release AVX2
|
||||
secrets: inherit
|
||||
|
||||
build_qt_sse4_cmake:
|
||||
name: "CMake SSE4"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
secrets: inherit
|
||||
|
||||
build_qt_clang_sse4:
|
||||
needs: lint_vs_proj_files
|
||||
name: "SSE4"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt Clang
|
||||
configuration: Release Clang
|
||||
simd: "SSE4"
|
||||
secrets: inherit
|
||||
|
||||
build_qt_clang_avx2:
|
||||
needs: lint_vs_proj_files
|
||||
name: "AVX2"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt Clang
|
||||
configuration: Release Clang AVX2
|
||||
secrets: inherit
|
||||
@@ -0,0 +1,133 @@
|
||||
name: Windows Build Steps - Qt
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
jobName:
|
||||
required: true
|
||||
type: string
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: windows-2022
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
default: x64
|
||||
configuration:
|
||||
required: true
|
||||
type: string
|
||||
simd:
|
||||
required: false
|
||||
type: string
|
||||
default: AVX2
|
||||
buildSystem:
|
||||
required: false
|
||||
type: string
|
||||
default: msbuild
|
||||
qt_binary_url:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2-windows-dependencies/releases/download/2022-11-20/qt-6.4.0-x64.7z
|
||||
qt_dir:
|
||||
required: false
|
||||
type: string
|
||||
default: 3rdparty\qt\6.4.0\msvc2022_64
|
||||
cheats_url:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
|
||||
jobs:
|
||||
build_windows_qt:
|
||||
name: ${{ inputs.jobName }}
|
||||
runs-on: ${{ inputs.os }}
|
||||
# Set some sort of timeout in the event of run-away builds. We are limited on concurrent jobs so, get rid of them.
|
||||
timeout-minutes: 60
|
||||
env:
|
||||
POWERSHELL_TELEMETRY_OPTOUT: 1
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
env:
|
||||
OS: windows
|
||||
BUILD_SYSTEM: ${{ inputs.buildSystem }}
|
||||
GUI_FRAMEWORK: Qt
|
||||
ARCH: ${{ inputs.platform }}
|
||||
SIMD: ${{ inputs.simd }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
PR_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: ./.github/workflows/scripts/common/name-artifacts.sh
|
||||
|
||||
- name: Setup msbuild
|
||||
if: inputs.configuration != 'CMake'
|
||||
uses: microsoft/setup-msbuild@v1
|
||||
|
||||
- name: Download Qt build files
|
||||
shell: cmd
|
||||
run: |
|
||||
cd 3rdparty\qt
|
||||
aria2c ${{ inputs.qt_binary_url }}
|
||||
7z x qt-*-x64.7z
|
||||
del qt-*-x64.7z
|
||||
|
||||
- name: Download cheats
|
||||
shell: cmd
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.cheats_url }}/cheats_ni.zip" "${{ inputs.cheats_url }}/cheats_ws.zip"
|
||||
|
||||
- name: Generate CMake
|
||||
if: inputs.configuration == 'CMake'
|
||||
id: cmake
|
||||
shell: cmd
|
||||
run: |
|
||||
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cmake . -B build "-DCMAKE_PREFIX_PATH=%cd%\${{ inputs.qt_dir }}" -DQT_BUILD=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DDISABLE_ADVANCE_SIMD=ON -G Ninja
|
||||
|
||||
- name: Build PCSX2
|
||||
shell: cmd
|
||||
run: |
|
||||
if "${{ inputs.configuration }}"=="CMake" (
|
||||
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cmake --build build --config Release || exit /b
|
||||
cmake --install build --config Release || exit /b
|
||||
) else (
|
||||
msbuild "PCSX2_qt.sln" /m /v:m /p:Configuration="${{ inputs.configuration }}" /p:Platform="${{ inputs.platform }}"
|
||||
)
|
||||
|
||||
- name: Run Tests
|
||||
if: inputs.configuration == 'CMake'
|
||||
shell: cmd
|
||||
run: |
|
||||
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cmake --build build --config Release --target unittests
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: |
|
||||
./bin
|
||||
!./bin/**/*.bsc
|
||||
!./bin/**/*.exp
|
||||
!./bin/**/*.ilk
|
||||
!./bin/**/*.iobj
|
||||
!./bin/**/*.ipdb
|
||||
!./bin/**/*.pdb
|
||||
!./bin/**/*.lib
|
||||
|
||||
- name: Upload artifact - with symbols
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}-symbols
|
||||
path: ./bin/**/*.pdb
|
||||
+11
-29
@@ -30,15 +30,11 @@
|
||||
**/x64/Debug*
|
||||
**/x64/Devel*
|
||||
|
||||
**/bin/PCSX2-linux.sh
|
||||
|
||||
_ReSharper.*
|
||||
pcsx2.snapshot_*
|
||||
svnrev.h
|
||||
|
||||
/build
|
||||
/build_dev
|
||||
/build_dbg
|
||||
/build*
|
||||
/obj-*
|
||||
*.obj
|
||||
|
||||
@@ -47,9 +43,7 @@ Thumbs.db
|
||||
|
||||
Debug.txt
|
||||
install_log.txt
|
||||
padLog.txt
|
||||
GS_opengl_debug_hw.txt
|
||||
GS_opengl_debug_sw.txt
|
||||
bad_shader_*
|
||||
|
||||
Debug
|
||||
Release
|
||||
@@ -69,18 +63,19 @@ oprofile_data/
|
||||
/.vscode*
|
||||
|
||||
/bin/**/*.dll
|
||||
/bin/**/*.dmp
|
||||
/bin/**/*.exp
|
||||
/bin/**/*.ilk
|
||||
/bin/**/*.lib
|
||||
/bin/**/*.pdb
|
||||
/bin/PCSX2
|
||||
/bin/PCSX2-linux.sh
|
||||
/bin/*ReplayLoader
|
||||
/bin/PCSX2-linux.sh
|
||||
/bin/GS*.txt
|
||||
/bin/pcsx2*
|
||||
/bin/qt.conf
|
||||
/bin/bios
|
||||
/bin/cache
|
||||
/bin/cheats
|
||||
/bin/covers
|
||||
/bin/dumps
|
||||
/bin/gamesettings
|
||||
/bin/help
|
||||
/bin/inis
|
||||
/bin/logs
|
||||
@@ -88,26 +83,13 @@ oprofile_data/
|
||||
/bin/plugins
|
||||
/bin/snaps
|
||||
/bin/sstates
|
||||
/bin/textures
|
||||
/bin/translations
|
||||
/bin/inputprofiles
|
||||
/deps
|
||||
/ipch
|
||||
|
||||
!/3rdparty/libjpeg/change.log
|
||||
/3rdparty/portaudio/portaudio-2.0.pc
|
||||
/3rdparty/portaudio/bin
|
||||
/3rdparty/portaudio/bin-*
|
||||
/3rdparty/portaudio/autom4te.cache
|
||||
/3rdparty/portaudio/libtool
|
||||
/3rdparty/portaudio/config.*
|
||||
/3rdparty/portaudio/lib-stamp
|
||||
/3rdparty/portaudio/Makefile
|
||||
/3rdparty/portaudio/bindings
|
||||
/3rdparty/portaudio/test
|
||||
/3rdparty/portaudio/testcvs
|
||||
/3rdparty/portaudio/src/hostapi/asio/ASIOSDK/common
|
||||
/3rdparty/portaudio/src/hostapi/asio/ASIOSDK/host
|
||||
/3rdparty/portaudio/src/hostapi/wasapi/mingw-include
|
||||
/3rdparty/**/include/wx/setup.h
|
||||
/3rdparty/**/wx/msw/rcdefs.h
|
||||
/pcsx2/gui/Resources/*.h
|
||||
!/pcsx2/gui/Resources/EmbeddedImage.h
|
||||
/tools/bin
|
||||
|
||||
+22
-3
@@ -7,9 +7,6 @@
|
||||
[submodule "3rdparty/fmt/fmt"]
|
||||
path = 3rdparty/fmt/fmt
|
||||
url = https://github.com/fmtlib/fmt.git
|
||||
[submodule "3rdparty/yaml-cpp/yaml-cpp"]
|
||||
path = 3rdparty/yaml-cpp/yaml-cpp
|
||||
url = https://github.com/jbeder/yaml-cpp.git
|
||||
[submodule "3rdparty/libchdr/libchdr"]
|
||||
path = 3rdparty/libchdr/libchdr
|
||||
url = https://github.com/rtissera/libchdr.git
|
||||
@@ -17,3 +14,25 @@
|
||||
path = 3rdparty/wil
|
||||
url = https://github.com/microsoft/wil.git
|
||||
branch = master
|
||||
[submodule "3rdparty/rapidyaml/rapidyaml"]
|
||||
path = 3rdparty/rapidyaml/rapidyaml
|
||||
url = https://github.com/biojppm/rapidyaml.git
|
||||
branch = master
|
||||
[submodule "3rdparty/glslang/glslang"]
|
||||
path = 3rdparty/glslang/glslang
|
||||
url = https://github.com/KhronosGroup/glslang.git
|
||||
[submodule "3rdparty/vulkan-headers"]
|
||||
path = 3rdparty/vulkan-headers
|
||||
url = https://github.com/KhronosGroup/Vulkan-Headers.git
|
||||
[submodule "3rdparty/sdl2/SDL"]
|
||||
path = 3rdparty/sdl2/SDL
|
||||
url = https://github.com/libsdl-org/SDL.git
|
||||
[submodule "3rdparty/libzip/libzip"]
|
||||
path = 3rdparty/libzip/libzip
|
||||
url = https://github.com/nih-at/libzip.git
|
||||
[submodule "3rdparty/zstd/zstd"]
|
||||
path = 3rdparty/zstd/zstd
|
||||
url = https://github.com/facebook/zstd.git
|
||||
[submodule "3rdparty/rcheevos/rcheevos"]
|
||||
path = 3rdparty/rcheevos/rcheevos
|
||||
url = https://github.com/RetroAchievements/rcheevos.git
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
overrides:
|
||||
- files: "**/GameIndex.yaml"
|
||||
options:
|
||||
tabWidth: 2
|
||||
useTabs: false
|
||||
quoteProps: consistent
|
||||
endOfLine: auto
|
||||
proseWrap: preserve
|
||||
Vendored
-1
@@ -10,7 +10,6 @@
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__WIN32__;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<StructMemberAlignment>16Bytes</StructMemberAlignment>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
|
||||
Vendored
-55
@@ -1,55 +0,0 @@
|
||||
add_library(baseclasses
|
||||
amextra.cpp
|
||||
amfilter.cpp
|
||||
amvideo.cpp
|
||||
combase.cpp
|
||||
ctlutil.cpp
|
||||
ddmm.cpp
|
||||
mtype.cpp
|
||||
outputq.cpp
|
||||
pstream.cpp
|
||||
pullpin.cpp
|
||||
refclock.cpp
|
||||
renbase.cpp
|
||||
schedule.cpp
|
||||
seekpt.cpp
|
||||
source.cpp
|
||||
strmctl.cpp
|
||||
sysclock.cpp
|
||||
transfrm.cpp
|
||||
transip.cpp
|
||||
vtrans.cpp
|
||||
wxdebug.cpp
|
||||
wxlist.cpp
|
||||
wxutil.cpp
|
||||
amextra.h
|
||||
amfilter.h
|
||||
cache.h
|
||||
combase.h
|
||||
ctlutil.h
|
||||
ddmm.h
|
||||
fourcc.h
|
||||
measure.h
|
||||
msgthrd.h
|
||||
mtype.h
|
||||
outputq.h
|
||||
pstream.h
|
||||
pullpin.h
|
||||
refclock.h
|
||||
reftime.h
|
||||
renbase.h
|
||||
schedule.h
|
||||
seekpt.h
|
||||
source.h
|
||||
streams.h
|
||||
strmctl.h
|
||||
sysclock.h
|
||||
transfrm.h
|
||||
transip.h
|
||||
vtrans.h
|
||||
wxdebug.h
|
||||
wxlist.h
|
||||
wxutil.h
|
||||
)
|
||||
target_include_directories(baseclasses PUBLIC .)
|
||||
target_precompile_headers(baseclasses PRIVATE streams.h)
|
||||
Vendored
-21
@@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
Vendored
-111
@@ -1,111 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: AMExtra.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes - implements CRenderedInputPin class.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h> // DirectShow base class definitions
|
||||
#include <mmsystem.h> // Needed for definition of timeGetTime
|
||||
#include <limits.h> // Standard data type limit definitions
|
||||
#include <measure.h> // Used for time critical log functions
|
||||
|
||||
#include "amextra.h"
|
||||
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
// Implements CRenderedInputPin class
|
||||
|
||||
CRenderedInputPin::CRenderedInputPin(__in_opt LPCTSTR pObjectName,
|
||||
__in CBaseFilter *pFilter,
|
||||
__in CCritSec *pLock,
|
||||
__inout HRESULT *phr,
|
||||
__in_opt LPCWSTR pName) :
|
||||
CBaseInputPin(pObjectName, pFilter, pLock, phr, pName),
|
||||
m_bAtEndOfStream(FALSE),
|
||||
m_bCompleteNotified(FALSE)
|
||||
{
|
||||
}
|
||||
#ifdef UNICODE
|
||||
CRenderedInputPin::CRenderedInputPin(__in_opt LPCSTR pObjectName,
|
||||
__in CBaseFilter *pFilter,
|
||||
__in CCritSec *pLock,
|
||||
__inout HRESULT *phr,
|
||||
__in_opt LPCWSTR pName) :
|
||||
CBaseInputPin(pObjectName, pFilter, pLock, phr, pName),
|
||||
m_bAtEndOfStream(FALSE),
|
||||
m_bCompleteNotified(FALSE)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
// Flush end of stream condition - caller should do any
|
||||
// necessary stream level locking before calling this
|
||||
|
||||
STDMETHODIMP CRenderedInputPin::EndOfStream()
|
||||
{
|
||||
HRESULT hr = CheckStreaming();
|
||||
|
||||
// Do EC_COMPLETE handling for rendered pins
|
||||
if (S_OK == hr && !m_bAtEndOfStream) {
|
||||
m_bAtEndOfStream = TRUE;
|
||||
FILTER_STATE fs;
|
||||
EXECUTE_ASSERT(SUCCEEDED(m_pFilter->GetState(0, &fs)));
|
||||
if (fs == State_Running) {
|
||||
DoCompleteHandling();
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
// Called to complete the flush
|
||||
|
||||
STDMETHODIMP CRenderedInputPin::EndFlush()
|
||||
{
|
||||
CAutoLock lck(m_pLock);
|
||||
|
||||
// Clean up renderer state
|
||||
m_bAtEndOfStream = FALSE;
|
||||
m_bCompleteNotified = FALSE;
|
||||
|
||||
return CBaseInputPin::EndFlush();
|
||||
}
|
||||
|
||||
|
||||
// Notify of Run() from filter
|
||||
|
||||
HRESULT CRenderedInputPin::Run(REFERENCE_TIME tStart)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(tStart);
|
||||
m_bCompleteNotified = FALSE;
|
||||
if (m_bAtEndOfStream) {
|
||||
DoCompleteHandling();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
// Clear status on going into paused state
|
||||
|
||||
HRESULT CRenderedInputPin::Active()
|
||||
{
|
||||
m_bAtEndOfStream = FALSE;
|
||||
m_bCompleteNotified = FALSE;
|
||||
return CBaseInputPin::Active();
|
||||
}
|
||||
|
||||
|
||||
// Do stuff to deliver end of stream
|
||||
|
||||
void CRenderedInputPin::DoCompleteHandling()
|
||||
{
|
||||
ASSERT(m_bAtEndOfStream);
|
||||
if (!m_bCompleteNotified) {
|
||||
m_bCompleteNotified = TRUE;
|
||||
m_pFilter->NotifyEvent(EC_COMPLETE, S_OK, (LONG_PTR)(IBaseFilter *)m_pFilter);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
-56
@@ -1,56 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: AMExtra.h
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __AMEXTRA__
|
||||
#define __AMEXTRA__
|
||||
|
||||
// Simple rendered input pin
|
||||
//
|
||||
// NOTE if your filter queues stuff before rendering then it may not be
|
||||
// appropriate to use this class
|
||||
//
|
||||
// In that case queue the end of stream condition until the last sample
|
||||
// is actually rendered and flush the condition appropriately
|
||||
|
||||
class CRenderedInputPin : public CBaseInputPin
|
||||
{
|
||||
public:
|
||||
|
||||
CRenderedInputPin(__in_opt LPCTSTR pObjectName,
|
||||
__in CBaseFilter *pFilter,
|
||||
__in CCritSec *pLock,
|
||||
__inout HRESULT *phr,
|
||||
__in_opt LPCWSTR pName);
|
||||
#ifdef UNICODE
|
||||
CRenderedInputPin(__in_opt LPCSTR pObjectName,
|
||||
__in CBaseFilter *pFilter,
|
||||
__in CCritSec *pLock,
|
||||
__inout HRESULT *phr,
|
||||
__in_opt LPCWSTR pName);
|
||||
#endif
|
||||
|
||||
// Override methods to track end of stream state
|
||||
STDMETHODIMP EndOfStream();
|
||||
STDMETHODIMP EndFlush();
|
||||
|
||||
HRESULT Active();
|
||||
HRESULT Run(REFERENCE_TIME tStart);
|
||||
|
||||
protected:
|
||||
|
||||
// Member variables to track state
|
||||
BOOL m_bAtEndOfStream; // Set by EndOfStream
|
||||
BOOL m_bCompleteNotified; // Set when we notify for EC_COMPLETE
|
||||
|
||||
private:
|
||||
void DoCompleteHandling();
|
||||
};
|
||||
|
||||
#endif // __AMEXTRA__
|
||||
|
||||
Vendored
-5358
File diff suppressed because it is too large
Load Diff
Vendored
-1587
File diff suppressed because it is too large
Load Diff
Vendored
-275
@@ -1,275 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: AMVideo.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes - implements helper functions for
|
||||
// bitmap formats.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
#include <limits.h>
|
||||
|
||||
// These are bit field masks for true colour devices
|
||||
|
||||
const DWORD bits555[] = {0x007C00,0x0003E0,0x00001F};
|
||||
const DWORD bits565[] = {0x00F800,0x0007E0,0x00001F};
|
||||
const DWORD bits888[] = {0xFF0000,0x00FF00,0x0000FF};
|
||||
|
||||
// This maps bitmap subtypes into a bits per pixel value and also a
|
||||
// name. unicode and ansi versions are stored because we have to
|
||||
// return a pointer to a static string.
|
||||
const struct {
|
||||
const GUID *pSubtype;
|
||||
WORD BitCount;
|
||||
CHAR *pName;
|
||||
WCHAR *wszName;
|
||||
} BitCountMap[] = { &MEDIASUBTYPE_RGB1, 1, "RGB Monochrome", L"RGB Monochrome",
|
||||
&MEDIASUBTYPE_RGB4, 4, "RGB VGA", L"RGB VGA",
|
||||
&MEDIASUBTYPE_RGB8, 8, "RGB 8", L"RGB 8",
|
||||
&MEDIASUBTYPE_RGB565, 16, "RGB 565 (16 bit)", L"RGB 565 (16 bit)",
|
||||
&MEDIASUBTYPE_RGB555, 16, "RGB 555 (16 bit)", L"RGB 555 (16 bit)",
|
||||
&MEDIASUBTYPE_RGB24, 24, "RGB 24", L"RGB 24",
|
||||
&MEDIASUBTYPE_RGB32, 32, "RGB 32", L"RGB 32",
|
||||
&MEDIASUBTYPE_ARGB32, 32, "ARGB 32", L"ARGB 32",
|
||||
&MEDIASUBTYPE_Overlay, 0, "Overlay", L"Overlay",
|
||||
&GUID_NULL, 0, "UNKNOWN", L"UNKNOWN"
|
||||
};
|
||||
|
||||
// Return the size of the bitmap as defined by this header
|
||||
|
||||
STDAPI_(DWORD) GetBitmapSize(const BITMAPINFOHEADER *pHeader)
|
||||
{
|
||||
return DIBSIZE(*pHeader);
|
||||
}
|
||||
|
||||
|
||||
// This is called if the header has a 16 bit colour depth and needs to work
|
||||
// out the detailed type from the bit fields (either RGB 565 or RGB 555)
|
||||
|
||||
STDAPI_(const GUID) GetTrueColorType(const BITMAPINFOHEADER *pbmiHeader)
|
||||
{
|
||||
BITMAPINFO *pbmInfo = (BITMAPINFO *) pbmiHeader;
|
||||
ASSERT(pbmiHeader->biBitCount == 16);
|
||||
|
||||
// If its BI_RGB then it's RGB 555 by default
|
||||
|
||||
if (pbmiHeader->biCompression == BI_RGB) {
|
||||
return MEDIASUBTYPE_RGB555;
|
||||
}
|
||||
|
||||
// Compare the bit fields with RGB 555
|
||||
|
||||
DWORD *pMask = (DWORD *) pbmInfo->bmiColors;
|
||||
if (pMask[0] == bits555[0]) {
|
||||
if (pMask[1] == bits555[1]) {
|
||||
if (pMask[2] == bits555[2]) {
|
||||
return MEDIASUBTYPE_RGB555;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compare the bit fields with RGB 565
|
||||
|
||||
pMask = (DWORD *) pbmInfo->bmiColors;
|
||||
if (pMask[0] == bits565[0]) {
|
||||
if (pMask[1] == bits565[1]) {
|
||||
if (pMask[2] == bits565[2]) {
|
||||
return MEDIASUBTYPE_RGB565;
|
||||
}
|
||||
}
|
||||
}
|
||||
return GUID_NULL;
|
||||
}
|
||||
|
||||
|
||||
// Given a BITMAPINFOHEADER structure this returns the GUID sub type that is
|
||||
// used to describe it in format negotiations. For example a video codec fills
|
||||
// in the format block with a VIDEOINFO structure, it also fills in the major
|
||||
// type with MEDIATYPE_VIDEO and the subtype with a GUID that matches the bit
|
||||
// count, for example if it is an eight bit image then MEDIASUBTYPE_RGB8
|
||||
|
||||
STDAPI_(const GUID) GetBitmapSubtype(const BITMAPINFOHEADER *pbmiHeader)
|
||||
{
|
||||
ASSERT(pbmiHeader);
|
||||
|
||||
// If it's not RGB then create a GUID from the compression type
|
||||
|
||||
if (pbmiHeader->biCompression != BI_RGB) {
|
||||
if (pbmiHeader->biCompression != BI_BITFIELDS) {
|
||||
FOURCCMap FourCCMap(pbmiHeader->biCompression);
|
||||
return (const GUID) FourCCMap;
|
||||
}
|
||||
}
|
||||
|
||||
// Map the RGB DIB bit depth to a image GUID
|
||||
|
||||
switch(pbmiHeader->biBitCount) {
|
||||
case 1 : return MEDIASUBTYPE_RGB1;
|
||||
case 4 : return MEDIASUBTYPE_RGB4;
|
||||
case 8 : return MEDIASUBTYPE_RGB8;
|
||||
case 16 : return GetTrueColorType(pbmiHeader);
|
||||
case 24 : return MEDIASUBTYPE_RGB24;
|
||||
case 32 : return MEDIASUBTYPE_RGB32;
|
||||
}
|
||||
return GUID_NULL;
|
||||
}
|
||||
|
||||
|
||||
// Given a video bitmap subtype we return the number of bits per pixel it uses
|
||||
// We return a WORD bit count as thats what the BITMAPINFOHEADER uses. If the
|
||||
// GUID subtype is not found in the table we return an invalid USHRT_MAX
|
||||
|
||||
STDAPI_(WORD) GetBitCount(const GUID *pSubtype)
|
||||
{
|
||||
ASSERT(pSubtype);
|
||||
const GUID *pMediaSubtype;
|
||||
INT iPosition = 0;
|
||||
|
||||
// Scan the mapping list seeing if the source GUID matches any known
|
||||
// bitmap subtypes, the list is terminated by a GUID_NULL entry
|
||||
|
||||
while (TRUE) {
|
||||
pMediaSubtype = BitCountMap[iPosition].pSubtype;
|
||||
if (IsEqualGUID(*pMediaSubtype,GUID_NULL)) {
|
||||
return USHRT_MAX;
|
||||
}
|
||||
if (IsEqualGUID(*pMediaSubtype,*pSubtype)) {
|
||||
return BitCountMap[iPosition].BitCount;
|
||||
}
|
||||
iPosition++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Given a bitmap subtype we return a description name that can be used for
|
||||
// debug purposes. In a retail build this function still returns the names
|
||||
// If the subtype isn't found in the lookup table we return string UNKNOWN
|
||||
|
||||
int LocateSubtype(const GUID *pSubtype)
|
||||
{
|
||||
ASSERT(pSubtype);
|
||||
const GUID *pMediaSubtype;
|
||||
INT iPosition = 0;
|
||||
|
||||
// Scan the mapping list seeing if the source GUID matches any known
|
||||
// bitmap subtypes, the list is terminated by a GUID_NULL entry
|
||||
|
||||
while (TRUE) {
|
||||
pMediaSubtype = BitCountMap[iPosition].pSubtype;
|
||||
if (IsEqualGUID(*pMediaSubtype,*pSubtype) ||
|
||||
IsEqualGUID(*pMediaSubtype,GUID_NULL)
|
||||
)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
iPosition++;
|
||||
}
|
||||
|
||||
return iPosition;
|
||||
}
|
||||
|
||||
|
||||
|
||||
STDAPI_(WCHAR *) GetSubtypeNameW(const GUID *pSubtype)
|
||||
{
|
||||
return BitCountMap[LocateSubtype(pSubtype)].wszName;
|
||||
}
|
||||
|
||||
STDAPI_(CHAR *) GetSubtypeNameA(const GUID *pSubtype)
|
||||
{
|
||||
return BitCountMap[LocateSubtype(pSubtype)].pName;
|
||||
}
|
||||
|
||||
#ifndef GetSubtypeName
|
||||
#error wxutil.h should have defined GetSubtypeName
|
||||
#endif
|
||||
#undef GetSubtypeName
|
||||
|
||||
// this is here for people that linked to it directly; most people
|
||||
// would use the header file that picks the A or W version.
|
||||
STDAPI_(CHAR *) GetSubtypeName(const GUID *pSubtype)
|
||||
{
|
||||
return GetSubtypeNameA(pSubtype);
|
||||
}
|
||||
|
||||
|
||||
// The mechanism for describing a bitmap format is with the BITMAPINFOHEADER
|
||||
// This is really messy to deal with because it invariably has fields that
|
||||
// follow it holding bit fields, palettes and the rest. This function gives
|
||||
// the number of bytes required to hold a VIDEOINFO that represents it. This
|
||||
// count includes the prefix information (like the rcSource rectangle) the
|
||||
// BITMAPINFOHEADER field, and any other colour information on the end.
|
||||
//
|
||||
// WARNING If you want to copy a BITMAPINFOHEADER into a VIDEOINFO always make
|
||||
// sure that you use the HEADER macro because the BITMAPINFOHEADER field isn't
|
||||
// right at the start of the VIDEOINFO (there are a number of other fields),
|
||||
//
|
||||
// CopyMemory(HEADER(pVideoInfo),pbmi,sizeof(BITMAPINFOHEADER));
|
||||
//
|
||||
|
||||
STDAPI_(LONG) GetBitmapFormatSize(const BITMAPINFOHEADER *pHeader)
|
||||
{
|
||||
// Everyone has this to start with this
|
||||
LONG Size = SIZE_PREHEADER + pHeader->biSize;
|
||||
|
||||
ASSERT(pHeader->biSize >= sizeof(BITMAPINFOHEADER));
|
||||
|
||||
// Does this format use a palette, if the number of colours actually used
|
||||
// is zero then it is set to the maximum that are allowed for that colour
|
||||
// depth (an example is 256 for eight bits). Truecolour formats may also
|
||||
// pass a palette with them in which case the used count is non zero
|
||||
|
||||
// This would scare me.
|
||||
ASSERT(pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed == 0);
|
||||
|
||||
if (pHeader->biBitCount <= iPALETTE || pHeader->biClrUsed) {
|
||||
LONG Entries = (DWORD) 1 << pHeader->biBitCount;
|
||||
if (pHeader->biClrUsed) {
|
||||
Entries = pHeader->biClrUsed;
|
||||
}
|
||||
Size += Entries * sizeof(RGBQUAD);
|
||||
}
|
||||
|
||||
// Truecolour formats may have a BI_BITFIELDS specifier for compression
|
||||
// type which means that room for three DWORDs should be allocated that
|
||||
// specify where in each pixel the RGB colour components may be found
|
||||
|
||||
if (pHeader->biCompression == BI_BITFIELDS) {
|
||||
Size += SIZE_MASKS;
|
||||
}
|
||||
|
||||
// A BITMAPINFO for a palettised image may also contain a palette map that
|
||||
// provides the information to map from a source palette to a destination
|
||||
// palette during a BitBlt for example, because this information is only
|
||||
// ever processed during drawing you don't normally store the palette map
|
||||
// nor have any way of knowing if it is present in the data structure
|
||||
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
// Returns TRUE if the VIDEOINFO contains a palette
|
||||
|
||||
STDAPI_(BOOL) ContainsPalette(const VIDEOINFOHEADER *pVideoInfo)
|
||||
{
|
||||
if (PALETTISED(pVideoInfo) == FALSE) {
|
||||
if (pVideoInfo->bmiHeader.biClrUsed == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Return a pointer to the first entry in a palette
|
||||
|
||||
STDAPI_(const RGBQUAD *) GetBitmapPalette(const VIDEOINFOHEADER *pVideoInfo)
|
||||
{
|
||||
if (pVideoInfo->bmiHeader.biCompression == BI_BITFIELDS) {
|
||||
return TRUECOLOR(pVideoInfo)->bmiColors;
|
||||
}
|
||||
return COLORS(pVideoInfo);
|
||||
}
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(SolutionDir)common\vsprops\BaseProjectConfig.props" />
|
||||
<Import Project="$(SolutionDir)common\vsprops\WinSDK.props" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{27F17499-A372-4408-8AFA-4F9F4584FBD3}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization Condition="$(Configuration.Contains(Release))">true</WholeProgramOptimization>
|
||||
<UseDebugLibraries Condition="$(Configuration.Contains(Debug))">true</UseDebugLibraries>
|
||||
<UseDebugLibraries Condition="!$(Configuration.Contains(Debug))">false</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="..\..\3rdparty\DefaultProjectRootDir.props" />
|
||||
<Import Project="..\..\3rdparty\3rdparty.props" />
|
||||
<Import Condition="$(Configuration.Contains(Debug))" Project="..\..\common\vsprops\CodeGen_Debug.props" />
|
||||
<Import Condition="$(Configuration.Contains(Release))" Project="..\..\common\vsprops\CodeGen_Release.props" />
|
||||
<Import Condition="!$(Configuration.Contains(Release))" Project="..\..\common\vsprops\IncrementalLinking.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>streams.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="amextra.h" />
|
||||
<ClInclude Include="amfilter.h" />
|
||||
<ClInclude Include="cache.h" />
|
||||
<ClInclude Include="combase.h" />
|
||||
<ClInclude Include="ctlutil.h" />
|
||||
<ClInclude Include="ddmm.h" />
|
||||
<ClInclude Include="fourcc.h" />
|
||||
<ClInclude Include="measure.h" />
|
||||
<ClInclude Include="msgthrd.h" />
|
||||
<ClInclude Include="mtype.h" />
|
||||
<ClInclude Include="outputq.h" />
|
||||
<ClInclude Include="pstream.h" />
|
||||
<ClInclude Include="pullpin.h" />
|
||||
<ClInclude Include="refclock.h" />
|
||||
<ClInclude Include="reftime.h" />
|
||||
<ClInclude Include="renbase.h" />
|
||||
<ClInclude Include="schedule.h" />
|
||||
<ClInclude Include="seekpt.h" />
|
||||
<ClInclude Include="source.h" />
|
||||
<ClInclude Include="streams.h" />
|
||||
<ClInclude Include="strmctl.h" />
|
||||
<ClInclude Include="sysclock.h" />
|
||||
<ClInclude Include="transfrm.h" />
|
||||
<ClInclude Include="transip.h" />
|
||||
<ClInclude Include="vtrans.h" />
|
||||
<ClInclude Include="wxdebug.h" />
|
||||
<ClInclude Include="wxlist.h" />
|
||||
<ClInclude Include="wxutil.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="amextra.cpp" />
|
||||
<ClCompile Include="amfilter.cpp" />
|
||||
<ClCompile Include="amvideo.cpp" />
|
||||
<ClCompile Include="combase.cpp" />
|
||||
<ClCompile Include="ctlutil.cpp" />
|
||||
<ClCompile Include="ddmm.cpp">
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mtype.cpp" />
|
||||
<ClCompile Include="outputq.cpp" />
|
||||
<ClCompile Include="pstream.cpp" />
|
||||
<ClCompile Include="pullpin.cpp" />
|
||||
<ClCompile Include="refclock.cpp" />
|
||||
<ClCompile Include="renbase.cpp" />
|
||||
<ClCompile Include="schedule.cpp" />
|
||||
<ClCompile Include="seekpt.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source.cpp" />
|
||||
<ClCompile Include="strmctl.cpp" />
|
||||
<ClCompile Include="sysclock.cpp" />
|
||||
<ClCompile Include="transfrm.cpp" />
|
||||
<ClCompile Include="transip.cpp" />
|
||||
<ClCompile Include="vtrans.cpp" />
|
||||
<ClCompile Include="wxdebug.cpp" />
|
||||
<ClCompile Include="wxlist.cpp" />
|
||||
<ClCompile Include="wxutil.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
</Project>
|
||||
-174
@@ -1,174 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="amextra.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="amfilter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cache.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="combase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ctlutil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ddmm.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="fourcc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="msgthrd.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="reftime.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="refclock.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pullpin.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pstream.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="outputq.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mtype.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="measure.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="renbase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="schedule.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="seekpt.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="streams.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="strmctl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="sysclock.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transfrm.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="transip.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vtrans.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wxdebug.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wxlist.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wxutil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="amextra.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="amfilter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="amvideo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="combase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ctlutil.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ddmm.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mtype.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="outputq.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pstream.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pullpin.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="refclock.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="renbase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="schedule.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="seekpt.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="strmctl.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="sysclock.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="transfrm.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="transip.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vtrans.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wxdebug.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wxlist.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wxutil.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Vendored
-74
@@ -1,74 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: Cache.h
|
||||
//
|
||||
// Desc: DirectShow base classes - efines a non-MFC generic cache class.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/* This class implements a simple cache. A cache object is instantiated
|
||||
with the number of items it is to hold. An item is a pointer to an
|
||||
object derived from CBaseObject (helps reduce memory leaks). The cache
|
||||
can then have objects added to it and removed from it. The cache size
|
||||
is fixed at construction time and may therefore run out or be flooded.
|
||||
If it runs out it returns a NULL pointer, if it fills up it also returns
|
||||
a NULL pointer instead of a pointer to the object just inserted */
|
||||
|
||||
/* Making these classes inherit from CBaseObject does nothing for their
|
||||
functionality but it allows us to check there are no memory leaks */
|
||||
|
||||
/* WARNING Be very careful when using this class, what it lets you do is
|
||||
store and retrieve objects so that you can minimise object creation
|
||||
which in turns improves efficiency. However the object you store is
|
||||
exactly the same as the object you get back which means that it short
|
||||
circuits the constructor initialisation phase. This means any class
|
||||
variables the object has (eg pointers) are highly likely to be invalid.
|
||||
Therefore ensure you reinitialise the object before using it again */
|
||||
|
||||
|
||||
#ifndef __CACHE__
|
||||
#define __CACHE__
|
||||
|
||||
|
||||
class CCache : CBaseObject {
|
||||
|
||||
/* Make copy constructor and assignment operator inaccessible */
|
||||
|
||||
CCache(const CCache &refCache);
|
||||
CCache &operator=(const CCache &refCache);
|
||||
|
||||
private:
|
||||
|
||||
/* These are initialised in the constructor. The first variable points to
|
||||
an array of pointers, each of which points to a CBaseObject derived
|
||||
object. The m_iCacheSize is the static fixed size for the cache and the
|
||||
m_iUsed defines the number of places filled with objects at any time.
|
||||
We fill the array of pointers from the start (ie m_ppObjects[0] first)
|
||||
and then only add and remove objects from the end position, so in this
|
||||
respect the array of object pointers should be treated as a stack */
|
||||
|
||||
CBaseObject **m_ppObjects;
|
||||
const INT m_iCacheSize;
|
||||
INT m_iUsed;
|
||||
|
||||
public:
|
||||
|
||||
CCache(__in_opt LPCTSTR pName,INT iItems);
|
||||
virtual ~CCache();
|
||||
|
||||
/* Add an item to the cache */
|
||||
CBaseObject *AddToCache(__in CBaseObject *pObject);
|
||||
|
||||
/* Remove an item from the cache */
|
||||
CBaseObject *RemoveFromCache();
|
||||
|
||||
/* Delete all the objects held in the cache */
|
||||
void RemoveAll(void);
|
||||
|
||||
/* Return the cache size which is set during construction */
|
||||
INT GetCacheSize(void) const {return m_iCacheSize;};
|
||||
};
|
||||
|
||||
#endif /* __CACHE__ */
|
||||
|
||||
Vendored
-265
@@ -1,265 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: ComBase.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes - implements class hierarchy for creating
|
||||
// COM objects.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
#pragma warning( disable : 4514 ) // Disable warnings re unused inline functions
|
||||
|
||||
|
||||
/* Define the static member variable */
|
||||
|
||||
LONG CBaseObject::m_cObjects = 0;
|
||||
|
||||
|
||||
/* Constructor */
|
||||
|
||||
CBaseObject::CBaseObject(__in_opt LPCTSTR pName)
|
||||
{
|
||||
/* Increment the number of active objects */
|
||||
InterlockedIncrement(&m_cObjects);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#ifdef UNICODE
|
||||
m_dwCookie = DbgRegisterObjectCreation(0, pName);
|
||||
#else
|
||||
m_dwCookie = DbgRegisterObjectCreation(pName, 0);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef UNICODE
|
||||
CBaseObject::CBaseObject(const char *pName)
|
||||
{
|
||||
/* Increment the number of active objects */
|
||||
InterlockedIncrement(&m_cObjects);
|
||||
|
||||
#ifdef DEBUG
|
||||
m_dwCookie = DbgRegisterObjectCreation(pName, 0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
HINSTANCE hlibOLEAut32;
|
||||
|
||||
/* Destructor */
|
||||
|
||||
CBaseObject::~CBaseObject()
|
||||
{
|
||||
/* Decrement the number of objects active */
|
||||
if (InterlockedDecrement(&m_cObjects) == 0) {
|
||||
if (hlibOLEAut32) {
|
||||
FreeLibrary(hlibOLEAut32);
|
||||
|
||||
hlibOLEAut32 = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
DbgRegisterObjectDestruction(m_dwCookie);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const TCHAR szOle32Aut[] = TEXT("OleAut32.dll");
|
||||
|
||||
HINSTANCE LoadOLEAut32()
|
||||
{
|
||||
if (hlibOLEAut32 == 0) {
|
||||
|
||||
hlibOLEAut32 = LoadLibrary(szOle32Aut);
|
||||
}
|
||||
|
||||
return hlibOLEAut32;
|
||||
}
|
||||
|
||||
|
||||
/* Constructor */
|
||||
|
||||
// We know we use "this" in the initialization list, we also know we don't modify *phr.
|
||||
#pragma warning( disable : 4355 4100 )
|
||||
CUnknown::CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk)
|
||||
: CBaseObject(pName)
|
||||
/* Start the object with a reference count of zero - when the */
|
||||
/* object is queried for it's first interface this may be */
|
||||
/* incremented depending on whether or not this object is */
|
||||
/* currently being aggregated upon */
|
||||
, m_cRef(0)
|
||||
/* Set our pointer to our IUnknown interface. */
|
||||
/* If we have an outer, use its, otherwise use ours. */
|
||||
/* This pointer effectivly points to the owner of */
|
||||
/* this object and can be accessed by the GetOwner() method. */
|
||||
, m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
|
||||
/* Why the double cast? Well, the inner cast is a type-safe cast */
|
||||
/* to pointer to a type from which we inherit. The second is */
|
||||
/* type-unsafe but works because INonDelegatingUnknown "behaves */
|
||||
/* like" IUnknown. (Only the names on the methods change.) */
|
||||
{
|
||||
// Everything we need to do has been done in the initializer list
|
||||
}
|
||||
|
||||
// This does the same as above except it has a useless HRESULT argument
|
||||
// use the previous constructor, this is just left for compatibility...
|
||||
CUnknown::CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) :
|
||||
CBaseObject(pName),
|
||||
m_cRef(0),
|
||||
m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
|
||||
{
|
||||
}
|
||||
|
||||
#ifdef UNICODE
|
||||
CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk)
|
||||
: CBaseObject(pName), m_cRef(0),
|
||||
m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
|
||||
{ }
|
||||
|
||||
CUnknown::CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) :
|
||||
CBaseObject(pName), m_cRef(0),
|
||||
m_pUnknown( pUnk != 0 ? pUnk : reinterpret_cast<LPUNKNOWN>( static_cast<PNDUNKNOWN>(this) ) )
|
||||
{ }
|
||||
|
||||
#endif
|
||||
|
||||
#pragma warning( default : 4355 4100 )
|
||||
|
||||
|
||||
/* QueryInterface */
|
||||
|
||||
STDMETHODIMP CUnknown::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv)
|
||||
{
|
||||
CheckPointer(ppv,E_POINTER);
|
||||
ValidateReadWritePtr(ppv,sizeof(PVOID));
|
||||
|
||||
/* We know only about IUnknown */
|
||||
|
||||
if (riid == IID_IUnknown) {
|
||||
GetInterface((LPUNKNOWN) (PNDUNKNOWN) this, ppv);
|
||||
return NOERROR;
|
||||
} else {
|
||||
*ppv = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
/* We have to ensure that we DON'T use a max macro, since these will typically */
|
||||
/* lead to one of the parameters being evaluated twice. Since we are worried */
|
||||
/* about concurrency, we can't afford to access the m_cRef twice since we can't */
|
||||
/* afford to run the risk that its value having changed between accesses. */
|
||||
|
||||
template<class T> inline static T ourmax( const T & a, const T & b )
|
||||
{
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
/* AddRef */
|
||||
|
||||
STDMETHODIMP_(ULONG) CUnknown::NonDelegatingAddRef()
|
||||
{
|
||||
LONG lRef = InterlockedIncrement( &m_cRef );
|
||||
ASSERT(lRef > 0);
|
||||
DbgLog((LOG_MEMORY,3,TEXT(" Obj %d ref++ = %d"),
|
||||
m_dwCookie, m_cRef));
|
||||
return ourmax(ULONG(m_cRef), 1ul);
|
||||
}
|
||||
|
||||
|
||||
/* Release */
|
||||
|
||||
STDMETHODIMP_(ULONG) CUnknown::NonDelegatingRelease()
|
||||
{
|
||||
/* If the reference count drops to zero delete ourselves */
|
||||
|
||||
LONG lRef = InterlockedDecrement( &m_cRef );
|
||||
ASSERT(lRef >= 0);
|
||||
|
||||
DbgLog((LOG_MEMORY,3,TEXT(" Object %d ref-- = %d"),
|
||||
m_dwCookie, m_cRef));
|
||||
if (lRef == 0) {
|
||||
|
||||
// COM rules say we must protect against re-entrancy.
|
||||
// If we are an aggregator and we hold our own interfaces
|
||||
// on the aggregatee, the QI for these interfaces will
|
||||
// addref ourselves. So after doing the QI we must release
|
||||
// a ref count on ourselves. Then, before releasing the
|
||||
// private interface, we must addref ourselves. When we do
|
||||
// this from the destructor here it will result in the ref
|
||||
// count going to 1 and then back to 0 causing us to
|
||||
// re-enter the destructor. Hence we add an extra refcount here
|
||||
// once we know we will delete the object.
|
||||
// for an example aggregator see filgraph\distrib.cpp.
|
||||
|
||||
m_cRef++;
|
||||
|
||||
delete this;
|
||||
return ULONG(0);
|
||||
} else {
|
||||
// Don't touch m_cRef again even in this leg as the object
|
||||
// may have just been released on another thread too
|
||||
return ourmax(ULONG(lRef), 1ul);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Return an interface pointer to a requesting client
|
||||
performing a thread safe AddRef as necessary */
|
||||
|
||||
STDAPI GetInterface(LPUNKNOWN pUnk, __out void **ppv)
|
||||
{
|
||||
CheckPointer(ppv, E_POINTER);
|
||||
*ppv = pUnk;
|
||||
pUnk->AddRef();
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Compares two interfaces and returns TRUE if they are on the same object */
|
||||
|
||||
BOOL WINAPI IsEqualObject(IUnknown *pFirst, IUnknown *pSecond)
|
||||
{
|
||||
/* Different objects can't have the same interface pointer for
|
||||
any interface
|
||||
*/
|
||||
if (pFirst == pSecond) {
|
||||
return TRUE;
|
||||
}
|
||||
/* OK - do it the hard way - check if they have the same
|
||||
IUnknown pointers - a single object can only have one of these
|
||||
*/
|
||||
LPUNKNOWN pUnknown1; // Retrieve the IUnknown interface
|
||||
LPUNKNOWN pUnknown2; // Retrieve the other IUnknown interface
|
||||
HRESULT hr; // General OLE return code
|
||||
|
||||
ASSERT(pFirst);
|
||||
ASSERT(pSecond);
|
||||
|
||||
/* See if the IUnknown pointers match */
|
||||
|
||||
hr = pFirst->QueryInterface(IID_IUnknown,(void **) &pUnknown1);
|
||||
if (FAILED(hr)) {
|
||||
return FALSE;
|
||||
}
|
||||
ASSERT(pUnknown1);
|
||||
|
||||
/* Release the extra interface we hold */
|
||||
|
||||
pUnknown1->Release();
|
||||
|
||||
hr = pSecond->QueryInterface(IID_IUnknown,(void **) &pUnknown2);
|
||||
if (FAILED(hr)) {
|
||||
return FALSE;
|
||||
}
|
||||
ASSERT(pUnknown2);
|
||||
|
||||
/* Release the extra interface we hold */
|
||||
|
||||
pUnknown2->Release();
|
||||
return (pUnknown1 == pUnknown2);
|
||||
}
|
||||
|
||||
Vendored
-305
@@ -1,305 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: ComBase.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines a class hierarchy for creating
|
||||
// COM objects.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/*
|
||||
|
||||
a. Derive your COM object from CUnknown
|
||||
|
||||
b. Make a static CreateInstance function that takes an LPUNKNOWN, an HRESULT *
|
||||
and a TCHAR *. The LPUNKNOWN defines the object to delegate IUnknown calls
|
||||
to. The HRESULT * allows error codes to be passed around constructors and
|
||||
the TCHAR * is a descriptive name that can be printed on the debugger.
|
||||
|
||||
It is important that constructors only change the HRESULT * if they have
|
||||
to set an ERROR code, if it was successful then leave it alone or you may
|
||||
overwrite an error code from an object previously created.
|
||||
|
||||
When you call a constructor the descriptive name should be in static store
|
||||
as we do not copy the string. To stop large amounts of memory being used
|
||||
in retail builds by all these static strings use the NAME macro,
|
||||
|
||||
CMyFilter = new CImplFilter(NAME("My filter"),pUnknown,phr);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
In retail builds NAME(_x_) compiles to NULL, the base CBaseObject class
|
||||
knows not to do anything with objects that don't have a name.
|
||||
|
||||
c. Have a constructor for your object that passes the LPUNKNOWN, HRESULT * and
|
||||
TCHAR * to the CUnknown constructor. You can set the HRESULT if you have an
|
||||
error, or just simply pass it through to the constructor.
|
||||
|
||||
The object creation will fail in the class factory if the HRESULT indicates
|
||||
an error (ie FAILED(HRESULT) == TRUE)
|
||||
|
||||
d. Create a FactoryTemplate with your object's class id and CreateInstance
|
||||
function.
|
||||
|
||||
Then (for each interface) either
|
||||
|
||||
Multiple inheritance
|
||||
|
||||
1. Also derive it from ISomeInterface
|
||||
2. Include DECLARE_IUNKNOWN in your class definition to declare
|
||||
implementations of QueryInterface, AddRef and Release that
|
||||
call the outer unknown
|
||||
3. Override NonDelegatingQueryInterface to expose ISomeInterface by
|
||||
code something like
|
||||
|
||||
if (riid == IID_ISomeInterface) {
|
||||
return GetInterface((ISomeInterface *) this, ppv);
|
||||
} else {
|
||||
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
||||
}
|
||||
|
||||
4. Declare and implement the member functions of ISomeInterface.
|
||||
|
||||
or: Nested interfaces
|
||||
|
||||
1. Declare a class derived from CUnknown
|
||||
2. Include DECLARE_IUNKNOWN in your class definition
|
||||
3. Override NonDelegatingQueryInterface to expose ISomeInterface by
|
||||
code something like
|
||||
|
||||
if (riid == IID_ISomeInterface) {
|
||||
return GetInterface((ISomeInterface *) this, ppv);
|
||||
} else {
|
||||
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
||||
}
|
||||
|
||||
4. Implement the member functions of ISomeInterface. Use GetOwner() to
|
||||
access the COM object class.
|
||||
|
||||
And in your COM object class:
|
||||
|
||||
5. Make the nested class a friend of the COM object class, and declare
|
||||
an instance of the nested class as a member of the COM object class.
|
||||
|
||||
NOTE that because you must always pass the outer unknown and an hResult
|
||||
to the CUnknown constructor you cannot use a default constructor, in
|
||||
other words you will have to make the member variable a pointer to the
|
||||
class and make a NEW call in your constructor to actually create it.
|
||||
|
||||
6. override the NonDelegatingQueryInterface with code like this:
|
||||
|
||||
if (riid == IID_ISomeInterface) {
|
||||
return m_pImplFilter->
|
||||
NonDelegatingQueryInterface(IID_ISomeInterface, ppv);
|
||||
} else {
|
||||
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
||||
}
|
||||
|
||||
You can have mixed classes which support some interfaces via multiple
|
||||
inheritance and some via nested classes
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __COMBASE__
|
||||
#define __COMBASE__
|
||||
|
||||
// Filter Setup data structures no defined in axextend.idl
|
||||
|
||||
typedef REGPINTYPES
|
||||
AMOVIESETUP_MEDIATYPE, * PAMOVIESETUP_MEDIATYPE, * FAR LPAMOVIESETUP_MEDIATYPE;
|
||||
|
||||
typedef REGFILTERPINS
|
||||
AMOVIESETUP_PIN, * PAMOVIESETUP_PIN, * FAR LPAMOVIESETUP_PIN;
|
||||
|
||||
typedef struct _AMOVIESETUP_FILTER
|
||||
{
|
||||
const CLSID * clsID;
|
||||
const WCHAR * strName;
|
||||
DWORD dwMerit;
|
||||
UINT nPins;
|
||||
const AMOVIESETUP_PIN * lpPin;
|
||||
}
|
||||
AMOVIESETUP_FILTER, * PAMOVIESETUP_FILTER, * FAR LPAMOVIESETUP_FILTER;
|
||||
|
||||
/* The DLLENTRY module initialises the module handle on loading */
|
||||
|
||||
extern HINSTANCE g_hInst;
|
||||
|
||||
/* On DLL load remember which platform we are running on */
|
||||
|
||||
extern DWORD g_amPlatform;
|
||||
extern OSVERSIONINFO g_osInfo; // Filled in by GetVersionEx
|
||||
|
||||
/* Version of IUnknown that is renamed to allow a class to support both
|
||||
non delegating and delegating IUnknowns in the same COM object */
|
||||
|
||||
#ifndef INONDELEGATINGUNKNOWN_DEFINED
|
||||
DECLARE_INTERFACE(INonDelegatingUnknown)
|
||||
{
|
||||
STDMETHOD(NonDelegatingQueryInterface) (THIS_ REFIID, LPVOID *) PURE;
|
||||
STDMETHOD_(ULONG, NonDelegatingAddRef)(THIS) PURE;
|
||||
STDMETHOD_(ULONG, NonDelegatingRelease)(THIS) PURE;
|
||||
};
|
||||
#define INONDELEGATINGUNKNOWN_DEFINED
|
||||
#endif
|
||||
|
||||
typedef INonDelegatingUnknown *PNDUNKNOWN;
|
||||
|
||||
|
||||
/* This is the base object class that supports active object counting. As
|
||||
part of the debug facilities we trace every time a C++ object is created
|
||||
or destroyed. The name of the object has to be passed up through the class
|
||||
derivation list during construction as you cannot call virtual functions
|
||||
in the constructor. The downside of all this is that every single object
|
||||
constructor has to take an object name parameter that describes it */
|
||||
|
||||
class CBaseObject
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
// Disable the copy constructor and assignment by default so you will get
|
||||
// compiler errors instead of unexpected behaviour if you pass objects
|
||||
// by value or assign objects.
|
||||
CBaseObject(const CBaseObject& objectSrc); // no implementation
|
||||
void operator=(const CBaseObject& objectSrc); // no implementation
|
||||
|
||||
private:
|
||||
static LONG m_cObjects; /* Total number of objects active */
|
||||
|
||||
protected:
|
||||
#ifdef DEBUG
|
||||
DWORD m_dwCookie; /* Cookie identifying this object */
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/* These increment and decrement the number of active objects */
|
||||
|
||||
CBaseObject(__in_opt LPCTSTR pName);
|
||||
#ifdef UNICODE
|
||||
CBaseObject(__in_opt LPCSTR pName);
|
||||
#endif
|
||||
~CBaseObject();
|
||||
|
||||
/* Call this to find if there are any CUnknown derived objects active */
|
||||
|
||||
static LONG ObjectsActive() {
|
||||
return m_cObjects;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* An object that supports one or more COM interfaces will be based on
|
||||
this class. It supports counting of total objects for DLLCanUnloadNow
|
||||
support, and an implementation of the core non delegating IUnknown */
|
||||
|
||||
class AM_NOVTABLE CUnknown : public INonDelegatingUnknown,
|
||||
public CBaseObject
|
||||
{
|
||||
private:
|
||||
const LPUNKNOWN m_pUnknown; /* Owner of this object */
|
||||
|
||||
protected: /* So we can override NonDelegatingRelease() */
|
||||
volatile LONG m_cRef; /* Number of reference counts */
|
||||
|
||||
public:
|
||||
|
||||
CUnknown(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk);
|
||||
virtual ~CUnknown() {};
|
||||
|
||||
// This is redundant, just use the other constructor
|
||||
// as we never touch the HRESULT in this anyway
|
||||
CUnknown(__in_opt LPCTSTR Name, __in_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr);
|
||||
#ifdef UNICODE
|
||||
CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk);
|
||||
CUnknown(__in_opt LPCSTR pName, __in_opt LPUNKNOWN pUnk,__inout_opt HRESULT *phr);
|
||||
#endif
|
||||
|
||||
/* Return the owner of this object */
|
||||
|
||||
LPUNKNOWN GetOwner() const {
|
||||
return m_pUnknown;
|
||||
};
|
||||
|
||||
/* Called from the class factory to create a new instance, it is
|
||||
pure virtual so it must be overriden in your derived class */
|
||||
|
||||
/* static CUnknown *CreateInstance(LPUNKNOWN, HRESULT *) */
|
||||
|
||||
/* Non delegating unknown implementation */
|
||||
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID, __deref_out void **);
|
||||
STDMETHODIMP_(ULONG) NonDelegatingAddRef();
|
||||
STDMETHODIMP_(ULONG) NonDelegatingRelease();
|
||||
};
|
||||
|
||||
/* Return an interface pointer to a requesting client
|
||||
performing a thread safe AddRef as necessary */
|
||||
|
||||
STDAPI GetInterface(LPUNKNOWN pUnk, __out void **ppv);
|
||||
|
||||
/* A function that can create a new COM object */
|
||||
|
||||
typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(__in_opt LPUNKNOWN pUnkOuter, __inout_opt HRESULT *phr);
|
||||
|
||||
/* A function (can be NULL) which is called from the DLL entrypoint
|
||||
routine for each factory template:
|
||||
|
||||
bLoading - TRUE on DLL load, FALSE on DLL unload
|
||||
rclsid - the m_ClsID of the entry
|
||||
*/
|
||||
typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, const CLSID *rclsid);
|
||||
|
||||
/* Create one of these per object class in an array so that
|
||||
the default class factory code can create new instances */
|
||||
|
||||
class CFactoryTemplate {
|
||||
|
||||
public:
|
||||
|
||||
const WCHAR * m_Name;
|
||||
const CLSID * m_ClsID;
|
||||
LPFNNewCOMObject m_lpfnNew;
|
||||
LPFNInitRoutine m_lpfnInit;
|
||||
const AMOVIESETUP_FILTER * m_pAMovieSetup_Filter;
|
||||
|
||||
BOOL IsClassID(REFCLSID rclsid) const {
|
||||
return (IsEqualCLSID(*m_ClsID,rclsid));
|
||||
};
|
||||
|
||||
CUnknown *CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout_opt HRESULT *phr) const {
|
||||
CheckPointer(phr,NULL);
|
||||
return m_lpfnNew(pUnk, phr);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/* You must override the (pure virtual) NonDelegatingQueryInterface to return
|
||||
interface pointers (using GetInterface) to the interfaces your derived
|
||||
class supports (the default implementation only supports IUnknown) */
|
||||
|
||||
#define DECLARE_IUNKNOWN \
|
||||
STDMETHODIMP QueryInterface(REFIID riid, __deref_out void **ppv) { \
|
||||
return GetOwner()->QueryInterface(riid,ppv); \
|
||||
}; \
|
||||
STDMETHODIMP_(ULONG) AddRef() { \
|
||||
return GetOwner()->AddRef(); \
|
||||
}; \
|
||||
STDMETHODIMP_(ULONG) Release() { \
|
||||
return GetOwner()->Release(); \
|
||||
};
|
||||
|
||||
|
||||
|
||||
HINSTANCE LoadOLEAut32();
|
||||
|
||||
|
||||
#endif /* __COMBASE__ */
|
||||
|
||||
|
||||
|
||||
|
||||
Vendored
-2541
File diff suppressed because it is too large
Load Diff
Vendored
-923
@@ -1,923 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: CtlUtil.h
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Base classes implementing IDispatch parsing for the basic control dual
|
||||
// interfaces. Derive from these and implement just the custom method and
|
||||
// property methods. We also implement CPosPassThru that can be used by
|
||||
// renderers and transforms to pass by IMediaPosition and IMediaSeeking
|
||||
|
||||
#ifndef __CTLUTIL__
|
||||
#define __CTLUTIL__
|
||||
|
||||
// OLE Automation has different ideas of TRUE and FALSE
|
||||
|
||||
#define OATRUE (-1)
|
||||
#define OAFALSE (0)
|
||||
|
||||
|
||||
// It's possible that we could replace this class with CreateStdDispatch
|
||||
|
||||
class CBaseDispatch
|
||||
{
|
||||
ITypeInfo * m_pti;
|
||||
|
||||
public:
|
||||
|
||||
CBaseDispatch() : m_pti(NULL) {}
|
||||
~CBaseDispatch();
|
||||
|
||||
/* IDispatch methods */
|
||||
STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
|
||||
|
||||
STDMETHODIMP GetTypeInfo(
|
||||
REFIID riid,
|
||||
UINT itinfo,
|
||||
LCID lcid,
|
||||
__deref_out ITypeInfo ** pptinfo);
|
||||
|
||||
STDMETHODIMP GetIDsOfNames(
|
||||
REFIID riid,
|
||||
__in_ecount(cNames) LPOLESTR * rgszNames,
|
||||
UINT cNames,
|
||||
LCID lcid,
|
||||
__out_ecount(cNames) DISPID * rgdispid);
|
||||
};
|
||||
|
||||
|
||||
class AM_NOVTABLE CMediaControl :
|
||||
public IMediaControl,
|
||||
public CUnknown
|
||||
{
|
||||
CBaseDispatch m_basedisp;
|
||||
|
||||
public:
|
||||
|
||||
CMediaControl(const TCHAR *, LPUNKNOWN);
|
||||
|
||||
DECLARE_IUNKNOWN
|
||||
|
||||
// override this to publicise our interfaces
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
|
||||
|
||||
/* IDispatch methods */
|
||||
STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
|
||||
|
||||
STDMETHODIMP GetTypeInfo(
|
||||
UINT itinfo,
|
||||
LCID lcid,
|
||||
__deref_out ITypeInfo ** pptinfo);
|
||||
|
||||
STDMETHODIMP GetIDsOfNames(
|
||||
REFIID riid,
|
||||
__in_ecount(cNames) LPOLESTR * rgszNames,
|
||||
UINT cNames,
|
||||
LCID lcid,
|
||||
__out_ecount(cNames) DISPID * rgdispid);
|
||||
|
||||
STDMETHODIMP Invoke(
|
||||
DISPID dispidMember,
|
||||
REFIID riid,
|
||||
LCID lcid,
|
||||
WORD wFlags,
|
||||
__in DISPPARAMS * pdispparams,
|
||||
__out_opt VARIANT * pvarResult,
|
||||
__out_opt EXCEPINFO * pexcepinfo,
|
||||
__out_opt UINT * puArgErr);
|
||||
};
|
||||
|
||||
|
||||
class AM_NOVTABLE CMediaEvent :
|
||||
public IMediaEventEx,
|
||||
public CUnknown
|
||||
{
|
||||
CBaseDispatch m_basedisp;
|
||||
|
||||
public:
|
||||
|
||||
CMediaEvent(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
|
||||
|
||||
DECLARE_IUNKNOWN
|
||||
|
||||
// override this to publicise our interfaces
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
|
||||
|
||||
/* IDispatch methods */
|
||||
STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
|
||||
|
||||
STDMETHODIMP GetTypeInfo(
|
||||
UINT itinfo,
|
||||
LCID lcid,
|
||||
__deref_out ITypeInfo ** pptinfo);
|
||||
|
||||
STDMETHODIMP GetIDsOfNames(
|
||||
REFIID riid,
|
||||
__in_ecount(cNames) LPOLESTR * rgszNames,
|
||||
UINT cNames,
|
||||
LCID lcid,
|
||||
__out_ecount(cNames) DISPID * rgdispid);
|
||||
|
||||
STDMETHODIMP Invoke(
|
||||
DISPID dispidMember,
|
||||
REFIID riid,
|
||||
LCID lcid,
|
||||
WORD wFlags,
|
||||
__in DISPPARAMS * pdispparams,
|
||||
__out_opt VARIANT * pvarResult,
|
||||
__out_opt EXCEPINFO * pexcepinfo,
|
||||
__out_opt UINT * puArgErr);
|
||||
};
|
||||
|
||||
|
||||
class AM_NOVTABLE CMediaPosition :
|
||||
public IMediaPosition,
|
||||
public CUnknown
|
||||
{
|
||||
CBaseDispatch m_basedisp;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
CMediaPosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
|
||||
CMediaPosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT *phr);
|
||||
|
||||
DECLARE_IUNKNOWN
|
||||
|
||||
// override this to publicise our interfaces
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
|
||||
|
||||
/* IDispatch methods */
|
||||
STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
|
||||
|
||||
STDMETHODIMP GetTypeInfo(
|
||||
UINT itinfo,
|
||||
LCID lcid,
|
||||
__deref_out ITypeInfo ** pptinfo);
|
||||
|
||||
STDMETHODIMP GetIDsOfNames(
|
||||
REFIID riid,
|
||||
__in_ecount(cNames) LPOLESTR * rgszNames,
|
||||
UINT cNames,
|
||||
LCID lcid,
|
||||
__out_ecount(cNames) DISPID * rgdispid);
|
||||
|
||||
STDMETHODIMP Invoke(
|
||||
DISPID dispidMember,
|
||||
REFIID riid,
|
||||
LCID lcid,
|
||||
WORD wFlags,
|
||||
__in DISPPARAMS * pdispparams,
|
||||
__out_opt VARIANT * pvarResult,
|
||||
__out_opt EXCEPINFO * pexcepinfo,
|
||||
__out_opt UINT * puArgErr);
|
||||
|
||||
};
|
||||
|
||||
|
||||
// OA-compatibility means that we must use double as the RefTime value,
|
||||
// and REFERENCE_TIME (essentially a LONGLONG) within filters.
|
||||
// this class converts between the two
|
||||
|
||||
class COARefTime : public CRefTime {
|
||||
public:
|
||||
|
||||
COARefTime() {
|
||||
};
|
||||
|
||||
COARefTime(CRefTime t)
|
||||
: CRefTime(t)
|
||||
{
|
||||
};
|
||||
|
||||
COARefTime(REFERENCE_TIME t)
|
||||
: CRefTime(t)
|
||||
{
|
||||
};
|
||||
|
||||
COARefTime(double d) {
|
||||
m_time = (LONGLONG) (d * 10000000);
|
||||
};
|
||||
|
||||
operator double() {
|
||||
return double(m_time) / 10000000;
|
||||
};
|
||||
|
||||
operator REFERENCE_TIME() {
|
||||
return m_time;
|
||||
};
|
||||
|
||||
COARefTime& operator=(const double& rd) {
|
||||
m_time = (LONGLONG) (rd * 10000000);
|
||||
return *this;
|
||||
}
|
||||
|
||||
COARefTime& operator=(const REFERENCE_TIME& rt) {
|
||||
m_time = rt;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline BOOL operator==(const COARefTime& rt)
|
||||
{
|
||||
return m_time == rt.m_time;
|
||||
};
|
||||
|
||||
inline BOOL operator!=(const COARefTime& rt)
|
||||
{
|
||||
return m_time != rt.m_time;
|
||||
};
|
||||
|
||||
inline BOOL operator < (const COARefTime& rt)
|
||||
{
|
||||
return m_time < rt.m_time;
|
||||
};
|
||||
|
||||
inline BOOL operator > (const COARefTime& rt)
|
||||
{
|
||||
return m_time > rt.m_time;
|
||||
};
|
||||
|
||||
inline BOOL operator >= (const COARefTime& rt)
|
||||
{
|
||||
return m_time >= rt.m_time;
|
||||
};
|
||||
|
||||
inline BOOL operator <= (const COARefTime& rt)
|
||||
{
|
||||
return m_time <= rt.m_time;
|
||||
};
|
||||
|
||||
inline COARefTime operator+(const COARefTime& rt)
|
||||
{
|
||||
return COARefTime(m_time + rt.m_time);
|
||||
};
|
||||
|
||||
inline COARefTime operator-(const COARefTime& rt)
|
||||
{
|
||||
return COARefTime(m_time - rt.m_time);
|
||||
};
|
||||
|
||||
inline COARefTime operator*(LONG l)
|
||||
{
|
||||
return COARefTime(m_time * l);
|
||||
};
|
||||
|
||||
inline COARefTime operator/(LONG l)
|
||||
{
|
||||
return COARefTime(m_time / l);
|
||||
};
|
||||
|
||||
private:
|
||||
// Prevent bugs from constructing from LONG (which gets
|
||||
// converted to double and then multiplied by 10000000
|
||||
COARefTime(LONG);
|
||||
LONG operator=(LONG);
|
||||
};
|
||||
|
||||
|
||||
// A utility class that handles IMediaPosition and IMediaSeeking on behalf
|
||||
// of single-input pin renderers, or transform filters.
|
||||
//
|
||||
// Renderers will expose this from the filter; transform filters will
|
||||
// expose it from the output pin and not the renderer.
|
||||
//
|
||||
// Create one of these, giving it your IPin* for your input pin, and delegate
|
||||
// all IMediaPosition methods to it. It will query the input pin for
|
||||
// IMediaPosition and respond appropriately.
|
||||
//
|
||||
// Call ForceRefresh if the pin connection changes.
|
||||
//
|
||||
// This class no longer caches the upstream IMediaPosition or IMediaSeeking
|
||||
// it acquires it on each method call. This means ForceRefresh is not needed.
|
||||
// The method is kept for source compatibility and to minimise the changes
|
||||
// if we need to put it back later for performance reasons.
|
||||
|
||||
class CPosPassThru : public IMediaSeeking, public CMediaPosition
|
||||
{
|
||||
IPin *m_pPin;
|
||||
|
||||
HRESULT GetPeer(__deref_out IMediaPosition **ppMP);
|
||||
HRESULT GetPeerSeeking(__deref_out IMediaSeeking **ppMS);
|
||||
|
||||
public:
|
||||
|
||||
CPosPassThru(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, IPin *);
|
||||
DECLARE_IUNKNOWN
|
||||
|
||||
HRESULT ForceRefresh() {
|
||||
return S_OK;
|
||||
};
|
||||
|
||||
// override to return an accurate current position
|
||||
virtual HRESULT GetMediaTime(__out LONGLONG *pStartTime, __out_opt LONGLONG *pEndTime) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out void **ppv);
|
||||
|
||||
// IMediaSeeking methods
|
||||
STDMETHODIMP GetCapabilities( __out DWORD * pCapabilities );
|
||||
STDMETHODIMP CheckCapabilities( __inout DWORD * pCapabilities );
|
||||
STDMETHODIMP SetTimeFormat(const GUID * pFormat);
|
||||
STDMETHODIMP GetTimeFormat(__out GUID *pFormat);
|
||||
STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
|
||||
STDMETHODIMP IsFormatSupported( const GUID * pFormat);
|
||||
STDMETHODIMP QueryPreferredFormat( __out GUID *pFormat);
|
||||
STDMETHODIMP ConvertTimeFormat(__out LONGLONG * pTarget,
|
||||
__in_opt const GUID * pTargetFormat,
|
||||
LONGLONG Source,
|
||||
__in_opt const GUID * pSourceFormat );
|
||||
STDMETHODIMP SetPositions( __inout_opt LONGLONG * pCurrent, DWORD CurrentFlags
|
||||
, __inout_opt LONGLONG * pStop, DWORD StopFlags );
|
||||
|
||||
STDMETHODIMP GetPositions( __out_opt LONGLONG * pCurrent, __out_opt LONGLONG * pStop );
|
||||
STDMETHODIMP GetCurrentPosition( __out LONGLONG * pCurrent );
|
||||
STDMETHODIMP GetStopPosition( __out LONGLONG * pStop );
|
||||
STDMETHODIMP SetRate( double dRate);
|
||||
STDMETHODIMP GetRate( __out double * pdRate);
|
||||
STDMETHODIMP GetDuration( __out LONGLONG *pDuration);
|
||||
STDMETHODIMP GetAvailable( __out_opt LONGLONG *pEarliest, __out_opt LONGLONG *pLatest );
|
||||
STDMETHODIMP GetPreroll( __out LONGLONG *pllPreroll );
|
||||
|
||||
// IMediaPosition properties
|
||||
STDMETHODIMP get_Duration(__out REFTIME * plength);
|
||||
STDMETHODIMP put_CurrentPosition(REFTIME llTime);
|
||||
STDMETHODIMP get_StopTime(__out REFTIME * pllTime);
|
||||
STDMETHODIMP put_StopTime(REFTIME llTime);
|
||||
STDMETHODIMP get_PrerollTime(__out REFTIME * pllTime);
|
||||
STDMETHODIMP put_PrerollTime(REFTIME llTime);
|
||||
STDMETHODIMP get_Rate(__out double * pdRate);
|
||||
STDMETHODIMP put_Rate(double dRate);
|
||||
STDMETHODIMP get_CurrentPosition(__out REFTIME * pllTime);
|
||||
STDMETHODIMP CanSeekForward(__out LONG *pCanSeekForward);
|
||||
STDMETHODIMP CanSeekBackward(__out LONG *pCanSeekBackward);
|
||||
|
||||
private:
|
||||
HRESULT GetSeekingLongLong( HRESULT (__stdcall IMediaSeeking::*pMethod)( LONGLONG * ),
|
||||
__out LONGLONG * pll );
|
||||
};
|
||||
|
||||
|
||||
// Adds the ability to return a current position
|
||||
|
||||
class CRendererPosPassThru : public CPosPassThru
|
||||
{
|
||||
CCritSec m_PositionLock; // Locks access to our position
|
||||
LONGLONG m_StartMedia; // Start media time last seen
|
||||
LONGLONG m_EndMedia; // And likewise the end media
|
||||
BOOL m_bReset; // Have media times been set
|
||||
|
||||
public:
|
||||
|
||||
// Used to help with passing media times through graph
|
||||
|
||||
CRendererPosPassThru(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, IPin *);
|
||||
HRESULT RegisterMediaTime(IMediaSample *pMediaSample);
|
||||
HRESULT RegisterMediaTime(LONGLONG StartTime,LONGLONG EndTime);
|
||||
HRESULT GetMediaTime(__out LONGLONG *pStartTime,__out_opt LONGLONG *pEndTime);
|
||||
HRESULT ResetMediaTime();
|
||||
HRESULT EOS();
|
||||
};
|
||||
|
||||
STDAPI CreatePosPassThru(
|
||||
__in_opt LPUNKNOWN pAgg,
|
||||
BOOL bRenderer,
|
||||
IPin *pPin,
|
||||
__deref_out IUnknown **ppPassThru
|
||||
);
|
||||
|
||||
// A class that handles the IDispatch part of IBasicAudio and leaves the
|
||||
// properties and methods themselves pure virtual.
|
||||
|
||||
class AM_NOVTABLE CBasicAudio : public IBasicAudio, public CUnknown
|
||||
{
|
||||
CBaseDispatch m_basedisp;
|
||||
|
||||
public:
|
||||
|
||||
CBasicAudio(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
|
||||
|
||||
DECLARE_IUNKNOWN
|
||||
|
||||
// override this to publicise our interfaces
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
|
||||
|
||||
/* IDispatch methods */
|
||||
STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
|
||||
|
||||
STDMETHODIMP GetTypeInfo(
|
||||
UINT itinfo,
|
||||
LCID lcid,
|
||||
__deref_out ITypeInfo ** pptinfo);
|
||||
|
||||
STDMETHODIMP GetIDsOfNames(
|
||||
REFIID riid,
|
||||
__in_ecount(cNames) LPOLESTR * rgszNames,
|
||||
UINT cNames,
|
||||
LCID lcid,
|
||||
__out_ecount(cNames) DISPID * rgdispid);
|
||||
|
||||
STDMETHODIMP Invoke(
|
||||
DISPID dispidMember,
|
||||
REFIID riid,
|
||||
LCID lcid,
|
||||
WORD wFlags,
|
||||
__in DISPPARAMS * pdispparams,
|
||||
__out_opt VARIANT * pvarResult,
|
||||
__out_opt EXCEPINFO * pexcepinfo,
|
||||
__out_opt UINT * puArgErr);
|
||||
};
|
||||
|
||||
|
||||
// A class that handles the IDispatch part of IBasicVideo and leaves the
|
||||
// properties and methods themselves pure virtual.
|
||||
|
||||
class AM_NOVTABLE CBaseBasicVideo : public IBasicVideo2, public CUnknown
|
||||
{
|
||||
CBaseDispatch m_basedisp;
|
||||
|
||||
public:
|
||||
|
||||
CBaseBasicVideo(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
|
||||
|
||||
DECLARE_IUNKNOWN
|
||||
|
||||
// override this to publicise our interfaces
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
|
||||
|
||||
/* IDispatch methods */
|
||||
STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
|
||||
|
||||
STDMETHODIMP GetTypeInfo(
|
||||
UINT itinfo,
|
||||
LCID lcid,
|
||||
__deref_out ITypeInfo ** pptinfo);
|
||||
|
||||
STDMETHODIMP GetIDsOfNames(
|
||||
REFIID riid,
|
||||
__in_ecount(cNames) LPOLESTR * rgszNames,
|
||||
UINT cNames,
|
||||
LCID lcid,
|
||||
__out_ecount(cNames) DISPID * rgdispid);
|
||||
|
||||
STDMETHODIMP Invoke(
|
||||
DISPID dispidMember,
|
||||
REFIID riid,
|
||||
LCID lcid,
|
||||
WORD wFlags,
|
||||
__in DISPPARAMS * pdispparams,
|
||||
__out_opt VARIANT * pvarResult,
|
||||
__out_opt EXCEPINFO * pexcepinfo,
|
||||
__out_opt UINT * puArgErr);
|
||||
|
||||
STDMETHODIMP GetPreferredAspectRatio(
|
||||
__out long *plAspectX,
|
||||
__out long *plAspectY)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// A class that handles the IDispatch part of IVideoWindow and leaves the
|
||||
// properties and methods themselves pure virtual.
|
||||
|
||||
class AM_NOVTABLE CBaseVideoWindow : public IVideoWindow, public CUnknown
|
||||
{
|
||||
CBaseDispatch m_basedisp;
|
||||
|
||||
public:
|
||||
|
||||
CBaseVideoWindow(__in_opt LPCTSTR, __in_opt LPUNKNOWN);
|
||||
|
||||
DECLARE_IUNKNOWN
|
||||
|
||||
// override this to publicise our interfaces
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
|
||||
|
||||
/* IDispatch methods */
|
||||
STDMETHODIMP GetTypeInfoCount(__out UINT * pctinfo);
|
||||
|
||||
STDMETHODIMP GetTypeInfo(
|
||||
UINT itinfo,
|
||||
LCID lcid,
|
||||
__deref_out ITypeInfo ** pptinfo);
|
||||
|
||||
STDMETHODIMP GetIDsOfNames(
|
||||
REFIID riid,
|
||||
__in_ecount(cNames) LPOLESTR * rgszNames,
|
||||
UINT cNames,
|
||||
LCID lcid,
|
||||
__out_ecount(cNames) DISPID * rgdispid);
|
||||
|
||||
STDMETHODIMP Invoke(
|
||||
DISPID dispidMember,
|
||||
REFIID riid,
|
||||
LCID lcid,
|
||||
WORD wFlags,
|
||||
__in DISPPARAMS * pdispparams,
|
||||
__out_opt VARIANT * pvarResult,
|
||||
__out_opt EXCEPINFO * pexcepinfo,
|
||||
__out_opt UINT * puArgErr);
|
||||
};
|
||||
|
||||
|
||||
// abstract class to help source filters with their implementation
|
||||
// of IMediaPosition. Derive from this and set the duration (and stop
|
||||
// position). Also override NotifyChange to do something when the properties
|
||||
// change.
|
||||
|
||||
class AM_NOVTABLE CSourcePosition : public CMediaPosition
|
||||
{
|
||||
|
||||
public:
|
||||
CSourcePosition(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, __in CCritSec *);
|
||||
|
||||
// IMediaPosition methods
|
||||
STDMETHODIMP get_Duration(__out REFTIME * plength);
|
||||
STDMETHODIMP put_CurrentPosition(REFTIME llTime);
|
||||
STDMETHODIMP get_StopTime(__out REFTIME * pllTime);
|
||||
STDMETHODIMP put_StopTime(REFTIME llTime);
|
||||
STDMETHODIMP get_PrerollTime(__out REFTIME * pllTime);
|
||||
STDMETHODIMP put_PrerollTime(REFTIME llTime);
|
||||
STDMETHODIMP get_Rate(__out double * pdRate);
|
||||
STDMETHODIMP put_Rate(double dRate);
|
||||
STDMETHODIMP CanSeekForward(__out LONG *pCanSeekForward);
|
||||
STDMETHODIMP CanSeekBackward(__out LONG *pCanSeekBackward);
|
||||
|
||||
// override if you can return the data you are actually working on
|
||||
STDMETHODIMP get_CurrentPosition(__out REFTIME * pllTime) {
|
||||
return E_NOTIMPL;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
// we call this to notify changes. Override to handle them
|
||||
virtual HRESULT ChangeStart() PURE;
|
||||
virtual HRESULT ChangeStop() PURE;
|
||||
virtual HRESULT ChangeRate() PURE;
|
||||
|
||||
COARefTime m_Duration;
|
||||
COARefTime m_Start;
|
||||
COARefTime m_Stop;
|
||||
double m_Rate;
|
||||
|
||||
CCritSec * m_pLock;
|
||||
};
|
||||
|
||||
class AM_NOVTABLE CSourceSeeking :
|
||||
public IMediaSeeking,
|
||||
public CUnknown
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
DECLARE_IUNKNOWN;
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv);
|
||||
|
||||
// IMediaSeeking methods
|
||||
|
||||
STDMETHODIMP IsFormatSupported(const GUID * pFormat);
|
||||
STDMETHODIMP QueryPreferredFormat(__out GUID *pFormat);
|
||||
STDMETHODIMP SetTimeFormat(const GUID * pFormat);
|
||||
STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
|
||||
STDMETHODIMP GetTimeFormat(__out GUID *pFormat);
|
||||
STDMETHODIMP GetDuration(__out LONGLONG *pDuration);
|
||||
STDMETHODIMP GetStopPosition(__out LONGLONG *pStop);
|
||||
STDMETHODIMP GetCurrentPosition(__out LONGLONG *pCurrent);
|
||||
STDMETHODIMP GetCapabilities( __out DWORD * pCapabilities );
|
||||
STDMETHODIMP CheckCapabilities( __inout DWORD * pCapabilities );
|
||||
STDMETHODIMP ConvertTimeFormat( __out LONGLONG * pTarget,
|
||||
__in_opt const GUID * pTargetFormat,
|
||||
LONGLONG Source,
|
||||
__in_opt const GUID * pSourceFormat );
|
||||
|
||||
STDMETHODIMP SetPositions( __inout_opt LONGLONG * pCurrent, DWORD CurrentFlags
|
||||
, __inout_opt LONGLONG * pStop, DWORD StopFlags );
|
||||
|
||||
STDMETHODIMP GetPositions( __out_opt LONGLONG * pCurrent, __out_opt LONGLONG * pStop );
|
||||
|
||||
STDMETHODIMP GetAvailable( __out_opt LONGLONG * pEarliest, __out_opt LONGLONG * pLatest );
|
||||
STDMETHODIMP SetRate( double dRate);
|
||||
STDMETHODIMP GetRate( __out double * pdRate);
|
||||
STDMETHODIMP GetPreroll(__out LONGLONG *pPreroll);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// ctor
|
||||
CSourceSeeking(__in_opt LPCTSTR, __in_opt LPUNKNOWN, __inout HRESULT*, __in CCritSec *);
|
||||
|
||||
// we call this to notify changes. Override to handle them
|
||||
virtual HRESULT ChangeStart() PURE;
|
||||
virtual HRESULT ChangeStop() PURE;
|
||||
virtual HRESULT ChangeRate() PURE;
|
||||
|
||||
CRefTime m_rtDuration; // length of stream
|
||||
CRefTime m_rtStart; // source will start here
|
||||
CRefTime m_rtStop; // source will stop here
|
||||
double m_dRateSeeking;
|
||||
|
||||
// seeking capabilities
|
||||
DWORD m_dwSeekingCaps;
|
||||
|
||||
CCritSec * m_pLock;
|
||||
};
|
||||
|
||||
|
||||
// Base classes supporting Deferred commands.
|
||||
|
||||
// Deferred commands are queued by calls to methods on the IQueueCommand
|
||||
// interface, exposed by the filtergraph and by some filters. A successful
|
||||
// call to one of these methods will return an IDeferredCommand interface
|
||||
// representing the queued command.
|
||||
//
|
||||
// A CDeferredCommand object represents a single deferred command, and exposes
|
||||
// the IDeferredCommand interface as well as other methods permitting time
|
||||
// checks and actual execution. It contains a reference to the CCommandQueue
|
||||
// object on which it is queued.
|
||||
//
|
||||
// CCommandQueue is a base class providing a queue of CDeferredCommand
|
||||
// objects, and methods to add, remove, check status and invoke the queued
|
||||
// commands. A CCommandQueue object would be part of an object that
|
||||
// implemented IQueueCommand.
|
||||
|
||||
class CCmdQueue;
|
||||
|
||||
// take a copy of the params and store them. Release any allocated
|
||||
// memory in destructor
|
||||
|
||||
class CDispParams : public DISPPARAMS
|
||||
{
|
||||
public:
|
||||
CDispParams(UINT nArgs, __in_ecount(nArgs) VARIANT* pArgs, __inout_opt HRESULT *phr = NULL);
|
||||
~CDispParams();
|
||||
};
|
||||
|
||||
|
||||
// CDeferredCommand lifetime is controlled by refcounts. Caller of
|
||||
// InvokeAt.. gets a refcounted interface pointer, and the CCmdQueue
|
||||
// object also holds a refcount on us. Calling Cancel or Invoke takes
|
||||
// us off the CCmdQueue and thus reduces the refcount by 1. Once taken
|
||||
// off the queue we cannot be put back on the queue.
|
||||
|
||||
class CDeferredCommand
|
||||
: public CUnknown,
|
||||
public IDeferredCommand
|
||||
{
|
||||
public:
|
||||
|
||||
CDeferredCommand(
|
||||
__inout CCmdQueue * pQ,
|
||||
__in_opt LPUNKNOWN pUnk, // aggregation outer unk
|
||||
__inout HRESULT * phr,
|
||||
__in LPUNKNOWN pUnkExecutor, // object that will execute this cmd
|
||||
REFTIME time,
|
||||
__in GUID* iid,
|
||||
long dispidMethod,
|
||||
short wFlags,
|
||||
long cArgs,
|
||||
__in_ecount(cArgs) VARIANT* pDispParams,
|
||||
__out VARIANT* pvarResult,
|
||||
__out short* puArgErr,
|
||||
BOOL bStream
|
||||
);
|
||||
|
||||
DECLARE_IUNKNOWN
|
||||
|
||||
// override this to publicise our interfaces
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __out void **ppv);
|
||||
|
||||
// IDeferredCommand methods
|
||||
STDMETHODIMP Cancel();
|
||||
STDMETHODIMP Confidence(
|
||||
__out LONG* pConfidence);
|
||||
STDMETHODIMP Postpone(
|
||||
REFTIME newtime);
|
||||
STDMETHODIMP GetHResult(
|
||||
__out HRESULT* phrResult);
|
||||
|
||||
// other public methods
|
||||
|
||||
HRESULT Invoke();
|
||||
|
||||
// access methods
|
||||
|
||||
// returns TRUE if streamtime, FALSE if presentation time
|
||||
BOOL IsStreamTime() {
|
||||
return m_bStream;
|
||||
};
|
||||
|
||||
CRefTime GetTime() {
|
||||
return m_time;
|
||||
};
|
||||
|
||||
REFIID GetIID() {
|
||||
return *m_iid;
|
||||
};
|
||||
|
||||
long GetMethod() {
|
||||
return m_dispidMethod;
|
||||
};
|
||||
|
||||
short GetFlags() {
|
||||
return m_wFlags;
|
||||
};
|
||||
|
||||
DISPPARAMS* GetParams() {
|
||||
return &m_DispParams;
|
||||
};
|
||||
|
||||
VARIANT* GetResult() {
|
||||
return m_pvarResult;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
CCmdQueue* m_pQueue;
|
||||
|
||||
// pUnk for the interface that we will execute the command on
|
||||
LPUNKNOWN m_pUnk;
|
||||
|
||||
// stored command data
|
||||
REFERENCE_TIME m_time;
|
||||
GUID* m_iid;
|
||||
long m_dispidMethod;
|
||||
short m_wFlags;
|
||||
VARIANT* m_pvarResult;
|
||||
BOOL m_bStream;
|
||||
CDispParams m_DispParams;
|
||||
DISPID m_DispId; // For get and put
|
||||
|
||||
// we use this for ITypeInfo access
|
||||
CBaseDispatch m_Dispatch;
|
||||
|
||||
// save retval here
|
||||
HRESULT m_hrResult;
|
||||
};
|
||||
|
||||
|
||||
// a list of CDeferredCommand objects. this is a base class providing
|
||||
// the basics of access to the list. If you want to use CDeferredCommand
|
||||
// objects then your queue needs to be derived from this class.
|
||||
|
||||
class AM_NOVTABLE CCmdQueue
|
||||
{
|
||||
public:
|
||||
CCmdQueue(__inout_opt HRESULT *phr = NULL);
|
||||
virtual ~CCmdQueue();
|
||||
|
||||
// returns a new CDeferredCommand object that will be initialised with
|
||||
// the parameters and will be added to the queue during construction.
|
||||
// returns S_OK if successfully created otherwise an error and
|
||||
// no object has been queued.
|
||||
virtual HRESULT New(
|
||||
__out CDeferredCommand **ppCmd,
|
||||
__in LPUNKNOWN pUnk,
|
||||
REFTIME time,
|
||||
__in GUID* iid,
|
||||
long dispidMethod,
|
||||
short wFlags,
|
||||
long cArgs,
|
||||
__in_ecount(cArgs) VARIANT* pDispParams,
|
||||
__out VARIANT* pvarResult,
|
||||
__out short* puArgErr,
|
||||
BOOL bStream
|
||||
);
|
||||
|
||||
// called by the CDeferredCommand object to add and remove itself
|
||||
// from the queue
|
||||
virtual HRESULT Insert(__in CDeferredCommand* pCmd);
|
||||
virtual HRESULT Remove(__in CDeferredCommand* pCmd);
|
||||
|
||||
// Command-Due Checking
|
||||
//
|
||||
// There are two schemes of synchronisation: coarse and accurate. In
|
||||
// coarse mode, you wait till the time arrives and then execute the cmd.
|
||||
// In accurate mode, you wait until you are processing the sample that
|
||||
// will appear at the time, and then execute the command. It's up to the
|
||||
// filter which one it will implement. The filtergraph will always
|
||||
// implement coarse mode for commands queued at the filtergraph.
|
||||
//
|
||||
// If you want coarse sync, you probably want to wait until there is a
|
||||
// command due, and then execute it. You can do this by calling
|
||||
// GetDueCommand. If you have several things to wait for, get the
|
||||
// event handle from GetDueHandle() and when this is signalled then call
|
||||
// GetDueCommand. Stream time will only advance between calls to Run and
|
||||
// EndRun. Note that to avoid an extra thread there is no guarantee that
|
||||
// if the handle is set there will be a command ready. Each time the
|
||||
// event is signalled, call GetDueCommand (probably with a 0 timeout);
|
||||
// This may return E_ABORT.
|
||||
//
|
||||
// If you want accurate sync, you must call GetCommandDueFor, passing
|
||||
// as a parameter the stream time of the samples you are about to process.
|
||||
// This will return:
|
||||
// -- a stream-time command due at or before that stream time
|
||||
// -- a presentation-time command due at or before the
|
||||
// time that stream time will be presented (only between Run
|
||||
// and EndRun calls, since outside of this, the mapping from
|
||||
// stream time to presentation time is not known.
|
||||
// -- any presentation-time command due now.
|
||||
// This means that if you want accurate synchronisation on samples that
|
||||
// might be processed during Paused mode, you need to use
|
||||
// stream-time commands.
|
||||
//
|
||||
// In all cases, commands remain queued until Invoked or Cancelled. The
|
||||
// setting and resetting of the event handle is managed entirely by this
|
||||
// queue object.
|
||||
|
||||
// set the clock used for timing
|
||||
virtual HRESULT SetSyncSource(__in_opt IReferenceClock*);
|
||||
|
||||
// switch to run mode. Streamtime to Presentation time mapping known.
|
||||
virtual HRESULT Run(REFERENCE_TIME tStreamTimeOffset);
|
||||
|
||||
// switch to Stopped or Paused mode. Time mapping not known.
|
||||
virtual HRESULT EndRun();
|
||||
|
||||
// return a pointer to the next due command. Blocks for msTimeout
|
||||
// milliseconds until there is a due command.
|
||||
// Stream-time commands will only become due between Run and Endrun calls.
|
||||
// The command remains queued until invoked or cancelled.
|
||||
// Returns E_ABORT if timeout occurs, otherwise S_OK (or other error).
|
||||
// Returns an AddRef-ed object
|
||||
virtual HRESULT GetDueCommand(__out CDeferredCommand ** ppCmd, long msTimeout);
|
||||
|
||||
// return the event handle that will be signalled whenever
|
||||
// there are deferred commands due for execution (when GetDueCommand
|
||||
// will not block).
|
||||
HANDLE GetDueHandle() {
|
||||
return HANDLE(m_evDue);
|
||||
};
|
||||
|
||||
// return a pointer to a command that will be due for a given time.
|
||||
// Pass in a stream time here. The stream time offset will be passed
|
||||
// in via the Run method.
|
||||
// Commands remain queued until invoked or cancelled.
|
||||
// This method will not block. It will report VFW_E_NOT_FOUND if there
|
||||
// are no commands due yet.
|
||||
// Returns an AddRef-ed object
|
||||
virtual HRESULT GetCommandDueFor(REFERENCE_TIME tStream, __out CDeferredCommand**ppCmd);
|
||||
|
||||
// check if a given time is due (TRUE if it is due yet)
|
||||
BOOL CheckTime(CRefTime time, BOOL bStream) {
|
||||
|
||||
// if no clock, nothing is due!
|
||||
if (!m_pClock) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// stream time
|
||||
if (bStream) {
|
||||
|
||||
// not valid if not running
|
||||
if (!m_bRunning) {
|
||||
return FALSE;
|
||||
}
|
||||
// add on known stream time offset to get presentation time
|
||||
time += m_StreamTimeOffset;
|
||||
}
|
||||
|
||||
CRefTime Now;
|
||||
m_pClock->GetTime((REFERENCE_TIME*)&Now);
|
||||
return (time <= Now);
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
// protect access to lists etc
|
||||
CCritSec m_Lock;
|
||||
|
||||
// commands queued in presentation time are stored here
|
||||
CGenericList<CDeferredCommand> m_listPresentation;
|
||||
|
||||
// commands queued in stream time are stored here
|
||||
CGenericList<CDeferredCommand> m_listStream;
|
||||
|
||||
// set when any commands are due
|
||||
CAMEvent m_evDue;
|
||||
|
||||
// creates an advise for the earliest time required, if any
|
||||
void SetTimeAdvise(void);
|
||||
|
||||
// advise id from reference clock (0 if no outstanding advise)
|
||||
DWORD_PTR m_dwAdvise;
|
||||
|
||||
// advise time is for this presentation time
|
||||
CRefTime m_tCurrentAdvise;
|
||||
|
||||
// the reference clock we are using (addrefed)
|
||||
IReferenceClock* m_pClock;
|
||||
|
||||
// true when running
|
||||
BOOL m_bRunning;
|
||||
|
||||
// contains stream time offset when m_bRunning is true
|
||||
CRefTime m_StreamTimeOffset;
|
||||
};
|
||||
|
||||
#endif // __CTLUTIL__
|
||||
Vendored
-129
@@ -1,129 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: DDMM.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes - implements routines for using DirectDraw
|
||||
// on a multimonitor system.
|
||||
//
|
||||
// Copyright (c) 1995-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
#include <ddraw.h>
|
||||
#include "ddmm.h"
|
||||
|
||||
/*
|
||||
* FindDeviceCallback
|
||||
*/
|
||||
typedef struct {
|
||||
LPSTR szDevice;
|
||||
GUID* lpGUID;
|
||||
GUID GUID;
|
||||
BOOL fFound;
|
||||
} FindDeviceData;
|
||||
|
||||
BOOL CALLBACK FindDeviceCallback(__in_opt GUID* lpGUID, __in LPSTR szName, __in LPSTR szDevice, __in LPVOID lParam)
|
||||
{
|
||||
FindDeviceData *p = (FindDeviceData*)lParam;
|
||||
|
||||
if (lstrcmpiA(p->szDevice, szDevice) == 0) {
|
||||
if (lpGUID) {
|
||||
p->GUID = *lpGUID;
|
||||
p->lpGUID = &p->GUID;
|
||||
} else {
|
||||
p->lpGUID = NULL;
|
||||
}
|
||||
p->fFound = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
BOOL CALLBACK FindDeviceCallbackEx(__in_opt GUID* lpGUID, __in LPSTR szName, __in LPSTR szDevice, __in LPVOID lParam, HMONITOR hMonitor)
|
||||
{
|
||||
FindDeviceData *p = (FindDeviceData*)lParam;
|
||||
|
||||
if (lstrcmpiA(p->szDevice, szDevice) == 0) {
|
||||
if (lpGUID) {
|
||||
p->GUID = *lpGUID;
|
||||
p->lpGUID = &p->GUID;
|
||||
} else {
|
||||
p->lpGUID = NULL;
|
||||
}
|
||||
p->fFound = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DirectDrawCreateFromDevice
|
||||
*
|
||||
* create a DirectDraw object for a particular device
|
||||
*/
|
||||
IDirectDraw * DirectDrawCreateFromDevice(__in_opt LPSTR szDevice, PDRAWCREATE DirectDrawCreateP, PDRAWENUM DirectDrawEnumerateP)
|
||||
{
|
||||
IDirectDraw* pdd = NULL;
|
||||
FindDeviceData find;
|
||||
|
||||
if (szDevice == NULL) {
|
||||
DirectDrawCreateP(NULL, &pdd, NULL);
|
||||
return pdd;
|
||||
}
|
||||
|
||||
find.szDevice = szDevice;
|
||||
find.fFound = FALSE;
|
||||
DirectDrawEnumerateP(FindDeviceCallback, (LPVOID)&find);
|
||||
|
||||
if (find.fFound)
|
||||
{
|
||||
//
|
||||
// In 4bpp mode the following DDraw call causes a message box to be popped
|
||||
// up by DDraw (!?!). It's DDraw's fault, but we don't like it. So we
|
||||
// make sure it doesn't happen.
|
||||
//
|
||||
UINT ErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
DirectDrawCreateP(find.lpGUID, &pdd, NULL);
|
||||
SetErrorMode(ErrorMode);
|
||||
}
|
||||
|
||||
return pdd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DirectDrawCreateFromDeviceEx
|
||||
*
|
||||
* create a DirectDraw object for a particular device
|
||||
*/
|
||||
IDirectDraw * DirectDrawCreateFromDeviceEx(__in_opt LPSTR szDevice, PDRAWCREATE DirectDrawCreateP, LPDIRECTDRAWENUMERATEEXA DirectDrawEnumerateExP)
|
||||
{
|
||||
IDirectDraw* pdd = NULL;
|
||||
FindDeviceData find;
|
||||
|
||||
if (szDevice == NULL) {
|
||||
DirectDrawCreateP(NULL, &pdd, NULL);
|
||||
return pdd;
|
||||
}
|
||||
|
||||
find.szDevice = szDevice;
|
||||
find.fFound = FALSE;
|
||||
DirectDrawEnumerateExP(FindDeviceCallbackEx, (LPVOID)&find,
|
||||
DDENUM_ATTACHEDSECONDARYDEVICES);
|
||||
|
||||
if (find.fFound)
|
||||
{
|
||||
//
|
||||
// In 4bpp mode the following DDraw call causes a message box to be popped
|
||||
// up by DDraw (!?!). It's DDraw's fault, but we don't like it. So we
|
||||
// make sure it doesn't happen.
|
||||
//
|
||||
UINT ErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
DirectDrawCreateP(find.lpGUID, &pdd, NULL);
|
||||
SetErrorMode(ErrorMode);
|
||||
}
|
||||
|
||||
return pdd;
|
||||
}
|
||||
Vendored
-28
@@ -1,28 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: DDMM.h
|
||||
//
|
||||
// Desc: DirectShow base classes - efines routines for using DirectDraw
|
||||
// on a multimonitor system.
|
||||
//
|
||||
// Copyright (c) 1995-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" { /* Assume C declarations for C++ */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
// DDRAW.H might not include these
|
||||
#ifndef DDENUM_ATTACHEDSECONDARYDEVICES
|
||||
#define DDENUM_ATTACHEDSECONDARYDEVICES 0x00000001L
|
||||
#endif
|
||||
|
||||
typedef HRESULT (*PDRAWCREATE)(IID *,LPDIRECTDRAW *,LPUNKNOWN);
|
||||
typedef HRESULT (*PDRAWENUM)(LPDDENUMCALLBACKA, LPVOID);
|
||||
|
||||
IDirectDraw * DirectDrawCreateFromDevice(__in_opt LPSTR, PDRAWCREATE, PDRAWENUM);
|
||||
IDirectDraw * DirectDrawCreateFromDeviceEx(__in_opt LPSTR, PDRAWCREATE, LPDIRECTDRAWENUMERATEEXA);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
Vendored
-101
@@ -1,101 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: FourCC.h
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// FOURCCMap
|
||||
//
|
||||
// provides a mapping between old-style multimedia format DWORDs
|
||||
// and new-style GUIDs.
|
||||
//
|
||||
// A range of 4 billion GUIDs has been allocated to ensure that this
|
||||
// mapping can be done straightforwardly one-to-one in both directions.
|
||||
//
|
||||
// January 95
|
||||
|
||||
|
||||
#ifndef __FOURCC__
|
||||
#define __FOURCC__
|
||||
|
||||
|
||||
// Multimedia format types are marked with DWORDs built from four 8-bit
|
||||
// chars and known as FOURCCs. New multimedia AM_MEDIA_TYPE definitions include
|
||||
// a subtype GUID. In order to simplify the mapping, GUIDs in the range:
|
||||
// XXXXXXXX-0000-0010-8000-00AA00389B71
|
||||
// are reserved for FOURCCs.
|
||||
|
||||
class FOURCCMap : public GUID
|
||||
{
|
||||
|
||||
public:
|
||||
FOURCCMap();
|
||||
FOURCCMap(DWORD Fourcc);
|
||||
FOURCCMap(const GUID *);
|
||||
|
||||
|
||||
DWORD GetFOURCC(void);
|
||||
void SetFOURCC(DWORD fourcc);
|
||||
void SetFOURCC(const GUID *);
|
||||
|
||||
private:
|
||||
void InitGUID();
|
||||
};
|
||||
|
||||
#define GUID_Data2 0
|
||||
#define GUID_Data3 0x10
|
||||
#define GUID_Data4_1 0xaa000080
|
||||
#define GUID_Data4_2 0x719b3800
|
||||
|
||||
inline void
|
||||
FOURCCMap::InitGUID() {
|
||||
Data2 = GUID_Data2;
|
||||
Data3 = GUID_Data3;
|
||||
((DWORD *)Data4)[0] = GUID_Data4_1;
|
||||
((DWORD *)Data4)[1] = GUID_Data4_2;
|
||||
}
|
||||
|
||||
inline
|
||||
FOURCCMap::FOURCCMap() {
|
||||
InitGUID();
|
||||
SetFOURCC( DWORD(0));
|
||||
}
|
||||
|
||||
inline
|
||||
FOURCCMap::FOURCCMap(DWORD fourcc)
|
||||
{
|
||||
InitGUID();
|
||||
SetFOURCC(fourcc);
|
||||
}
|
||||
|
||||
inline
|
||||
FOURCCMap::FOURCCMap(const GUID * pGuid)
|
||||
{
|
||||
InitGUID();
|
||||
SetFOURCC(pGuid);
|
||||
}
|
||||
|
||||
inline void
|
||||
FOURCCMap::SetFOURCC(const GUID * pGuid)
|
||||
{
|
||||
FOURCCMap * p = (FOURCCMap*) pGuid;
|
||||
SetFOURCC(p->GetFOURCC());
|
||||
}
|
||||
|
||||
inline void
|
||||
FOURCCMap::SetFOURCC(DWORD fourcc)
|
||||
{
|
||||
Data1 = fourcc;
|
||||
}
|
||||
|
||||
inline DWORD
|
||||
FOURCCMap::GetFOURCC(void)
|
||||
{
|
||||
return Data1;
|
||||
}
|
||||
|
||||
#endif /* __FOURCC__ */
|
||||
|
||||
Vendored
-222
@@ -1,222 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: Measure.h
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
/*
|
||||
The idea is to pepper the source code with interesting measurements and
|
||||
have the last few thousand of these recorded in a circular buffer that
|
||||
can be post-processed to give interesting numbers.
|
||||
|
||||
WHAT THE LOG LOOKS LIKE:
|
||||
|
||||
Time (sec) Type Delta Incident_Name
|
||||
0.055,41 NOTE -. Incident Nine - Another note
|
||||
0.055,42 NOTE 0.000,01 Incident Nine - Another note
|
||||
0.055,44 NOTE 0.000,02 Incident Nine - Another note
|
||||
0.055,45 STOP -. Incident Eight - Also random
|
||||
0.055,47 START -. Incident Seven - Random
|
||||
0.055,49 NOTE 0.000,05 Incident Nine - Another note
|
||||
------- <etc. there is a lot of this> ----------------
|
||||
0.125,60 STOP 0.000,03 Msr_Stop
|
||||
0.125,62 START -. Msr_Start
|
||||
0.125,63 START -. Incident Two - Start/Stop
|
||||
0.125,65 STOP 0.000,03 Msr_Start
|
||||
0.125,66 START -. Msr_Stop
|
||||
0.125,68 STOP 0.000,05 Incident Two - Start/Stop
|
||||
0.125,70 STOP 0.000,04 Msr_Stop
|
||||
0.125,72 START -. Msr_Start
|
||||
0.125,73 START -. Incident Two - Start/Stop
|
||||
0.125,75 STOP 0.000,03 Msr_Start
|
||||
0.125,77 START -. Msr_Stop
|
||||
0.125,78 STOP 0.000,05 Incident Two - Start/Stop
|
||||
0.125,80 STOP 0.000,03 Msr_Stop
|
||||
0.125,81 NOTE -. Incident Three - single Note
|
||||
0.125,83 START -. Incident Four - Start, no stop
|
||||
0.125,85 START -. Incident Five - Single Start/Stop
|
||||
0.125,87 STOP 0.000,02 Incident Five - Single Start/Stop
|
||||
|
||||
Number Average StdDev Smallest Largest Incident_Name
|
||||
10 0.000,58 0.000,10 0.000,55 0.000,85 Incident One - Note
|
||||
50 0.000,05 0.000,00 0.000,05 0.000,05 Incident Two - Start/Stop
|
||||
1 -. -. -. -. Incident Three - single Note
|
||||
0 -. -. -. -. Incident Four - Start, no stop
|
||||
1 0.000,02 -. 0.000,02 0.000,02 Incident Five - Single Start/Stop
|
||||
0 -. -. -. -. Incident Six - zero occurrences
|
||||
100 0.000,25 0.000,12 0.000,02 0.000,62 Incident Seven - Random
|
||||
100 0.000,79 0.000,48 0.000,02 0.001,92 Incident Eight - Also random
|
||||
5895 0.000,01 0.000,01 0.000,01 0.000,56 Incident Nine - Another note
|
||||
10 0.000,03 0.000,00 0.000,03 0.000,04 Msr_Note
|
||||
50 0.000,03 0.000,00 0.000,03 0.000,04 Msr_Start
|
||||
50 0.000,04 0.000,03 0.000,03 0.000,31 Msr_Stop
|
||||
|
||||
WHAT IT MEANS:
|
||||
The log shows what happened and when. Each line shows the time at which
|
||||
something happened (see WHAT YOU CODE below) what it was that happened
|
||||
and (if approporate) the time since the corresponding previous event
|
||||
(that's the delta column).
|
||||
|
||||
The statistics show how many times each event occurred, what the average
|
||||
delta time was, also the standard deviation, largest and smalles delta.
|
||||
|
||||
WHAT YOU CODE:
|
||||
|
||||
Before anything else executes: - register your ids
|
||||
|
||||
int id1 = Msr_Register("Incident One - Note");
|
||||
int id2 = Msr_Register("Incident Two - Start/Stop");
|
||||
int id3 = Msr_Register("Incident Three - single Note");
|
||||
etc.
|
||||
|
||||
At interesting moments:
|
||||
|
||||
// To measure a repetitive event - e.g. end of bitblt to screen
|
||||
Msr_Note(Id9); // e.g. "video frame hiting the screen NOW!"
|
||||
|
||||
or
|
||||
|
||||
// To measure an elapsed time e.g. time taken to decode an MPEG B-frame
|
||||
Msr_Start(Id2); // e.g. "Starting to decode MPEG B-frame"
|
||||
. . .
|
||||
MsrStop(Id2); // "Finished MPEG decode"
|
||||
|
||||
At the end:
|
||||
|
||||
HANDLE hFile;
|
||||
hFile = CreateFile("Perf.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
Msr_Dump(hFile); // This writes the log out to the file
|
||||
CloseHandle(hFile);
|
||||
|
||||
or
|
||||
|
||||
Msr_Dump(NULL); // This writes it to DbgLog((LOG_TRACE,0, ... ));
|
||||
// but if you are writing it out to the debugger
|
||||
// then the times are probably all garbage because
|
||||
// the debugger can make things run awfully slow.
|
||||
|
||||
A given id should be used either for start / stop or Note calls. If Notes
|
||||
are mixed in with Starts and Stops their statistics will be gibberish.
|
||||
|
||||
If you code the calls in upper case i.e. MSR_START(idMunge); then you get
|
||||
macros which will turn into nothing unless PERF is defined.
|
||||
|
||||
You can reset the statistical counts for a given id by calling Reset(Id).
|
||||
They are reset by default at the start.
|
||||
It logs Reset as a special incident, so you can see it in the log.
|
||||
|
||||
The log is a circular buffer in storage (to try to minimise disk I/O).
|
||||
It overwrites the oldest entries once full. The statistics include ALL
|
||||
incidents since the last Reset, whether still visible in the log or not.
|
||||
*/
|
||||
|
||||
#ifndef __MEASURE__
|
||||
#define __MEASURE__
|
||||
|
||||
#ifdef PERF
|
||||
#define MSR_INIT() Msr_Init()
|
||||
#define MSR_TERMINATE() Msr_Terminate()
|
||||
#define MSR_REGISTER(a) Msr_Register(a)
|
||||
#define MSR_RESET(a) Msr_Reset(a)
|
||||
#define MSR_CONTROL(a) Msr_Control(a)
|
||||
#define MSR_START(a) Msr_Start(a)
|
||||
#define MSR_STOP(a) Msr_Stop(a)
|
||||
#define MSR_NOTE(a) Msr_Note(a)
|
||||
#define MSR_INTEGER(a,b) Msr_Integer(a,b)
|
||||
#define MSR_DUMP(a) Msr_Dump(a)
|
||||
#define MSR_DUMPSTATS(a) Msr_DumpStats(a)
|
||||
#else
|
||||
#define MSR_INIT() ((void)0)
|
||||
#define MSR_TERMINATE() ((void)0)
|
||||
#define MSR_REGISTER(a) 0
|
||||
#define MSR_RESET(a) ((void)0)
|
||||
#define MSR_CONTROL(a) ((void)0)
|
||||
#define MSR_START(a) ((void)0)
|
||||
#define MSR_STOP(a) ((void)0)
|
||||
#define MSR_NOTE(a) ((void)0)
|
||||
#define MSR_INTEGER(a,b) ((void)0)
|
||||
#define MSR_DUMP(a) ((void)0)
|
||||
#define MSR_DUMPSTATS(a) ((void)0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// This must be called first - (called by the DllEntry)
|
||||
|
||||
void WINAPI Msr_Init(void);
|
||||
|
||||
|
||||
// Call this last to clean up (or just let it fall off the end - who cares?)
|
||||
|
||||
void WINAPI Msr_Terminate(void);
|
||||
|
||||
|
||||
// Call this to get an Id for an "incident" that you can pass to Start, Stop or Note
|
||||
// everything that's logged is called an "incident".
|
||||
|
||||
int WINAPI Msr_Register(__in LPTSTR Incident);
|
||||
|
||||
|
||||
// Reset the statistical counts for an incident
|
||||
|
||||
void WINAPI Msr_Reset(int Id);
|
||||
|
||||
|
||||
// Reset all the counts for all incidents
|
||||
#define MSR_RESET_ALL 0
|
||||
#define MSR_PAUSE 1
|
||||
#define MSR_RUN 2
|
||||
|
||||
void WINAPI Msr_Control(int iAction);
|
||||
|
||||
|
||||
// log the start of an operation
|
||||
|
||||
void WINAPI Msr_Start(int Id);
|
||||
|
||||
|
||||
// log the end of an operation
|
||||
|
||||
void WINAPI Msr_Stop(int Id);
|
||||
|
||||
|
||||
// log a one-off or repetitive operation
|
||||
|
||||
void WINAPI Msr_Note(int Id);
|
||||
|
||||
|
||||
// log an integer (on which we can see statistics later)
|
||||
void WINAPI Msr_Integer(int Id, int n);
|
||||
|
||||
|
||||
// print out all the vaialable log (it may have wrapped) and then the statistics.
|
||||
// When the log wraps you lose log but the statistics are still complete.
|
||||
// hFIle==NULL => use DbgLog
|
||||
// otherwise hFile must have come from CreateFile or OpenFile.
|
||||
|
||||
void WINAPI Msr_Dump(HANDLE hFile);
|
||||
|
||||
|
||||
// just dump the statistics - never mind the log
|
||||
|
||||
void WINAPI Msr_DumpStats(HANDLE hFile);
|
||||
|
||||
// Type definitions in case you want to declare a pointer to the dump functions
|
||||
// (makes it a trifle easier to do dynamic linking
|
||||
// i.e. LoadModule, GetProcAddress and call that)
|
||||
|
||||
// Typedefs so can declare MSR_DUMPPROC *MsrDumpStats; or whatever
|
||||
typedef void WINAPI MSR_DUMPPROC(HANDLE hFile);
|
||||
typedef void WINAPI MSR_CONTROLPROC(int iAction);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __MEASURE__
|
||||
Vendored
-120
@@ -1,120 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: MsgThrd.h
|
||||
//
|
||||
// Desc: DirectShow base classes - provides support for a worker thread
|
||||
// class to which one can asynchronously post messages.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Message class - really just a structure.
|
||||
//
|
||||
class CMsg {
|
||||
public:
|
||||
UINT uMsg;
|
||||
DWORD dwFlags;
|
||||
LPVOID lpParam;
|
||||
CAMEvent *pEvent;
|
||||
|
||||
CMsg(UINT u, DWORD dw, __inout_opt LPVOID lp, __in_opt CAMEvent *pEvnt)
|
||||
: uMsg(u), dwFlags(dw), lpParam(lp), pEvent(pEvnt) {}
|
||||
|
||||
CMsg()
|
||||
: uMsg(0), dwFlags(0L), lpParam(NULL), pEvent(NULL) {}
|
||||
};
|
||||
|
||||
// This is the actual thread class. It exports all the usual thread control
|
||||
// functions. The created thread is different from a normal WIN32 thread in
|
||||
// that it is prompted to perform particaular tasks by responding to messages
|
||||
// posted to its message queue.
|
||||
//
|
||||
class AM_NOVTABLE CMsgThread {
|
||||
private:
|
||||
static DWORD WINAPI DefaultThreadProc(__inout LPVOID lpParam);
|
||||
DWORD m_ThreadId;
|
||||
HANDLE m_hThread;
|
||||
|
||||
protected:
|
||||
|
||||
// if you want to override GetThreadMsg to block on other things
|
||||
// as well as this queue, you need access to this
|
||||
CGenericList<CMsg> m_ThreadQueue;
|
||||
CCritSec m_Lock;
|
||||
HANDLE m_hSem;
|
||||
LONG m_lWaiting;
|
||||
|
||||
public:
|
||||
CMsgThread()
|
||||
: m_ThreadId(0),
|
||||
m_hThread(NULL),
|
||||
m_lWaiting(0),
|
||||
m_hSem(NULL),
|
||||
// make a list with a cache of 5 items
|
||||
m_ThreadQueue(NAME("MsgThread list"), 5)
|
||||
{
|
||||
}
|
||||
|
||||
~CMsgThread();
|
||||
// override this if you want to block on other things as well
|
||||
// as the message loop
|
||||
void virtual GetThreadMsg(__out CMsg *msg);
|
||||
|
||||
// override this if you want to do something on thread startup
|
||||
virtual void OnThreadInit() {
|
||||
};
|
||||
|
||||
BOOL CreateThread();
|
||||
|
||||
BOOL WaitForThreadExit(__out LPDWORD lpdwExitCode) {
|
||||
if (m_hThread != NULL) {
|
||||
WaitForSingleObject(m_hThread, INFINITE);
|
||||
return GetExitCodeThread(m_hThread, lpdwExitCode);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD ResumeThread() {
|
||||
return ::ResumeThread(m_hThread);
|
||||
}
|
||||
|
||||
DWORD SuspendThread() {
|
||||
return ::SuspendThread(m_hThread);
|
||||
}
|
||||
|
||||
int GetThreadPriority() {
|
||||
return ::GetThreadPriority(m_hThread);
|
||||
}
|
||||
|
||||
BOOL SetThreadPriority(int nPriority) {
|
||||
return ::SetThreadPriority(m_hThread, nPriority);
|
||||
}
|
||||
|
||||
HANDLE GetThreadHandle() {
|
||||
return m_hThread;
|
||||
}
|
||||
|
||||
DWORD GetThreadId() {
|
||||
return m_ThreadId;
|
||||
}
|
||||
|
||||
|
||||
void PutThreadMsg(UINT uMsg, DWORD dwMsgFlags,
|
||||
__in_opt LPVOID lpMsgParam, __in_opt CAMEvent *pEvent = NULL) {
|
||||
CAutoLock lck(&m_Lock);
|
||||
CMsg* pMsg = new CMsg(uMsg, dwMsgFlags, lpMsgParam, pEvent);
|
||||
m_ThreadQueue.AddTail(pMsg);
|
||||
if (m_lWaiting != 0) {
|
||||
ReleaseSemaphore(m_hSem, m_lWaiting, 0);
|
||||
m_lWaiting = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// This is the function prototype of the function that the client
|
||||
// supplies. It is always called on the created thread, never on
|
||||
// the creator thread.
|
||||
//
|
||||
virtual LRESULT ThreadMessageProc(
|
||||
UINT uMsg, DWORD dwFlags, __inout_opt LPVOID lpParam, __in_opt CAMEvent *pEvent) = 0;
|
||||
};
|
||||
|
||||
Vendored
-478
@@ -1,478 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: MType.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes - implements a class that holds and
|
||||
// manages media type information.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// helper class that derived pin objects can use to compare media
|
||||
// types etc. Has same data members as the struct AM_MEDIA_TYPE defined
|
||||
// in the streams IDL file, but also has (non-virtual) functions
|
||||
|
||||
#include <streams.h>
|
||||
#include <mmreg.h>
|
||||
|
||||
CMediaType::~CMediaType(){
|
||||
FreeMediaType(*this);
|
||||
}
|
||||
|
||||
|
||||
CMediaType::CMediaType()
|
||||
{
|
||||
InitMediaType();
|
||||
}
|
||||
|
||||
|
||||
CMediaType::CMediaType(const GUID * type)
|
||||
{
|
||||
InitMediaType();
|
||||
majortype = *type;
|
||||
}
|
||||
|
||||
|
||||
// copy constructor does a deep copy of the format block
|
||||
|
||||
CMediaType::CMediaType(const AM_MEDIA_TYPE& rt, __out_opt HRESULT* phr)
|
||||
{
|
||||
HRESULT hr = CopyMediaType(this, &rt);
|
||||
if (FAILED(hr) && (NULL != phr)) {
|
||||
*phr = hr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CMediaType::CMediaType(const CMediaType& rt, __out_opt HRESULT* phr)
|
||||
{
|
||||
HRESULT hr = CopyMediaType(this, &rt);
|
||||
if (FAILED(hr) && (NULL != phr)) {
|
||||
*phr = hr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// this class inherits publicly from AM_MEDIA_TYPE so the compiler could generate
|
||||
// the following assignment operator itself, however it could introduce some
|
||||
// memory conflicts and leaks in the process because the structure contains
|
||||
// a dynamically allocated block (pbFormat) which it will not copy correctly
|
||||
|
||||
CMediaType&
|
||||
CMediaType::operator=(const AM_MEDIA_TYPE& rt)
|
||||
{
|
||||
Set(rt);
|
||||
return *this;
|
||||
}
|
||||
|
||||
CMediaType&
|
||||
CMediaType::operator=(const CMediaType& rt)
|
||||
{
|
||||
*this = (AM_MEDIA_TYPE &) rt;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOL
|
||||
CMediaType::operator == (const CMediaType& rt) const
|
||||
{
|
||||
// I don't believe we need to check sample size or
|
||||
// temporal compression flags, since I think these must
|
||||
// be represented in the type, subtype and format somehow. They
|
||||
// are pulled out as separate flags so that people who don't understand
|
||||
// the particular format representation can still see them, but
|
||||
// they should duplicate information in the format block.
|
||||
|
||||
return ((IsEqualGUID(majortype,rt.majortype) == TRUE) &&
|
||||
(IsEqualGUID(subtype,rt.subtype) == TRUE) &&
|
||||
(IsEqualGUID(formattype,rt.formattype) == TRUE) &&
|
||||
(cbFormat == rt.cbFormat) &&
|
||||
( (cbFormat == 0) ||
|
||||
pbFormat != NULL && rt.pbFormat != NULL &&
|
||||
(memcmp(pbFormat, rt.pbFormat, cbFormat) == 0)));
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
CMediaType::operator != (const CMediaType& rt) const
|
||||
{
|
||||
/* Check to see if they are equal */
|
||||
|
||||
if (*this == rt) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
HRESULT
|
||||
CMediaType::Set(const CMediaType& rt)
|
||||
{
|
||||
return Set((AM_MEDIA_TYPE &) rt);
|
||||
}
|
||||
|
||||
|
||||
HRESULT
|
||||
CMediaType::Set(const AM_MEDIA_TYPE& rt)
|
||||
{
|
||||
if (&rt != this) {
|
||||
FreeMediaType(*this);
|
||||
HRESULT hr = CopyMediaType(this, &rt);
|
||||
if (FAILED(hr)) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
BOOL
|
||||
CMediaType::IsValid() const
|
||||
{
|
||||
return (!IsEqualGUID(majortype,GUID_NULL));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CMediaType::SetType(const GUID* ptype)
|
||||
{
|
||||
majortype = *ptype;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CMediaType::SetSubtype(const GUID* ptype)
|
||||
{
|
||||
subtype = *ptype;
|
||||
}
|
||||
|
||||
|
||||
ULONG
|
||||
CMediaType::GetSampleSize() const {
|
||||
if (IsFixedSize()) {
|
||||
return lSampleSize;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CMediaType::SetSampleSize(ULONG sz) {
|
||||
if (sz == 0) {
|
||||
SetVariableSize();
|
||||
} else {
|
||||
bFixedSizeSamples = TRUE;
|
||||
lSampleSize = sz;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CMediaType::SetVariableSize() {
|
||||
bFixedSizeSamples = FALSE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CMediaType::SetTemporalCompression(BOOL bCompressed) {
|
||||
bTemporalCompression = bCompressed;
|
||||
}
|
||||
|
||||
BOOL
|
||||
CMediaType::SetFormat(__in_bcount(cb) BYTE * pformat, ULONG cb)
|
||||
{
|
||||
if (NULL == AllocFormatBuffer(cb))
|
||||
return(FALSE);
|
||||
|
||||
ASSERT(pbFormat);
|
||||
memcpy(pbFormat, pformat, cb);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
// set the type of the media type format block, this type defines what you
|
||||
// will actually find in the format pointer. For example FORMAT_VideoInfo or
|
||||
// FORMAT_WaveFormatEx. In the future this may be an interface pointer to a
|
||||
// property set. Before sending out media types this should be filled in.
|
||||
|
||||
void
|
||||
CMediaType::SetFormatType(const GUID *pformattype)
|
||||
{
|
||||
formattype = *pformattype;
|
||||
}
|
||||
|
||||
|
||||
// reset the format buffer
|
||||
|
||||
void CMediaType::ResetFormatBuffer()
|
||||
{
|
||||
if (cbFormat) {
|
||||
CoTaskMemFree((PVOID)pbFormat);
|
||||
}
|
||||
cbFormat = 0;
|
||||
pbFormat = NULL;
|
||||
}
|
||||
|
||||
|
||||
// allocate length bytes for the format and return a read/write pointer
|
||||
// If we cannot allocate the new block of memory we return NULL leaving
|
||||
// the original block of memory untouched (as does ReallocFormatBuffer)
|
||||
|
||||
BYTE*
|
||||
CMediaType::AllocFormatBuffer(ULONG length)
|
||||
{
|
||||
ASSERT(length);
|
||||
|
||||
// do the types have the same buffer size
|
||||
|
||||
if (cbFormat == length) {
|
||||
return pbFormat;
|
||||
}
|
||||
|
||||
// allocate the new format buffer
|
||||
|
||||
BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
|
||||
if (pNewFormat == NULL) {
|
||||
if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// delete the old format
|
||||
|
||||
if (cbFormat != 0) {
|
||||
ASSERT(pbFormat);
|
||||
CoTaskMemFree((PVOID)pbFormat);
|
||||
}
|
||||
|
||||
cbFormat = length;
|
||||
pbFormat = pNewFormat;
|
||||
return pbFormat;
|
||||
}
|
||||
|
||||
|
||||
// reallocate length bytes for the format and return a read/write pointer
|
||||
// to it. We keep as much information as we can given the new buffer size
|
||||
// if this fails the original format buffer is left untouched. The caller
|
||||
// is responsible for ensuring the size of memory required is non zero
|
||||
|
||||
BYTE*
|
||||
CMediaType::ReallocFormatBuffer(ULONG length)
|
||||
{
|
||||
ASSERT(length);
|
||||
|
||||
// do the types have the same buffer size
|
||||
|
||||
if (cbFormat == length) {
|
||||
return pbFormat;
|
||||
}
|
||||
|
||||
// allocate the new format buffer
|
||||
|
||||
BYTE *pNewFormat = (PBYTE)CoTaskMemAlloc(length);
|
||||
if (pNewFormat == NULL) {
|
||||
if (length <= cbFormat) return pbFormat; //reuse the old block anyway.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// copy any previous format (or part of if new is smaller)
|
||||
// delete the old format and replace with the new one
|
||||
|
||||
if (cbFormat != 0) {
|
||||
ASSERT(pbFormat);
|
||||
memcpy(pNewFormat,pbFormat,min(length,cbFormat));
|
||||
CoTaskMemFree((PVOID)pbFormat);
|
||||
}
|
||||
|
||||
cbFormat = length;
|
||||
pbFormat = pNewFormat;
|
||||
return pNewFormat;
|
||||
}
|
||||
|
||||
// initialise a media type structure
|
||||
|
||||
void CMediaType::InitMediaType()
|
||||
{
|
||||
ZeroMemory((PVOID)this, sizeof(*this));
|
||||
lSampleSize = 1;
|
||||
bFixedSizeSamples = TRUE;
|
||||
}
|
||||
|
||||
|
||||
// a partially specified media type can be passed to IPin::Connect
|
||||
// as a constraint on the media type used in the connection.
|
||||
// the type, subtype or format type can be null.
|
||||
BOOL
|
||||
CMediaType::IsPartiallySpecified(void) const
|
||||
{
|
||||
if ((majortype == GUID_NULL) ||
|
||||
(formattype == GUID_NULL)) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
CMediaType::MatchesPartial(const CMediaType* ppartial) const
|
||||
{
|
||||
if ((ppartial->majortype != GUID_NULL) &&
|
||||
(majortype != ppartial->majortype)) {
|
||||
return FALSE;
|
||||
}
|
||||
if ((ppartial->subtype != GUID_NULL) &&
|
||||
(subtype != ppartial->subtype)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ppartial->formattype != GUID_NULL) {
|
||||
// if the format block is specified then it must match exactly
|
||||
if (formattype != ppartial->formattype) {
|
||||
return FALSE;
|
||||
}
|
||||
if (cbFormat != ppartial->cbFormat) {
|
||||
return FALSE;
|
||||
}
|
||||
if ((cbFormat != 0) &&
|
||||
(memcmp(pbFormat, ppartial->pbFormat, cbFormat) != 0)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// general purpose function to delete a heap allocated AM_MEDIA_TYPE structure
|
||||
// which is useful when calling IEnumMediaTypes::Next as the interface
|
||||
// implementation allocates the structures which you must later delete
|
||||
// the format block may also be a pointer to an interface to release
|
||||
|
||||
void WINAPI DeleteMediaType(__inout_opt AM_MEDIA_TYPE *pmt)
|
||||
{
|
||||
// allow NULL pointers for coding simplicity
|
||||
|
||||
if (pmt == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
FreeMediaType(*pmt);
|
||||
CoTaskMemFree((PVOID)pmt);
|
||||
}
|
||||
|
||||
|
||||
// this also comes in useful when using the IEnumMediaTypes interface so
|
||||
// that you can copy a media type, you can do nearly the same by creating
|
||||
// a CMediaType object but as soon as it goes out of scope the destructor
|
||||
// will delete the memory it allocated (this takes a copy of the memory)
|
||||
|
||||
AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc)
|
||||
{
|
||||
ASSERT(pSrc);
|
||||
|
||||
// Allocate a block of memory for the media type
|
||||
|
||||
AM_MEDIA_TYPE *pMediaType =
|
||||
(AM_MEDIA_TYPE *)CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE));
|
||||
|
||||
if (pMediaType == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
// Copy the variable length format block
|
||||
|
||||
HRESULT hr = CopyMediaType(pMediaType,pSrc);
|
||||
if (FAILED(hr)) {
|
||||
CoTaskMemFree((PVOID)pMediaType);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pMediaType;
|
||||
}
|
||||
|
||||
|
||||
// Copy 1 media type to another
|
||||
|
||||
HRESULT WINAPI CopyMediaType(__out AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource)
|
||||
{
|
||||
// We'll leak if we copy onto one that already exists - there's one
|
||||
// case we can check like that - copying to itself.
|
||||
ASSERT(pmtSource != pmtTarget);
|
||||
*pmtTarget = *pmtSource;
|
||||
if (pmtSource->cbFormat != 0) {
|
||||
ASSERT(pmtSource->pbFormat != NULL);
|
||||
pmtTarget->pbFormat = (PBYTE)CoTaskMemAlloc(pmtSource->cbFormat);
|
||||
if (pmtTarget->pbFormat == NULL) {
|
||||
pmtTarget->cbFormat = 0;
|
||||
return E_OUTOFMEMORY;
|
||||
} else {
|
||||
CopyMemory((PVOID)pmtTarget->pbFormat, (PVOID)pmtSource->pbFormat,
|
||||
pmtTarget->cbFormat);
|
||||
}
|
||||
}
|
||||
if (pmtTarget->pUnk != NULL) {
|
||||
pmtTarget->pUnk->AddRef();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Free an existing media type (ie free resources it holds)
|
||||
|
||||
void WINAPI FreeMediaType(__inout AM_MEDIA_TYPE& mt)
|
||||
{
|
||||
if (mt.cbFormat != 0) {
|
||||
CoTaskMemFree((PVOID)mt.pbFormat);
|
||||
|
||||
// Strictly unnecessary but tidier
|
||||
mt.cbFormat = 0;
|
||||
mt.pbFormat = NULL;
|
||||
}
|
||||
if (mt.pUnk != NULL) {
|
||||
mt.pUnk->Release();
|
||||
mt.pUnk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize a media type from a WAVEFORMATEX
|
||||
|
||||
STDAPI CreateAudioMediaType(
|
||||
const WAVEFORMATEX *pwfx,
|
||||
__out AM_MEDIA_TYPE *pmt,
|
||||
BOOL bSetFormat
|
||||
)
|
||||
{
|
||||
pmt->majortype = MEDIATYPE_Audio;
|
||||
if (pwfx->wFormatTag == WAVE_FORMAT_EXTENSIBLE) {
|
||||
pmt->subtype = ((PWAVEFORMATEXTENSIBLE)pwfx)->SubFormat;
|
||||
} else {
|
||||
pmt->subtype = FOURCCMap(pwfx->wFormatTag);
|
||||
}
|
||||
pmt->formattype = FORMAT_WaveFormatEx;
|
||||
pmt->bFixedSizeSamples = TRUE;
|
||||
pmt->bTemporalCompression = FALSE;
|
||||
pmt->lSampleSize = pwfx->nBlockAlign;
|
||||
pmt->pUnk = NULL;
|
||||
if (bSetFormat) {
|
||||
if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
|
||||
pmt->cbFormat = sizeof(WAVEFORMATEX);
|
||||
} else {
|
||||
pmt->cbFormat = sizeof(WAVEFORMATEX) + pwfx->cbSize;
|
||||
}
|
||||
pmt->pbFormat = (PBYTE)CoTaskMemAlloc(pmt->cbFormat);
|
||||
if (pmt->pbFormat == NULL) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
if (pwfx->wFormatTag == WAVE_FORMAT_PCM) {
|
||||
CopyMemory(pmt->pbFormat, pwfx, sizeof(PCMWAVEFORMAT));
|
||||
((WAVEFORMATEX *)pmt->pbFormat)->cbSize = 0;
|
||||
} else {
|
||||
CopyMemory(pmt->pbFormat, pwfx, pmt->cbFormat);
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// eliminate very many spurious warnings from MS compiler
|
||||
#pragma warning(disable:4514)
|
||||
Vendored
-89
@@ -1,89 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: MtType.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines a class that holds and manages
|
||||
// media type information.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __MTYPE__
|
||||
#define __MTYPE__
|
||||
|
||||
/* Helper class that derived pin objects can use to compare media
|
||||
types etc. Has same data members as the struct AM_MEDIA_TYPE defined
|
||||
in the streams IDL file, but also has (non-virtual) functions */
|
||||
|
||||
class CMediaType : public _AMMediaType {
|
||||
|
||||
public:
|
||||
|
||||
~CMediaType();
|
||||
CMediaType();
|
||||
CMediaType(const GUID * majortype);
|
||||
CMediaType(const AM_MEDIA_TYPE&, __out_opt HRESULT* phr = NULL);
|
||||
CMediaType(const CMediaType&, __out_opt HRESULT* phr = NULL);
|
||||
|
||||
CMediaType& operator=(const CMediaType&);
|
||||
CMediaType& operator=(const AM_MEDIA_TYPE&);
|
||||
|
||||
BOOL operator == (const CMediaType&) const;
|
||||
BOOL operator != (const CMediaType&) const;
|
||||
|
||||
HRESULT Set(const CMediaType& rt);
|
||||
HRESULT Set(const AM_MEDIA_TYPE& rt);
|
||||
|
||||
BOOL IsValid() const;
|
||||
|
||||
const GUID *Type() const { return &majortype;} ;
|
||||
void SetType(const GUID *);
|
||||
const GUID *Subtype() const { return &subtype;} ;
|
||||
void SetSubtype(const GUID *);
|
||||
|
||||
BOOL IsFixedSize() const {return bFixedSizeSamples; };
|
||||
BOOL IsTemporalCompressed() const {return bTemporalCompression; };
|
||||
ULONG GetSampleSize() const;
|
||||
|
||||
void SetSampleSize(ULONG sz);
|
||||
void SetVariableSize();
|
||||
void SetTemporalCompression(BOOL bCompressed);
|
||||
|
||||
// read/write pointer to format - can't change length without
|
||||
// calling SetFormat, AllocFormatBuffer or ReallocFormatBuffer
|
||||
|
||||
BYTE* Format() const {return pbFormat; };
|
||||
ULONG FormatLength() const { return cbFormat; };
|
||||
|
||||
void SetFormatType(const GUID *);
|
||||
const GUID *FormatType() const {return &formattype; };
|
||||
BOOL SetFormat(__in_bcount(length) BYTE *pFormat, ULONG length);
|
||||
void ResetFormatBuffer();
|
||||
BYTE* AllocFormatBuffer(ULONG length);
|
||||
BYTE* ReallocFormatBuffer(ULONG length);
|
||||
|
||||
void InitMediaType();
|
||||
|
||||
BOOL MatchesPartial(const CMediaType* ppartial) const;
|
||||
BOOL IsPartiallySpecified(void) const;
|
||||
};
|
||||
|
||||
|
||||
/* General purpose functions to copy and delete a task allocated AM_MEDIA_TYPE
|
||||
structure which is useful when using the IEnumMediaFormats interface as
|
||||
the implementation allocates the structures which you must later delete */
|
||||
|
||||
void WINAPI DeleteMediaType(__inout_opt AM_MEDIA_TYPE *pmt);
|
||||
AM_MEDIA_TYPE * WINAPI CreateMediaType(AM_MEDIA_TYPE const *pSrc);
|
||||
HRESULT WINAPI CopyMediaType(__out AM_MEDIA_TYPE *pmtTarget, const AM_MEDIA_TYPE *pmtSource);
|
||||
void WINAPI FreeMediaType(__inout AM_MEDIA_TYPE& mt);
|
||||
|
||||
// Initialize a media type from a WAVEFORMATEX
|
||||
|
||||
STDAPI CreateAudioMediaType(
|
||||
const WAVEFORMATEX *pwfx,
|
||||
__out AM_MEDIA_TYPE *pmt,
|
||||
BOOL bSetFormat);
|
||||
|
||||
#endif /* __MTYPE__ */
|
||||
|
||||
Vendored
-801
@@ -1,801 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: OutputQ.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes - implements COutputQueue class used by an
|
||||
// output pin which may sometimes want to queue output samples on a
|
||||
// separate thread and sometimes call Receive() directly on the input
|
||||
// pin.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
|
||||
|
||||
//
|
||||
// COutputQueue Constructor :
|
||||
//
|
||||
// Determines if a thread is to be created and creates resources
|
||||
//
|
||||
// pInputPin - the downstream input pin we're queueing samples to
|
||||
//
|
||||
// phr - changed to a failure code if this function fails
|
||||
// (otherwise unchanges)
|
||||
//
|
||||
// bAuto - Ask pInputPin if it can block in Receive by calling
|
||||
// its ReceiveCanBlock method and create a thread if
|
||||
// it can block, otherwise not.
|
||||
//
|
||||
// bQueue - if bAuto == FALSE then we create a thread if and only
|
||||
// if bQueue == TRUE
|
||||
//
|
||||
// lBatchSize - work in batches of lBatchSize
|
||||
//
|
||||
// bBatchEact - Use exact batch sizes so don't send until the
|
||||
// batch is full or SendAnyway() is called
|
||||
//
|
||||
// lListSize - If we create a thread make the list of samples queued
|
||||
// to the thread have this size cache
|
||||
//
|
||||
// dwPriority - If we create a thread set its priority to this
|
||||
//
|
||||
COutputQueue::COutputQueue(
|
||||
IPin *pInputPin, // Pin to send stuff to
|
||||
__inout HRESULT *phr, // 'Return code'
|
||||
BOOL bAuto, // Ask pin if queue or not
|
||||
BOOL bQueue, // Send through queue
|
||||
LONG lBatchSize, // Batch
|
||||
BOOL bBatchExact, // Batch exactly to BatchSize
|
||||
LONG lListSize,
|
||||
DWORD dwPriority,
|
||||
bool bFlushingOpt // flushing optimization
|
||||
) : m_lBatchSize(lBatchSize),
|
||||
m_bBatchExact(bBatchExact && (lBatchSize > 1)),
|
||||
m_hThread(NULL),
|
||||
m_hSem(NULL),
|
||||
m_List(NULL),
|
||||
m_pPin(pInputPin),
|
||||
m_ppSamples(NULL),
|
||||
m_lWaiting(0),
|
||||
m_evFlushComplete(FALSE, phr),
|
||||
m_pInputPin(NULL),
|
||||
m_bSendAnyway(FALSE),
|
||||
m_nBatched(0),
|
||||
m_bFlushing(FALSE),
|
||||
m_bFlushed(TRUE),
|
||||
m_bFlushingOpt(bFlushingOpt),
|
||||
m_bTerminate(FALSE),
|
||||
m_hEventPop(NULL),
|
||||
m_hr(S_OK)
|
||||
{
|
||||
ASSERT(m_lBatchSize > 0);
|
||||
|
||||
|
||||
if (FAILED(*phr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the input pin is OK and cache its IMemInputPin interface
|
||||
|
||||
*phr = pInputPin->QueryInterface(IID_IMemInputPin, (void **)&m_pInputPin);
|
||||
if (FAILED(*phr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// See if we should ask the downstream pin
|
||||
|
||||
if (bAuto) {
|
||||
HRESULT hr = m_pInputPin->ReceiveCanBlock();
|
||||
if (SUCCEEDED(hr)) {
|
||||
bQueue = hr == S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Create our sample batch
|
||||
|
||||
m_ppSamples = new PMEDIASAMPLE[m_lBatchSize];
|
||||
if (m_ppSamples == NULL) {
|
||||
*phr = E_OUTOFMEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're queueing allocate resources
|
||||
|
||||
if (bQueue) {
|
||||
DbgLog((LOG_TRACE, 2, TEXT("Creating thread for output pin")));
|
||||
m_hSem = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
|
||||
if (m_hSem == NULL) {
|
||||
DWORD dwError = GetLastError();
|
||||
*phr = AmHresultFromWin32(dwError);
|
||||
return;
|
||||
}
|
||||
m_List = new CSampleList(NAME("Sample Queue List"),
|
||||
lListSize,
|
||||
FALSE // No lock
|
||||
);
|
||||
if (m_List == NULL) {
|
||||
*phr = E_OUTOFMEMORY;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
DWORD dwThreadId;
|
||||
m_hThread = CreateThread(NULL,
|
||||
0,
|
||||
InitialThreadProc,
|
||||
(LPVOID)this,
|
||||
0,
|
||||
&dwThreadId);
|
||||
if (m_hThread == NULL) {
|
||||
DWORD dwError = GetLastError();
|
||||
*phr = AmHresultFromWin32(dwError);
|
||||
return;
|
||||
}
|
||||
SetThreadPriority(m_hThread, dwPriority);
|
||||
} else {
|
||||
DbgLog((LOG_TRACE, 2, TEXT("Calling input pin directly - no thread")));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// COutputQueuee Destructor :
|
||||
//
|
||||
// Free all resources -
|
||||
//
|
||||
// Thread,
|
||||
// Batched samples
|
||||
//
|
||||
COutputQueue::~COutputQueue()
|
||||
{
|
||||
DbgLog((LOG_TRACE, 3, TEXT("COutputQueue::~COutputQueue")));
|
||||
/* Free our pointer */
|
||||
if (m_pInputPin != NULL) {
|
||||
m_pInputPin->Release();
|
||||
}
|
||||
if (m_hThread != NULL) {
|
||||
{
|
||||
CAutoLock lck(this);
|
||||
m_bTerminate = TRUE;
|
||||
m_hr = S_FALSE;
|
||||
NotifyThread();
|
||||
}
|
||||
DbgWaitForSingleObject(m_hThread);
|
||||
EXECUTE_ASSERT(CloseHandle(m_hThread));
|
||||
|
||||
// The thread frees the samples when asked to terminate
|
||||
|
||||
ASSERT(m_List->GetCount() == 0);
|
||||
delete m_List;
|
||||
} else {
|
||||
FreeSamples();
|
||||
}
|
||||
if (m_hSem != NULL) {
|
||||
EXECUTE_ASSERT(CloseHandle(m_hSem));
|
||||
}
|
||||
delete [] m_ppSamples;
|
||||
}
|
||||
|
||||
//
|
||||
// Call the real thread proc as a member function
|
||||
//
|
||||
DWORD WINAPI COutputQueue::InitialThreadProc(__in LPVOID pv)
|
||||
{
|
||||
HRESULT hrCoInit = CAMThread::CoInitializeHelper();
|
||||
|
||||
COutputQueue *pSampleQueue = (COutputQueue *)pv;
|
||||
DWORD dwReturn = pSampleQueue->ThreadProc();
|
||||
|
||||
if(hrCoInit == S_OK) {
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
return dwReturn;
|
||||
}
|
||||
|
||||
//
|
||||
// Thread sending the samples downstream :
|
||||
//
|
||||
// When there is nothing to do the thread sets m_lWaiting (while
|
||||
// holding the critical section) and then waits for m_hSem to be
|
||||
// set (not holding the critical section)
|
||||
//
|
||||
DWORD COutputQueue::ThreadProc()
|
||||
{
|
||||
while (TRUE) {
|
||||
BOOL bWait = FALSE;
|
||||
IMediaSample *pSample;
|
||||
LONG lNumberToSend; // Local copy
|
||||
NewSegmentPacket* ppacket;
|
||||
|
||||
//
|
||||
// Get a batch of samples and send it if possible
|
||||
// In any case exit the loop if there is a control action
|
||||
// requested
|
||||
//
|
||||
{
|
||||
CAutoLock lck(this);
|
||||
while (TRUE) {
|
||||
|
||||
if (m_bTerminate) {
|
||||
FreeSamples();
|
||||
return 0;
|
||||
}
|
||||
if (m_bFlushing) {
|
||||
FreeSamples();
|
||||
SetEvent(m_evFlushComplete);
|
||||
}
|
||||
|
||||
// Get a sample off the list
|
||||
|
||||
pSample = m_List->RemoveHead();
|
||||
// inform derived class we took something off the queue
|
||||
if (m_hEventPop) {
|
||||
//DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
|
||||
SetEvent(m_hEventPop);
|
||||
}
|
||||
|
||||
if (pSample != NULL &&
|
||||
!IsSpecialSample(pSample)) {
|
||||
|
||||
// If its just a regular sample just add it to the batch
|
||||
// and exit the loop if the batch is full
|
||||
|
||||
m_ppSamples[m_nBatched++] = pSample;
|
||||
if (m_nBatched == m_lBatchSize) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
||||
// If there was nothing in the queue and there's nothing
|
||||
// to send (either because there's nothing or the batch
|
||||
// isn't full) then prepare to wait
|
||||
|
||||
if (pSample == NULL &&
|
||||
(m_bBatchExact || m_nBatched == 0)) {
|
||||
|
||||
// Tell other thread to set the event when there's
|
||||
// something do to
|
||||
|
||||
ASSERT(m_lWaiting == 0);
|
||||
m_lWaiting++;
|
||||
bWait = TRUE;
|
||||
} else {
|
||||
|
||||
// We break out of the loop on SEND_PACKET unless
|
||||
// there's nothing to send
|
||||
|
||||
if (pSample == SEND_PACKET && m_nBatched == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pSample == NEW_SEGMENT) {
|
||||
// now we need the parameters - we are
|
||||
// guaranteed that the next packet contains them
|
||||
ppacket = (NewSegmentPacket *) m_List->RemoveHead();
|
||||
// we took something off the queue
|
||||
if (m_hEventPop) {
|
||||
//DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
|
||||
SetEvent(m_hEventPop);
|
||||
}
|
||||
|
||||
ASSERT(ppacket);
|
||||
}
|
||||
// EOS_PACKET falls through here and we exit the loop
|
||||
// In this way it acts like SEND_PACKET
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bWait) {
|
||||
// We look at m_nBatched from the client side so keep
|
||||
// it up to date inside the critical section
|
||||
lNumberToSend = m_nBatched; // Local copy
|
||||
m_nBatched = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for some more data
|
||||
|
||||
if (bWait) {
|
||||
DbgWaitForSingleObject(m_hSem);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// OK - send it if there's anything to send
|
||||
// We DON'T check m_bBatchExact here because either we've got
|
||||
// a full batch or we dropped through because we got
|
||||
// SEND_PACKET or EOS_PACKET - both of which imply we should
|
||||
// flush our batch
|
||||
|
||||
if (lNumberToSend != 0) {
|
||||
long nProcessed;
|
||||
if (m_hr == S_OK) {
|
||||
ASSERT(!m_bFlushed);
|
||||
HRESULT hr = m_pInputPin->ReceiveMultiple(m_ppSamples,
|
||||
lNumberToSend,
|
||||
&nProcessed);
|
||||
/* Don't overwrite a flushing state HRESULT */
|
||||
CAutoLock lck(this);
|
||||
if (m_hr == S_OK) {
|
||||
m_hr = hr;
|
||||
}
|
||||
ASSERT(!m_bFlushed);
|
||||
}
|
||||
while (lNumberToSend != 0) {
|
||||
m_ppSamples[--lNumberToSend]->Release();
|
||||
}
|
||||
if (m_hr != S_OK) {
|
||||
|
||||
// In any case wait for more data - S_OK just
|
||||
// means there wasn't an error
|
||||
|
||||
DbgLog((LOG_ERROR, 2, TEXT("ReceiveMultiple returned %8.8X"),
|
||||
m_hr));
|
||||
}
|
||||
}
|
||||
|
||||
// Check for end of stream
|
||||
|
||||
if (pSample == EOS_PACKET) {
|
||||
|
||||
// We don't send even end of stream on if we've previously
|
||||
// returned something other than S_OK
|
||||
// This is because in that case the pin which returned
|
||||
// something other than S_OK should have either sent
|
||||
// EndOfStream() or notified the filter graph
|
||||
|
||||
if (m_hr == S_OK) {
|
||||
DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()")));
|
||||
HRESULT hr = m_pPin->EndOfStream();
|
||||
if (FAILED(hr)) {
|
||||
DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Data from a new source
|
||||
|
||||
if (pSample == RESET_PACKET) {
|
||||
m_hr = S_OK;
|
||||
SetEvent(m_evFlushComplete);
|
||||
}
|
||||
|
||||
if (pSample == NEW_SEGMENT) {
|
||||
m_pPin->NewSegment(ppacket->tStart, ppacket->tStop, ppacket->dRate);
|
||||
delete ppacket;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send batched stuff anyway
|
||||
void COutputQueue::SendAnyway()
|
||||
{
|
||||
if (!IsQueued()) {
|
||||
|
||||
// m_bSendAnyway is a private parameter checked in ReceiveMultiple
|
||||
|
||||
m_bSendAnyway = TRUE;
|
||||
LONG nProcessed;
|
||||
ReceiveMultiple(NULL, 0, &nProcessed);
|
||||
m_bSendAnyway = FALSE;
|
||||
|
||||
} else {
|
||||
CAutoLock lck(this);
|
||||
QueueSample(SEND_PACKET);
|
||||
NotifyThread();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
COutputQueue::NewSegment(
|
||||
REFERENCE_TIME tStart,
|
||||
REFERENCE_TIME tStop,
|
||||
double dRate)
|
||||
{
|
||||
if (!IsQueued()) {
|
||||
if (S_OK == m_hr) {
|
||||
if (m_bBatchExact) {
|
||||
SendAnyway();
|
||||
}
|
||||
m_pPin->NewSegment(tStart, tStop, dRate);
|
||||
}
|
||||
} else {
|
||||
if (m_hr == S_OK) {
|
||||
//
|
||||
// we need to queue the new segment to appear in order in the
|
||||
// data, but we need to pass parameters to it. Rather than
|
||||
// take the hit of wrapping every single sample so we can tell
|
||||
// special ones apart, we queue special pointers to indicate
|
||||
// special packets, and we guarantee (by holding the
|
||||
// critical section) that the packet immediately following a
|
||||
// NEW_SEGMENT value is a NewSegmentPacket containing the
|
||||
// parameters.
|
||||
NewSegmentPacket * ppack = new NewSegmentPacket;
|
||||
if (ppack == NULL) {
|
||||
return;
|
||||
}
|
||||
ppack->tStart = tStart;
|
||||
ppack->tStop = tStop;
|
||||
ppack->dRate = dRate;
|
||||
|
||||
CAutoLock lck(this);
|
||||
QueueSample(NEW_SEGMENT);
|
||||
QueueSample( (IMediaSample*) ppack);
|
||||
NotifyThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// End of Stream is queued to output device
|
||||
//
|
||||
void COutputQueue::EOS()
|
||||
{
|
||||
CAutoLock lck(this);
|
||||
if (!IsQueued()) {
|
||||
if (m_bBatchExact) {
|
||||
SendAnyway();
|
||||
}
|
||||
if (m_hr == S_OK) {
|
||||
DbgLog((LOG_TRACE, 2, TEXT("COutputQueue sending EndOfStream()")));
|
||||
m_bFlushed = FALSE;
|
||||
HRESULT hr = m_pPin->EndOfStream();
|
||||
if (FAILED(hr)) {
|
||||
DbgLog((LOG_ERROR, 2, TEXT("COutputQueue got code 0x%8.8X from EndOfStream()")));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_hr == S_OK) {
|
||||
m_bFlushed = FALSE;
|
||||
QueueSample(EOS_PACKET);
|
||||
NotifyThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Flush all the samples in the queue
|
||||
//
|
||||
void COutputQueue::BeginFlush()
|
||||
{
|
||||
if (IsQueued()) {
|
||||
{
|
||||
CAutoLock lck(this);
|
||||
|
||||
// block receives -- we assume this is done by the
|
||||
// filter in which we are a component
|
||||
|
||||
// discard all queued data
|
||||
|
||||
m_bFlushing = TRUE;
|
||||
|
||||
// Make sure we discard all samples from now on
|
||||
|
||||
if (m_hr == S_OK) {
|
||||
m_hr = S_FALSE;
|
||||
}
|
||||
|
||||
// Optimize so we don't keep calling downstream all the time
|
||||
|
||||
if (m_bFlushed && m_bFlushingOpt) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we really wait for the flush to complete
|
||||
m_evFlushComplete.Reset();
|
||||
|
||||
NotifyThread();
|
||||
}
|
||||
|
||||
// pass this downstream
|
||||
|
||||
m_pPin->BeginFlush();
|
||||
} else {
|
||||
// pass downstream first to avoid deadlocks
|
||||
m_pPin->BeginFlush();
|
||||
CAutoLock lck(this);
|
||||
// discard all queued data
|
||||
|
||||
m_bFlushing = TRUE;
|
||||
|
||||
// Make sure we discard all samples from now on
|
||||
|
||||
if (m_hr == S_OK) {
|
||||
m_hr = S_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// leave flush mode - pass this downstream
|
||||
void COutputQueue::EndFlush()
|
||||
{
|
||||
{
|
||||
CAutoLock lck(this);
|
||||
ASSERT(m_bFlushing);
|
||||
if (m_bFlushingOpt && m_bFlushed && IsQueued()) {
|
||||
m_bFlushing = FALSE;
|
||||
m_hr = S_OK;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// sync with pushing thread -- done in BeginFlush
|
||||
// ensure no more data to go downstream -- done in BeginFlush
|
||||
//
|
||||
// Because we are synching here there is no need to hold the critical
|
||||
// section (in fact we'd deadlock if we did!)
|
||||
|
||||
if (IsQueued()) {
|
||||
m_evFlushComplete.Wait();
|
||||
} else {
|
||||
FreeSamples();
|
||||
}
|
||||
|
||||
// Be daring - the caller has guaranteed no samples will arrive
|
||||
// before EndFlush() returns
|
||||
|
||||
m_bFlushing = FALSE;
|
||||
m_bFlushed = TRUE;
|
||||
|
||||
// call EndFlush on downstream pins
|
||||
|
||||
m_pPin->EndFlush();
|
||||
|
||||
m_hr = S_OK;
|
||||
}
|
||||
|
||||
// COutputQueue::QueueSample
|
||||
//
|
||||
// private method to Send a sample to the output queue
|
||||
// The critical section MUST be held when this is called
|
||||
|
||||
void COutputQueue::QueueSample(IMediaSample *pSample)
|
||||
{
|
||||
if (NULL == m_List->AddTail(pSample)) {
|
||||
if (!IsSpecialSample(pSample)) {
|
||||
pSample->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// COutputQueue::Receive()
|
||||
//
|
||||
// Send a single sample by the multiple sample route
|
||||
// (NOTE - this could be optimized if necessary)
|
||||
//
|
||||
// On return the sample will have been Release()'d
|
||||
//
|
||||
|
||||
HRESULT COutputQueue::Receive(IMediaSample *pSample)
|
||||
{
|
||||
LONG nProcessed;
|
||||
return ReceiveMultiple(&pSample, 1, &nProcessed);
|
||||
}
|
||||
|
||||
//
|
||||
// COutputQueue::ReceiveMultiple()
|
||||
//
|
||||
// Send a set of samples to the downstream pin
|
||||
//
|
||||
// ppSamples - array of samples
|
||||
// nSamples - how many
|
||||
// nSamplesProcessed - How many were processed
|
||||
//
|
||||
// On return all samples will have been Release()'d
|
||||
//
|
||||
|
||||
HRESULT COutputQueue::ReceiveMultiple (
|
||||
__in_ecount(nSamples) IMediaSample **ppSamples,
|
||||
long nSamples,
|
||||
__out long *nSamplesProcessed)
|
||||
{
|
||||
if (nSamples < 0) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
CAutoLock lck(this);
|
||||
// Either call directly or queue up the samples
|
||||
|
||||
if (!IsQueued()) {
|
||||
|
||||
// If we already had a bad return code then just return
|
||||
|
||||
if (S_OK != m_hr) {
|
||||
|
||||
// If we've never received anything since the last Flush()
|
||||
// and the sticky return code is not S_OK we must be
|
||||
// flushing
|
||||
// ((!A || B) is equivalent to A implies B)
|
||||
ASSERT(!m_bFlushed || m_bFlushing);
|
||||
|
||||
// We're supposed to Release() them anyway!
|
||||
*nSamplesProcessed = 0;
|
||||
for (int i = 0; i < nSamples; i++) {
|
||||
DbgLog((LOG_TRACE, 3, TEXT("COutputQueue (direct) : Discarding %d samples code 0x%8.8X"),
|
||||
nSamples, m_hr));
|
||||
ppSamples[i]->Release();
|
||||
}
|
||||
|
||||
return m_hr;
|
||||
}
|
||||
//
|
||||
// If we're flushing the sticky return code should be S_FALSE
|
||||
//
|
||||
ASSERT(!m_bFlushing);
|
||||
m_bFlushed = FALSE;
|
||||
|
||||
ASSERT(m_nBatched < m_lBatchSize);
|
||||
ASSERT(m_nBatched == 0 || m_bBatchExact);
|
||||
|
||||
// Loop processing the samples in batches
|
||||
|
||||
LONG iLost = 0;
|
||||
long iDone = 0;
|
||||
for (iDone = 0;
|
||||
iDone < nSamples || (m_nBatched != 0 && m_bSendAnyway);
|
||||
) {
|
||||
|
||||
//pragma message (REMIND("Implement threshold scheme"))
|
||||
ASSERT(m_nBatched < m_lBatchSize);
|
||||
if (iDone < nSamples) {
|
||||
m_ppSamples[m_nBatched++] = ppSamples[iDone++];
|
||||
}
|
||||
if (m_nBatched == m_lBatchSize ||
|
||||
nSamples == 0 && (m_bSendAnyway || !m_bBatchExact)) {
|
||||
LONG nDone;
|
||||
DbgLog((LOG_TRACE, 4, TEXT("Batching %d samples"),
|
||||
m_nBatched));
|
||||
|
||||
if (m_hr == S_OK) {
|
||||
m_hr = m_pInputPin->ReceiveMultiple(m_ppSamples,
|
||||
m_nBatched,
|
||||
&nDone);
|
||||
} else {
|
||||
nDone = 0;
|
||||
}
|
||||
iLost += m_nBatched - nDone;
|
||||
for (LONG i = 0; i < m_nBatched; i++) {
|
||||
m_ppSamples[i]->Release();
|
||||
}
|
||||
m_nBatched = 0;
|
||||
}
|
||||
}
|
||||
*nSamplesProcessed = iDone - iLost;
|
||||
if (*nSamplesProcessed < 0) {
|
||||
*nSamplesProcessed = 0;
|
||||
}
|
||||
return m_hr;
|
||||
} else {
|
||||
/* We're sending to our thread */
|
||||
|
||||
if (m_hr != S_OK) {
|
||||
*nSamplesProcessed = 0;
|
||||
DbgLog((LOG_TRACE, 3, TEXT("COutputQueue (queued) : Discarding %d samples code 0x%8.8X"),
|
||||
nSamples, m_hr));
|
||||
for (int i = 0; i < nSamples; i++) {
|
||||
ppSamples[i]->Release();
|
||||
}
|
||||
return m_hr;
|
||||
}
|
||||
m_bFlushed = FALSE;
|
||||
for (long i = 0; i < nSamples; i++) {
|
||||
QueueSample(ppSamples[i]);
|
||||
}
|
||||
*nSamplesProcessed = nSamples;
|
||||
if (!m_bBatchExact ||
|
||||
m_nBatched + m_List->GetCount() >= m_lBatchSize) {
|
||||
NotifyThread();
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Get ready for new data - cancels sticky m_hr
|
||||
void COutputQueue::Reset()
|
||||
{
|
||||
if (!IsQueued()) {
|
||||
m_hr = S_OK;
|
||||
} else {
|
||||
{
|
||||
CAutoLock lck(this);
|
||||
QueueSample(RESET_PACKET);
|
||||
NotifyThread();
|
||||
}
|
||||
m_evFlushComplete.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove and Release() all queued and Batched samples
|
||||
void COutputQueue::FreeSamples()
|
||||
{
|
||||
CAutoLock lck(this);
|
||||
if (IsQueued()) {
|
||||
while (TRUE) {
|
||||
IMediaSample *pSample = m_List->RemoveHead();
|
||||
// inform derived class we took something off the queue
|
||||
if (m_hEventPop) {
|
||||
//DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
|
||||
SetEvent(m_hEventPop);
|
||||
}
|
||||
|
||||
if (pSample == NULL) {
|
||||
break;
|
||||
}
|
||||
if (!IsSpecialSample(pSample)) {
|
||||
pSample->Release();
|
||||
} else {
|
||||
if (pSample == NEW_SEGMENT) {
|
||||
// Free NEW_SEGMENT packet
|
||||
NewSegmentPacket *ppacket =
|
||||
(NewSegmentPacket *) m_List->RemoveHead();
|
||||
// inform derived class we took something off the queue
|
||||
if (m_hEventPop) {
|
||||
//DbgLog((LOG_TRACE,3,TEXT("Queue: Delivered SET EVENT")));
|
||||
SetEvent(m_hEventPop);
|
||||
}
|
||||
|
||||
ASSERT(ppacket != NULL);
|
||||
delete ppacket;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < m_nBatched; i++) {
|
||||
m_ppSamples[i]->Release();
|
||||
}
|
||||
m_nBatched = 0;
|
||||
}
|
||||
|
||||
// Notify the thread if there is something to do
|
||||
//
|
||||
// The critical section MUST be held when this is called
|
||||
void COutputQueue::NotifyThread()
|
||||
{
|
||||
// Optimize - no need to signal if it's not waiting
|
||||
ASSERT(IsQueued());
|
||||
if (m_lWaiting) {
|
||||
ReleaseSemaphore(m_hSem, m_lWaiting, NULL);
|
||||
m_lWaiting = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// See if there's any work to do
|
||||
// Returns
|
||||
// TRUE if there is nothing on the queue and nothing in the batch
|
||||
// and all data has been sent
|
||||
// FALSE otherwise
|
||||
//
|
||||
BOOL COutputQueue::IsIdle()
|
||||
{
|
||||
CAutoLock lck(this);
|
||||
|
||||
// We're idle if
|
||||
// there is no thread (!IsQueued()) OR
|
||||
// the thread is waiting for more work (m_lWaiting != 0)
|
||||
// AND
|
||||
// there's nothing in the current batch (m_nBatched == 0)
|
||||
|
||||
if (IsQueued() && m_lWaiting == 0 || m_nBatched != 0) {
|
||||
return FALSE;
|
||||
} else {
|
||||
|
||||
// If we're idle it shouldn't be possible for there
|
||||
// to be anything on the work queue
|
||||
|
||||
ASSERT(!IsQueued() || m_List->GetCount() == 0);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void COutputQueue::SetPopEvent(HANDLE hEvent)
|
||||
{
|
||||
m_hEventPop = hEvent;
|
||||
}
|
||||
Vendored
-137
@@ -1,137 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: OutputQ.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines the COutputQueue class, which
|
||||
// makes a queue of samples and sends them to an output pin. The
|
||||
// class will optionally send the samples to the pin directly.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
typedef CGenericList<IMediaSample> CSampleList;
|
||||
|
||||
class COutputQueue : public CCritSec
|
||||
{
|
||||
public:
|
||||
// Constructor
|
||||
COutputQueue(IPin *pInputPin, // Pin to send stuff to
|
||||
__inout HRESULT *phr, // 'Return code'
|
||||
BOOL bAuto = TRUE, // Ask pin if blocks
|
||||
BOOL bQueue = TRUE, // Send through queue (ignored if
|
||||
// bAuto set)
|
||||
LONG lBatchSize = 1, // Batch
|
||||
BOOL bBatchExact = FALSE,// Batch exactly to BatchSize
|
||||
LONG lListSize = // Likely number in the list
|
||||
DEFAULTCACHE,
|
||||
DWORD dwPriority = // Priority of thread to create
|
||||
THREAD_PRIORITY_NORMAL,
|
||||
bool bFlushingOpt = false // flushing optimization
|
||||
);
|
||||
~COutputQueue();
|
||||
|
||||
// enter flush state - discard all data
|
||||
void BeginFlush(); // Begin flushing samples
|
||||
|
||||
// re-enable receives (pass this downstream)
|
||||
void EndFlush(); // Complete flush of samples - downstream
|
||||
// pin guaranteed not to block at this stage
|
||||
|
||||
void EOS(); // Call this on End of stream
|
||||
|
||||
void SendAnyway(); // Send batched samples anyway (if bBatchExact set)
|
||||
|
||||
void NewSegment(
|
||||
REFERENCE_TIME tStart,
|
||||
REFERENCE_TIME tStop,
|
||||
double dRate);
|
||||
|
||||
HRESULT Receive(IMediaSample *pSample);
|
||||
|
||||
// do something with these media samples
|
||||
HRESULT ReceiveMultiple (
|
||||
__in_ecount(nSamples) IMediaSample **pSamples,
|
||||
long nSamples,
|
||||
__out long *nSamplesProcessed);
|
||||
|
||||
void Reset(); // Reset m_hr ready for more data
|
||||
|
||||
// See if its idle or not
|
||||
BOOL IsIdle();
|
||||
|
||||
// give the class an event to fire after everything removed from the queue
|
||||
void SetPopEvent(HANDLE hEvent);
|
||||
|
||||
protected:
|
||||
static DWORD WINAPI InitialThreadProc(__in LPVOID pv);
|
||||
DWORD ThreadProc();
|
||||
BOOL IsQueued()
|
||||
{
|
||||
return m_List != NULL;
|
||||
};
|
||||
|
||||
// The critical section MUST be held when this is called
|
||||
void QueueSample(IMediaSample *pSample);
|
||||
|
||||
BOOL IsSpecialSample(IMediaSample *pSample)
|
||||
{
|
||||
return (DWORD_PTR)pSample > (DWORD_PTR)(LONG_PTR)(-16);
|
||||
};
|
||||
|
||||
// Remove and Release() batched and queued samples
|
||||
void FreeSamples();
|
||||
|
||||
// Notify the thread there is something to do
|
||||
void NotifyThread();
|
||||
|
||||
|
||||
protected:
|
||||
// Queue 'messages'
|
||||
#define SEND_PACKET ((IMediaSample *)(LONG_PTR)(-2)) // Send batch
|
||||
#define EOS_PACKET ((IMediaSample *)(LONG_PTR)(-3)) // End of stream
|
||||
#define RESET_PACKET ((IMediaSample *)(LONG_PTR)(-4)) // Reset m_hr
|
||||
#define NEW_SEGMENT ((IMediaSample *)(LONG_PTR)(-5)) // send NewSegment
|
||||
|
||||
// new segment packet is always followed by one of these
|
||||
struct NewSegmentPacket {
|
||||
REFERENCE_TIME tStart;
|
||||
REFERENCE_TIME tStop;
|
||||
double dRate;
|
||||
};
|
||||
|
||||
// Remember input stuff
|
||||
IPin * const m_pPin;
|
||||
IMemInputPin * m_pInputPin;
|
||||
BOOL const m_bBatchExact;
|
||||
LONG const m_lBatchSize;
|
||||
|
||||
CSampleList * m_List;
|
||||
HANDLE m_hSem;
|
||||
CAMEvent m_evFlushComplete;
|
||||
HANDLE m_hThread;
|
||||
__field_ecount_opt(m_lBatchSize) IMediaSample ** m_ppSamples;
|
||||
__range(0, m_lBatchSize) LONG m_nBatched;
|
||||
|
||||
// Wait optimization
|
||||
LONG m_lWaiting;
|
||||
// Flush synchronization
|
||||
BOOL m_bFlushing;
|
||||
|
||||
// flushing optimization. some downstream filters have trouble
|
||||
// with the queue's flushing optimization. other rely on it
|
||||
BOOL m_bFlushed;
|
||||
bool m_bFlushingOpt;
|
||||
|
||||
// Terminate now
|
||||
BOOL m_bTerminate;
|
||||
|
||||
// Send anyway flag for batching
|
||||
BOOL m_bSendAnyway;
|
||||
|
||||
// Deferred 'return code'
|
||||
HRESULT volatile m_hr;
|
||||
|
||||
// an event that can be fired after every deliver
|
||||
HANDLE m_hEventPop;
|
||||
};
|
||||
|
||||
Vendored
-197
@@ -1,197 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: PStream.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#ifdef PERF
|
||||
#include <measure.h>
|
||||
#endif
|
||||
// #include "pstream.h" in streams.h
|
||||
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
CPersistStream::CPersistStream(IUnknown *punk, __inout HRESULT *phr)
|
||||
: mPS_fDirty(FALSE)
|
||||
{
|
||||
mPS_dwFileVersion = GetSoftwareVersion();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Destructor
|
||||
//
|
||||
CPersistStream::~CPersistStream() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
#if 0
|
||||
SAMPLE CODE TO COPY - not active at the moment
|
||||
|
||||
//
|
||||
// NonDelegatingQueryInterface
|
||||
//
|
||||
// This object supports IPersist & IPersistStream
|
||||
STDMETHODIMP CPersistStream::NonDelegatingQueryInterface(REFIID riid, __deref_out void **ppv)
|
||||
{
|
||||
if (riid == IID_IPersist) {
|
||||
return GetInterface((IPersist *) this, ppv); // ???
|
||||
}
|
||||
else if (riid == IID_IPersistStream) {
|
||||
return GetInterface((IPersistStream *) this, ppv);
|
||||
}
|
||||
else {
|
||||
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//
|
||||
// WriteToStream
|
||||
//
|
||||
// Writes to the stream (default action is to write nothing)
|
||||
HRESULT CPersistStream::WriteToStream(IStream *pStream)
|
||||
{
|
||||
// You can override this to do things like
|
||||
// hr = pStream->Write(MyStructure, sizeof(MyStructure), NULL);
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT CPersistStream::ReadFromStream(IStream * pStream)
|
||||
{
|
||||
// You can override this to do things like
|
||||
// hr = pStream->Read(MyStructure, sizeof(MyStructure), NULL);
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Load
|
||||
//
|
||||
// Load all the data from the given stream
|
||||
STDMETHODIMP CPersistStream::Load(LPSTREAM pStm)
|
||||
{
|
||||
HRESULT hr;
|
||||
// Load the version number then the data
|
||||
mPS_dwFileVersion = ReadInt(pStm, hr);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return ReadFromStream(pStm);
|
||||
} // Load
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Save
|
||||
//
|
||||
// Save the contents of this Stream.
|
||||
STDMETHODIMP CPersistStream::Save(LPSTREAM pStm, BOOL fClearDirty)
|
||||
{
|
||||
|
||||
HRESULT hr = WriteInt(pStm, GetSoftwareVersion());
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = WriteToStream(pStm);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
mPS_fDirty = !fClearDirty;
|
||||
|
||||
return hr;
|
||||
} // Save
|
||||
|
||||
|
||||
// WriteInt
|
||||
//
|
||||
// Writes an integer to an IStream as 11 UNICODE characters followed by one space.
|
||||
// You could use this for shorts or unsigneds or anything (up to 32 bits)
|
||||
// where the value isn't actually truncated by squeezing it into 32 bits.
|
||||
// Values such as (unsigned) 0x80000000 would come out as -2147483648
|
||||
// but would then load as 0x80000000 through ReadInt. Cast as you please.
|
||||
|
||||
STDAPI WriteInt(IStream *pIStream, int n)
|
||||
{
|
||||
WCHAR Buff[13]; // Allows for trailing null that we don't write
|
||||
(void)StringCchPrintfW(Buff, NUMELMS(Buff),L"%011d ",n);
|
||||
return pIStream->Write(&(Buff[0]), 12*sizeof(WCHAR), NULL);
|
||||
} // WriteInt
|
||||
|
||||
|
||||
// ReadInt
|
||||
//
|
||||
// Reads an integer from an IStream.
|
||||
// Read as 4 bytes. You could use this for shorts or unsigneds or anything
|
||||
// where the value isn't actually truncated by squeezing it into 32 bits
|
||||
// Striped down subset of what sscanf can do (without dragging in the C runtime)
|
||||
|
||||
STDAPI_(int) ReadInt(IStream *pIStream, __out HRESULT &hr)
|
||||
{
|
||||
|
||||
int Sign = 1;
|
||||
unsigned int n = 0; // result wil be n*Sign
|
||||
WCHAR wch;
|
||||
|
||||
hr = pIStream->Read( &wch, sizeof(wch), NULL);
|
||||
if (FAILED(hr)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wch==L'-'){
|
||||
Sign = -1;
|
||||
hr = pIStream->Read( &wch, sizeof(wch), NULL);
|
||||
if (FAILED(hr)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for( ; ; ) {
|
||||
if (wch>=L'0' && wch<=L'9') {
|
||||
n = 10*n+(int)(wch-L'0');
|
||||
} else if ( wch == L' '
|
||||
|| wch == L'\t'
|
||||
|| wch == L'\r'
|
||||
|| wch == L'\n'
|
||||
|| wch == L'\0'
|
||||
) {
|
||||
break;
|
||||
} else {
|
||||
hr = VFW_E_INVALID_FILE_FORMAT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
hr = pIStream->Read( &wch, sizeof(wch), NULL);
|
||||
if (FAILED(hr)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (n==0x80000000 && Sign==-1) {
|
||||
// This is the negative number that has no positive version!
|
||||
return (int)n;
|
||||
}
|
||||
else return (int)n * Sign;
|
||||
} // ReadInt
|
||||
|
||||
|
||||
// The microsoft C/C++ compile generates level 4 warnings to the effect that
|
||||
// a particular inline function (from some base class) was not needed.
|
||||
// This line gets rid of hundreds of such unwanted messages and makes
|
||||
// -W4 compilation feasible:
|
||||
#pragma warning(disable: 4514)
|
||||
Vendored
-114
@@ -1,114 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: PStream.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines a class for persistent properties
|
||||
// of filters.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __PSTREAM__
|
||||
#define __PSTREAM__
|
||||
|
||||
// Base class for persistent properties of filters
|
||||
// (i.e. filter properties in saved graphs)
|
||||
|
||||
// The simplest way to use this is:
|
||||
// 1. Arrange for your filter to inherit this class
|
||||
// 2. Implement in your class WriteToStream and ReadFromStream
|
||||
// These will override the "do nothing" functions here.
|
||||
// 3. Change your NonDelegatingQueryInterface to handle IPersistStream
|
||||
// 4. Implement SizeMax to return the number of bytes of data you save.
|
||||
// If you save UNICODE data, don't forget a char is 2 bytes.
|
||||
// 5. Whenever your data changes, call SetDirty()
|
||||
//
|
||||
// At some point you may decide to alter, or extend the format of your data.
|
||||
// At that point you will wish that you had a version number in all the old
|
||||
// saved graphs, so that you can tell, when you read them, whether they
|
||||
// represent the old or new form. To assist you in this, this class
|
||||
// writes and reads a version number.
|
||||
// When it writes, it calls GetSoftwareVersion() to enquire what version
|
||||
// of the software we have at the moment. (In effect this is a version number
|
||||
// of the data layout in the file). It writes this as the first thing in the data.
|
||||
// If you want to change the version, implement (override) GetSoftwareVersion().
|
||||
// It reads this from the file into mPS_dwFileVersion before calling ReadFromStream,
|
||||
// so in ReadFromStream you can check mPS_dwFileVersion to see if you are reading
|
||||
// an old version file.
|
||||
// Normally you should accept files whose version is no newer than the software
|
||||
// version that's reading them.
|
||||
|
||||
|
||||
// CPersistStream
|
||||
//
|
||||
// Implements IPersistStream.
|
||||
// See 'OLE Programmers Reference (Vol 1):Structured Storage Overview' for
|
||||
// more implementation information.
|
||||
class CPersistStream : public IPersistStream {
|
||||
private:
|
||||
|
||||
// Internal state:
|
||||
|
||||
protected:
|
||||
DWORD mPS_dwFileVersion; // version number of file (being read)
|
||||
BOOL mPS_fDirty;
|
||||
|
||||
public:
|
||||
|
||||
// IPersistStream methods
|
||||
|
||||
STDMETHODIMP IsDirty()
|
||||
{return (mPS_fDirty ? S_OK : S_FALSE);} // note FALSE means clean
|
||||
STDMETHODIMP Load(LPSTREAM pStm);
|
||||
STDMETHODIMP Save(LPSTREAM pStm, BOOL fClearDirty);
|
||||
STDMETHODIMP GetSizeMax(__out ULARGE_INTEGER * pcbSize)
|
||||
// Allow 24 bytes for version.
|
||||
{ pcbSize->QuadPart = 12*sizeof(WCHAR)+SizeMax(); return NOERROR; }
|
||||
|
||||
// implementation
|
||||
|
||||
CPersistStream(IUnknown *punk, __inout HRESULT *phr);
|
||||
~CPersistStream();
|
||||
|
||||
HRESULT SetDirty(BOOL fDirty)
|
||||
{ mPS_fDirty = fDirty; return NOERROR;}
|
||||
|
||||
|
||||
// override to reveal IPersist & IPersistStream
|
||||
// STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
|
||||
|
||||
// --- IPersist ---
|
||||
|
||||
// You must override this to provide your own class id
|
||||
STDMETHODIMP GetClassID(__out CLSID *pClsid) PURE;
|
||||
|
||||
// overrideable if you want
|
||||
// file version number. Override it if you ever change format
|
||||
virtual DWORD GetSoftwareVersion(void) { return 0; }
|
||||
|
||||
|
||||
//=========================================================================
|
||||
// OVERRIDE THESE to read and write your data
|
||||
// OVERRIDE THESE to read and write your data
|
||||
// OVERRIDE THESE to read and write your data
|
||||
|
||||
virtual int SizeMax() {return 0;}
|
||||
virtual HRESULT WriteToStream(IStream *pStream);
|
||||
virtual HRESULT ReadFromStream(IStream *pStream);
|
||||
//=========================================================================
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
// --- Useful helpers ---
|
||||
|
||||
|
||||
// Writes an int to an IStream as UNICODE.
|
||||
STDAPI WriteInt(IStream *pIStream, int n);
|
||||
|
||||
// inverse of WriteInt
|
||||
STDAPI_(int) ReadInt(IStream *pIStream, __out HRESULT &hr);
|
||||
|
||||
#endif // __PSTREAM__
|
||||
Vendored
-588
@@ -1,588 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: PullPin.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes - implements CPullPin class that pulls data
|
||||
// from IAsyncReader.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
#include "pullpin.h"
|
||||
|
||||
#ifdef DXMPERF
|
||||
#include "dxmperf.h"
|
||||
#endif // DXMPERF
|
||||
|
||||
|
||||
CPullPin::CPullPin()
|
||||
: m_pReader(NULL),
|
||||
m_pAlloc(NULL),
|
||||
m_State(TM_Exit)
|
||||
{
|
||||
#ifdef DXMPERF
|
||||
PERFLOG_CTOR( L"CPullPin", this );
|
||||
#endif // DXMPERF
|
||||
|
||||
}
|
||||
|
||||
CPullPin::~CPullPin()
|
||||
{
|
||||
Disconnect();
|
||||
|
||||
#ifdef DXMPERF
|
||||
PERFLOG_DTOR( L"CPullPin", this );
|
||||
#endif // DXMPERF
|
||||
|
||||
}
|
||||
|
||||
// returns S_OK if successfully connected to an IAsyncReader interface
|
||||
// from this object
|
||||
// Optional allocator should be proposed as a preferred allocator if
|
||||
// necessary
|
||||
HRESULT
|
||||
CPullPin::Connect(IUnknown* pUnk, IMemAllocator* pAlloc, BOOL bSync)
|
||||
{
|
||||
CAutoLock lock(&m_AccessLock);
|
||||
|
||||
if (m_pReader) {
|
||||
return VFW_E_ALREADY_CONNECTED;
|
||||
}
|
||||
|
||||
HRESULT hr = pUnk->QueryInterface(IID_IAsyncReader, (void**)&m_pReader);
|
||||
if (FAILED(hr)) {
|
||||
|
||||
#ifdef DXMPERF
|
||||
{
|
||||
AM_MEDIA_TYPE * pmt = NULL;
|
||||
PERFLOG_CONNECT( this, pUnk, hr, pmt );
|
||||
}
|
||||
#endif // DXMPERF
|
||||
|
||||
return(hr);
|
||||
}
|
||||
|
||||
hr = DecideAllocator(pAlloc, NULL);
|
||||
if (FAILED(hr)) {
|
||||
Disconnect();
|
||||
|
||||
#ifdef DXMPERF
|
||||
{
|
||||
AM_MEDIA_TYPE * pmt = NULL;
|
||||
PERFLOG_CONNECT( this, pUnk, hr, pmt );
|
||||
}
|
||||
#endif // DXMPERF
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
LONGLONG llTotal, llAvail;
|
||||
hr = m_pReader->Length(&llTotal, &llAvail);
|
||||
if (FAILED(hr)) {
|
||||
Disconnect();
|
||||
|
||||
#ifdef DXMPERF
|
||||
{
|
||||
AM_MEDIA_TYPE * pmt = NULL;
|
||||
PERFLOG_CONNECT( this, pUnk, hr, pmt );
|
||||
}
|
||||
#endif
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// convert from file position to reference time
|
||||
m_tDuration = llTotal * UNITS;
|
||||
m_tStop = m_tDuration;
|
||||
m_tStart = 0;
|
||||
|
||||
m_bSync = bSync;
|
||||
|
||||
#ifdef DXMPERF
|
||||
{
|
||||
AM_MEDIA_TYPE * pmt = NULL;
|
||||
PERFLOG_CONNECT( this, pUnk, S_OK, pmt );
|
||||
}
|
||||
#endif // DXMPERF
|
||||
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// disconnect any connection made in Connect
|
||||
HRESULT
|
||||
CPullPin::Disconnect()
|
||||
{
|
||||
CAutoLock lock(&m_AccessLock);
|
||||
|
||||
StopThread();
|
||||
|
||||
|
||||
#ifdef DXMPERF
|
||||
PERFLOG_DISCONNECT( this, m_pReader, S_OK );
|
||||
#endif // DXMPERF
|
||||
|
||||
|
||||
if (m_pReader) {
|
||||
m_pReader->Release();
|
||||
m_pReader = NULL;
|
||||
}
|
||||
|
||||
if (m_pAlloc) {
|
||||
m_pAlloc->Release();
|
||||
m_pAlloc = NULL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// agree an allocator using RequestAllocator - optional
|
||||
// props param specifies your requirements (non-zero fields).
|
||||
// returns an error code if fail to match requirements.
|
||||
// optional IMemAllocator interface is offered as a preferred allocator
|
||||
// but no error occurs if it can't be met.
|
||||
HRESULT
|
||||
CPullPin::DecideAllocator(
|
||||
IMemAllocator * pAlloc,
|
||||
__inout_opt ALLOCATOR_PROPERTIES * pProps)
|
||||
{
|
||||
ALLOCATOR_PROPERTIES *pRequest;
|
||||
ALLOCATOR_PROPERTIES Request;
|
||||
if (pProps == NULL) {
|
||||
Request.cBuffers = 3;
|
||||
Request.cbBuffer = 64*1024;
|
||||
Request.cbAlign = 0;
|
||||
Request.cbPrefix = 0;
|
||||
pRequest = &Request;
|
||||
} else {
|
||||
pRequest = pProps;
|
||||
}
|
||||
HRESULT hr = m_pReader->RequestAllocator(
|
||||
pAlloc,
|
||||
pRequest,
|
||||
&m_pAlloc);
|
||||
return hr;
|
||||
}
|
||||
|
||||
// start pulling data
|
||||
HRESULT
|
||||
CPullPin::Active(void)
|
||||
{
|
||||
ASSERT(!ThreadExists());
|
||||
return StartThread();
|
||||
}
|
||||
|
||||
// stop pulling data
|
||||
HRESULT
|
||||
CPullPin::Inactive(void)
|
||||
{
|
||||
StopThread();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CPullPin::Seek(REFERENCE_TIME tStart, REFERENCE_TIME tStop)
|
||||
{
|
||||
CAutoLock lock(&m_AccessLock);
|
||||
|
||||
ThreadMsg AtStart = m_State;
|
||||
|
||||
if (AtStart == TM_Start) {
|
||||
BeginFlush();
|
||||
PauseThread();
|
||||
EndFlush();
|
||||
}
|
||||
|
||||
m_tStart = tStart;
|
||||
m_tStop = tStop;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
if (AtStart == TM_Start) {
|
||||
hr = StartThread();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CPullPin::Duration(__out REFERENCE_TIME* ptDuration)
|
||||
{
|
||||
*ptDuration = m_tDuration;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
HRESULT
|
||||
CPullPin::StartThread()
|
||||
{
|
||||
CAutoLock lock(&m_AccessLock);
|
||||
|
||||
if (!m_pAlloc || !m_pReader) {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
if (!ThreadExists()) {
|
||||
|
||||
// commit allocator
|
||||
hr = m_pAlloc->Commit();
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
// start thread
|
||||
if (!Create()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
m_State = TM_Start;
|
||||
hr = (HRESULT) CallWorker(m_State);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CPullPin::PauseThread()
|
||||
{
|
||||
CAutoLock lock(&m_AccessLock);
|
||||
|
||||
if (!ThreadExists()) {
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
// need to flush to ensure the thread is not blocked
|
||||
// in WaitForNext
|
||||
HRESULT hr = m_pReader->BeginFlush();
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
m_State = TM_Pause;
|
||||
hr = CallWorker(TM_Pause);
|
||||
|
||||
m_pReader->EndFlush();
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CPullPin::StopThread()
|
||||
{
|
||||
CAutoLock lock(&m_AccessLock);
|
||||
|
||||
if (!ThreadExists()) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
// need to flush to ensure the thread is not blocked
|
||||
// in WaitForNext
|
||||
HRESULT hr = m_pReader->BeginFlush();
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
m_State = TM_Exit;
|
||||
hr = CallWorker(TM_Exit);
|
||||
|
||||
m_pReader->EndFlush();
|
||||
|
||||
// wait for thread to completely exit
|
||||
Close();
|
||||
|
||||
// decommit allocator
|
||||
if (m_pAlloc) {
|
||||
m_pAlloc->Decommit();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
DWORD
|
||||
CPullPin::ThreadProc(void)
|
||||
{
|
||||
while(1) {
|
||||
DWORD cmd = GetRequest();
|
||||
switch(cmd) {
|
||||
case TM_Exit:
|
||||
Reply(S_OK);
|
||||
return 0;
|
||||
|
||||
case TM_Pause:
|
||||
// we are paused already
|
||||
Reply(S_OK);
|
||||
break;
|
||||
|
||||
case TM_Start:
|
||||
Reply(S_OK);
|
||||
Process();
|
||||
break;
|
||||
}
|
||||
|
||||
// at this point, there should be no outstanding requests on the
|
||||
// upstream filter.
|
||||
// We should force begin/endflush to ensure that this is true.
|
||||
// !!!Note that we may currently be inside a BeginFlush/EndFlush pair
|
||||
// on another thread, but the premature EndFlush will do no harm now
|
||||
// that we are idle.
|
||||
m_pReader->BeginFlush();
|
||||
CleanupCancelled();
|
||||
m_pReader->EndFlush();
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CPullPin::QueueSample(
|
||||
__inout REFERENCE_TIME& tCurrent,
|
||||
REFERENCE_TIME tAlignStop,
|
||||
BOOL bDiscontinuity
|
||||
)
|
||||
{
|
||||
IMediaSample* pSample;
|
||||
|
||||
HRESULT hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS);
|
||||
if (tStopThis > tAlignStop) {
|
||||
tStopThis = tAlignStop;
|
||||
}
|
||||
pSample->SetTime(&tCurrent, &tStopThis);
|
||||
tCurrent = tStopThis;
|
||||
|
||||
pSample->SetDiscontinuity(bDiscontinuity);
|
||||
|
||||
hr = m_pReader->Request(
|
||||
pSample,
|
||||
0);
|
||||
if (FAILED(hr)) {
|
||||
pSample->Release();
|
||||
|
||||
CleanupCancelled();
|
||||
OnError(hr);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CPullPin::CollectAndDeliver(
|
||||
REFERENCE_TIME tStart,
|
||||
REFERENCE_TIME tStop)
|
||||
{
|
||||
IMediaSample* pSample = NULL; // better be sure pSample is set
|
||||
DWORD_PTR dwUnused;
|
||||
HRESULT hr = m_pReader->WaitForNext(
|
||||
INFINITE,
|
||||
&pSample,
|
||||
&dwUnused);
|
||||
if (FAILED(hr)) {
|
||||
if (pSample) {
|
||||
pSample->Release();
|
||||
}
|
||||
} else {
|
||||
hr = DeliverSample(pSample, tStart, tStop);
|
||||
}
|
||||
if (FAILED(hr)) {
|
||||
CleanupCancelled();
|
||||
OnError(hr);
|
||||
}
|
||||
return hr;
|
||||
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CPullPin::DeliverSample(
|
||||
IMediaSample* pSample,
|
||||
REFERENCE_TIME tStart,
|
||||
REFERENCE_TIME tStop
|
||||
)
|
||||
{
|
||||
// fix up sample if past actual stop (for sector alignment)
|
||||
REFERENCE_TIME t1, t2;
|
||||
if (S_OK == pSample->GetTime(&t1, &t2)) {
|
||||
if (t2 > tStop) {
|
||||
t2 = tStop;
|
||||
}
|
||||
|
||||
// adjust times to be relative to (aligned) start time
|
||||
t1 -= tStart;
|
||||
t2 -= tStart;
|
||||
HRESULT hr = pSample->SetTime(&t1, &t2);
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DXMPERF
|
||||
{
|
||||
AM_MEDIA_TYPE * pmt = NULL;
|
||||
pSample->GetMediaType( &pmt );
|
||||
PERFLOG_RECEIVE( L"CPullPin", m_pReader, this, pSample, pmt );
|
||||
}
|
||||
#endif
|
||||
|
||||
HRESULT hr = Receive(pSample);
|
||||
pSample->Release();
|
||||
return hr;
|
||||
}
|
||||
|
||||
void
|
||||
CPullPin::Process(void)
|
||||
{
|
||||
// is there anything to do?
|
||||
if (m_tStop <= m_tStart) {
|
||||
EndOfStream();
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL bDiscontinuity = TRUE;
|
||||
|
||||
// if there is more than one sample at the allocator,
|
||||
// then try to queue 2 at once in order to overlap.
|
||||
// -- get buffer count and required alignment
|
||||
ALLOCATOR_PROPERTIES Actual;
|
||||
HRESULT hr = m_pAlloc->GetProperties(&Actual);
|
||||
|
||||
// align the start position downwards
|
||||
REFERENCE_TIME tStart = AlignDown(m_tStart / UNITS, Actual.cbAlign) * UNITS;
|
||||
REFERENCE_TIME tCurrent = tStart;
|
||||
|
||||
REFERENCE_TIME tStop = m_tStop;
|
||||
if (tStop > m_tDuration) {
|
||||
tStop = m_tDuration;
|
||||
}
|
||||
|
||||
// align the stop position - may be past stop, but that
|
||||
// doesn't matter
|
||||
REFERENCE_TIME tAlignStop = AlignUp(tStop / UNITS, Actual.cbAlign) * UNITS;
|
||||
|
||||
|
||||
DWORD dwRequest;
|
||||
|
||||
if (!m_bSync) {
|
||||
|
||||
// Break out of the loop either if we get to the end or we're asked
|
||||
// to do something else
|
||||
while (tCurrent < tAlignStop) {
|
||||
|
||||
// Break out without calling EndOfStream if we're asked to
|
||||
// do something different
|
||||
if (CheckRequest(&dwRequest)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// queue a first sample
|
||||
if (Actual.cBuffers > 1) {
|
||||
|
||||
hr = QueueSample(tCurrent, tAlignStop, TRUE);
|
||||
bDiscontinuity = FALSE;
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// loop queueing second and waiting for first..
|
||||
while (tCurrent < tAlignStop) {
|
||||
|
||||
hr = QueueSample(tCurrent, tAlignStop, bDiscontinuity);
|
||||
bDiscontinuity = FALSE;
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
hr = CollectAndDeliver(tStart, tStop);
|
||||
if (S_OK != hr) {
|
||||
|
||||
// stop if error, or if downstream filter said
|
||||
// to stop.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Actual.cBuffers > 1) {
|
||||
hr = CollectAndDeliver(tStart, tStop);
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
// sync version of above loop
|
||||
while (tCurrent < tAlignStop) {
|
||||
|
||||
// Break out without calling EndOfStream if we're asked to
|
||||
// do something different
|
||||
if (CheckRequest(&dwRequest)) {
|
||||
return;
|
||||
}
|
||||
|
||||
IMediaSample* pSample;
|
||||
|
||||
hr = m_pAlloc->GetBuffer(&pSample, NULL, NULL, 0);
|
||||
if (FAILED(hr)) {
|
||||
OnError(hr);
|
||||
return;
|
||||
}
|
||||
|
||||
LONGLONG tStopThis = tCurrent + (pSample->GetSize() * UNITS);
|
||||
if (tStopThis > tAlignStop) {
|
||||
tStopThis = tAlignStop;
|
||||
}
|
||||
pSample->SetTime(&tCurrent, &tStopThis);
|
||||
tCurrent = tStopThis;
|
||||
|
||||
if (bDiscontinuity) {
|
||||
pSample->SetDiscontinuity(TRUE);
|
||||
bDiscontinuity = FALSE;
|
||||
}
|
||||
|
||||
hr = m_pReader->SyncReadAligned(pSample);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
pSample->Release();
|
||||
OnError(hr);
|
||||
return;
|
||||
}
|
||||
|
||||
hr = DeliverSample(pSample, tStart, tStop);
|
||||
if (hr != S_OK) {
|
||||
if (FAILED(hr)) {
|
||||
OnError(hr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EndOfStream();
|
||||
}
|
||||
|
||||
// after a flush, cancelled i/o will be waiting for collection
|
||||
// and release
|
||||
void
|
||||
CPullPin::CleanupCancelled(void)
|
||||
{
|
||||
while (1) {
|
||||
IMediaSample * pSample;
|
||||
DWORD_PTR dwUnused;
|
||||
|
||||
HRESULT hr = m_pReader->WaitForNext(
|
||||
0, // no wait
|
||||
&pSample,
|
||||
&dwUnused);
|
||||
if(pSample) {
|
||||
pSample->Release();
|
||||
} else {
|
||||
// no more samples
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
-152
@@ -1,152 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: PullPin.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines CPullPin class.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __PULLPIN_H__
|
||||
#define __PULLPIN_H__
|
||||
|
||||
//
|
||||
// CPullPin
|
||||
//
|
||||
// object supporting pulling data from an IAsyncReader interface.
|
||||
// Given a start/stop position, calls a pure Receive method with each
|
||||
// IMediaSample received.
|
||||
//
|
||||
// This is essentially for use in a MemInputPin when it finds itself
|
||||
// connected to an IAsyncReader pin instead of a pushing pin.
|
||||
//
|
||||
|
||||
class CPullPin : public CAMThread
|
||||
{
|
||||
IAsyncReader* m_pReader;
|
||||
REFERENCE_TIME m_tStart;
|
||||
REFERENCE_TIME m_tStop;
|
||||
REFERENCE_TIME m_tDuration;
|
||||
BOOL m_bSync;
|
||||
|
||||
enum ThreadMsg {
|
||||
TM_Pause, // stop pulling and wait for next message
|
||||
TM_Start, // start pulling
|
||||
TM_Exit, // stop and exit
|
||||
};
|
||||
|
||||
ThreadMsg m_State;
|
||||
|
||||
// override pure thread proc from CAMThread
|
||||
DWORD ThreadProc(void);
|
||||
|
||||
// running pull method (check m_bSync)
|
||||
void Process(void);
|
||||
|
||||
// clean up any cancelled i/o after a flush
|
||||
void CleanupCancelled(void);
|
||||
|
||||
// suspend thread from pulling, eg during seek
|
||||
HRESULT PauseThread();
|
||||
|
||||
// start thread pulling - create thread if necy
|
||||
HRESULT StartThread();
|
||||
|
||||
// stop and close thread
|
||||
HRESULT StopThread();
|
||||
|
||||
// called from ProcessAsync to queue and collect requests
|
||||
HRESULT QueueSample(
|
||||
__inout REFERENCE_TIME& tCurrent,
|
||||
REFERENCE_TIME tAlignStop,
|
||||
BOOL bDiscontinuity);
|
||||
|
||||
HRESULT CollectAndDeliver(
|
||||
REFERENCE_TIME tStart,
|
||||
REFERENCE_TIME tStop);
|
||||
|
||||
HRESULT DeliverSample(
|
||||
IMediaSample* pSample,
|
||||
REFERENCE_TIME tStart,
|
||||
REFERENCE_TIME tStop);
|
||||
|
||||
protected:
|
||||
IMemAllocator * m_pAlloc;
|
||||
|
||||
public:
|
||||
CPullPin();
|
||||
virtual ~CPullPin();
|
||||
|
||||
// returns S_OK if successfully connected to an IAsyncReader interface
|
||||
// from this object
|
||||
// Optional allocator should be proposed as a preferred allocator if
|
||||
// necessary
|
||||
// bSync is TRUE if we are to use sync reads instead of the
|
||||
// async methods.
|
||||
HRESULT Connect(IUnknown* pUnk, IMemAllocator* pAlloc, BOOL bSync);
|
||||
|
||||
// disconnect any connection made in Connect
|
||||
HRESULT Disconnect();
|
||||
|
||||
// agree an allocator using RequestAllocator - optional
|
||||
// props param specifies your requirements (non-zero fields).
|
||||
// returns an error code if fail to match requirements.
|
||||
// optional IMemAllocator interface is offered as a preferred allocator
|
||||
// but no error occurs if it can't be met.
|
||||
virtual HRESULT DecideAllocator(
|
||||
IMemAllocator* pAlloc,
|
||||
__inout_opt ALLOCATOR_PROPERTIES * pProps);
|
||||
|
||||
// set start and stop position. if active, will start immediately at
|
||||
// the new position. Default is 0 to duration
|
||||
HRESULT Seek(REFERENCE_TIME tStart, REFERENCE_TIME tStop);
|
||||
|
||||
// return the total duration
|
||||
HRESULT Duration(__out REFERENCE_TIME* ptDuration);
|
||||
|
||||
// start pulling data
|
||||
HRESULT Active(void);
|
||||
|
||||
// stop pulling data
|
||||
HRESULT Inactive(void);
|
||||
|
||||
// helper functions
|
||||
LONGLONG AlignDown(LONGLONG ll, LONG lAlign) {
|
||||
// aligning downwards is just truncation
|
||||
return ll & ~(lAlign-1);
|
||||
};
|
||||
|
||||
LONGLONG AlignUp(LONGLONG ll, LONG lAlign) {
|
||||
// align up: round up to next boundary
|
||||
return (ll + (lAlign -1)) & ~(lAlign -1);
|
||||
};
|
||||
|
||||
// GetReader returns the (addrefed) IAsyncReader interface
|
||||
// for SyncRead etc
|
||||
IAsyncReader* GetReader() {
|
||||
m_pReader->AddRef();
|
||||
return m_pReader;
|
||||
};
|
||||
|
||||
// -- pure --
|
||||
|
||||
// override this to handle data arrival
|
||||
// return value other than S_OK will stop data
|
||||
virtual HRESULT Receive(IMediaSample*) PURE;
|
||||
|
||||
// override this to handle end-of-stream
|
||||
virtual HRESULT EndOfStream(void) PURE;
|
||||
|
||||
// called on runtime errors that will have caused pulling
|
||||
// to stop
|
||||
// these errors are all returned from the upstream filter, who
|
||||
// will have already reported any errors to the filtergraph.
|
||||
virtual void OnError(HRESULT hr) PURE;
|
||||
|
||||
// flush this pin and all downstream
|
||||
virtual HRESULT BeginFlush() PURE;
|
||||
virtual HRESULT EndFlush() PURE;
|
||||
|
||||
};
|
||||
|
||||
#endif //__PULLPIN_H__
|
||||
Vendored
-402
@@ -1,402 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: RefClock.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes - implements the IReferenceClock interface.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef DXMPERF
|
||||
#include "dxmperf.h"
|
||||
#endif // DXMPERF
|
||||
|
||||
|
||||
// 'this' used in constructor list
|
||||
#pragma warning(disable:4355)
|
||||
|
||||
|
||||
STDMETHODIMP CBaseReferenceClock::NonDelegatingQueryInterface(
|
||||
REFIID riid,
|
||||
__deref_out void ** ppv)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (riid == IID_IReferenceClock)
|
||||
{
|
||||
hr = GetInterface((IReferenceClock *) this, ppv);
|
||||
}
|
||||
else if (riid == IID_IReferenceClockTimerControl)
|
||||
{
|
||||
hr = GetInterface((IReferenceClockTimerControl *) this, ppv);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
CBaseReferenceClock::~CBaseReferenceClock()
|
||||
{
|
||||
#ifdef DXMPERF
|
||||
PERFLOG_DTOR( L"CBaseReferenceClock", (IReferenceClock *) this );
|
||||
#endif // DXMPERF
|
||||
|
||||
if (m_TimerResolution) timeEndPeriod(m_TimerResolution);
|
||||
|
||||
if (m_pSchedule)
|
||||
{
|
||||
m_pSchedule->DumpLinkedList();
|
||||
}
|
||||
|
||||
if (m_hThread)
|
||||
{
|
||||
m_bAbort = TRUE;
|
||||
TriggerThread();
|
||||
WaitForSingleObject( m_hThread, INFINITE );
|
||||
EXECUTE_ASSERT( CloseHandle(m_hThread) );
|
||||
m_hThread = 0;
|
||||
EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) );
|
||||
delete m_pSchedule;
|
||||
}
|
||||
}
|
||||
|
||||
// A derived class may supply a hThreadEvent if it has its own thread that will take care
|
||||
// of calling the schedulers Advise method. (Refere to CBaseReferenceClock::AdviseThread()
|
||||
// to see what such a thread has to do.)
|
||||
CBaseReferenceClock::CBaseReferenceClock( __in_opt LPCTSTR pName,
|
||||
__inout_opt LPUNKNOWN pUnk,
|
||||
__inout HRESULT *phr,
|
||||
__inout_opt CAMSchedule * pShed )
|
||||
: CUnknown( pName, pUnk )
|
||||
, m_rtLastGotTime(0)
|
||||
, m_TimerResolution(0)
|
||||
, m_bAbort( FALSE )
|
||||
, m_pSchedule( pShed ? pShed : new CAMSchedule(CreateEvent(NULL, FALSE, FALSE, NULL)) )
|
||||
, m_hThread(0)
|
||||
{
|
||||
|
||||
#ifdef DXMPERF
|
||||
PERFLOG_CTOR( pName ? pName : L"CBaseReferenceClock", (IReferenceClock *) this );
|
||||
#endif // DXMPERF
|
||||
|
||||
ASSERT(m_pSchedule);
|
||||
if (!m_pSchedule)
|
||||
{
|
||||
*phr = E_OUTOFMEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set up the highest resolution timer we can manage
|
||||
TIMECAPS tc;
|
||||
m_TimerResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc)))
|
||||
? tc.wPeriodMin
|
||||
: 1;
|
||||
|
||||
timeBeginPeriod(m_TimerResolution);
|
||||
|
||||
/* Initialise our system times - the derived clock should set the right values */
|
||||
m_dwPrevSystemTime = timeGetTime();
|
||||
m_rtPrivateTime = (UNITS / MILLISECONDS) * m_dwPrevSystemTime;
|
||||
|
||||
#ifdef PERF
|
||||
m_idGetSystemTime = MSR_REGISTER(TEXT("CBaseReferenceClock::GetTime"));
|
||||
#endif
|
||||
|
||||
if ( !pShed )
|
||||
{
|
||||
DWORD ThreadID;
|
||||
m_hThread = ::CreateThread(NULL, // Security attributes
|
||||
(DWORD) 0, // Initial stack size
|
||||
AdviseThreadFunction, // Thread start address
|
||||
(LPVOID) this, // Thread parameter
|
||||
(DWORD) 0, // Creation flags
|
||||
&ThreadID); // Thread identifier
|
||||
|
||||
if (m_hThread)
|
||||
{
|
||||
SetThreadPriority( m_hThread, THREAD_PRIORITY_TIME_CRITICAL );
|
||||
}
|
||||
else
|
||||
{
|
||||
*phr = E_FAIL;
|
||||
EXECUTE_ASSERT( CloseHandle(m_pSchedule->GetEvent()) );
|
||||
delete m_pSchedule;
|
||||
m_pSchedule = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBaseReferenceClock::Restart (IN REFERENCE_TIME rtMinTime)
|
||||
{
|
||||
Lock();
|
||||
m_rtLastGotTime = rtMinTime ;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
STDMETHODIMP CBaseReferenceClock::GetTime(__out REFERENCE_TIME *pTime)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (pTime)
|
||||
{
|
||||
REFERENCE_TIME rtNow;
|
||||
Lock();
|
||||
rtNow = GetPrivateTime();
|
||||
if (rtNow > m_rtLastGotTime)
|
||||
{
|
||||
m_rtLastGotTime = rtNow;
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
*pTime = m_rtLastGotTime;
|
||||
Unlock();
|
||||
MSR_INTEGER(m_idGetSystemTime, LONG((*pTime) / (UNITS/MILLISECONDS)) );
|
||||
|
||||
#ifdef DXMPERF
|
||||
PERFLOG_GETTIME( (IReferenceClock *) this, *pTime );
|
||||
#endif // DXMPERF
|
||||
|
||||
}
|
||||
else hr = E_POINTER;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/* Ask for an async notification that a time has elapsed */
|
||||
|
||||
STDMETHODIMP CBaseReferenceClock::AdviseTime(
|
||||
REFERENCE_TIME baseTime, // base reference time
|
||||
REFERENCE_TIME streamTime, // stream offset time
|
||||
HEVENT hEvent, // advise via this event
|
||||
__out DWORD_PTR *pdwAdviseCookie)// where your cookie goes
|
||||
{
|
||||
CheckPointer(pdwAdviseCookie, E_POINTER);
|
||||
*pdwAdviseCookie = 0;
|
||||
|
||||
// Check that the event is not already set
|
||||
ASSERT(WAIT_TIMEOUT == WaitForSingleObject(HANDLE(hEvent),0));
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
const REFERENCE_TIME lRefTime = baseTime + streamTime;
|
||||
if ( lRefTime <= 0 || lRefTime == MAX_TIME )
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdwAdviseCookie = m_pSchedule->AddAdvisePacket( lRefTime, 0, HANDLE(hEvent), FALSE );
|
||||
hr = *pdwAdviseCookie ? NOERROR : E_OUTOFMEMORY;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
/* Ask for an asynchronous periodic notification that a time has elapsed */
|
||||
|
||||
STDMETHODIMP CBaseReferenceClock::AdvisePeriodic(
|
||||
REFERENCE_TIME StartTime, // starting at this time
|
||||
REFERENCE_TIME PeriodTime, // time between notifications
|
||||
HSEMAPHORE hSemaphore, // advise via a semaphore
|
||||
__out DWORD_PTR *pdwAdviseCookie) // where your cookie goes
|
||||
{
|
||||
CheckPointer(pdwAdviseCookie, E_POINTER);
|
||||
*pdwAdviseCookie = 0;
|
||||
|
||||
HRESULT hr;
|
||||
if (StartTime > 0 && PeriodTime > 0 && StartTime != MAX_TIME )
|
||||
{
|
||||
*pdwAdviseCookie = m_pSchedule->AddAdvisePacket( StartTime, PeriodTime, HANDLE(hSemaphore), TRUE );
|
||||
hr = *pdwAdviseCookie ? NOERROR : E_OUTOFMEMORY;
|
||||
}
|
||||
else hr = E_INVALIDARG;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CBaseReferenceClock::Unadvise(DWORD_PTR dwAdviseCookie)
|
||||
{
|
||||
return m_pSchedule->Unadvise(dwAdviseCookie);
|
||||
}
|
||||
|
||||
|
||||
REFERENCE_TIME CBaseReferenceClock::GetPrivateTime()
|
||||
{
|
||||
CAutoLock cObjectLock(this);
|
||||
|
||||
|
||||
/* If the clock has wrapped then the current time will be less than
|
||||
* the last time we were notified so add on the extra milliseconds
|
||||
*
|
||||
* The time period is long enough so that the likelihood of
|
||||
* successive calls spanning the clock cycle is not considered.
|
||||
*/
|
||||
|
||||
DWORD dwTime = timeGetTime();
|
||||
{
|
||||
m_rtPrivateTime += Int32x32To64(UNITS / MILLISECONDS, (DWORD)(dwTime - m_dwPrevSystemTime));
|
||||
m_dwPrevSystemTime = dwTime;
|
||||
}
|
||||
|
||||
return m_rtPrivateTime;
|
||||
}
|
||||
|
||||
|
||||
/* Adjust the current time by the input value. This allows an
|
||||
external time source to work out some of the latency of the clock
|
||||
system and adjust the "current" time accordingly. The intent is
|
||||
that the time returned to the user is synchronised to a clock
|
||||
source and allows drift to be catered for.
|
||||
|
||||
For example: if the clock source detects a drift it can pass a delta
|
||||
to the current time rather than having to set an explicit time.
|
||||
*/
|
||||
|
||||
STDMETHODIMP CBaseReferenceClock::SetTimeDelta(const REFERENCE_TIME & TimeDelta)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
||||
// Just break if passed an improper time delta value
|
||||
LONGLONG llDelta = TimeDelta > 0 ? TimeDelta : -TimeDelta;
|
||||
if (llDelta > UNITS * 1000) {
|
||||
DbgLog((LOG_TRACE, 0, TEXT("Bad Time Delta")));
|
||||
//DebugBreak();
|
||||
}
|
||||
|
||||
// We're going to calculate a "severity" for the time change. Max -1
|
||||
// min 8. We'll then use this as the debug logging level for a
|
||||
// debug log message.
|
||||
const LONG usDelta = LONG(TimeDelta/10); // Delta in micro-secs
|
||||
|
||||
DWORD delta = abs(usDelta); // varying delta
|
||||
// Severity == 8 - ceil(log<base 8>(abs( micro-secs delta)))
|
||||
int Severity = 8;
|
||||
while ( delta > 0 )
|
||||
{
|
||||
delta >>= 3; // div 8
|
||||
Severity--;
|
||||
}
|
||||
|
||||
// Sev == 0 => > 2 second delta!
|
||||
DbgLog((LOG_TIMING, Severity < 0 ? 0 : Severity,
|
||||
TEXT("Sev %2i: CSystemClock::SetTimeDelta(%8ld us) %lu -> %lu ms."),
|
||||
Severity, usDelta, DWORD(ConvertToMilliseconds(m_rtPrivateTime)),
|
||||
DWORD(ConvertToMilliseconds(TimeDelta+m_rtPrivateTime)) ));
|
||||
|
||||
// Don't want the DbgBreak to fire when running stress on debug-builds.
|
||||
#ifdef BREAK_ON_SEVERE_TIME_DELTA
|
||||
if (Severity < 0)
|
||||
DbgBreakPoint(TEXT("SetTimeDelta > 16 seconds!"),
|
||||
TEXT(__FILE__),__LINE__);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
CAutoLock cObjectLock(this);
|
||||
m_rtPrivateTime += TimeDelta;
|
||||
// If time goes forwards, and we have advises, then we need to
|
||||
// trigger the thread so that it can re-evaluate its wait time.
|
||||
// Since we don't want the cost of the thread switches if the change
|
||||
// is really small, only do it if clock goes forward by more than
|
||||
// 0.5 millisecond. If the time goes backwards, the thread will
|
||||
// wake up "early" (relativly speaking) and will re-evaluate at
|
||||
// that time.
|
||||
if ( TimeDelta > 5000 && m_pSchedule->GetAdviseCount() > 0 ) TriggerThread();
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
// Thread stuff
|
||||
|
||||
DWORD __stdcall CBaseReferenceClock::AdviseThreadFunction(__in LPVOID p)
|
||||
{
|
||||
return DWORD(reinterpret_cast<CBaseReferenceClock*>(p)->AdviseThread());
|
||||
}
|
||||
|
||||
HRESULT CBaseReferenceClock::AdviseThread()
|
||||
{
|
||||
DWORD dwWait = INFINITE;
|
||||
|
||||
// The first thing we do is wait until something interesting happens
|
||||
// (meaning a first advise or shutdown). This prevents us calling
|
||||
// GetPrivateTime immediately which is goodness as that is a virtual
|
||||
// routine and the derived class may not yet be constructed. (This
|
||||
// thread is created in the base class constructor.)
|
||||
|
||||
while ( !m_bAbort )
|
||||
{
|
||||
// Wait for an interesting event to happen
|
||||
DbgLog((LOG_TIMING, 3, TEXT("CBaseRefClock::AdviseThread() Delay: %lu ms"), dwWait ));
|
||||
WaitForSingleObject(m_pSchedule->GetEvent(), dwWait);
|
||||
if (m_bAbort) break;
|
||||
|
||||
// There are several reasons why we need to work from the internal
|
||||
// time, mainly to do with what happens when time goes backwards.
|
||||
// Mainly, it stop us looping madly if an event is just about to
|
||||
// expire when the clock goes backward (i.e. GetTime stop for a
|
||||
// while).
|
||||
const REFERENCE_TIME rtNow = GetPrivateTime();
|
||||
|
||||
DbgLog((LOG_TIMING, 3,
|
||||
TEXT("CBaseRefClock::AdviseThread() Woke at = %lu ms"),
|
||||
ConvertToMilliseconds(rtNow) ));
|
||||
|
||||
// We must add in a millisecond, since this is the resolution of our
|
||||
// WaitForSingleObject timer. Failure to do so will cause us to loop
|
||||
// franticly for (approx) 1 a millisecond.
|
||||
m_rtNextAdvise = m_pSchedule->Advise( 10000 + rtNow );
|
||||
LONGLONG llWait = m_rtNextAdvise - rtNow;
|
||||
|
||||
ASSERT( llWait > 0 );
|
||||
|
||||
llWait = ConvertToMilliseconds(llWait);
|
||||
// DON'T replace this with a max!! (The type's of these things is VERY important)
|
||||
dwWait = (llWait > REFERENCE_TIME(UINT_MAX)) ? UINT_MAX : DWORD(llWait);
|
||||
};
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT CBaseReferenceClock::SetDefaultTimerResolution(
|
||||
REFERENCE_TIME timerResolution // in 100ns
|
||||
)
|
||||
{
|
||||
CAutoLock cObjectLock(this);
|
||||
if( 0 == timerResolution ) {
|
||||
if( m_TimerResolution ) {
|
||||
timeEndPeriod( m_TimerResolution );
|
||||
m_TimerResolution = 0;
|
||||
}
|
||||
} else {
|
||||
TIMECAPS tc;
|
||||
DWORD dwMinResolution = (TIMERR_NOERROR == timeGetDevCaps(&tc, sizeof(tc)))
|
||||
? tc.wPeriodMin
|
||||
: 1;
|
||||
DWORD dwResolution = max( dwMinResolution, DWORD(timerResolution / 10000) );
|
||||
if( dwResolution != m_TimerResolution ) {
|
||||
timeEndPeriod(m_TimerResolution);
|
||||
m_TimerResolution = dwResolution;
|
||||
timeBeginPeriod( m_TimerResolution );
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT CBaseReferenceClock::GetDefaultTimerResolution(
|
||||
__out REFERENCE_TIME* pTimerResolution // in 100ns
|
||||
)
|
||||
{
|
||||
if( !pTimerResolution ) {
|
||||
return E_POINTER;
|
||||
}
|
||||
CAutoLock cObjectLock(this);
|
||||
*pTimerResolution = m_TimerResolution * 10000;
|
||||
return S_OK;
|
||||
}
|
||||
Vendored
-184
@@ -1,184 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: RefClock.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines the IReferenceClock interface.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __BASEREFCLOCK__
|
||||
#define __BASEREFCLOCK__
|
||||
|
||||
#include <Schedule.h>
|
||||
|
||||
const UINT RESOLUTION = 1; /* High resolution timer */
|
||||
const INT ADVISE_CACHE = 4; /* Default cache size */
|
||||
const LONGLONG MAX_TIME = 0x7FFFFFFFFFFFFFFF; /* Maximum LONGLONG value */
|
||||
|
||||
inline LONGLONG WINAPI ConvertToMilliseconds(const REFERENCE_TIME& RT)
|
||||
{
|
||||
/* This converts an arbitrary value representing a reference time
|
||||
into a MILLISECONDS value for use in subsequent system calls */
|
||||
|
||||
return (RT / (UNITS / MILLISECONDS));
|
||||
}
|
||||
|
||||
/* This class hierarchy will support an IReferenceClock interface so
|
||||
that an audio card (or other externally driven clock) can update the
|
||||
system wide clock that everyone uses.
|
||||
|
||||
The interface will be pretty thin with probably just one update method
|
||||
This interface has not yet been defined.
|
||||
*/
|
||||
|
||||
/* This abstract base class implements the IReferenceClock
|
||||
* interface. Classes that actually provide clock signals (from
|
||||
* whatever source) have to be derived from this class.
|
||||
*
|
||||
* The abstract class provides implementations for:
|
||||
* CUnknown support
|
||||
* locking support (CCritSec)
|
||||
* client advise code (creates a thread)
|
||||
*
|
||||
* Question: what can we do about quality? Change the timer
|
||||
* resolution to lower the system load? Up the priority of the
|
||||
* timer thread to force more responsive signals?
|
||||
*
|
||||
* During class construction we create a worker thread that is destroyed during
|
||||
* destuction. This thread executes a series of WaitForSingleObject calls,
|
||||
* waking up when a command is given to the thread or the next wake up point
|
||||
* is reached. The wakeup points are determined by clients making Advise
|
||||
* calls.
|
||||
*
|
||||
* Each advise call defines a point in time when they wish to be notified. A
|
||||
* periodic advise is a series of these such events. We maintain a list of
|
||||
* advise links and calculate when the nearest event notification is due for.
|
||||
* We then call WaitForSingleObject with a timeout equal to this time. The
|
||||
* handle we wait on is used by the class to signal that something has changed
|
||||
* and that we must reschedule the next event. This typically happens when
|
||||
* someone comes in and asks for an advise link while we are waiting for an
|
||||
* event to timeout.
|
||||
*
|
||||
* While we are modifying the list of advise requests we
|
||||
* are protected from interference through a critical section. Clients are NOT
|
||||
* advised through callbacks. One shot clients have an event set, while
|
||||
* periodic clients have a semaphore released for each event notification. A
|
||||
* semaphore allows a client to be kept up to date with the number of events
|
||||
* actually triggered and be assured that they can't miss multiple events being
|
||||
* set.
|
||||
*
|
||||
* Keeping track of advises is taken care of by the CAMSchedule class.
|
||||
*/
|
||||
|
||||
class CBaseReferenceClock
|
||||
: public CUnknown, public IReferenceClock, public CCritSec, public IReferenceClockTimerControl
|
||||
{
|
||||
protected:
|
||||
virtual ~CBaseReferenceClock(); // Don't let me be created on the stack!
|
||||
public:
|
||||
CBaseReferenceClock(__in_opt LPCTSTR pName,
|
||||
__inout_opt LPUNKNOWN pUnk,
|
||||
__inout HRESULT *phr,
|
||||
__inout_opt CAMSchedule * pSched = 0 );
|
||||
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
|
||||
|
||||
DECLARE_IUNKNOWN
|
||||
|
||||
/* IReferenceClock methods */
|
||||
// Derived classes must implement GetPrivateTime(). All our GetTime
|
||||
// does is call GetPrivateTime and then check so that time does not
|
||||
// go backwards. A return code of S_FALSE implies that the internal
|
||||
// clock has gone backwards and GetTime time has halted until internal
|
||||
// time has caught up. (Don't know if this will be much use to folk,
|
||||
// but it seems odd not to use the return code for something useful.)
|
||||
STDMETHODIMP GetTime(__out REFERENCE_TIME *pTime);
|
||||
// When this is called, it sets m_rtLastGotTime to the time it returns.
|
||||
|
||||
/* Provide standard mechanisms for scheduling events */
|
||||
|
||||
/* Ask for an async notification that a time has elapsed */
|
||||
STDMETHODIMP AdviseTime(
|
||||
REFERENCE_TIME baseTime, // base reference time
|
||||
REFERENCE_TIME streamTime, // stream offset time
|
||||
HEVENT hEvent, // advise via this event
|
||||
__out DWORD_PTR *pdwAdviseCookie// where your cookie goes
|
||||
);
|
||||
|
||||
/* Ask for an asynchronous periodic notification that a time has elapsed */
|
||||
STDMETHODIMP AdvisePeriodic(
|
||||
REFERENCE_TIME StartTime, // starting at this time
|
||||
REFERENCE_TIME PeriodTime, // time between notifications
|
||||
HSEMAPHORE hSemaphore, // advise via a semaphore
|
||||
__out DWORD_PTR *pdwAdviseCookie// where your cookie goes
|
||||
);
|
||||
|
||||
/* Cancel a request for notification(s) - if the notification was
|
||||
* a one shot timer then this function doesn't need to be called
|
||||
* as the advise is automatically cancelled, however it does no
|
||||
* harm to explicitly cancel a one-shot advise. It is REQUIRED that
|
||||
* clients call Unadvise to clear a Periodic advise setting.
|
||||
*/
|
||||
|
||||
STDMETHODIMP Unadvise(DWORD_PTR dwAdviseCookie);
|
||||
|
||||
/* Methods for the benefit of derived classes or outer objects */
|
||||
|
||||
// GetPrivateTime() is the REAL clock. GetTime is just a cover for
|
||||
// it. Derived classes will probably override this method but not
|
||||
// GetTime() itself.
|
||||
// The important point about GetPrivateTime() is it's allowed to go
|
||||
// backwards. Our GetTime() will keep returning the LastGotTime
|
||||
// until GetPrivateTime() catches up.
|
||||
virtual REFERENCE_TIME GetPrivateTime();
|
||||
|
||||
/* Provide a method for correcting drift */
|
||||
STDMETHODIMP SetTimeDelta( const REFERENCE_TIME& TimeDelta );
|
||||
|
||||
CAMSchedule * GetSchedule() const { return m_pSchedule; }
|
||||
|
||||
// IReferenceClockTimerControl methods
|
||||
//
|
||||
// Setting a default of 0 disables the default of 1ms
|
||||
STDMETHODIMP SetDefaultTimerResolution(
|
||||
REFERENCE_TIME timerResolution // in 100ns
|
||||
);
|
||||
STDMETHODIMP GetDefaultTimerResolution(
|
||||
__out REFERENCE_TIME* pTimerResolution // in 100ns
|
||||
);
|
||||
|
||||
private:
|
||||
REFERENCE_TIME m_rtPrivateTime; // Current best estimate of time
|
||||
DWORD m_dwPrevSystemTime; // Last vaule we got from timeGetTime
|
||||
REFERENCE_TIME m_rtLastGotTime; // Last time returned by GetTime
|
||||
REFERENCE_TIME m_rtNextAdvise; // Time of next advise
|
||||
UINT m_TimerResolution;
|
||||
|
||||
#ifdef PERF
|
||||
int m_idGetSystemTime;
|
||||
#endif
|
||||
|
||||
// Thread stuff
|
||||
public:
|
||||
void TriggerThread() // Wakes thread up. Need to do this if
|
||||
{ // time to next advise needs reevaluating.
|
||||
EXECUTE_ASSERT(SetEvent(m_pSchedule->GetEvent()));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
BOOL m_bAbort; // Flag used for thread shutdown
|
||||
HANDLE m_hThread; // Thread handle
|
||||
|
||||
HRESULT AdviseThread(); // Method in which the advise thread runs
|
||||
static DWORD __stdcall AdviseThreadFunction(__in LPVOID); // Function used to get there
|
||||
|
||||
protected:
|
||||
CAMSchedule * m_pSchedule;
|
||||
|
||||
void Restart (IN REFERENCE_TIME rtMinTime = 0I64) ;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Vendored
-116
@@ -1,116 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: RefTime.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines CRefTime, a class that manages
|
||||
// reference times.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//
|
||||
// CRefTime
|
||||
//
|
||||
// Manage reference times.
|
||||
// Shares same data layout as REFERENCE_TIME, but adds some (nonvirtual)
|
||||
// functions providing simple comparison, conversion and arithmetic.
|
||||
//
|
||||
// A reference time (at the moment) is a unit of seconds represented in
|
||||
// 100ns units as is used in the Win32 FILETIME structure. BUT the time
|
||||
// a REFERENCE_TIME represents is NOT the time elapsed since 1/1/1601 it
|
||||
// will either be stream time or reference time depending upon context
|
||||
//
|
||||
// This class provides simple arithmetic operations on reference times
|
||||
//
|
||||
// keep non-virtual otherwise the data layout will not be the same as
|
||||
// REFERENCE_TIME
|
||||
|
||||
|
||||
// -----
|
||||
// note that you are safe to cast a CRefTime* to a REFERENCE_TIME*, but
|
||||
// you will need to do so explicitly
|
||||
// -----
|
||||
|
||||
|
||||
#ifndef __REFTIME__
|
||||
#define __REFTIME__
|
||||
|
||||
|
||||
const LONGLONG MILLISECONDS = (1000); // 10 ^ 3
|
||||
const LONGLONG NANOSECONDS = (1000000000); // 10 ^ 9
|
||||
const LONGLONG UNITS = (NANOSECONDS / 100); // 10 ^ 7
|
||||
|
||||
/* Unfortunately an inline function here generates a call to __allmul
|
||||
- even for constants!
|
||||
*/
|
||||
#define MILLISECONDS_TO_100NS_UNITS(lMs) \
|
||||
Int32x32To64((lMs), (UNITS / MILLISECONDS))
|
||||
|
||||
class CRefTime
|
||||
{
|
||||
public:
|
||||
|
||||
// *MUST* be the only data member so that this class is exactly
|
||||
// equivalent to a REFERENCE_TIME.
|
||||
// Also, must be *no virtual functions*
|
||||
|
||||
REFERENCE_TIME m_time;
|
||||
|
||||
inline CRefTime()
|
||||
{
|
||||
// default to 0 time
|
||||
m_time = 0;
|
||||
};
|
||||
|
||||
inline CRefTime(LONG msecs)
|
||||
{
|
||||
m_time = MILLISECONDS_TO_100NS_UNITS(msecs);
|
||||
};
|
||||
|
||||
inline CRefTime(REFERENCE_TIME rt)
|
||||
{
|
||||
m_time = rt;
|
||||
};
|
||||
|
||||
inline operator REFERENCE_TIME() const
|
||||
{
|
||||
return m_time;
|
||||
};
|
||||
|
||||
inline CRefTime& operator=(const CRefTime& rt)
|
||||
{
|
||||
m_time = rt.m_time;
|
||||
return *this;
|
||||
};
|
||||
|
||||
inline CRefTime& operator=(const LONGLONG ll)
|
||||
{
|
||||
m_time = ll;
|
||||
return *this;
|
||||
};
|
||||
|
||||
inline CRefTime& operator+=(const CRefTime& rt)
|
||||
{
|
||||
return (*this = *this + rt);
|
||||
};
|
||||
|
||||
inline CRefTime& operator-=(const CRefTime& rt)
|
||||
{
|
||||
return (*this = *this - rt);
|
||||
};
|
||||
|
||||
inline LONG Millisecs(void)
|
||||
{
|
||||
return (LONG)(m_time / (UNITS / MILLISECONDS));
|
||||
};
|
||||
|
||||
inline LONGLONG GetUnits(void)
|
||||
{
|
||||
return m_time;
|
||||
};
|
||||
};
|
||||
|
||||
const LONGLONG TimeZero = 0;
|
||||
|
||||
#endif /* __REFTIME__ */
|
||||
|
||||
Vendored
-2858
File diff suppressed because it is too large
Load Diff
Vendored
-478
@@ -1,478 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: RenBase.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines a generic ActiveX base renderer
|
||||
// class.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __RENBASE__
|
||||
#define __RENBASE__
|
||||
|
||||
// Forward class declarations
|
||||
|
||||
class CBaseRenderer;
|
||||
class CBaseVideoRenderer;
|
||||
class CRendererInputPin;
|
||||
|
||||
// This is our input pin class that channels calls to the renderer
|
||||
|
||||
class CRendererInputPin : public CBaseInputPin
|
||||
{
|
||||
protected:
|
||||
|
||||
CBaseRenderer *m_pRenderer;
|
||||
|
||||
public:
|
||||
|
||||
CRendererInputPin(__inout CBaseRenderer *pRenderer,
|
||||
__inout HRESULT *phr,
|
||||
__in_opt LPCWSTR Name);
|
||||
|
||||
// Overriden from the base pin classes
|
||||
|
||||
HRESULT BreakConnect();
|
||||
HRESULT CompleteConnect(IPin *pReceivePin);
|
||||
HRESULT SetMediaType(const CMediaType *pmt);
|
||||
HRESULT CheckMediaType(const CMediaType *pmt);
|
||||
HRESULT Active();
|
||||
HRESULT Inactive();
|
||||
|
||||
// Add rendering behaviour to interface functions
|
||||
|
||||
STDMETHODIMP QueryId(__deref_out LPWSTR *Id);
|
||||
STDMETHODIMP EndOfStream();
|
||||
STDMETHODIMP BeginFlush();
|
||||
STDMETHODIMP EndFlush();
|
||||
STDMETHODIMP Receive(IMediaSample *pMediaSample);
|
||||
|
||||
// Helper
|
||||
IMemAllocator inline *Allocator() const
|
||||
{
|
||||
return m_pAllocator;
|
||||
}
|
||||
};
|
||||
|
||||
// Main renderer class that handles synchronisation and state changes
|
||||
|
||||
class CBaseRenderer : public CBaseFilter
|
||||
{
|
||||
protected:
|
||||
|
||||
friend class CRendererInputPin;
|
||||
|
||||
friend void CALLBACK EndOfStreamTimer(UINT uID, // Timer identifier
|
||||
UINT uMsg, // Not currently used
|
||||
DWORD_PTR dwUser, // User information
|
||||
DWORD_PTR dw1, // Windows reserved
|
||||
DWORD_PTR dw2); // Is also reserved
|
||||
|
||||
CRendererPosPassThru *m_pPosition; // Media seeking pass by object
|
||||
CAMEvent m_RenderEvent; // Used to signal timer events
|
||||
CAMEvent m_ThreadSignal; // Signalled to release worker thread
|
||||
CAMEvent m_evComplete; // Signalled when state complete
|
||||
BOOL m_bAbort; // Stop us from rendering more data
|
||||
BOOL m_bStreaming; // Are we currently streaming
|
||||
DWORD_PTR m_dwAdvise; // Timer advise cookie
|
||||
IMediaSample *m_pMediaSample; // Current image media sample
|
||||
BOOL m_bEOS; // Any more samples in the stream
|
||||
BOOL m_bEOSDelivered; // Have we delivered an EC_COMPLETE
|
||||
CRendererInputPin *m_pInputPin; // Our renderer input pin object
|
||||
CCritSec m_InterfaceLock; // Critical section for interfaces
|
||||
CCritSec m_RendererLock; // Controls access to internals
|
||||
IQualityControl * m_pQSink; // QualityControl sink
|
||||
BOOL m_bRepaintStatus; // Can we signal an EC_REPAINT
|
||||
// Avoid some deadlocks by tracking filter during stop
|
||||
volatile BOOL m_bInReceive; // Inside Receive between PrepareReceive
|
||||
// And actually processing the sample
|
||||
REFERENCE_TIME m_SignalTime; // Time when we signal EC_COMPLETE
|
||||
UINT m_EndOfStreamTimer; // Used to signal end of stream
|
||||
CCritSec m_ObjectCreationLock; // This lock protects the creation and
|
||||
// of m_pPosition and m_pInputPin. It
|
||||
// ensures that two threads cannot create
|
||||
// either object simultaneously.
|
||||
|
||||
public:
|
||||
|
||||
CBaseRenderer(REFCLSID RenderClass, // CLSID for this renderer
|
||||
__in_opt LPCTSTR pName, // Debug ONLY description
|
||||
__inout_opt LPUNKNOWN pUnk, // Aggregated owner object
|
||||
__inout HRESULT *phr); // General OLE return code
|
||||
|
||||
~CBaseRenderer();
|
||||
|
||||
// Overriden to say what interfaces we support and where
|
||||
|
||||
virtual HRESULT GetMediaPositionInterface(REFIID riid, __deref_out void **ppv);
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID, __deref_out void **);
|
||||
|
||||
virtual HRESULT SourceThreadCanWait(BOOL bCanWait);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Debug only dump of the renderer state
|
||||
void DisplayRendererState();
|
||||
#endif
|
||||
virtual HRESULT WaitForRenderTime();
|
||||
virtual HRESULT CompleteStateChange(FILTER_STATE OldState);
|
||||
|
||||
// Return internal information about this filter
|
||||
|
||||
BOOL IsEndOfStream() { return m_bEOS; };
|
||||
BOOL IsEndOfStreamDelivered() { return m_bEOSDelivered; };
|
||||
BOOL IsStreaming() { return m_bStreaming; };
|
||||
void SetAbortSignal(BOOL bAbort) { m_bAbort = bAbort; };
|
||||
virtual void OnReceiveFirstSample(IMediaSample *pMediaSample) { };
|
||||
CAMEvent *GetRenderEvent() { return &m_RenderEvent; };
|
||||
|
||||
// Permit access to the transition state
|
||||
|
||||
void Ready() { m_evComplete.Set(); };
|
||||
void NotReady() { m_evComplete.Reset(); };
|
||||
BOOL CheckReady() { return m_evComplete.Check(); };
|
||||
|
||||
virtual int GetPinCount();
|
||||
virtual CBasePin *GetPin(int n);
|
||||
FILTER_STATE GetRealState();
|
||||
void SendRepaint();
|
||||
void SendNotifyWindow(IPin *pPin,HWND hwnd);
|
||||
BOOL OnDisplayChange();
|
||||
void SetRepaintStatus(BOOL bRepaint);
|
||||
|
||||
// Override the filter and pin interface functions
|
||||
|
||||
STDMETHODIMP Stop();
|
||||
STDMETHODIMP Pause();
|
||||
STDMETHODIMP Run(REFERENCE_TIME StartTime);
|
||||
STDMETHODIMP GetState(DWORD dwMSecs, __out FILTER_STATE *State);
|
||||
STDMETHODIMP FindPin(LPCWSTR Id, __deref_out IPin **ppPin);
|
||||
|
||||
// These are available for a quality management implementation
|
||||
|
||||
virtual void OnRenderStart(IMediaSample *pMediaSample);
|
||||
virtual void OnRenderEnd(IMediaSample *pMediaSample);
|
||||
virtual HRESULT OnStartStreaming() { return NOERROR; };
|
||||
virtual HRESULT OnStopStreaming() { return NOERROR; };
|
||||
virtual void OnWaitStart() { };
|
||||
virtual void OnWaitEnd() { };
|
||||
virtual void PrepareRender() { };
|
||||
|
||||
#ifdef PERF
|
||||
REFERENCE_TIME m_trRenderStart; // Just before we started drawing
|
||||
// Set in OnRenderStart, Used in OnRenderEnd
|
||||
int m_idBaseStamp; // MSR_id for frame time stamp
|
||||
int m_idBaseRenderTime; // MSR_id for true wait time
|
||||
int m_idBaseAccuracy; // MSR_id for time frame is late (int)
|
||||
#endif
|
||||
|
||||
// Quality management implementation for scheduling rendering
|
||||
|
||||
virtual BOOL ScheduleSample(IMediaSample *pMediaSample);
|
||||
virtual HRESULT GetSampleTimes(IMediaSample *pMediaSample,
|
||||
__out REFERENCE_TIME *pStartTime,
|
||||
__out REFERENCE_TIME *pEndTime);
|
||||
|
||||
virtual HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
|
||||
__out REFERENCE_TIME *ptrStart,
|
||||
__out REFERENCE_TIME *ptrEnd);
|
||||
|
||||
// Lots of end of stream complexities
|
||||
|
||||
void TimerCallback();
|
||||
void ResetEndOfStreamTimer();
|
||||
HRESULT NotifyEndOfStream();
|
||||
virtual HRESULT SendEndOfStream();
|
||||
virtual HRESULT ResetEndOfStream();
|
||||
virtual HRESULT EndOfStream();
|
||||
|
||||
// Rendering is based around the clock
|
||||
|
||||
void SignalTimerFired();
|
||||
virtual HRESULT CancelNotification();
|
||||
virtual HRESULT ClearPendingSample();
|
||||
|
||||
// Called when the filter changes state
|
||||
|
||||
virtual HRESULT Active();
|
||||
virtual HRESULT Inactive();
|
||||
virtual HRESULT StartStreaming();
|
||||
virtual HRESULT StopStreaming();
|
||||
virtual HRESULT BeginFlush();
|
||||
virtual HRESULT EndFlush();
|
||||
|
||||
// Deal with connections and type changes
|
||||
|
||||
virtual HRESULT BreakConnect();
|
||||
virtual HRESULT SetMediaType(const CMediaType *pmt);
|
||||
virtual HRESULT CompleteConnect(IPin *pReceivePin);
|
||||
|
||||
// These look after the handling of data samples
|
||||
|
||||
virtual HRESULT PrepareReceive(IMediaSample *pMediaSample);
|
||||
virtual HRESULT Receive(IMediaSample *pMediaSample);
|
||||
virtual BOOL HaveCurrentSample();
|
||||
virtual IMediaSample *GetCurrentSample();
|
||||
virtual HRESULT Render(IMediaSample *pMediaSample);
|
||||
|
||||
// Derived classes MUST override these
|
||||
virtual HRESULT DoRenderSample(IMediaSample *pMediaSample) PURE;
|
||||
virtual HRESULT CheckMediaType(const CMediaType *) PURE;
|
||||
|
||||
// Helper
|
||||
void WaitForReceiveToComplete();
|
||||
};
|
||||
|
||||
|
||||
// CBaseVideoRenderer is a renderer class (see its ancestor class) and
|
||||
// it handles scheduling of media samples so that they are drawn at the
|
||||
// correct time by the reference clock. It implements a degradation
|
||||
// strategy. Possible degradation modes are:
|
||||
// Drop frames here (only useful if the drawing takes significant time)
|
||||
// Signal supplier (upstream) to drop some frame(s) - i.e. one-off skip.
|
||||
// Signal supplier to change the frame rate - i.e. ongoing skipping.
|
||||
// Or any combination of the above.
|
||||
// In order to determine what's useful to try we need to know what's going
|
||||
// on. This is done by timing various operations (including the supplier).
|
||||
// This timing is done by using timeGetTime as it is accurate enough and
|
||||
// usually cheaper than calling the reference clock. It also tells the
|
||||
// truth if there is an audio break and the reference clock stops.
|
||||
// We provide a number of public entry points (named OnXxxStart, OnXxxEnd)
|
||||
// which the rest of the renderer calls at significant moments. These do
|
||||
// the timing.
|
||||
|
||||
// the number of frames that the sliding averages are averaged over.
|
||||
// the rule is (1024*NewObservation + (AVGPERIOD-1) * PreviousAverage)/AVGPERIOD
|
||||
#define AVGPERIOD 4
|
||||
#define DO_MOVING_AVG(avg,obs) (avg = (1024*obs + (AVGPERIOD-1)*avg)/AVGPERIOD)
|
||||
// Spot the bug in this macro - I can't. but it doesn't work!
|
||||
|
||||
class CBaseVideoRenderer : public CBaseRenderer, // Base renderer class
|
||||
public IQualProp, // Property page guff
|
||||
public IQualityControl // Allow throttling
|
||||
{
|
||||
protected:
|
||||
|
||||
// Hungarian:
|
||||
// tFoo is the time Foo in mSec (beware m_tStart from filter.h)
|
||||
// trBar is the time Bar by the reference clock
|
||||
|
||||
//******************************************************************
|
||||
// State variables to control synchronisation
|
||||
//******************************************************************
|
||||
|
||||
// Control of sending Quality messages. We need to know whether
|
||||
// we are in trouble (e.g. frames being dropped) and where the time
|
||||
// is being spent.
|
||||
|
||||
// When we drop a frame we play the next one early.
|
||||
// The frame after that is likely to wait before drawing and counting this
|
||||
// wait as spare time is unfair, so we count it as a zero wait.
|
||||
// We therefore need to know whether we are playing frames early or not.
|
||||
|
||||
int m_nNormal; // The number of consecutive frames
|
||||
// drawn at their normal time (not early)
|
||||
// -1 means we just dropped a frame.
|
||||
|
||||
#ifdef PERF
|
||||
BOOL m_bDrawLateFrames; // Don't drop any frames (debug and I'm
|
||||
// not keen on people using it!)
|
||||
#endif
|
||||
|
||||
BOOL m_bSupplierHandlingQuality;// The response to Quality messages says
|
||||
// our supplier is handling things.
|
||||
// We will allow things to go extra late
|
||||
// before dropping frames. We will play
|
||||
// very early after he has dropped one.
|
||||
|
||||
// Control of scheduling, frame dropping etc.
|
||||
// We need to know where the time is being spent so as to tell whether
|
||||
// we should be taking action here, signalling supplier or what.
|
||||
// The variables are initialised to a mode of NOT dropping frames.
|
||||
// They will tell the truth after a few frames.
|
||||
// We typically record a start time for an event, later we get the time
|
||||
// again and subtract to get the elapsed time, and we average this over
|
||||
// a few frames. The average is used to tell what mode we are in.
|
||||
|
||||
// Although these are reference times (64 bit) they are all DIFFERENCES
|
||||
// between times which are small. An int will go up to 214 secs before
|
||||
// overflow. Avoiding 64 bit multiplications and divisions seems
|
||||
// worth while.
|
||||
|
||||
|
||||
|
||||
// Audio-video throttling. If the user has turned up audio quality
|
||||
// very high (in principle it could be any other stream, not just audio)
|
||||
// then we can receive cries for help via the graph manager. In this case
|
||||
// we put in a wait for some time after rendering each frame.
|
||||
int m_trThrottle;
|
||||
|
||||
// The time taken to render (i.e. BitBlt) frames controls which component
|
||||
// needs to degrade. If the blt is expensive, the renderer degrades.
|
||||
// If the blt is cheap it's done anyway and the supplier degrades.
|
||||
int m_trRenderAvg; // Time frames are taking to blt
|
||||
int m_trRenderLast; // Time for last frame blt
|
||||
int m_tRenderStart; // Just before we started drawing (mSec)
|
||||
// derived from timeGetTime.
|
||||
|
||||
// When frames are dropped we will play the next frame as early as we can.
|
||||
// If it was a false alarm and the machine is fast we slide gently back to
|
||||
// normal timing. To do this, we record the offset showing just how early
|
||||
// we really are. This will normally be negative meaning early or zero.
|
||||
int m_trEarliness;
|
||||
|
||||
// Target provides slow long-term feedback to try to reduce the
|
||||
// average sync offset to zero. Whenever a frame is actually rendered
|
||||
// early we add a msec or two, whenever late we take off a few.
|
||||
// We add or take off 1/32 of the error time.
|
||||
// Eventually we should be hovering around zero. For a really bad case
|
||||
// where we were (say) 300mSec off, it might take 100 odd frames to
|
||||
// settle down. The rate of change of this is intended to be slower
|
||||
// than any other mechanism in Quartz, thereby avoiding hunting.
|
||||
int m_trTarget;
|
||||
|
||||
// The proportion of time spent waiting for the right moment to blt
|
||||
// controls whether we bother to drop a frame or whether we reckon that
|
||||
// we're doing well enough that we can stand a one-frame glitch.
|
||||
int m_trWaitAvg; // Average of last few wait times
|
||||
// (actually we just average how early
|
||||
// we were). Negative here means LATE.
|
||||
|
||||
// The average inter-frame time.
|
||||
// This is used to calculate the proportion of the time used by the
|
||||
// three operations (supplying us, waiting, rendering)
|
||||
int m_trFrameAvg; // Average inter-frame time
|
||||
int m_trDuration; // duration of last frame.
|
||||
|
||||
#ifdef PERF
|
||||
// Performance logging identifiers
|
||||
int m_idTimeStamp; // MSR_id for frame time stamp
|
||||
int m_idEarliness; // MSR_id for earliness fudge
|
||||
int m_idTarget; // MSR_id for Target fudge
|
||||
int m_idWaitReal; // MSR_id for true wait time
|
||||
int m_idWait; // MSR_id for wait time recorded
|
||||
int m_idFrameAccuracy; // MSR_id for time frame is late (int)
|
||||
int m_idRenderAvg; // MSR_id for Render time recorded (int)
|
||||
int m_idSchLateTime; // MSR_id for lateness at scheduler
|
||||
int m_idQualityRate; // MSR_id for Quality rate requested
|
||||
int m_idQualityTime; // MSR_id for Quality time requested
|
||||
int m_idDecision; // MSR_id for decision code
|
||||
int m_idDuration; // MSR_id for duration of a frame
|
||||
int m_idThrottle; // MSR_id for audio-video throttling
|
||||
//int m_idDebug; // MSR_id for trace style debugging
|
||||
//int m_idSendQuality; // MSR_id for timing the notifications per se
|
||||
#endif // PERF
|
||||
REFERENCE_TIME m_trRememberStampForPerf; // original time stamp of frame
|
||||
// with no earliness fudges etc.
|
||||
#ifdef PERF
|
||||
REFERENCE_TIME m_trRememberFrameForPerf; // time when previous frame rendered
|
||||
|
||||
// debug...
|
||||
int m_idFrameAvg;
|
||||
int m_idWaitAvg;
|
||||
#endif
|
||||
|
||||
// PROPERTY PAGE
|
||||
// This has edit fields that show the user what's happening
|
||||
// These member variables hold these counts.
|
||||
|
||||
int m_cFramesDropped; // cumulative frames dropped IN THE RENDERER
|
||||
int m_cFramesDrawn; // Frames since streaming started seen BY THE
|
||||
// RENDERER (some may be dropped upstream)
|
||||
|
||||
// Next two support average sync offset and standard deviation of sync offset.
|
||||
LONGLONG m_iTotAcc; // Sum of accuracies in mSec
|
||||
LONGLONG m_iSumSqAcc; // Sum of squares of (accuracies in mSec)
|
||||
|
||||
// Next two allow jitter calculation. Jitter is std deviation of frame time.
|
||||
REFERENCE_TIME m_trLastDraw; // Time of prev frame (for inter-frame times)
|
||||
LONGLONG m_iSumSqFrameTime; // Sum of squares of (inter-frame time in mSec)
|
||||
LONGLONG m_iSumFrameTime; // Sum of inter-frame times in mSec
|
||||
|
||||
// To get performance statistics on frame rate, jitter etc, we need
|
||||
// to record the lateness and inter-frame time. What we actually need are the
|
||||
// data above (sum, sum of squares and number of entries for each) but the data
|
||||
// is generated just ahead of time and only later do we discover whether the
|
||||
// frame was actually drawn or not. So we have to hang on to the data
|
||||
int m_trLate; // hold onto frame lateness
|
||||
int m_trFrame; // hold onto inter-frame time
|
||||
|
||||
int m_tStreamingStart; // if streaming then time streaming started
|
||||
// else time of last streaming session
|
||||
// used for property page statistics
|
||||
#ifdef PERF
|
||||
LONGLONG m_llTimeOffset; // timeGetTime()*10000+m_llTimeOffset==ref time
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
|
||||
CBaseVideoRenderer(REFCLSID RenderClass, // CLSID for this renderer
|
||||
__in_opt LPCTSTR pName, // Debug ONLY description
|
||||
__inout_opt LPUNKNOWN pUnk, // Aggregated owner object
|
||||
__inout HRESULT *phr); // General OLE return code
|
||||
|
||||
~CBaseVideoRenderer();
|
||||
|
||||
// IQualityControl methods - Notify allows audio-video throttling
|
||||
|
||||
STDMETHODIMP SetSink( IQualityControl * piqc);
|
||||
STDMETHODIMP Notify( IBaseFilter * pSelf, Quality q);
|
||||
|
||||
// These provide a full video quality management implementation
|
||||
|
||||
void OnRenderStart(IMediaSample *pMediaSample);
|
||||
void OnRenderEnd(IMediaSample *pMediaSample);
|
||||
void OnWaitStart();
|
||||
void OnWaitEnd();
|
||||
HRESULT OnStartStreaming();
|
||||
HRESULT OnStopStreaming();
|
||||
void ThrottleWait();
|
||||
|
||||
// Handle the statistics gathering for our quality management
|
||||
|
||||
void PreparePerformanceData(int trLate, int trFrame);
|
||||
virtual void RecordFrameLateness(int trLate, int trFrame);
|
||||
virtual void OnDirectRender(IMediaSample *pMediaSample);
|
||||
virtual HRESULT ResetStreamingTimes();
|
||||
BOOL ScheduleSample(IMediaSample *pMediaSample);
|
||||
HRESULT ShouldDrawSampleNow(IMediaSample *pMediaSample,
|
||||
__inout REFERENCE_TIME *ptrStart,
|
||||
__inout REFERENCE_TIME *ptrEnd);
|
||||
|
||||
virtual HRESULT SendQuality(REFERENCE_TIME trLate, REFERENCE_TIME trRealStream);
|
||||
STDMETHODIMP JoinFilterGraph(__inout_opt IFilterGraph * pGraph, __in_opt LPCWSTR pName);
|
||||
|
||||
//
|
||||
// Do estimates for standard deviations for per-frame
|
||||
// statistics
|
||||
//
|
||||
// *piResult = (llSumSq - iTot * iTot / m_cFramesDrawn - 1) /
|
||||
// (m_cFramesDrawn - 2)
|
||||
// or 0 if m_cFramesDrawn <= 3
|
||||
//
|
||||
HRESULT GetStdDev(
|
||||
int nSamples,
|
||||
__out int *piResult,
|
||||
LONGLONG llSumSq,
|
||||
LONGLONG iTot
|
||||
);
|
||||
public:
|
||||
|
||||
// IQualProp property page support
|
||||
|
||||
STDMETHODIMP get_FramesDroppedInRenderer(__out int *cFramesDropped);
|
||||
STDMETHODIMP get_FramesDrawn(__out int *pcFramesDrawn);
|
||||
STDMETHODIMP get_AvgFrameRate(__out int *piAvgFrameRate);
|
||||
STDMETHODIMP get_Jitter(__out int *piJitter);
|
||||
STDMETHODIMP get_AvgSyncOffset(__out int *piAvg);
|
||||
STDMETHODIMP get_DevSyncOffset(__out int *piDev);
|
||||
|
||||
// Implement an IUnknown interface and expose IQualProp
|
||||
|
||||
DECLARE_IUNKNOWN
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,__deref_out VOID **ppv);
|
||||
};
|
||||
|
||||
#endif // __RENBASE__
|
||||
|
||||
Vendored
-284
@@ -1,284 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: Schedule.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
|
||||
// DbgLog values (all on LOG_TIMING):
|
||||
//
|
||||
// 2 for schedulting, firing and shunting of events
|
||||
// 3 for wait delays and wake-up times of event thread
|
||||
// 4 for details of whats on the list when the thread awakes
|
||||
|
||||
/* Construct & destructors */
|
||||
|
||||
CAMSchedule::CAMSchedule( HANDLE ev )
|
||||
: CBaseObject(TEXT("CAMSchedule"))
|
||||
, head(&z, 0), z(0, MAX_TIME)
|
||||
, m_dwNextCookie(0), m_dwAdviseCount(0)
|
||||
, m_pAdviseCache(0), m_dwCacheCount(0)
|
||||
, m_ev( ev )
|
||||
{
|
||||
head.m_dwAdviseCookie = z.m_dwAdviseCookie = 0;
|
||||
}
|
||||
|
||||
CAMSchedule::~CAMSchedule()
|
||||
{
|
||||
m_Serialize.Lock();
|
||||
|
||||
// Delete cache
|
||||
CAdvisePacket * p = m_pAdviseCache;
|
||||
while (p)
|
||||
{
|
||||
CAdvisePacket *const p_next = p->m_next;
|
||||
delete p;
|
||||
p = p_next;
|
||||
}
|
||||
|
||||
ASSERT( m_dwAdviseCount == 0 );
|
||||
// Better to be safe than sorry
|
||||
if ( m_dwAdviseCount > 0 )
|
||||
{
|
||||
DumpLinkedList();
|
||||
while ( !head.m_next->IsZ() )
|
||||
{
|
||||
head.DeleteNext();
|
||||
--m_dwAdviseCount;
|
||||
}
|
||||
}
|
||||
|
||||
// If, in the debug version, we assert twice, it means, not only
|
||||
// did we have left over advises, but we have also let m_dwAdviseCount
|
||||
// get out of sync. with the number of advises actually on the list.
|
||||
ASSERT( m_dwAdviseCount == 0 );
|
||||
|
||||
m_Serialize.Unlock();
|
||||
}
|
||||
|
||||
/* Public methods */
|
||||
|
||||
DWORD CAMSchedule::GetAdviseCount()
|
||||
{
|
||||
// No need to lock, m_dwAdviseCount is 32bits & declared volatile
|
||||
return m_dwAdviseCount;
|
||||
}
|
||||
|
||||
REFERENCE_TIME CAMSchedule::GetNextAdviseTime()
|
||||
{
|
||||
CAutoLock lck(&m_Serialize); // Need to stop the linked list from changing
|
||||
return head.m_next->m_rtEventTime;
|
||||
}
|
||||
|
||||
DWORD_PTR CAMSchedule::AddAdvisePacket
|
||||
( const REFERENCE_TIME & time1
|
||||
, const REFERENCE_TIME & time2
|
||||
, HANDLE h, BOOL periodic
|
||||
)
|
||||
{
|
||||
// Since we use MAX_TIME as a sentry, we can't afford to
|
||||
// schedule a notification at MAX_TIME
|
||||
ASSERT( time1 < MAX_TIME );
|
||||
DWORD_PTR Result;
|
||||
CAdvisePacket * p;
|
||||
|
||||
m_Serialize.Lock();
|
||||
|
||||
if (m_pAdviseCache)
|
||||
{
|
||||
p = m_pAdviseCache;
|
||||
m_pAdviseCache = p->m_next;
|
||||
--m_dwCacheCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
p = new CAdvisePacket();
|
||||
}
|
||||
if (p)
|
||||
{
|
||||
p->m_rtEventTime = time1; p->m_rtPeriod = time2;
|
||||
p->m_hNotify = h; p->m_bPeriodic = periodic;
|
||||
Result = AddAdvisePacket( p );
|
||||
}
|
||||
else Result = 0;
|
||||
|
||||
m_Serialize.Unlock();
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
HRESULT CAMSchedule::Unadvise(DWORD_PTR dwAdviseCookie)
|
||||
{
|
||||
HRESULT hr = S_FALSE;
|
||||
CAdvisePacket * p_prev = &head;
|
||||
CAdvisePacket * p_n;
|
||||
m_Serialize.Lock();
|
||||
while ( p_n = p_prev->Next() ) // The Next() method returns NULL when it hits z
|
||||
{
|
||||
if ( p_n->m_dwAdviseCookie == dwAdviseCookie )
|
||||
{
|
||||
Delete( p_prev->RemoveNext() );
|
||||
--m_dwAdviseCount;
|
||||
hr = S_OK;
|
||||
// Having found one cookie that matches, there should be no more
|
||||
#ifdef DEBUG
|
||||
while (p_n = p_prev->Next())
|
||||
{
|
||||
ASSERT(p_n->m_dwAdviseCookie != dwAdviseCookie);
|
||||
p_prev = p_n;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
p_prev = p_n;
|
||||
};
|
||||
m_Serialize.Unlock();
|
||||
return hr;
|
||||
}
|
||||
|
||||
REFERENCE_TIME CAMSchedule::Advise( const REFERENCE_TIME & rtTime )
|
||||
{
|
||||
REFERENCE_TIME rtNextTime;
|
||||
CAdvisePacket * pAdvise;
|
||||
|
||||
DbgLog((LOG_TIMING, 2,
|
||||
TEXT("CAMSchedule::Advise( %lu ms )"), ULONG(rtTime / (UNITS / MILLISECONDS))));
|
||||
|
||||
CAutoLock lck(&m_Serialize);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (DbgCheckModuleLevel(LOG_TIMING, 4)) DumpLinkedList();
|
||||
#endif
|
||||
|
||||
// Note - DON'T cache the difference, it might overflow
|
||||
while ( rtTime >= (rtNextTime = (pAdvise=head.m_next)->m_rtEventTime) &&
|
||||
!pAdvise->IsZ() )
|
||||
{
|
||||
ASSERT(pAdvise->m_dwAdviseCookie); // If this is zero, its the head or the tail!!
|
||||
|
||||
ASSERT(pAdvise->m_hNotify != INVALID_HANDLE_VALUE);
|
||||
|
||||
if (pAdvise->m_bPeriodic == TRUE)
|
||||
{
|
||||
ReleaseSemaphore(pAdvise->m_hNotify,1,NULL);
|
||||
pAdvise->m_rtEventTime += pAdvise->m_rtPeriod;
|
||||
ShuntHead();
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT( pAdvise->m_bPeriodic == FALSE );
|
||||
EXECUTE_ASSERT(SetEvent(pAdvise->m_hNotify));
|
||||
--m_dwAdviseCount;
|
||||
Delete( head.RemoveNext() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DbgLog((LOG_TIMING, 3,
|
||||
TEXT("CAMSchedule::Advise() Next time stamp: %lu ms, for advise %lu."),
|
||||
DWORD(rtNextTime / (UNITS / MILLISECONDS)), pAdvise->m_dwAdviseCookie ));
|
||||
|
||||
return rtNextTime;
|
||||
}
|
||||
|
||||
/* Private methods */
|
||||
|
||||
DWORD_PTR CAMSchedule::AddAdvisePacket( __inout CAdvisePacket * pPacket )
|
||||
{
|
||||
ASSERT(pPacket->m_rtEventTime >= 0 && pPacket->m_rtEventTime < MAX_TIME);
|
||||
ASSERT(CritCheckIn(&m_Serialize));
|
||||
|
||||
CAdvisePacket * p_prev = &head;
|
||||
CAdvisePacket * p_n;
|
||||
|
||||
const DWORD_PTR Result = pPacket->m_dwAdviseCookie = ++m_dwNextCookie;
|
||||
// This relies on the fact that z is a sentry with a maximal m_rtEventTime
|
||||
for(;;p_prev = p_n)
|
||||
{
|
||||
p_n = p_prev->m_next;
|
||||
if ( p_n->m_rtEventTime >= pPacket->m_rtEventTime ) break;
|
||||
}
|
||||
p_prev->InsertAfter( pPacket );
|
||||
++m_dwAdviseCount;
|
||||
|
||||
DbgLog((LOG_TIMING, 2, TEXT("Added advise %lu, for thread 0x%02X, scheduled at %lu"),
|
||||
pPacket->m_dwAdviseCookie, GetCurrentThreadId(), (pPacket->m_rtEventTime / (UNITS / MILLISECONDS)) ));
|
||||
|
||||
// If packet added at the head, then clock needs to re-evaluate wait time.
|
||||
if ( p_prev == &head ) SetEvent( m_ev );
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
void CAMSchedule::Delete( __inout CAdvisePacket * pPacket )
|
||||
{
|
||||
if ( m_dwCacheCount >= dwCacheMax ) delete pPacket;
|
||||
else
|
||||
{
|
||||
m_Serialize.Lock();
|
||||
pPacket->m_next = m_pAdviseCache;
|
||||
m_pAdviseCache = pPacket;
|
||||
++m_dwCacheCount;
|
||||
m_Serialize.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Takes the head of the list & repositions it
|
||||
void CAMSchedule::ShuntHead()
|
||||
{
|
||||
CAdvisePacket * p_prev = &head;
|
||||
CAdvisePacket * p_n;
|
||||
|
||||
m_Serialize.Lock();
|
||||
CAdvisePacket *const pPacket = head.m_next;
|
||||
|
||||
// This will catch both an empty list,
|
||||
// and if somehow a MAX_TIME time gets into the list
|
||||
// (which would also break this method).
|
||||
ASSERT( pPacket->m_rtEventTime < MAX_TIME );
|
||||
|
||||
// This relies on the fact that z is a sentry with a maximal m_rtEventTime
|
||||
for(;;p_prev = p_n)
|
||||
{
|
||||
p_n = p_prev->m_next;
|
||||
if ( p_n->m_rtEventTime > pPacket->m_rtEventTime ) break;
|
||||
}
|
||||
// If p_prev == pPacket then we're already in the right place
|
||||
if (p_prev != pPacket)
|
||||
{
|
||||
head.m_next = pPacket->m_next;
|
||||
(p_prev->m_next = pPacket)->m_next = p_n;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
DbgLog((LOG_TIMING, 2, TEXT("Periodic advise %lu, shunted to %lu"),
|
||||
pPacket->m_dwAdviseCookie, (pPacket->m_rtEventTime / (UNITS / MILLISECONDS)) ));
|
||||
#endif
|
||||
m_Serialize.Unlock();
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void CAMSchedule::DumpLinkedList()
|
||||
{
|
||||
m_Serialize.Lock();
|
||||
int i=0;
|
||||
DbgLog((LOG_TIMING, 1, TEXT("CAMSchedule::DumpLinkedList() this = 0x%p"), this));
|
||||
for ( CAdvisePacket * p = &head
|
||||
; p
|
||||
; p = p->m_next , i++
|
||||
)
|
||||
{
|
||||
DbgLog((LOG_TIMING, 1, TEXT("Advise List # %lu, Cookie %d, RefTime %lu"),
|
||||
i,
|
||||
p->m_dwAdviseCookie,
|
||||
p->m_rtEventTime / (UNITS / MILLISECONDS)
|
||||
));
|
||||
}
|
||||
m_Serialize.Unlock();
|
||||
}
|
||||
#endif
|
||||
Vendored
-128
@@ -1,128 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: Schedule.h
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __CAMSchedule__
|
||||
#define __CAMSchedule__
|
||||
|
||||
class CAMSchedule : private CBaseObject
|
||||
{
|
||||
public:
|
||||
virtual ~CAMSchedule();
|
||||
// ev is the event we should fire if the advise time needs re-evaluating
|
||||
CAMSchedule( HANDLE ev );
|
||||
|
||||
DWORD GetAdviseCount();
|
||||
REFERENCE_TIME GetNextAdviseTime();
|
||||
|
||||
// We need a method for derived classes to add advise packets, we return the cookie
|
||||
DWORD_PTR AddAdvisePacket( const REFERENCE_TIME & time1, const REFERENCE_TIME & time2, HANDLE h, BOOL periodic );
|
||||
// And a way to cancel
|
||||
HRESULT Unadvise(DWORD_PTR dwAdviseCookie);
|
||||
|
||||
// Tell us the time please, and we'll dispatch the expired events. We return the time of the next event.
|
||||
// NB: The time returned will be "useless" if you start adding extra Advises. But that's the problem of
|
||||
// whoever is using this helper class (typically a clock).
|
||||
REFERENCE_TIME Advise( const REFERENCE_TIME & rtTime );
|
||||
|
||||
// Get the event handle which will be set if advise time requires re-evaluation.
|
||||
HANDLE GetEvent() const { return m_ev; }
|
||||
|
||||
private:
|
||||
// We define the nodes that will be used in our singly linked list
|
||||
// of advise packets. The list is ordered by time, with the
|
||||
// elements that will expire first at the front.
|
||||
class CAdvisePacket
|
||||
{
|
||||
public:
|
||||
CAdvisePacket()
|
||||
{}
|
||||
|
||||
CAdvisePacket * m_next;
|
||||
DWORD_PTR m_dwAdviseCookie;
|
||||
REFERENCE_TIME m_rtEventTime; // Time at which event should be set
|
||||
REFERENCE_TIME m_rtPeriod; // Periodic time
|
||||
HANDLE m_hNotify; // Handle to event or semephore
|
||||
BOOL m_bPeriodic; // TRUE => Periodic event
|
||||
|
||||
CAdvisePacket( __inout_opt CAdvisePacket * next, LONGLONG time ) : m_next(next), m_rtEventTime(time)
|
||||
{}
|
||||
|
||||
void InsertAfter( __inout CAdvisePacket * p )
|
||||
{
|
||||
p->m_next = m_next;
|
||||
m_next = p;
|
||||
}
|
||||
|
||||
int IsZ() const // That is, is it the node that represents the end of the list
|
||||
{ return m_next == 0; }
|
||||
|
||||
CAdvisePacket * RemoveNext()
|
||||
{
|
||||
CAdvisePacket *const next = m_next;
|
||||
CAdvisePacket *const new_next = next->m_next;
|
||||
m_next = new_next;
|
||||
return next;
|
||||
}
|
||||
|
||||
void DeleteNext()
|
||||
{
|
||||
delete RemoveNext();
|
||||
}
|
||||
|
||||
CAdvisePacket * Next() const
|
||||
{
|
||||
CAdvisePacket * result = m_next;
|
||||
if (result->IsZ()) result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
DWORD_PTR Cookie() const
|
||||
{ return m_dwAdviseCookie; }
|
||||
};
|
||||
|
||||
// Structure is:
|
||||
// head -> elmt1 -> elmt2 -> z -> null
|
||||
// So an empty list is: head -> z -> null
|
||||
// Having head & z as links makes insertaion,
|
||||
// deletion and shunting much easier.
|
||||
CAdvisePacket head, z; // z is both a tail and a sentry
|
||||
|
||||
volatile DWORD_PTR m_dwNextCookie; // Strictly increasing
|
||||
volatile DWORD m_dwAdviseCount; // Number of elements on list
|
||||
|
||||
CCritSec m_Serialize;
|
||||
|
||||
// AddAdvisePacket: adds the packet, returns the cookie (0 if failed)
|
||||
DWORD_PTR AddAdvisePacket( __inout CAdvisePacket * pPacket );
|
||||
// Event that we should set if the packed added above will be the next to fire.
|
||||
const HANDLE m_ev;
|
||||
|
||||
// A Shunt is where we have changed the first element in the
|
||||
// list and want it re-evaluating (i.e. repositioned) in
|
||||
// the list.
|
||||
void ShuntHead();
|
||||
|
||||
// Rather than delete advise packets, we cache them for future use
|
||||
CAdvisePacket * m_pAdviseCache;
|
||||
DWORD m_dwCacheCount;
|
||||
enum { dwCacheMax = 5 }; // Don't bother caching more than five
|
||||
|
||||
void Delete( __inout CAdvisePacket * pLink );// This "Delete" will cache the Link
|
||||
|
||||
// Attributes and methods for debugging
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
void DumpLinkedList();
|
||||
#else
|
||||
void DumpLinkedList() {}
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // __CAMSchedule__
|
||||
Vendored
-83
@@ -1,83 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: SeekPT.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
#include "seekpt.h"
|
||||
|
||||
//==================================================================
|
||||
// CreateInstance
|
||||
// This goes in the factory template table to create new instances
|
||||
// If there is already a mapper instance - return that, else make one
|
||||
// and save it in a static variable so that forever after we can return that.
|
||||
//==================================================================
|
||||
|
||||
CUnknown * CSeekingPassThru::CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr)
|
||||
{
|
||||
return new CSeekingPassThru(NAME("Seeking PassThru"),pUnk, phr);
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CSeekingPassThru::NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv)
|
||||
{
|
||||
if (riid == IID_ISeekingPassThru) {
|
||||
return GetInterface((ISeekingPassThru *) this, ppv);
|
||||
} else {
|
||||
if (m_pPosPassThru &&
|
||||
(riid == IID_IMediaSeeking ||
|
||||
riid == IID_IMediaPosition)) {
|
||||
return m_pPosPassThru->NonDelegatingQueryInterface(riid,ppv);
|
||||
} else {
|
||||
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSeekingPassThru::CSeekingPassThru( __in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr )
|
||||
: CUnknown(pName, pUnk, phr),
|
||||
m_pPosPassThru(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
CSeekingPassThru::~CSeekingPassThru()
|
||||
{
|
||||
delete m_pPosPassThru;
|
||||
}
|
||||
|
||||
STDMETHODIMP CSeekingPassThru::Init(BOOL bRendererSeeking, IPin *pPin)
|
||||
{
|
||||
HRESULT hr = NOERROR;
|
||||
if (m_pPosPassThru) {
|
||||
hr = E_FAIL;
|
||||
} else {
|
||||
m_pPosPassThru =
|
||||
bRendererSeeking ?
|
||||
new CRendererPosPassThru(
|
||||
NAME("Render Seeking COM object"),
|
||||
(IUnknown *)this,
|
||||
&hr,
|
||||
pPin) :
|
||||
new CPosPassThru(
|
||||
NAME("Render Seeking COM object"),
|
||||
(IUnknown *)this,
|
||||
&hr,
|
||||
pPin);
|
||||
if (!m_pPosPassThru) {
|
||||
hr = E_OUTOFMEMORY;
|
||||
} else {
|
||||
if (FAILED(hr)) {
|
||||
delete m_pPosPassThru;
|
||||
m_pPosPassThru = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
Vendored
-30
@@ -1,30 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: SeekPT.h
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __seekpt_h__
|
||||
#define __seekpt_h__
|
||||
|
||||
|
||||
class CSeekingPassThru : public ISeekingPassThru, public CUnknown
|
||||
{
|
||||
public:
|
||||
static CUnknown *CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr);
|
||||
CSeekingPassThru(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr);
|
||||
~CSeekingPassThru();
|
||||
|
||||
DECLARE_IUNKNOWN;
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
|
||||
|
||||
STDMETHODIMP Init(BOOL bSupportRendering, IPin *pPin);
|
||||
|
||||
private:
|
||||
CPosPassThru *m_pPosPassThru;
|
||||
};
|
||||
|
||||
#endif
|
||||
Vendored
-522
@@ -1,522 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: Source.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes - implements CSource, which is a Quartz
|
||||
// source filter 'template.'
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Locking Strategy.
|
||||
//
|
||||
// Hold the filter critical section (m_pFilter->pStateLock()) to serialise
|
||||
// access to functions. Note that, in general, this lock may be held
|
||||
// by a function when the worker thread may want to hold it. Therefore
|
||||
// if you wish to access shared state from the worker thread you will
|
||||
// need to add another critical section object. The execption is during
|
||||
// the threads processing loop, when it is safe to get the filter critical
|
||||
// section from within FillBuffer().
|
||||
|
||||
#include <streams.h>
|
||||
|
||||
|
||||
//
|
||||
// CSource::Constructor
|
||||
//
|
||||
// Initialise the pin count for the filter. The user will create the pins in
|
||||
// the derived class.
|
||||
CSource::CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid)
|
||||
: CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
|
||||
m_iPins(0),
|
||||
m_paStreams(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CSource::CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr)
|
||||
: CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
|
||||
m_iPins(0),
|
||||
m_paStreams(NULL)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(phr);
|
||||
}
|
||||
|
||||
#ifdef UNICODE
|
||||
CSource::CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid)
|
||||
: CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
|
||||
m_iPins(0),
|
||||
m_paStreams(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
CSource::CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr)
|
||||
: CBaseFilter(pName, lpunk, &m_cStateLock, clsid),
|
||||
m_iPins(0),
|
||||
m_paStreams(NULL)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(phr);
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// CSource::Destructor
|
||||
//
|
||||
CSource::~CSource()
|
||||
{
|
||||
/* Free our pins and pin array */
|
||||
while (m_iPins != 0) {
|
||||
// deleting the pins causes them to be removed from the array...
|
||||
delete m_paStreams[m_iPins - 1];
|
||||
}
|
||||
|
||||
ASSERT(m_paStreams == NULL);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Add a new pin
|
||||
//
|
||||
HRESULT CSource::AddPin(__in CSourceStream *pStream)
|
||||
{
|
||||
CAutoLock lock(&m_cStateLock);
|
||||
|
||||
/* Allocate space for this pin and the old ones */
|
||||
CSourceStream **paStreams = new CSourceStream *[m_iPins + 1];
|
||||
if (paStreams == NULL) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
if (m_paStreams != NULL) {
|
||||
CopyMemory((PVOID)paStreams, (PVOID)m_paStreams,
|
||||
m_iPins * sizeof(m_paStreams[0]));
|
||||
paStreams[m_iPins] = pStream;
|
||||
delete [] m_paStreams;
|
||||
}
|
||||
m_paStreams = paStreams;
|
||||
m_paStreams[m_iPins] = pStream;
|
||||
m_iPins++;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// Remove a pin - pStream is NOT deleted
|
||||
//
|
||||
HRESULT CSource::RemovePin(__in CSourceStream *pStream)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < m_iPins; i++) {
|
||||
if (m_paStreams[i] == pStream) {
|
||||
if (m_iPins == 1) {
|
||||
delete [] m_paStreams;
|
||||
m_paStreams = NULL;
|
||||
} else {
|
||||
/* no need to reallocate */
|
||||
while (++i < m_iPins)
|
||||
m_paStreams[i - 1] = m_paStreams[i];
|
||||
}
|
||||
m_iPins--;
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// FindPin
|
||||
//
|
||||
// Set *ppPin to the IPin* that has the id Id.
|
||||
// or to NULL if the Id cannot be matched.
|
||||
STDMETHODIMP CSource::FindPin(LPCWSTR Id, __deref_out IPin **ppPin)
|
||||
{
|
||||
CheckPointer(ppPin,E_POINTER);
|
||||
ValidateReadWritePtr(ppPin,sizeof(IPin *));
|
||||
// The -1 undoes the +1 in QueryId and ensures that totally invalid
|
||||
// strings (for which WstrToInt delivers 0) give a deliver a NULL pin.
|
||||
int i = WstrToInt(Id) -1;
|
||||
*ppPin = GetPin(i);
|
||||
if (*ppPin!=NULL){
|
||||
(*ppPin)->AddRef();
|
||||
return NOERROR;
|
||||
} else {
|
||||
return VFW_E_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// FindPinNumber
|
||||
//
|
||||
// return the number of the pin with this IPin* or -1 if none
|
||||
int CSource::FindPinNumber(__in IPin *iPin) {
|
||||
int i;
|
||||
for (i=0; i<m_iPins; ++i) {
|
||||
if ((IPin *)(m_paStreams[i])==iPin) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
//
|
||||
// GetPinCount
|
||||
//
|
||||
// Returns the number of pins this filter has
|
||||
int CSource::GetPinCount(void) {
|
||||
|
||||
CAutoLock lock(&m_cStateLock);
|
||||
return m_iPins;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetPin
|
||||
//
|
||||
// Return a non-addref'd pointer to pin n
|
||||
// needed by CBaseFilter
|
||||
CBasePin *CSource::GetPin(int n) {
|
||||
|
||||
CAutoLock lock(&m_cStateLock);
|
||||
|
||||
// n must be in the range 0..m_iPins-1
|
||||
// if m_iPins>n && n>=0 it follows that m_iPins>0
|
||||
// which is what used to be checked (i.e. checking that we have a pin)
|
||||
if ((n >= 0) && (n < m_iPins)) {
|
||||
|
||||
ASSERT(m_paStreams[n]);
|
||||
return m_paStreams[n];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
|
||||
|
||||
// *
|
||||
// * --- CSourceStream ----
|
||||
// *
|
||||
|
||||
//
|
||||
// Set Id to point to a CoTaskMemAlloc'd
|
||||
STDMETHODIMP CSourceStream::QueryId(__deref_out LPWSTR *Id) {
|
||||
CheckPointer(Id,E_POINTER);
|
||||
ValidateReadWritePtr(Id,sizeof(LPWSTR));
|
||||
|
||||
// We give the pins id's which are 1,2,...
|
||||
// FindPinNumber returns -1 for an invalid pin
|
||||
int i = 1+ m_pFilter->FindPinNumber(this);
|
||||
if (i<1) return VFW_E_NOT_FOUND;
|
||||
*Id = (LPWSTR)CoTaskMemAlloc(sizeof(WCHAR) * 12);
|
||||
if (*Id==NULL) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
IntToWstr(i, *Id);
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// CSourceStream::Constructor
|
||||
//
|
||||
// increments the number of pins present on the filter
|
||||
CSourceStream::CSourceStream(
|
||||
__in_opt LPCTSTR pObjectName,
|
||||
__inout HRESULT *phr,
|
||||
__inout CSource *ps,
|
||||
__in_opt LPCWSTR pPinName)
|
||||
: CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName),
|
||||
m_pFilter(ps) {
|
||||
|
||||
*phr = m_pFilter->AddPin(this);
|
||||
}
|
||||
|
||||
#ifdef UNICODE
|
||||
CSourceStream::CSourceStream(
|
||||
__in_opt LPCSTR pObjectName,
|
||||
__inout HRESULT *phr,
|
||||
__inout CSource *ps,
|
||||
__in_opt LPCWSTR pPinName)
|
||||
: CBaseOutputPin(pObjectName, ps, ps->pStateLock(), phr, pPinName),
|
||||
m_pFilter(ps) {
|
||||
|
||||
*phr = m_pFilter->AddPin(this);
|
||||
}
|
||||
#endif
|
||||
//
|
||||
// CSourceStream::Destructor
|
||||
//
|
||||
// Decrements the number of pins on this filter
|
||||
CSourceStream::~CSourceStream(void) {
|
||||
|
||||
m_pFilter->RemovePin(this);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CheckMediaType
|
||||
//
|
||||
// Do we support this type? Provides the default support for 1 type.
|
||||
HRESULT CSourceStream::CheckMediaType(const CMediaType *pMediaType) {
|
||||
|
||||
CAutoLock lock(m_pFilter->pStateLock());
|
||||
|
||||
CMediaType mt;
|
||||
GetMediaType(&mt);
|
||||
|
||||
if (mt == *pMediaType) {
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// GetMediaType/3
|
||||
//
|
||||
// By default we support only one type
|
||||
// iPosition indexes are 0-n
|
||||
HRESULT CSourceStream::GetMediaType(int iPosition, __inout CMediaType *pMediaType) {
|
||||
|
||||
CAutoLock lock(m_pFilter->pStateLock());
|
||||
|
||||
if (iPosition<0) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if (iPosition>0) {
|
||||
return VFW_S_NO_MORE_ITEMS;
|
||||
}
|
||||
return GetMediaType(pMediaType);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Active
|
||||
//
|
||||
// The pin is active - start up the worker thread
|
||||
HRESULT CSourceStream::Active(void) {
|
||||
|
||||
CAutoLock lock(m_pFilter->pStateLock());
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
if (m_pFilter->IsActive()) {
|
||||
return S_FALSE; // succeeded, but did not allocate resources (they already exist...)
|
||||
}
|
||||
|
||||
// do nothing if not connected - its ok not to connect to
|
||||
// all pins of a source filter
|
||||
if (!IsConnected()) {
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
hr = CBaseOutputPin::Active();
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
ASSERT(!ThreadExists());
|
||||
|
||||
// start the thread
|
||||
if (!Create()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Tell thread to initialize. If OnThreadCreate Fails, so does this.
|
||||
hr = Init();
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
return Pause();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Inactive
|
||||
//
|
||||
// Pin is inactive - shut down the worker thread
|
||||
// Waits for the worker to exit before returning.
|
||||
HRESULT CSourceStream::Inactive(void) {
|
||||
|
||||
CAutoLock lock(m_pFilter->pStateLock());
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
// do nothing if not connected - its ok not to connect to
|
||||
// all pins of a source filter
|
||||
if (!IsConnected()) {
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
// !!! need to do this before trying to stop the thread, because
|
||||
// we may be stuck waiting for our own allocator!!!
|
||||
|
||||
hr = CBaseOutputPin::Inactive(); // call this first to Decommit the allocator
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (ThreadExists()) {
|
||||
hr = Stop();
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = Exit();
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
Close(); // Wait for the thread to exit, then tidy up.
|
||||
}
|
||||
|
||||
// hr = CBaseOutputPin::Inactive(); // call this first to Decommit the allocator
|
||||
//if (FAILED(hr)) {
|
||||
// return hr;
|
||||
//}
|
||||
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// ThreadProc
|
||||
//
|
||||
// When this returns the thread exits
|
||||
// Return codes > 0 indicate an error occured
|
||||
DWORD CSourceStream::ThreadProc(void) {
|
||||
|
||||
HRESULT hr; // the return code from calls
|
||||
Command com;
|
||||
|
||||
do {
|
||||
com = GetRequest();
|
||||
if (com != CMD_INIT) {
|
||||
DbgLog((LOG_ERROR, 1, TEXT("Thread expected init command")));
|
||||
Reply((DWORD) E_UNEXPECTED);
|
||||
}
|
||||
} while (com != CMD_INIT);
|
||||
|
||||
DbgLog((LOG_TRACE, 1, TEXT("CSourceStream worker thread initializing")));
|
||||
|
||||
hr = OnThreadCreate(); // perform set up tasks
|
||||
if (FAILED(hr)) {
|
||||
DbgLog((LOG_ERROR, 1, TEXT("CSourceStream::OnThreadCreate failed. Aborting thread.")));
|
||||
OnThreadDestroy();
|
||||
Reply(hr); // send failed return code from OnThreadCreate
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Initialisation suceeded
|
||||
Reply(NOERROR);
|
||||
|
||||
Command cmd;
|
||||
do {
|
||||
cmd = GetRequest();
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case CMD_EXIT:
|
||||
Reply(NOERROR);
|
||||
break;
|
||||
|
||||
case CMD_RUN:
|
||||
DbgLog((LOG_ERROR, 1, TEXT("CMD_RUN received before a CMD_PAUSE???")));
|
||||
// !!! fall through???
|
||||
|
||||
case CMD_PAUSE:
|
||||
Reply(NOERROR);
|
||||
DoBufferProcessingLoop();
|
||||
break;
|
||||
|
||||
case CMD_STOP:
|
||||
Reply(NOERROR);
|
||||
break;
|
||||
|
||||
default:
|
||||
DbgLog((LOG_ERROR, 1, TEXT("Unknown command %d received!"), cmd));
|
||||
Reply((DWORD) E_NOTIMPL);
|
||||
break;
|
||||
}
|
||||
} while (cmd != CMD_EXIT);
|
||||
|
||||
hr = OnThreadDestroy(); // tidy up.
|
||||
if (FAILED(hr)) {
|
||||
DbgLog((LOG_ERROR, 1, TEXT("CSourceStream::OnThreadDestroy failed. Exiting thread.")));
|
||||
return 1;
|
||||
}
|
||||
|
||||
DbgLog((LOG_TRACE, 1, TEXT("CSourceStream worker thread exiting")));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// DoBufferProcessingLoop
|
||||
//
|
||||
// Grabs a buffer and calls the users processing function.
|
||||
// Overridable, so that different delivery styles can be catered for.
|
||||
HRESULT CSourceStream::DoBufferProcessingLoop(void) {
|
||||
|
||||
Command com;
|
||||
|
||||
OnThreadStartPlay();
|
||||
|
||||
do {
|
||||
while (!CheckRequest(&com)) {
|
||||
|
||||
IMediaSample *pSample;
|
||||
|
||||
HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
|
||||
if (FAILED(hr)) {
|
||||
Sleep(1);
|
||||
continue; // go round again. Perhaps the error will go away
|
||||
// or the allocator is decommited & we will be asked to
|
||||
// exit soon.
|
||||
}
|
||||
|
||||
// Virtual function user will override.
|
||||
hr = FillBuffer(pSample);
|
||||
|
||||
if (hr == S_OK) {
|
||||
hr = Deliver(pSample);
|
||||
pSample->Release();
|
||||
|
||||
// downstream filter returns S_FALSE if it wants us to
|
||||
// stop or an error if it's reporting an error.
|
||||
if(hr != S_OK)
|
||||
{
|
||||
DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} else if (hr == S_FALSE) {
|
||||
// derived class wants us to stop pushing data
|
||||
pSample->Release();
|
||||
DeliverEndOfStream();
|
||||
return S_OK;
|
||||
} else {
|
||||
// derived class encountered an error
|
||||
pSample->Release();
|
||||
DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr));
|
||||
DeliverEndOfStream();
|
||||
m_pFilter->NotifyEvent(EC_ERRORABORT, hr, 0);
|
||||
return hr;
|
||||
}
|
||||
|
||||
// all paths release the sample
|
||||
}
|
||||
|
||||
// For all commands sent to us there must be a Reply call!
|
||||
|
||||
if (com == CMD_RUN || com == CMD_PAUSE) {
|
||||
Reply(NOERROR);
|
||||
} else if (com != CMD_STOP) {
|
||||
Reply((DWORD) E_UNEXPECTED);
|
||||
DbgLog((LOG_ERROR, 1, TEXT("Unexpected command!!!")));
|
||||
}
|
||||
} while (com != CMD_STOP);
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
Vendored
-172
@@ -1,172 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: Source.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines classes to simplify creation of
|
||||
// ActiveX source filters that support continuous generation of data.
|
||||
// No support is provided for IMediaControl or IMediaPosition.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//
|
||||
// Derive your source filter from CSource.
|
||||
// During construction either:
|
||||
// Create some CSourceStream objects to manage your pins
|
||||
// Provide the user with a means of doing so eg, an IPersistFile interface.
|
||||
//
|
||||
// CSource provides:
|
||||
// IBaseFilter interface management
|
||||
// IMediaFilter interface management, via CBaseFilter
|
||||
// Pin counting for CBaseFilter
|
||||
//
|
||||
// Derive a class from CSourceStream to manage your output pin types
|
||||
// Implement GetMediaType/1 to return the type you support. If you support multiple
|
||||
// types then overide GetMediaType/3, CheckMediaType and GetMediaTypeCount.
|
||||
// Implement Fillbuffer() to put data into one buffer.
|
||||
//
|
||||
// CSourceStream provides:
|
||||
// IPin management via CBaseOutputPin
|
||||
// Worker thread management
|
||||
|
||||
#ifndef __CSOURCE__
|
||||
#define __CSOURCE__
|
||||
|
||||
class CSourceStream; // The class that will handle each pin
|
||||
|
||||
|
||||
//
|
||||
// CSource
|
||||
//
|
||||
// Override construction to provide a means of creating
|
||||
// CSourceStream derived objects - ie a way of creating pins.
|
||||
class CSource : public CBaseFilter {
|
||||
public:
|
||||
|
||||
CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr);
|
||||
CSource(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid);
|
||||
#ifdef UNICODE
|
||||
CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid, __inout HRESULT *phr);
|
||||
CSource(__in_opt LPCSTR pName, __inout_opt LPUNKNOWN lpunk, CLSID clsid);
|
||||
#endif
|
||||
~CSource();
|
||||
|
||||
int GetPinCount(void);
|
||||
CBasePin *GetPin(int n);
|
||||
|
||||
// -- Utilities --
|
||||
|
||||
CCritSec* pStateLock(void) { return &m_cStateLock; } // provide our critical section
|
||||
|
||||
HRESULT AddPin(__in CSourceStream *);
|
||||
HRESULT RemovePin(__in CSourceStream *);
|
||||
|
||||
STDMETHODIMP FindPin(
|
||||
LPCWSTR Id,
|
||||
__deref_out IPin ** ppPin
|
||||
);
|
||||
|
||||
int FindPinNumber(__in IPin *iPin);
|
||||
|
||||
protected:
|
||||
|
||||
int m_iPins; // The number of pins on this filter. Updated by CSourceStream
|
||||
// constructors & destructors.
|
||||
CSourceStream **m_paStreams; // the pins on this filter.
|
||||
|
||||
CCritSec m_cStateLock; // Lock this to serialize function accesses to the filter state
|
||||
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// CSourceStream
|
||||
//
|
||||
// Use this class to manage a stream of data that comes from a
|
||||
// pin.
|
||||
// Uses a worker thread to put data on the pin.
|
||||
class CSourceStream : public CAMThread, public CBaseOutputPin {
|
||||
public:
|
||||
|
||||
CSourceStream(__in_opt LPCTSTR pObjectName,
|
||||
__inout HRESULT *phr,
|
||||
__inout CSource *pms,
|
||||
__in_opt LPCWSTR pName);
|
||||
#ifdef UNICODE
|
||||
CSourceStream(__in_opt LPCSTR pObjectName,
|
||||
__inout HRESULT *phr,
|
||||
__inout CSource *pms,
|
||||
__in_opt LPCWSTR pName);
|
||||
#endif
|
||||
virtual ~CSourceStream(void); // virtual destructor ensures derived class destructors are called too.
|
||||
|
||||
protected:
|
||||
|
||||
CSource *m_pFilter; // The parent of this stream
|
||||
|
||||
// *
|
||||
// * Data Source
|
||||
// *
|
||||
// * The following three functions: FillBuffer, OnThreadCreate/Destroy, are
|
||||
// * called from within the ThreadProc. They are used in the creation of
|
||||
// * the media samples this pin will provide
|
||||
// *
|
||||
|
||||
// Override this to provide the worker thread a means
|
||||
// of processing a buffer
|
||||
virtual HRESULT FillBuffer(IMediaSample *pSamp) PURE;
|
||||
|
||||
// Called as the thread is created/destroyed - use to perform
|
||||
// jobs such as start/stop streaming mode
|
||||
// If OnThreadCreate returns an error the thread will exit.
|
||||
virtual HRESULT OnThreadCreate(void) {return NOERROR;};
|
||||
virtual HRESULT OnThreadDestroy(void) {return NOERROR;};
|
||||
virtual HRESULT OnThreadStartPlay(void) {return NOERROR;};
|
||||
|
||||
// *
|
||||
// * Worker Thread
|
||||
// *
|
||||
|
||||
HRESULT Active(void); // Starts up the worker thread
|
||||
HRESULT Inactive(void); // Exits the worker thread.
|
||||
|
||||
public:
|
||||
// thread commands
|
||||
enum Command {CMD_INIT, CMD_PAUSE, CMD_RUN, CMD_STOP, CMD_EXIT};
|
||||
HRESULT Init(void) { return CallWorker(CMD_INIT); }
|
||||
HRESULT Exit(void) { return CallWorker(CMD_EXIT); }
|
||||
HRESULT Run(void) { return CallWorker(CMD_RUN); }
|
||||
HRESULT Pause(void) { return CallWorker(CMD_PAUSE); }
|
||||
HRESULT Stop(void) { return CallWorker(CMD_STOP); }
|
||||
|
||||
protected:
|
||||
Command GetRequest(void) { return (Command) CAMThread::GetRequest(); }
|
||||
BOOL CheckRequest(Command *pCom) { return CAMThread::CheckRequest( (DWORD *) pCom); }
|
||||
|
||||
// override these if you want to add thread commands
|
||||
virtual DWORD ThreadProc(void); // the thread function
|
||||
|
||||
virtual HRESULT DoBufferProcessingLoop(void); // the loop executed whilst running
|
||||
|
||||
|
||||
// *
|
||||
// * AM_MEDIA_TYPE support
|
||||
// *
|
||||
|
||||
// If you support more than one media type then override these 2 functions
|
||||
virtual HRESULT CheckMediaType(const CMediaType *pMediaType);
|
||||
virtual HRESULT GetMediaType(int iPosition, __inout CMediaType *pMediaType); // List pos. 0-n
|
||||
|
||||
// If you support only one type then override this fn.
|
||||
// This will only be called by the default implementations
|
||||
// of CheckMediaType and GetMediaType(int, CMediaType*)
|
||||
// You must override this fn. or the above 2!
|
||||
virtual HRESULT GetMediaType(__inout CMediaType *pMediaType) {return E_UNEXPECTED;}
|
||||
|
||||
STDMETHODIMP QueryId(
|
||||
__deref_out LPWSTR * Id
|
||||
);
|
||||
};
|
||||
|
||||
#endif // __CSOURCE__
|
||||
|
||||
Vendored
-197
@@ -1,197 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: Streams.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines overall streams architecture.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __STREAMS__
|
||||
#define __STREAMS__
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// disable some level-4 warnings, use #pragma warning(enable:###) to re-enable
|
||||
#pragma warning(disable:4100) // warning C4100: unreferenced formal parameter
|
||||
#pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union
|
||||
#pragma warning(disable:4511) // warning C4511: copy constructor could not be generated
|
||||
#pragma warning(disable:4512) // warning C4512: assignment operator could not be generated
|
||||
#pragma warning(disable:4514) // warning C4514: "unreferenced inline function has been removed"
|
||||
|
||||
#if _MSC_VER>=1100
|
||||
#define AM_NOVTABLE __declspec(novtable)
|
||||
#else
|
||||
#define AM_NOVTABLE
|
||||
#endif
|
||||
#endif // MSC_VER
|
||||
|
||||
|
||||
// Because of differences between Visual C++ and older Microsoft SDKs,
|
||||
// you may have defined _DEBUG without defining DEBUG. This logic
|
||||
// ensures that both will be set if Visual C++ sets _DEBUG.
|
||||
#ifdef _DEBUG
|
||||
#ifndef DEBUG
|
||||
#define DEBUG
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <olectl.h>
|
||||
#include <ddraw.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
|
||||
#ifndef NUMELMS
|
||||
#if _WIN32_WINNT < 0x0600
|
||||
#define NUMELMS(aa) (sizeof(aa)/sizeof((aa)[0]))
|
||||
#else
|
||||
#define NUMELMS(aa) ARRAYSIZE(aa)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The following definitions come from the Platform SDK and are required if
|
||||
// the applicaiton is being compiled with the headers from Visual C++ 6.0.
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
#ifndef InterlockedExchangePointer
|
||||
#define InterlockedExchangePointer(Target, Value) \
|
||||
(PVOID)InterlockedExchange((PLONG)(Target), (LONG)(Value))
|
||||
#endif
|
||||
|
||||
#ifndef _WAVEFORMATEXTENSIBLE_
|
||||
#define _WAVEFORMATEXTENSIBLE_
|
||||
typedef struct {
|
||||
WAVEFORMATEX Format;
|
||||
union {
|
||||
WORD wValidBitsPerSample; /* bits of precision */
|
||||
WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */
|
||||
WORD wReserved; /* If neither applies, set to zero. */
|
||||
} Samples;
|
||||
DWORD dwChannelMask; /* which channels are */
|
||||
/* present in stream */
|
||||
GUID SubFormat;
|
||||
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;
|
||||
#endif // !_WAVEFORMATEXTENSIBLE_
|
||||
|
||||
#if !defined(WAVE_FORMAT_EXTENSIBLE)
|
||||
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
|
||||
#endif // !defined(WAVE_FORMAT_EXTENSIBLE)
|
||||
|
||||
#ifndef GetWindowLongPtr
|
||||
#define GetWindowLongPtrA GetWindowLongA
|
||||
#define GetWindowLongPtrW GetWindowLongW
|
||||
#ifdef UNICODE
|
||||
#define GetWindowLongPtr GetWindowLongPtrW
|
||||
#else
|
||||
#define GetWindowLongPtr GetWindowLongPtrA
|
||||
#endif // !UNICODE
|
||||
#endif // !GetWindowLongPtr
|
||||
|
||||
#ifndef SetWindowLongPtr
|
||||
#define SetWindowLongPtrA SetWindowLongA
|
||||
#define SetWindowLongPtrW SetWindowLongW
|
||||
#ifdef UNICODE
|
||||
#define SetWindowLongPtr SetWindowLongPtrW
|
||||
#else
|
||||
#define SetWindowLongPtr SetWindowLongPtrA
|
||||
#endif // !UNICODE
|
||||
#endif // !SetWindowLongPtr
|
||||
|
||||
#ifndef GWLP_WNDPROC
|
||||
#define GWLP_WNDPROC (-4)
|
||||
#endif
|
||||
#ifndef GWLP_HINSTANCE
|
||||
#define GWLP_HINSTANCE (-6)
|
||||
#endif
|
||||
#ifndef GWLP_HWNDPARENT
|
||||
#define GWLP_HWNDPARENT (-8)
|
||||
#endif
|
||||
#ifndef GWLP_USERDATA
|
||||
#define GWLP_USERDATA (-21)
|
||||
#endif
|
||||
#ifndef GWLP_ID
|
||||
#define GWLP_ID (-12)
|
||||
#endif
|
||||
#ifndef DWLP_MSGRESULT
|
||||
#define DWLP_MSGRESULT 0
|
||||
#endif
|
||||
#ifndef DWLP_DLGPROC
|
||||
#define DWLP_DLGPROC DWLP_MSGRESULT + sizeof(LRESULT)
|
||||
#endif
|
||||
#ifndef DWLP_USER
|
||||
#define DWLP_USER DWLP_DLGPROC + sizeof(DLGPROC)
|
||||
#endif
|
||||
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4312 4244)
|
||||
// _GetWindowLongPtr
|
||||
// Templated version of GetWindowLongPtr, to suppress spurious compiler warning.
|
||||
template <class T>
|
||||
T _GetWindowLongPtr(HWND hwnd, int nIndex)
|
||||
{
|
||||
return (T)GetWindowLongPtr(hwnd, nIndex);
|
||||
}
|
||||
|
||||
// _SetWindowLongPtr
|
||||
// Templated version of SetWindowLongPtr, to suppress spurious compiler warning.
|
||||
template <class T>
|
||||
LONG_PTR _SetWindowLongPtr(HWND hwnd, int nIndex, T p)
|
||||
{
|
||||
return SetWindowLongPtr(hwnd, nIndex, (LONG_PTR)p);
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// End Platform SDK definitions
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include <strmif.h> // Generated IDL header file for streams interfaces
|
||||
#include <intsafe.h> // required by amvideo.h
|
||||
|
||||
#include <reftime.h> // Helper class for REFERENCE_TIME management
|
||||
#include <wxdebug.h> // Debug support for logging and ASSERTs
|
||||
#include <amvideo.h> // ActiveMovie video interfaces and definitions
|
||||
//include amaudio.h explicitly if you need it. it requires the DX SDK.
|
||||
//#include <amaudio.h> // ActiveMovie audio interfaces and definitions
|
||||
#include <wxutil.h> // General helper classes for threads etc
|
||||
#include <combase.h> // Base COM classes to support IUnknown
|
||||
#include <measure.h> // Performance measurement
|
||||
#include <comlite.h> // Light weight com function prototypes
|
||||
|
||||
#include <cache.h> // Simple cache container class
|
||||
#include <wxlist.h> // Non MFC generic list class
|
||||
#include <msgthrd.h> // CMsgThread
|
||||
#include <mtype.h> // Helper class for managing media types
|
||||
#include <fourcc.h> // conversions between FOURCCs and GUIDs
|
||||
#include <control.h> // generated from control.odl
|
||||
#include <ctlutil.h> // control interface utility classes
|
||||
#include <evcode.h> // event code definitions
|
||||
#include <amfilter.h> // Main streams architecture class hierachy
|
||||
#include <transfrm.h> // Generic transform filter
|
||||
#include <transip.h> // Generic transform-in-place filter
|
||||
#include <uuids.h> // declaration of type GUIDs and well-known clsids
|
||||
#include <source.h> // Generic source filter
|
||||
#include <outputq.h> // Output pin queueing
|
||||
#include <errors.h> // HRESULT status and error definitions
|
||||
#include <renbase.h> // Base class for writing ActiveX renderers
|
||||
#include <refclock.h> // Base clock class
|
||||
#include <sysclock.h> // System clock
|
||||
#include <pstream.h> // IPersistStream helper class
|
||||
#include <vtrans.h> // Video Transform Filter base class
|
||||
#include <amextra.h>
|
||||
#include <strmctl.h> // IAMStreamControl support
|
||||
#include <edevdefs.h> // External device control interface defines
|
||||
#include <audevcod.h> // audio filter device error event codes
|
||||
|
||||
|
||||
|
||||
#else
|
||||
#ifdef DEBUG
|
||||
#pragma message("STREAMS.H included TWICE")
|
||||
#endif
|
||||
#endif // __STREAMS__
|
||||
|
||||
Vendored
-402
@@ -1,402 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: StrmCtl.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
#include <strmctl.h>
|
||||
|
||||
CBaseStreamControl::CBaseStreamControl(__inout HRESULT *phr)
|
||||
: m_StreamState(STREAM_FLOWING)
|
||||
, m_StreamStateOnStop(STREAM_FLOWING) // means no pending stop
|
||||
, m_tStartTime(MAX_TIME)
|
||||
, m_tStopTime(MAX_TIME)
|
||||
, m_StreamEvent(FALSE, phr)
|
||||
, m_dwStartCookie(0)
|
||||
, m_dwStopCookie(0)
|
||||
, m_pRefClock(NULL)
|
||||
, m_FilterState(State_Stopped)
|
||||
, m_bIsFlushing(FALSE)
|
||||
, m_bStopSendExtra(FALSE)
|
||||
{}
|
||||
|
||||
CBaseStreamControl::~CBaseStreamControl()
|
||||
{
|
||||
// Make sure we release the clock.
|
||||
SetSyncSource(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP CBaseStreamControl::StopAt(const REFERENCE_TIME * ptStop, BOOL bSendExtra, DWORD dwCookie)
|
||||
{
|
||||
CAutoLock lck(&m_CritSec);
|
||||
m_bStopSendExtra = FALSE; // reset
|
||||
m_bStopExtraSent = FALSE;
|
||||
if (ptStop)
|
||||
{
|
||||
if (*ptStop == MAX_TIME)
|
||||
{
|
||||
DbgLog((LOG_TRACE,2,TEXT("StopAt: Cancel stop")));
|
||||
CancelStop();
|
||||
// If there's now a command to start in the future, we assume
|
||||
// they want to be stopped when the graph is first run
|
||||
if (m_FilterState == State_Stopped && m_tStartTime < MAX_TIME) {
|
||||
m_StreamState = STREAM_DISCARDING;
|
||||
DbgLog((LOG_TRACE,2,TEXT("graph will begin by DISCARDING")));
|
||||
}
|
||||
return NOERROR;
|
||||
}
|
||||
DbgLog((LOG_TRACE,2,TEXT("StopAt: %dms extra=%d"),
|
||||
(int)(*ptStop/10000), bSendExtra));
|
||||
// if the first command is to stop in the future, then we assume they
|
||||
// want to be started when the graph is first run
|
||||
if (m_FilterState == State_Stopped && m_tStartTime > *ptStop) {
|
||||
m_StreamState = STREAM_FLOWING;
|
||||
DbgLog((LOG_TRACE,2,TEXT("graph will begin by FLOWING")));
|
||||
}
|
||||
m_bStopSendExtra = bSendExtra;
|
||||
m_tStopTime = *ptStop;
|
||||
m_dwStopCookie = dwCookie;
|
||||
m_StreamStateOnStop = STREAM_DISCARDING;
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgLog((LOG_TRACE,2,TEXT("StopAt: now")));
|
||||
// sending an extra frame when told to stop now would mess people up
|
||||
m_bStopSendExtra = FALSE;
|
||||
m_tStopTime = MAX_TIME;
|
||||
m_dwStopCookie = 0;
|
||||
m_StreamState = STREAM_DISCARDING;
|
||||
m_StreamStateOnStop = STREAM_FLOWING; // no pending stop
|
||||
}
|
||||
// we might change our mind what to do with a sample we're blocking
|
||||
m_StreamEvent.Set();
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
STDMETHODIMP CBaseStreamControl::StartAt
|
||||
( const REFERENCE_TIME *ptStart, DWORD dwCookie )
|
||||
{
|
||||
CAutoLock lck(&m_CritSec);
|
||||
if (ptStart)
|
||||
{
|
||||
if (*ptStart == MAX_TIME)
|
||||
{
|
||||
DbgLog((LOG_TRACE,2,TEXT("StartAt: Cancel start")));
|
||||
CancelStart();
|
||||
// If there's now a command to stop in the future, we assume
|
||||
// they want to be started when the graph is first run
|
||||
if (m_FilterState == State_Stopped && m_tStopTime < MAX_TIME) {
|
||||
DbgLog((LOG_TRACE,2,TEXT("graph will begin by FLOWING")));
|
||||
m_StreamState = STREAM_FLOWING;
|
||||
}
|
||||
return NOERROR;
|
||||
}
|
||||
DbgLog((LOG_TRACE,2,TEXT("StartAt: %dms"), (int)(*ptStart/10000)));
|
||||
// if the first command is to start in the future, then we assume they
|
||||
// want to be stopped when the graph is first run
|
||||
if (m_FilterState == State_Stopped && m_tStopTime >= *ptStart) {
|
||||
DbgLog((LOG_TRACE,2,TEXT("graph will begin by DISCARDING")));
|
||||
m_StreamState = STREAM_DISCARDING;
|
||||
}
|
||||
m_tStartTime = *ptStart;
|
||||
m_dwStartCookie = dwCookie;
|
||||
// if (m_tStopTime == m_tStartTime) CancelStop();
|
||||
}
|
||||
else
|
||||
{
|
||||
DbgLog((LOG_TRACE,2,TEXT("StartAt: now")));
|
||||
m_tStartTime = MAX_TIME;
|
||||
m_dwStartCookie = 0;
|
||||
m_StreamState = STREAM_FLOWING;
|
||||
}
|
||||
// we might change our mind what to do with a sample we're blocking
|
||||
m_StreamEvent.Set();
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
// Retrieve information about current settings
|
||||
STDMETHODIMP CBaseStreamControl::GetInfo(__out AM_STREAM_INFO *pInfo)
|
||||
{
|
||||
if (pInfo == NULL)
|
||||
return E_POINTER;
|
||||
|
||||
pInfo->tStart = m_tStartTime;
|
||||
pInfo->tStop = m_tStopTime;
|
||||
pInfo->dwStartCookie = m_dwStartCookie;
|
||||
pInfo->dwStopCookie = m_dwStopCookie;
|
||||
pInfo->dwFlags = m_bStopSendExtra ? AM_STREAM_INFO_STOP_SEND_EXTRA : 0;
|
||||
pInfo->dwFlags |= m_tStartTime == MAX_TIME ? 0 : AM_STREAM_INFO_START_DEFINED;
|
||||
pInfo->dwFlags |= m_tStopTime == MAX_TIME ? 0 : AM_STREAM_INFO_STOP_DEFINED;
|
||||
switch (m_StreamState) {
|
||||
default:
|
||||
DbgBreak("Invalid stream state");
|
||||
case STREAM_FLOWING:
|
||||
break;
|
||||
case STREAM_DISCARDING:
|
||||
pInfo->dwFlags |= AM_STREAM_INFO_DISCARDING;
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
void CBaseStreamControl::ExecuteStop()
|
||||
{
|
||||
ASSERT(CritCheckIn(&m_CritSec));
|
||||
m_StreamState = m_StreamStateOnStop;
|
||||
if (m_dwStopCookie && m_pSink) {
|
||||
DbgLog((LOG_TRACE,2,TEXT("*sending EC_STREAM_CONTROL_STOPPED (%d)"),
|
||||
m_dwStopCookie));
|
||||
m_pSink->Notify(EC_STREAM_CONTROL_STOPPED, (LONG_PTR)this, m_dwStopCookie);
|
||||
}
|
||||
CancelStop(); // This will do the tidy up
|
||||
}
|
||||
|
||||
void CBaseStreamControl::ExecuteStart()
|
||||
{
|
||||
ASSERT(CritCheckIn(&m_CritSec));
|
||||
m_StreamState = STREAM_FLOWING;
|
||||
if (m_dwStartCookie) {
|
||||
DbgLog((LOG_TRACE,2,TEXT("*sending EC_STREAM_CONTROL_STARTED (%d)"),
|
||||
m_dwStartCookie));
|
||||
m_pSink->Notify(EC_STREAM_CONTROL_STARTED, (LONG_PTR)this, m_dwStartCookie);
|
||||
}
|
||||
CancelStart(); // This will do the tidy up
|
||||
}
|
||||
|
||||
void CBaseStreamControl::CancelStop()
|
||||
{
|
||||
ASSERT(CritCheckIn(&m_CritSec));
|
||||
m_tStopTime = MAX_TIME;
|
||||
m_dwStopCookie = 0;
|
||||
m_StreamStateOnStop = STREAM_FLOWING;
|
||||
}
|
||||
|
||||
void CBaseStreamControl::CancelStart()
|
||||
{
|
||||
ASSERT(CritCheckIn(&m_CritSec));
|
||||
m_tStartTime = MAX_TIME;
|
||||
m_dwStartCookie = 0;
|
||||
}
|
||||
|
||||
|
||||
// This guy will return one of the three StreamControlState's. Here's what the caller
|
||||
// should do for each one:
|
||||
//
|
||||
// STREAM_FLOWING: Proceed as usual (render or pass the sample on)
|
||||
// STREAM_DISCARDING: Calculate the time 'til *pSampleStart and wait that long
|
||||
// for the event handle (GetStreamEventHandle()). If the
|
||||
// wait expires, throw the sample away. If the event
|
||||
// fires, call me back, I've changed my mind.
|
||||
// I use pSampleStart (not Stop) so that live sources don't
|
||||
// block for the duration of their samples, since the clock
|
||||
// will always read approximately pSampleStart when called
|
||||
|
||||
|
||||
// All through this code, you'll notice the following rules:
|
||||
// - When start and stop time are the same, it's as if start was first
|
||||
// - An event is considered inside the sample when it's >= sample start time
|
||||
// but < sample stop time
|
||||
// - if any part of the sample is supposed to be sent, we'll send the whole
|
||||
// thing since we don't break it into smaller pieces
|
||||
// - If we skip over a start or stop without doing it, we still signal the event
|
||||
// and reset ourselves in case somebody's waiting for the event, and to make
|
||||
// sure we notice that the event is past and should be forgotten
|
||||
// Here are the 19 cases that have to be handled (x=start o=stop <-->=sample):
|
||||
//
|
||||
// 1. xo<--> start then stop
|
||||
// 2. ox<--> stop then start
|
||||
// 3. x<o-> start
|
||||
// 4. o<x-> stop then start
|
||||
// 5. x<-->o start
|
||||
// 6. o<-->x stop
|
||||
// 7. <x->o start
|
||||
// 8. <o->x no change
|
||||
// 9. <xo> start
|
||||
// 10. <ox> stop then start
|
||||
// 11. <-->xo no change
|
||||
// 12. <-->ox no change
|
||||
// 13. x<--> start
|
||||
// 14. <x-> start
|
||||
// 15. <-->x no change
|
||||
// 16. o<--> stop
|
||||
// 17. <o-> no change
|
||||
// 18. <-->o no change
|
||||
// 19. <--> no change
|
||||
|
||||
|
||||
enum CBaseStreamControl::StreamControlState CBaseStreamControl::CheckSampleTimes
|
||||
( __in const REFERENCE_TIME * pSampleStart, __in const REFERENCE_TIME * pSampleStop )
|
||||
{
|
||||
CAutoLock lck(&m_CritSec);
|
||||
|
||||
ASSERT(!m_bIsFlushing);
|
||||
ASSERT(pSampleStart && pSampleStop);
|
||||
|
||||
// Don't ask me how I came up with the code below to handle all 19 cases
|
||||
// - DannyMi
|
||||
|
||||
if (m_tStopTime >= *pSampleStart)
|
||||
{
|
||||
if (m_tStartTime >= *pSampleStop)
|
||||
return m_StreamState; // cases 8 11 12 15 17 18 19
|
||||
if (m_tStopTime < m_tStartTime)
|
||||
ExecuteStop(); // case 10
|
||||
ExecuteStart(); // cases 3 5 7 9 13 14
|
||||
return m_StreamState;
|
||||
}
|
||||
|
||||
if (m_tStartTime >= *pSampleStop)
|
||||
{
|
||||
ExecuteStop(); // cases 6 16
|
||||
return m_StreamState;
|
||||
}
|
||||
|
||||
if (m_tStartTime <= m_tStopTime)
|
||||
{
|
||||
ExecuteStart();
|
||||
ExecuteStop();
|
||||
return m_StreamState; // case 1
|
||||
}
|
||||
else
|
||||
{
|
||||
ExecuteStop();
|
||||
ExecuteStart();
|
||||
return m_StreamState; // cases 2 4
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum CBaseStreamControl::StreamControlState CBaseStreamControl::CheckStreamState( IMediaSample * pSample )
|
||||
{
|
||||
|
||||
REFERENCE_TIME rtBufferStart, rtBufferStop;
|
||||
const BOOL bNoBufferTimes =
|
||||
pSample == NULL ||
|
||||
FAILED(pSample->GetTime(&rtBufferStart, &rtBufferStop));
|
||||
|
||||
StreamControlState state;
|
||||
LONG lWait;
|
||||
|
||||
do
|
||||
{
|
||||
// something has to break out of the blocking
|
||||
if (m_bIsFlushing || m_FilterState == State_Stopped)
|
||||
return STREAM_DISCARDING;
|
||||
|
||||
if (bNoBufferTimes) {
|
||||
// Can't do anything until we get a time stamp
|
||||
state = m_StreamState;
|
||||
break;
|
||||
} else {
|
||||
state = CheckSampleTimes( &rtBufferStart, &rtBufferStop );
|
||||
if (state == STREAM_FLOWING)
|
||||
break;
|
||||
|
||||
// we aren't supposed to send this, but we've been
|
||||
// told to send one more than we were supposed to
|
||||
// (and the stop isn't still pending and we're streaming)
|
||||
if (m_bStopSendExtra && !m_bStopExtraSent &&
|
||||
m_tStopTime == MAX_TIME &&
|
||||
m_FilterState != State_Stopped) {
|
||||
m_bStopExtraSent = TRUE;
|
||||
DbgLog((LOG_TRACE,2,TEXT("%d sending an EXTRA frame"),
|
||||
m_dwStopCookie));
|
||||
state = STREAM_FLOWING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We're in discarding mode
|
||||
|
||||
// If we've no clock, discard as fast as we can
|
||||
if (!m_pRefClock) {
|
||||
break;
|
||||
|
||||
// If we're paused, we can't discard in a timely manner because
|
||||
// there's no such thing as stream times. We must block until
|
||||
// we run or stop, or we'll end up throwing the whole stream away
|
||||
// as quickly as possible
|
||||
} else if (m_FilterState == State_Paused) {
|
||||
lWait = INFINITE;
|
||||
|
||||
} else {
|
||||
// wait until it's time for the sample until we say "discard"
|
||||
// ("discard in a timely fashion")
|
||||
REFERENCE_TIME rtNow;
|
||||
EXECUTE_ASSERT(SUCCEEDED(m_pRefClock->GetTime(&rtNow)));
|
||||
rtNow -= m_tRunStart; // Into relative ref-time
|
||||
lWait = LONG((rtBufferStart - rtNow)/10000); // 100ns -> ms
|
||||
if (lWait < 10) break; // Not worth waiting - discard early
|
||||
}
|
||||
|
||||
} while(WaitForSingleObject(GetStreamEventHandle(), lWait) != WAIT_TIMEOUT);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
void CBaseStreamControl::NotifyFilterState( FILTER_STATE new_state, REFERENCE_TIME tStart )
|
||||
{
|
||||
CAutoLock lck(&m_CritSec);
|
||||
|
||||
// or we will get confused
|
||||
if (m_FilterState == new_state)
|
||||
return;
|
||||
|
||||
switch (new_state)
|
||||
{
|
||||
case State_Stopped:
|
||||
|
||||
DbgLog((LOG_TRACE,2,TEXT("Filter is STOPPED")));
|
||||
|
||||
// execute any pending starts and stops in the right order,
|
||||
// to make sure all notifications get sent, and we end up
|
||||
// in the right state to begin next time (??? why not?)
|
||||
|
||||
if (m_tStartTime != MAX_TIME && m_tStopTime == MAX_TIME) {
|
||||
ExecuteStart();
|
||||
} else if (m_tStopTime != MAX_TIME && m_tStartTime == MAX_TIME) {
|
||||
ExecuteStop();
|
||||
} else if (m_tStopTime != MAX_TIME && m_tStartTime != MAX_TIME) {
|
||||
if (m_tStartTime <= m_tStopTime) {
|
||||
ExecuteStart();
|
||||
ExecuteStop();
|
||||
} else {
|
||||
ExecuteStop();
|
||||
ExecuteStart();
|
||||
}
|
||||
}
|
||||
// always start off flowing when the graph starts streaming
|
||||
// unless told otherwise
|
||||
m_StreamState = STREAM_FLOWING;
|
||||
m_FilterState = new_state;
|
||||
break;
|
||||
|
||||
case State_Running:
|
||||
|
||||
DbgLog((LOG_TRACE,2,TEXT("Filter is RUNNING")));
|
||||
|
||||
m_tRunStart = tStart;
|
||||
// fall-through
|
||||
|
||||
default: // case State_Paused:
|
||||
m_FilterState = new_state;
|
||||
}
|
||||
// unblock!
|
||||
m_StreamEvent.Set();
|
||||
}
|
||||
|
||||
|
||||
void CBaseStreamControl::Flushing(BOOL bInProgress)
|
||||
{
|
||||
CAutoLock lck(&m_CritSec);
|
||||
m_bIsFlushing = bInProgress;
|
||||
m_StreamEvent.Set();
|
||||
}
|
||||
Vendored
-157
@@ -1,157 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: StrmCtl.h
|
||||
//
|
||||
// Desc: DirectShow base classes.
|
||||
//
|
||||
// Copyright (c) 1996-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __strmctl_h__
|
||||
#define __strmctl_h__
|
||||
|
||||
class CBaseStreamControl : public IAMStreamControl
|
||||
{
|
||||
public:
|
||||
// Used by the implementation
|
||||
enum StreamControlState
|
||||
{ STREAM_FLOWING = 0x1000,
|
||||
STREAM_DISCARDING
|
||||
};
|
||||
|
||||
private:
|
||||
enum StreamControlState m_StreamState; // Current stream state
|
||||
enum StreamControlState m_StreamStateOnStop; // State after next stop
|
||||
// (i.e.Blocking or Discarding)
|
||||
|
||||
REFERENCE_TIME m_tStartTime; // MAX_TIME implies none
|
||||
REFERENCE_TIME m_tStopTime; // MAX_TIME implies none
|
||||
DWORD m_dwStartCookie; // Cookie for notification to app
|
||||
DWORD m_dwStopCookie; // Cookie for notification to app
|
||||
volatile BOOL m_bIsFlushing; // No optimization pls!
|
||||
volatile BOOL m_bStopSendExtra; // bSendExtra was set
|
||||
volatile BOOL m_bStopExtraSent; // the extra one was sent
|
||||
|
||||
CCritSec m_CritSec; // CritSec to guard above attributes
|
||||
|
||||
// Event to fire when we can come
|
||||
// out of blocking, or to come out of waiting
|
||||
// to discard if we change our minds.
|
||||
//
|
||||
CAMEvent m_StreamEvent;
|
||||
|
||||
// All of these methods execute immediately. Helpers for others.
|
||||
//
|
||||
void ExecuteStop();
|
||||
void ExecuteStart();
|
||||
void CancelStop();
|
||||
void CancelStart();
|
||||
|
||||
// Some things we need to be told by our owning filter
|
||||
// Your pin must also expose IAMStreamControl when QI'd for it!
|
||||
//
|
||||
IReferenceClock * m_pRefClock; // Need it to set advises
|
||||
// Filter must tell us via
|
||||
// SetSyncSource
|
||||
IMediaEventSink * m_pSink; // Event sink
|
||||
// Filter must tell us after it
|
||||
// creates it in JoinFilterGraph()
|
||||
FILTER_STATE m_FilterState; // Just need it!
|
||||
// Filter must tell us via
|
||||
// NotifyFilterState
|
||||
REFERENCE_TIME m_tRunStart; // Per the Run call to the filter
|
||||
|
||||
// This guy will return one of the three StreamControlState's. Here's what
|
||||
// the caller should do for each one:
|
||||
//
|
||||
// STREAM_FLOWING: Proceed as usual (render or pass the sample on)
|
||||
// STREAM_DISCARDING: Calculate the time 'til *pSampleStop and wait
|
||||
// that long for the event handle
|
||||
// (GetStreamEventHandle()). If the wait
|
||||
// expires, throw the sample away. If the event
|
||||
// fires, call me back - I've changed my mind.
|
||||
//
|
||||
enum StreamControlState CheckSampleTimes( __in const REFERENCE_TIME * pSampleStart,
|
||||
__in const REFERENCE_TIME * pSampleStop );
|
||||
|
||||
public:
|
||||
// You don't have to tell us much when we're created, but there are other
|
||||
// obligations that must be met. See SetSyncSource & NotifyFilterState
|
||||
// below.
|
||||
//
|
||||
CBaseStreamControl(__inout_opt HRESULT *phr = NULL);
|
||||
~CBaseStreamControl();
|
||||
|
||||
// If you want this class to work properly, there are thing you need to
|
||||
// (keep) telling it. Filters with pins that use this class
|
||||
// should ensure that they pass through to this method any calls they
|
||||
// receive on their SetSyncSource.
|
||||
|
||||
// We need a clock to see what time it is. This is for the
|
||||
// "discard in a timely fashion" logic. If we discard everything as
|
||||
// quick as possible, a whole 60 minute file could get discarded in the
|
||||
// first 10 seconds, and if somebody wants to turn streaming on at 30
|
||||
// minutes into the file, and they make the call more than a few seconds
|
||||
// after the graph is run, it may be too late!
|
||||
// So we hold every sample until it's time has gone, then we discard it.
|
||||
// The filter should call this when it gets a SetSyncSource
|
||||
//
|
||||
void SetSyncSource( IReferenceClock * pRefClock )
|
||||
{
|
||||
CAutoLock lck(&m_CritSec);
|
||||
if (m_pRefClock) m_pRefClock->Release();
|
||||
m_pRefClock = pRefClock;
|
||||
if (m_pRefClock) m_pRefClock->AddRef();
|
||||
}
|
||||
|
||||
// Set event sink for notifications
|
||||
// The filter should call this in its JoinFilterGraph after it creates the
|
||||
// IMediaEventSink
|
||||
//
|
||||
void SetFilterGraph( IMediaEventSink *pSink ) {
|
||||
m_pSink = pSink;
|
||||
}
|
||||
|
||||
// Since we schedule in stream time, we need the tStart and must track the
|
||||
// state of our owning filter.
|
||||
// The app should call this ever state change
|
||||
//
|
||||
void NotifyFilterState( FILTER_STATE new_state, REFERENCE_TIME tStart = 0 );
|
||||
|
||||
// Filter should call Flushing(TRUE) in BeginFlush,
|
||||
// and Flushing(FALSE) in EndFlush.
|
||||
//
|
||||
void Flushing( BOOL bInProgress );
|
||||
|
||||
|
||||
// The two main methods of IAMStreamControl
|
||||
|
||||
// Class adds default values suitable for immediate
|
||||
// muting and unmuting of the stream.
|
||||
|
||||
STDMETHODIMP StopAt( const REFERENCE_TIME * ptStop = NULL,
|
||||
BOOL bSendExtra = FALSE,
|
||||
DWORD dwCookie = 0 );
|
||||
STDMETHODIMP StartAt( const REFERENCE_TIME * ptStart = NULL,
|
||||
DWORD dwCookie = 0 );
|
||||
STDMETHODIMP GetInfo( __out AM_STREAM_INFO *pInfo);
|
||||
|
||||
// Helper function for pin's receive method. Call this with
|
||||
// the sample and we'll tell you what to do with it. We'll do a
|
||||
// WaitForSingleObject within this call if one is required. This is
|
||||
// a "What should I do with this sample?" kind of call. We'll tell the
|
||||
// caller to either flow it or discard it.
|
||||
// If pSample is NULL we evaluate based on the current state
|
||||
// settings
|
||||
enum StreamControlState CheckStreamState( IMediaSample * pSample );
|
||||
|
||||
private:
|
||||
// These don't require locking, but we are relying on the fact that
|
||||
// m_StreamState can be retrieved with integrity, and is a snap shot that
|
||||
// may have just been, or may be just about to be, changed.
|
||||
HANDLE GetStreamEventHandle() const { return m_StreamEvent; }
|
||||
enum StreamControlState GetStreamState() const { return m_StreamState; }
|
||||
BOOL IsStreaming() const { return m_StreamState == STREAM_FLOWING; }
|
||||
};
|
||||
|
||||
#endif
|
||||
Vendored
-74
@@ -1,74 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: SysClock.cpp
|
||||
//
|
||||
// Desc: DirectShow base classes - implements a system clock based on
|
||||
// IReferenceClock.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#include <streams.h>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
#ifdef FILTER_DLL
|
||||
|
||||
/* List of class IDs and creator functions for the class factory. This
|
||||
provides the link between the OLE entry point in the DLL and an object
|
||||
being created. The class factory will call the static CreateInstance
|
||||
function when it is asked to create a CLSID_SystemClock object */
|
||||
|
||||
CFactoryTemplate g_Templates[1] = {
|
||||
{&CLSID_SystemClock, CSystemClock::CreateInstance}
|
||||
};
|
||||
|
||||
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
|
||||
#endif
|
||||
|
||||
/* This goes in the factory template table to create new instances */
|
||||
CUnknown * WINAPI CSystemClock::CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr)
|
||||
{
|
||||
return new CSystemClock(NAME("System reference clock"),pUnk, phr);
|
||||
}
|
||||
|
||||
|
||||
CSystemClock::CSystemClock(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr) :
|
||||
CBaseReferenceClock(pName, pUnk, phr)
|
||||
{
|
||||
}
|
||||
|
||||
STDMETHODIMP CSystemClock::NonDelegatingQueryInterface(
|
||||
REFIID riid,
|
||||
__deref_out void ** ppv)
|
||||
{
|
||||
if (riid == IID_IPersist)
|
||||
{
|
||||
return GetInterface(static_cast<IPersist *>(this), ppv);
|
||||
}
|
||||
else if (riid == IID_IAMClockAdjust)
|
||||
{
|
||||
return GetInterface(static_cast<IAMClockAdjust *>(this), ppv);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CBaseReferenceClock::NonDelegatingQueryInterface(riid, ppv);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the clock's clsid */
|
||||
STDMETHODIMP
|
||||
CSystemClock::GetClassID(__out CLSID *pClsID)
|
||||
{
|
||||
CheckPointer(pClsID,E_POINTER);
|
||||
ValidateReadWritePtr(pClsID,sizeof(CLSID));
|
||||
*pClsID = CLSID_SystemClock;
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
|
||||
STDMETHODIMP
|
||||
CSystemClock::SetClockDelta(REFERENCE_TIME rtDelta)
|
||||
{
|
||||
return SetTimeDelta(rtDelta);
|
||||
}
|
||||
Vendored
-39
@@ -1,39 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// File: SysClock.h
|
||||
//
|
||||
// Desc: DirectShow base classes - defines a system clock implementation of
|
||||
// IReferenceClock.
|
||||
//
|
||||
// Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
#ifndef __SYSTEMCLOCK__
|
||||
#define __SYSTEMCLOCK__
|
||||
|
||||
//
|
||||
// Base clock. Uses timeGetTime ONLY
|
||||
// Uses most of the code in the base reference clock.
|
||||
// Provides GetTime
|
||||
//
|
||||
|
||||
class CSystemClock : public CBaseReferenceClock, public IAMClockAdjust, public IPersist
|
||||
{
|
||||
public:
|
||||
// We must be able to create an instance of ourselves
|
||||
static CUnknown * WINAPI CreateInstance(__inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr);
|
||||
CSystemClock(__in_opt LPCTSTR pName, __inout_opt LPUNKNOWN pUnk, __inout HRESULT *phr);
|
||||
|
||||
DECLARE_IUNKNOWN
|
||||
|
||||
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, __deref_out void ** ppv);
|
||||
|
||||
// Yield up our class id so that we can be persisted
|
||||
// Implement required Ipersist method
|
||||
STDMETHODIMP GetClassID(__out CLSID *pClsID);
|
||||
|
||||
// IAMClockAdjust methods
|
||||
STDMETHODIMP SetClockDelta(REFERENCE_TIME rtDelta);
|
||||
}; //CSystemClock
|
||||
|
||||
#endif /* __SYSTEMCLOCK__ */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user