youtube_stream.inc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. #if defined _youtube_included
  2. #endinput
  3. #endif
  4. #define _youtube_included
  5. /**
  6. * Play an youtube 'audio stream'
  7. *
  8. * @note usually the API fails in newly videos...
  9. *
  10. * @version 1.0.2
  11. * @author Dayvison
  12. * @date 05-10-2016
  13. */
  14. //#define YOUTUBE_USE_TEXTDRAW
  15. //#define USE_REGEX
  16. #include <a_http>
  17. #if defined USE_REGEX
  18. #tryinclude <regex> // [Plugin] Regular expression by Fro1sha: http://forum.sa-mp.com/showthread.php?t=247893
  19. #if !defined _regex_included && !define regex_match_exid
  20. #undef USE_REGEX
  21. #error "Can't find regex plugin"
  22. #endif
  23. #endif
  24. #if defined YOUTUBE_USE_TEXTDRAW
  25. #define USE_TIMER
  26. #endif
  27. #if !defined USE_TIMER
  28. #if defined OnFinishYoutubeUrl
  29. #define USE_TIMER
  30. #endif
  31. #endif
  32. static
  33. #if defined YOUTUBE_USE_TEXTDRAW
  34. PlayerText:youtube_textdraw[MAX_PLAYERS],
  35. #endif
  36. #if defined USE_TIMER
  37. youtube_timer[MAX_PLAYERS],
  38. #endif
  39. youtube_title[MAX_PLAYERS][128 char],
  40. youtube_len[MAX_PLAYERS],
  41. Float:youtube_posX[MAX_PLAYERS],
  42. Float:youtube_posY[MAX_PLAYERS],
  43. Float:youtube_posZ[MAX_PLAYERS],
  44. Float:youtube_distance[MAX_PLAYERS],
  45. youtube_usepos[MAX_PLAYERS]
  46. ;
  47. #if defined OnPlayYoutubeUrl
  48. /**
  49. * Called when youtube url an played.
  50. *
  51. * @param playerid The playerid
  52. * @param title The title of url(if invalid \0)
  53. * @param len The length of url(if invalid 0)
  54. * @param response The response of url
  55. * Response codes:
  56. * 1 Sucess
  57. * -1 Invalid url
  58. * -2 Invalid page
  59. */
  60. forward OnPlayYoutubeUrl(playerid, title[], len, response);
  61. #endif
  62. #if defined OnPlayYoutubeUrl
  63. /**
  64. * Called when youtube url as finished.
  65. *
  66. * @param playerid The playerid
  67. * @param title The title of url
  68. * @param len The length of url
  69. */
  70. forward OnFinishYoutubeUrl(playerid, title[], len);
  71. #endif
  72. #if defined USE_REGEX
  73. /**
  74. * Determines if valid youtube url.
  75. *
  76. * @param url The url
  77. *
  78. * @author Dayvison
  79. * @date 04-10-2016
  80. * @return True if is a valid url, false not.
  81. */
  82. stock IsValidYoutubeUrl(const url[])
  83. {
  84. static RegEx:rHex;
  85. if(!rHex)
  86. {
  87. rHex = regex_build(\"((http(s)?:\/\/)?)(www\.)?((youtube\.com\/)|(youtu.be\/))[\S]+");
  88. }
  89. return regex_match_exid(url, rHex);
  90. }
  91. #endif
  92. /**
  93. * Converts an youtu.be url to youtube.com
  94. *
  95. * @param Url The url to convert
  96. * @param size The size
  97. *
  98. * @author Dayvison
  99. * @date 04-10-2016
  100. * @return True on convert have sucess, false not.
  101. */
  102. stock ConvertYoutubeUrl(Url[], size = sizeof(Url))
  103. {
  104. new find;
  105. if((find = strfind(Url, "youtu.be/")) == -1)
  106. return false;
  107. strdel(Url, 0, find + 4);
  108. format(Url, size, "https://www.youtube.com/watch?v=", Url);
  109. return true;
  110. }
  111. /**
  112. * Play an youtube 'audio stream' for a player.
  113. *
  114. * @param playerid The ID of the player to play the audio for.
  115. * @param url The url to play.
  116. * @param posX The X position at which to play the audio. Default 0.0. Has no effect unless usepos is set to 1.
  117. * @param posY The Y position at which to play the audio. Default 0.0. Has no effect unless usepos is set to 1.
  118. * @param posZ The Z position at which to play the audio. Default 0.0. Has no effect unless usepos is set to 1.
  119. * @param distance The distance over which the audio will be heard. Has no effect unless usepos is set to 1.
  120. * @param usepos Use the positions and distance specified. Default disabled (0).
  121. *
  122. * @author Dayvison
  123. * @date 04-10-2016
  124. * @return True on sucess, or false on failure. if USE_REGEX active is more efficient
  125. */
  126. stock PlayYoutubeStreamForPlayer(playerid, url[], Float:posX = 0.0, Float:posY = 0.0, Float:posZ = 0.0, Float:distance = 50.0, usepos = 0)
  127. {
  128. if(!IsPlayerConnected(playerid))
  129. return false;
  130. #if defined USE_REGEX
  131. if(!IsValidYoutubeUrl(url))
  132. {
  133. if(!ConvertYoutubeUrl(url, 256))
  134. return false;
  135. }
  136. #else
  137. if(strfind(url, "youtu.be/") != -1)
  138. if(!ConvertYoutubeUrl(url, 256))
  139. return false;
  140. #endif
  141. static string[256];
  142. format(string, sizeof(string), "youtubeinmp3.com/fetch/?format=text&video=%s", url);
  143. HTTP(playerid, HTTP_GET, string, "", "YoutubeResponse");
  144. youtube_posX[playerid] = posX;
  145. youtube_posY[playerid] = posY;
  146. youtube_posZ[playerid] = posZ;
  147. youtube_distance[playerid] = distance;
  148. youtube_usepos[playerid] = usepos;
  149. youtube_title[playerid]{0} = '\0';
  150. youtube_len[playerid] = 0;
  151. return true;
  152. }
  153. /**
  154. * Stop an youtube 'audio stream' for a player.
  155. *
  156. * @param playerid The ID of the player to play the audio for.
  157. *
  158. * @author Dayvison
  159. * @date 05-10-2016
  160. * @return True on sucess, or false on failure.
  161. */
  162. stock StopYoutubeStreamForPlayer(playerid)
  163. return StopAudioStreamForPlayer(playerid);
  164. /**
  165. * Gets the youtube stream title.
  166. *
  167. * @param playerid The playerid
  168. * @param dest The destination
  169. * @param size The size
  170. *
  171. * @author Dayvison
  172. * @date 05-10-2016
  173. * @return 1 on sucess, 0 on fails
  174. */
  175. stock GetYoutubeStreamTitle(playerid, dest[], size = sizeof(dest))
  176. {
  177. if(!IsPlayerConnected(playerid))
  178. return 0;
  179. strunpack(dest, youtube_title[playerid], size);
  180. return 1;
  181. }
  182. /**
  183. * Gets the youtube stream length.
  184. *
  185. * @param playerid The playerid
  186. *
  187. * @author Dayvison
  188. * @date 05-10-2016
  189. * @return The length of stream
  190. */
  191. stock GetYoutubeStreamLen(playerid)
  192. {
  193. if(!IsPlayerConnected(playerid))
  194. return 0;
  195. return youtube_len[playerid];
  196. }
  197. /**
  198. * Gets the youtube stream position.
  199. *
  200. * @param playerid The playerid
  201. * @param x The x position passed by reference
  202. * @param y The y position passed by reference
  203. * @param z The z position passed by reference
  204. *
  205. * @author Dayvison
  206. * @date 07-10-2016
  207. * @return 1 on sucess, 0 failure
  208. */
  209. stock GetYoutubeStreamPos(playerid, &x, &y, &z)
  210. {
  211. if(!IsPlayerConnected(playerid))
  212. return 0;
  213. x = youtube_posX[playerid];
  214. y = youtube_posY[playerid];
  215. z = youtube_posZ[playerid];
  216. return 1;
  217. }
  218. /**
  219. * Gets the youtube stream position x.
  220. *
  221. * @param playerid The playerid
  222. *
  223. * @author Dayvison
  224. * @date 05-10-2016
  225. * @return The position x
  226. */
  227. stock GetYoutubeStreamPosX(playerid)
  228. {
  229. if(!IsPlayerConnected(playerid))
  230. return 0.0;
  231. return youtube_posX[playerid];
  232. }
  233. /**
  234. * Gets the youtube stream position y.
  235. *
  236. * @param playerid The playerid
  237. *
  238. * @author Dayvison
  239. * @date 05-10-2016
  240. * @return The position y
  241. */
  242. stock GetYoutubeStreamPosY(playerid)
  243. {
  244. if(!IsPlayerConnected(playerid))
  245. return 0.0;
  246. return youtube_posY[playerid];
  247. }
  248. /**
  249. * Gets the youtube stream position z.
  250. *
  251. * @param playerid The playerid
  252. *
  253. * @author Dayvison
  254. * @date 05-10-2016
  255. * @return The position z
  256. */
  257. stock GetYoutubeStreamPosZ(playerid)
  258. {
  259. if(!IsPlayerConnected(playerid))
  260. return 0.0;
  261. return youtube_posZ[playerid];
  262. }
  263. /**
  264. * Gets the youtube stream distance.
  265. *
  266. * @param playerid The playerid
  267. *
  268. * @author Dayvison
  269. * @date 05-10-2016
  270. * @return The stream distance
  271. */
  272. stock GetYoutubeStreamDistance(playerid)
  273. {
  274. if(!IsPlayerConnected(playerid))
  275. return 0.0;
  276. return youtube_distance[playerid];
  277. }
  278. /**
  279. * Determines if youtube stream use position.
  280. *
  281. * @param playerid The playerid
  282. *
  283. * @author Dayvison
  284. * @date 05-10-2016
  285. * @return The usepos
  286. */
  287. stock bool:IsYoutubeStreamUsePos(playerid)
  288. {
  289. if(!IsPlayerConnected(playerid))
  290. return false;
  291. return youtube_usepos[playerid];
  292. }
  293. /**
  294. * Internal
  295. */
  296. #if defined USE_TIMER
  297. forward intern_OnStopUrl(playerid);
  298. public intern_OnStopUrl(playerid)
  299. {
  300. #if defined OnFinishYoutubeUrl
  301. static unpack[128];
  302. strunpack(unpack, youtube_title[playerid]);
  303. OnFinishYoutubeUrl(playerid, unpack, youtube_len[playerid]);
  304. #endif
  305. #if defined YOUTUBE_USE_TEXTDRAW
  306. PlayerTextDrawHide(playerid, youtube_textdraw[playerid]);
  307. #endif
  308. youtube_title[playerid]{0} = '\0';
  309. youtube_len[playerid] = 0;
  310. youtube_timer[playerid] = -1;
  311. }
  312. public OnPlayerDisconnect(playerid, reason)
  313. {
  314. if(youtube_timer[playerid] != -1)
  315. KillTimer(youtube_timer[playerid]);
  316. youtube_timer[playerid] = -1;
  317. #if defined stream_OnPlayerDisconnect
  318. return stream_OnPlayerDisconnect(playerid, reason);
  319. #else
  320. return 1;
  321. #endif
  322. }
  323. #if defined _ALS_OnPlayerDisconnect
  324. #undef OnPlayerDisconnect
  325. #else
  326. #define _ALS_OnPlayerDisconnect
  327. #endif
  328. #define OnPlayerDisconnect stream_OnPlayerDisconnect
  329. #if defined stream_OnPlayerDisconnect
  330. forward stream_OnPlayerDisconnect(playerid, reason);
  331. #endif
  332. #endif
  333. #if defined YOUTUBE_USE_TEXTDRAW
  334. public OnPlayerConnect(playerid)
  335. {
  336. youtube_textdraw[playerid] = CreatePlayerTextDraw(playerid, 6.000000, 435.000000, "--");
  337. PlayerTextDrawLetterSize(playerid, youtube_textdraw[playerid], 0.224304, 1.308333);
  338. PlayerTextDrawAlignment(playerid, youtube_textdraw[playerid], 1);
  339. PlayerTextDrawColor(playerid, youtube_textdraw[playerid], 0xC1C1C1DD);
  340. PlayerTextDrawSetShadow(playerid, youtube_textdraw[playerid], 0);
  341. PlayerTextDrawSetOutline(playerid, youtube_textdraw[playerid], 0);
  342. PlayerTextDrawBackgroundColor(playerid, youtube_textdraw[playerid], 0xC1C1C1DD);
  343. PlayerTextDrawFont(playerid, youtube_textdraw[playerid], 1);
  344. PlayerTextDrawSetProportional(playerid, youtube_textdraw[playerid], 1);
  345. PlayerTextDrawSetShadow(playerid, youtube_textdraw[playerid], 0);
  346. #if defined stream_OnPlayerConnect
  347. return stream_OnPlayerConnect(playerid);
  348. #else
  349. return 1;
  350. #endif
  351. }
  352. #if defined _ALS_OnPlayerConnect
  353. #undef OnPlayerConnect
  354. #else
  355. #define _ALS_OnPlayerConnect
  356. #endif
  357. #define OnPlayerConnect stream_OnPlayerConnect
  358. #if defined stream_OnPlayerConnect
  359. forward stream_OnPlayerConnect(playerid);
  360. #endif
  361. #endif
  362. forward YoutubeResponse(playerid, response, data[]);
  363. public YoutubeResponse(playerid, response, data[])
  364. {
  365. if(response == 200)
  366. {
  367. if(strfind(data, "No video was found") != -1 || strfind(data, "<meta http-equiv=") != -1)
  368. {
  369. #if defined OnPlayYoutubeUrl
  370. OnPlayYoutubeUrl(playerid, "\0", 0, -1);
  371. #endif
  372. return;
  373. }
  374. new
  375. title[60],
  376. len[5],
  377. Find
  378. ;
  379. Find = strfind(data, "<br/>");
  380. strmid(title, data, 7, Find-1);
  381. strdel(data, 0, Find+5);
  382. Find = strfind(data, "<br/>");
  383. strmid(len, data, 8, Find-1);
  384. strdel(data, 0, Find+11);
  385. strpack(youtube_title[playerid], title);
  386. youtube_len[playerid] = strval(len);
  387. PlayAudioStreamForPlayer(playerid, data, youtube_posX[playerid], youtube_posY[playerid], youtube_posZ[playerid], youtube_distance[playerid], youtube_usepos[playerid]);
  388. #if defined YOUTUBE_USE_TEXTDRAW
  389. PlayerTextDrawSetString(playerid, youtube_textdraw[playerid], title);
  390. PlayerTextDrawShow(playerid, youtube_textdraw[playerid]);
  391. print("Show");
  392. #endif
  393. #if defined USE_TIMER
  394. youtube_timer[playerid] = SetTimerEx("intern_OnStopUrl", strval(len)*1000, false, "d", playerid);
  395. #endif
  396. #if defined OnPlayYoutubeUrl
  397. OnPlayYoutubeUrl(playerid, title, strval(len), 1);
  398. #endif
  399. }
  400. else
  401. {
  402. #if defined OnPlayYoutubeUrl
  403. OnPlayYoutubeUrl(playerid, "\0", 0, -2);
  404. #endif
  405. }
  406. }