Ticket #3580: patchfile

File patchfile, 22.2 KB (added by robsbox@…, 19 years ago)
Line 
1Index: libs/libmythupnp/httprequest.cpp
2===================================================================
3--- libs/libmythupnp/httprequest.cpp (revision 13462)
4+++ libs/libmythupnp/httprequest.cpp (working copy)
5@@ -4,7 +4,7 @@
6 // Purpose - Http Request/Response
7 //
8 // Created By : David Blain Created On : Oct. 21, 2005
9-// Modified By : Modified On:
10+// Modified By : Rob Gingher Modified On: Jun. 4, 2007
11 //
12 //////////////////////////////////////////////////////////////////////////////
13
14@@ -41,26 +41,27 @@
15
16 static MIMETypes g_MIMETypes[] =
17 {
18+ { "swf" , "application/futuresplash" },
19+ { "pdf" , "application/pdf" },
20+ { "xls" , "application/vnd.ms-excel" },
21+ { "doc" , "application/vnd.ms-word" },
22+ { "rm" , "application/vnd.rn-realmedia" },
23+ { "zip" , "application/x-tar" },
24+ { "gz" , "application/x-tar" },
25+ { "mid" , "audio/midi" },
26+ { "mp3" , "audio/mpeg" },
27+ { "m3u" , "audio/x-mpegurl" },
28+ { "wav" , "audio/wav" },
29 { "gif" , "image/gif" },
30 { "jpg" , "image/jpeg" },
31 { "png" , "image/png" },
32+ { "css" , "text/css" },
33 { "htm" , "text/html" },
34 { "html", "text/html" },
35 { "js" , "text/html" },
36 { "txt" , "text/plain" },
37 { "xml" , "text/xml" },
38- { "pdf" , "application/pdf" },
39 { "avi" , "video/avi" },
40- { "css" , "text/css" },
41- { "swf" , "application/futuresplash" },
42- { "xls" , "application/vnd.ms-excel" },
43- { "doc" , "application/vnd.ms-word" },
44- { "mid" , "audio/midi" },
45- { "mp3" , "audio/mpeg" },
46- { "rm" , "application/vnd.rn-realmedia" },
47- { "wav" , "audio/wav" },
48- { "zip" , "application/x-tar" },
49- { "gz" , "application/x-tar" },
50 { "mpg" , "video/mpeg" },
51 { "mpeg", "video/mpeg" },
52 { "vob", "video/mpeg" },
53@@ -213,9 +214,9 @@
54 break;
55 }
56
57- // VERBOSE(VB_UPNP,QString("HTTPRequest::SendResponse(xml/html) :%1 -> %2:")
58- // .arg(GetResponseStatus())
59- // .arg(GetPeerAddress()));
60+// VERBOSE(VB_UPNP,QString("HTTPRequest::SendResponse(xml/html) :%1 -> %2:")
61+// .arg(GetResponseStatus())
62+// .arg(GetPeerAddress()));
63
64 // ----------------------------------------------------------------------
65 // Make it so the header is sent with the data
66@@ -271,16 +272,6 @@
67 m_eResponseType = ResponseTypeOther;
68 m_sResponseTypeText = "text/plain";
69
70- /*
71- Dump request header
72- for ( QStringMap::iterator it = m_mapHeaders.begin();
73- it != m_mapHeaders.end();
74- ++it )
75- {
76- cout << it.key() << ": " << it.data() << endl;
77- }
78- */
79-
80 // ----------------------------------------------------------------------
81 // Make it so the header is sent with the data
82 // ----------------------------------------------------------------------
83@@ -297,7 +288,7 @@
84 m_sResponseTypeText = GetMimeType( info.extension( FALSE ).lower() );
85
86 // ------------------------------------------------------------------
87- // Get File size
88+ // Get File size - set llEnd to whole file
89 // ------------------------------------------------------------------
90
91 struct stat st;
92@@ -306,42 +297,50 @@
93 llSize = llEnd = st.st_size;
94
95 m_nResponseStatus = 200;
96+ QString sUserAgent = GetHeaderValue( "User-Agent", "");
97
98- // ------------------------------------------------------------------
99- // The Content-Range header is apparently a problem for the
100- // AVeL LinkPlayer2 and probably other hardware players with
101- // Syabas firmware.
102- //
103- // -=>TODO: Need conformation
104- // ------------------------------------------------------------------
105+ // --------------------------------------------------------------
106+ // Process bytes parameter for start and end offsets of track
107+ // --------------------------------------------------------------
108
109 bool bRange = false;
110- QString sUserAgent = GetHeaderValue( "User-Agent", "");
111+ QString sBytes = m_mapParams[ "bytes"];
112+ long long llOffset = 0, llDummy = 0;
113
114- if ( sUserAgent.contains( "Syabas", false ) == 0 )
115- {
116- // --------------------------------------------------------------
117- // Process any Range Header
118- // --------------------------------------------------------------
119+ ParseRange ( sBytes, &llStart, &llEnd );
120
121- QString sRange = GetHeaderValue( "range", "" );
122+ // --------------------------------------------------------------
123+ // Process Range header for ff/rew -- Offset from start of track
124+ // --------------------------------------------------------------
125
126- if (sRange.length() > 0)
127- {
128- if ( bRange = ParseRange( sRange, llSize, &llStart, &llEnd ) )
129- {
130- m_nResponseStatus = 206;
131- m_mapRespHeaders[ "Content-Range" ] = QString("bytes %1-%2/%3")
132- .arg( llStart )
133- .arg( llEnd )
134- .arg( llSize );
135- llSize = (llEnd - llStart) + 1;
136- }
137- }
138- }
139-
140- // DSM-?20 specific response headers
141+ QString sRange = GetHeaderValue( "range", "" );
142+ bRange = ParseRange ( sRange, &llOffset, &llDummy );
143+
144+// VERBOSE(VB_UPNP,QString("HTTPRequest::SendResponseFile : Start/End %1-%2 Offset/Dummy %3-%4 bRange: %5")
145+// .arg(llStart)
146+// .arg(llEnd)
147+// .arg(llOffset)
148+// .arg(llDummy)
149+// .arg(bRange));
150
151+ //
152+ // Did user hit ff or rewind? Is there a different start pos.?
153+ //
154+ if ( bRange ) { /* process for partial content */
155+ m_nResponseStatus = 206;
156+ llDummy += llStart;
157+ llStart += llOffset;
158+ if( llDummy > llStart && llDummy << llEnd) llEnd = llDummy;
159+ llSize = (llEnd - llStart) + 1;
160+ }
161+
162+
163+ m_mapRespHeaders[ "Content-Range" ] = QString("bytes %1-%2/%3")
164+ .arg( llStart )
165+ .arg( llEnd )
166+ .arg( llSize );
167+
168+ // DSM-?20 specific response headers
169 if (bRange == false)
170 m_mapRespHeaders[ "User-Agent" ] = "redsonic";
171
172@@ -350,7 +349,7 @@
173 // ------------------------------------------------------------------
174
175 }
176- else
177+ else /* file does not exist */
178 m_nResponseStatus = 404;
179
180 // -=>TODO: Should set "Content-Length: *" if file is still recording
181@@ -405,6 +404,95 @@
182 }
183
184 /////////////////////////////////////////////////////////////////////////////
185+// Parse Range
186+// returns: true if a non-zero start or end range is provided
187+/////////////////////////////////////////////////////////////////////////////
188+
189+bool HTTPRequest::ParseRange( QString sRange,
190+ long long *pllStart,
191+ long long *pllEnd )
192+{
193+ // ----------------------------------------------------------------------
194+ // -=>TODO: Only handle 1 range at this time... should make work with full spec.
195+ // ----------------------------------------------------------------------
196+
197+ if (sRange.length() == 0)
198+ return false;
199+
200+ // ----------------------------------------------------------------------
201+ // remove any "bytes="
202+ // ----------------------------------------------------------------------
203+
204+ int nIdx = sRange.find( QRegExp( "(\\d|\\-)") );
205+
206+ if (nIdx < 0)
207+ return false;
208+
209+ if (nIdx > 0)
210+ sRange.remove( 0, nIdx );
211+
212+ // ----------------------------------------------------------------------
213+ // Split multiple ranges
214+ // ----------------------------------------------------------------------
215+
216+ QStringList ranges = QStringList::split( ",", sRange );
217+
218+ if (ranges.count() == 0)
219+ return false;
220+
221+ // ----------------------------------------------------------------------
222+ // Split first range into its components
223+ // ----------------------------------------------------------------------
224+
225+ QStringList parts = QStringList::split( "-", ranges[0], true );
226+
227+ if (parts.count() != 2)
228+ return false;
229+
230+ if (parts[0].isNull() && parts[1].isNull())
231+ return false;
232+
233+ // ----------------------------------------------------------------------
234+ //
235+ // ----------------------------------------------------------------------
236+
237+ if (parts[0].isNull())
238+ {
239+ // ------------------------------------------------------------------
240+ // Does it match "-####" ? return true
241+ // ------------------------------------------------------------------
242+
243+ *pllEnd = strtoll( parts[1], NULL, 10 );
244+ }
245+ else if (parts[1].isNull())
246+ {
247+ // ------------------------------------------------------------------
248+ // Does it match "####-"? if 0-, return false, else return true
249+ // ------------------------------------------------------------------
250+
251+ *pllStart = strtoll( parts[0], NULL, 10 );
252+
253+ if (*pllStart == 0) return false;
254+ }
255+ else
256+ {
257+ // ------------------------------------------------------------------
258+ // Must be "####-####" return false if invalid
259+ // ------------------------------------------------------------------
260+
261+ *pllStart = strtoll( parts[0], NULL, 10 );
262+ *pllEnd = strtoll( parts[1], NULL, 10 );
263+
264+ if (*pllStart > *pllEnd)
265+ return false;
266+ }
267+
268+ //cout << getSocketHandle() << "Range Requested " << *pllStart << " - " << *pllEnd << endl;
269+
270+ return true;
271+}
272+
273+/////////////////////////////////////////////////////////////////////////////
274 //
275 /////////////////////////////////////////////////////////////////////////////
276
277@@ -715,7 +803,7 @@
278
279 try
280 {
281- // Read first line to determin requestType
282+ // Read first line to determine requestType
283
284 QString sRequestLine = ReadLine( 2000 );
285
286@@ -896,101 +984,6 @@
287 //
288 /////////////////////////////////////////////////////////////////////////////
289
290-bool HTTPRequest::ParseRange( QString sRange,
291- long long llSize,
292- long long *pllStart,
293- long long *pllEnd )
294-{
295- // ----------------------------------------------------------------------
296- // -=>TODO: Only handle 1 range at this time... should make work with full spec.
297- // ----------------------------------------------------------------------
298-
299- if (sRange.length() == 0)
300- return false;
301-
302- // ----------------------------------------------------------------------
303- // remove any "bytes="
304- // ----------------------------------------------------------------------
305-
306- int nIdx = sRange.find( QRegExp( "(\\d|\\-)") );
307-
308- if (nIdx < 0)
309- return false;
310-
311- if (nIdx > 0)
312- sRange.remove( 0, nIdx );
313-
314- // ----------------------------------------------------------------------
315- // Split multiple ranges
316- // ----------------------------------------------------------------------
317-
318- QStringList ranges = QStringList::split( ",", sRange );
319-
320- if (ranges.count() == 0)
321- return false;
322-
323- // ----------------------------------------------------------------------
324- // Split first range into its components
325- // ----------------------------------------------------------------------
326-
327- QStringList parts = QStringList::split( "-", ranges[0], true );
328-
329- if (parts.count() != 2)
330- return false;
331-
332- if (parts[0].isNull() && parts[1].isNull())
333- return false;
334-
335- // ----------------------------------------------------------------------
336- //
337- // ----------------------------------------------------------------------
338-
339- if (parts[0].isNull())
340- {
341- // ------------------------------------------------------------------
342- // Does it match "-####"
343- // ------------------------------------------------------------------
344-
345- long long llValue = strtoll( parts[1], NULL, 10 );
346-
347- *pllStart = llSize - llValue;
348- *pllEnd = llSize - 1;
349- }
350- else if (parts[1].isNull())
351- {
352- // ------------------------------------------------------------------
353- // Does it match "####-"
354- // ------------------------------------------------------------------
355-
356- *pllStart = strtoll( parts[0], NULL, 10 );
357-
358- if (*pllStart == 0)
359- return false;
360-
361- *pllEnd = llSize - 1;
362- }
363- else
364- {
365- // ------------------------------------------------------------------
366- // Must be "####-####"
367- // ------------------------------------------------------------------
368-
369- *pllStart = strtoll( parts[0], NULL, 10 );
370- *pllEnd = strtoll( parts[1], NULL, 10 );
371-
372- if (*pllStart > *pllEnd)
373- return false;
374- }
375-
376- //cout << getSocketHandle() << "Range Requested " << *pllStart << " - " << *pllEnd << endl;
377-
378- return true;
379-}
380-
381-/////////////////////////////////////////////////////////////////////////////
382-//
383-/////////////////////////////////////////////////////////////////////////////
384-
385 void HTTPRequest::ExtractMethodFromURL()
386 {
387 QStringList sList = QStringList::split( "/", m_sBaseUrl, false );
388Index: libs/libmythupnp/httprequest.h
389===================================================================
390--- libs/libmythupnp/httprequest.h (revision 13462)
391+++ libs/libmythupnp/httprequest.h (working copy)
392@@ -147,7 +147,6 @@
393 QString GetAdditionalHeaders( void );
394
395 bool ParseRange ( QString sRange,
396- long long llSize,
397 long long *pllStart,
398 long long *pllEnd );
399
400Index: programs/mythbackend/mythxml.cpp
401===================================================================
402--- programs/mythbackend/mythxml.cpp (revision 13462)
403+++ programs/mythbackend/mythxml.cpp (working copy)
404@@ -4,8 +4,10 @@
405 // Purpose - Html & XML status HttpServerExtension
406 //
407 // Created By : David Blain Created On : Oct. 24, 2005
408-// Modified By : Modified On:
409-//
410+//
411+// Modified By : Robert Gingher Modified On: Jun. 5, 2007
412+// * added method genm3u for commercial break tracks
413+//
414 //////////////////////////////////////////////////////////////////////////////
415
416 #include "mythxml.h"
417@@ -85,6 +87,7 @@
418 if (sURI == "GetExpiring" ) return MXML_GetExpiring;
419 if (sURI == "GetPreviewImage" ) return MXML_GetPreviewImage;
420 if (sURI == "GetRecording" ) return MXML_GetRecording;
421+ if (sURI == "GenM3u" ) return MXML_GenM3u;
422 if (sURI == "GetVideo" ) return MXML_GetVideo;
423 if (sURI == "GetMusic" ) return MXML_GetMusic;
424 if (sURI == "GetConnectionInfo" ) return MXML_GetConnectionInfo;
425@@ -123,6 +126,7 @@
426 case MXML_GetPreviewImage : GetPreviewImage( pRequest ); return true;
427
428 case MXML_GetRecording : GetRecording ( pThread, pRequest ); return true;
429+ case MXML_GenM3u : GenM3u ( pRequest ); return true;
430 case MXML_GetMusic : GetMusic ( pThread, pRequest ); return true;
431 case MXML_GetVideo : GetVideo ( pThread, pRequest ); return true;
432
433@@ -1136,6 +1140,8 @@
434 }
435
436 /////////////////////////////////////////////////////////////////////////////
437+//
438+// GetRecording
439 //
440 /////////////////////////////////////////////////////////////////////////////
441
442@@ -1267,8 +1273,94 @@
443
444 /////////////////////////////////////////////////////////////////////////////
445 //
446+// GenM3u
447+//
448 /////////////////////////////////////////////////////////////////////////////
449
450+void MythXML::GenM3u ( HTTPRequest *pRequest )
451+{
452+
453+ pRequest->m_eResponseType = ResponseTypeHTML;
454+ pRequest->m_mapRespHeaders[ "Cache-Control" ] = "no-cache=\"Ext\", max-age = 5000";
455+ pRequest->m_nResponseStatus = 404;
456+
457+ QString sStartTime = pRequest->m_mapParams[ "StartTime" ];
458+ QString sChanId = pRequest->m_mapParams[ "ChanId" ];
459+
460+ QDateTime dtStart = QDateTime::fromString( sStartTime, Qt::ISODate );
461+
462+ if (!dtStart.isValid())
463+ {
464+ VERBOSE( VB_UPNP, "MythXML::GenM3u - StartTime missing.");
465+ return;
466+ }
467+
468+ QString sHostIP = gContext->GetSetting( "BackendServerIP", "localhost" );
469+ QString sHostName = gContext->GetHostName();
470+ QString sPort = gContext->GetSettingOnHost( "BackendStatusPort", sHostName);
471+ QString sRecordingUrl = QString( "http://%1:%2/GetRecording?ChanId=%3&StartTime=%4" )
472+ .arg( sHostIP )
473+ .arg( sPort )
474+ .arg( sChanId )
475+ .arg( sStartTime );
476+
477+ ProgramInfo *pInfo = ProgramInfo::GetProgramFromRecorded( sChanId, dtStart );
478+
479+ if (pInfo == NULL)
480+ {
481+ VERBOSE( VB_UPNP, QString( "MythXML::GenM3u - GetProgramFromRecorded( %1, %2 ) returned NULL" )
482+ .arg( sChanId )
483+ .arg( sStartTime ));
484+ return;
485+ }
486+
487+ frm_dir_map_t markmap;
488+ pInfo->GetMarkupMap(markmap, MARK_COMM_END);
489+
490+ int keyframe_dist = 15;
491+
492+ frm_pos_map_t posMap;
493+ pInfo->GetPositionMap(posMap, MARK_GOP_START);
494+
495+ if ( posMap.isEmpty() ) {
496+ pInfo->GetPositionMap(posMap, MARK_GOP_BYFRAME);
497+ keyframe_dist = 1;
498+ }
499+
500+ delete pInfo;
501+
502+ if ( markmap.isEmpty() || posMap.isEmpty() )
503+ {
504+ VERBOSE( VB_UPNP, "MythXML::GenM3u - No Commercial End Marks.");
505+ return;
506+ }
507+
508+ QMap<long long, int>::Iterator i;
509+ long long pos, offset = 0;
510+
511+ for (i = markmap.begin(); i != markmap.end(); ++i) {
512+ pos = i.key()/keyframe_dist;
513+ pRequest->m_response << QString("%1&bytes=%2-%3\r\n" )
514+ .arg( sRecordingUrl )
515+ .arg( offset )
516+ .arg( posMap[pos]-1 ) ;
517+ offset = posMap[pos];
518+ }
519+ pRequest->m_response << QString("%1&bytes=%2-\r\n" )
520+ .arg( sRecordingUrl )
521+ .arg( offset );
522+
523+
524+ pRequest->m_eResponseType = ResponseTypeOther;
525+ pRequest->m_sFileName = "GenM3u.m3u";
526+ pRequest->m_sResponseTypeText = pRequest->GetMimeType( "m3u" );
527+ pRequest->m_nResponseStatus = 200;
528+}
529+
530+/////////////////////////////////////////////////////////////////////////////
531+//
532+/////////////////////////////////////////////////////////////////////////////
533+
534 void MythXML::GetMusic( HttpWorkerThread *pThread,
535 HTTPRequest *pRequest )
536 {
537Index: programs/mythbackend/mythxml.h
538===================================================================
539--- programs/mythbackend/mythxml.h (revision 13462)
540+++ programs/mythbackend/mythxml.h (working copy)
541@@ -4,7 +4,7 @@
542 // Purpose - Myth XML protocol HttpServerExtension
543 //
544 // Created By : David Blain Created On : Oct. 24, 2005
545-// Modified By : Modified On:
546+// Modified By : R. Gingher Modified On: Jun. 5, 2007
547 //
548 //////////////////////////////////////////////////////////////////////////////
549
550@@ -44,14 +44,15 @@
551 MXML_GetPreviewImage = 9,
552
553 MXML_GetRecording = 10,
554- MXML_GetMusic = 11,
555+ MXML_GenM3u = 11,
556+ MXML_GetMusic = 12,
557
558- MXML_GetExpiring = 12,
559- MXML_GetProgramDetails = 13,
560- MXML_GetVideo = 14,
561+ MXML_GetExpiring = 13,
562+ MXML_GetProgramDetails = 14,
563+ MXML_GetVideo = 15,
564
565- MXML_GetConnectionInfo = 15,
566- MXML_GetAlbumArt = 16
567+ MXML_GetConnectionInfo = 16,
568+ MXML_GetAlbumArt = 17
569
570 } MythXMLMethod;
571
572@@ -114,14 +115,17 @@
573 void GetRecording ( HttpWorkerThread *pThread,
574 HTTPRequest *pRequest );
575
576+ void GenM3u ( HTTPRequest *pRequest );
577+
578+
579 void GetMusic ( HttpWorkerThread *pThread,
580 HTTPRequest *pRequest );
581
582 void GetVideo ( HttpWorkerThread *pThread,
583 HTTPRequest *pRequest );
584
585+ void GetDeviceDesc ( HTTPRequest *pRequest );
586
587- void GetDeviceDesc ( HTTPRequest *pRequest );
588 void GetFile ( HTTPRequest *pRequest, QString sFileName );
589
590 public: