Skip to content

Commit 4189eab

Browse files
author
dsward2
committed
In AppDelegate updateCurrentTasksText:, exit the method immediately if the application is terminating. This will avoid a potential crash when LocalRadio.app is quitting.
In Info.plist, some changes were made in the record for NSAppTransportSecurity to acommodate the current Icecast non-TLS transport configuration (http, not https). In localradio.js, the postMessage("startaudio", "*") calls in four methods were relocated to get called immediately after the "listen" request is sent, rather than getting called after the response for the "listen" request is received. It has to be this way due to Apple's policy on starting audio. In WebViewDelegate, a webView:decidePolicyForNavigationAction:request:frame:decisionListener: method was added, which simply calls [listener use].
1 parent 6e7dbf2 commit 4189eab

8 files changed

Lines changed: 94 additions & 70 deletions

File tree

LocalRadio/AppDelegate.m

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -237,51 +237,54 @@ - (void)restartServicesOnThread
237237

238238
- (IBAction)updateCurrentTasksText:(id)sender
239239
{
240-
NSMutableString * tasksString = [NSMutableString string];
241-
242-
[tasksString appendString:@"--- Icecast tasks ---\n\n"];
243-
244-
if (self.icecastController.icecastTaskProcessID != 0)
240+
if (self.applicationIsTerminating == NO)
245241
{
242+
NSMutableString * tasksString = [NSMutableString string];
246243

247-
[tasksString appendFormat:@"Icecast - process ID = %d\n\n", self.icecastController.icecastTaskProcessID];
248-
249-
[tasksString appendFormat:@"%@ %@\n\n",
250-
self.icecastController.quotedIcecastPath, self.icecastController.icecastTaskArgsString];
244+
[tasksString appendString:@"--- Icecast tasks ---\n\n"];
245+
246+
if (self.icecastController.icecastTaskProcessID != 0)
247+
{
251248

252-
AppDelegate * appDelegate = (AppDelegate *)[NSApp delegate];
253-
IcecastController * icecastController = appDelegate.icecastController;
254-
NSDictionary * icecastStatusDictionary = [icecastController icecastStatusDictionary];
249+
[tasksString appendFormat:@"Icecast - process ID = %d\n\n", self.icecastController.icecastTaskProcessID];
250+
251+
[tasksString appendFormat:@"%@ %@\n\n",
252+
self.icecastController.quotedIcecastPath, self.icecastController.icecastTaskArgsString];
255253

256-
NSString * icecastStatusString = [icecastStatusDictionary description];
257-
[tasksString appendString:icecastStatusString];
254+
AppDelegate * appDelegate = (AppDelegate *)[NSApp delegate];
255+
IcecastController * icecastController = appDelegate.icecastController;
256+
NSDictionary * icecastStatusDictionary = [icecastController icecastStatusDictionary];
258257

259-
[tasksString appendString:@"\n\n"];
260-
}
261-
else
262-
{
263-
[tasksString appendString:@"No tasks currently running\n\n"];
264-
}
258+
NSString * icecastStatusString = [icecastStatusDictionary description];
259+
[tasksString appendString:icecastStatusString];
260+
261+
[tasksString appendString:@"\n\n"];
262+
}
263+
else
264+
{
265+
[tasksString appendString:@"No tasks currently running\n\n"];
266+
}
265267

266-
[tasksString appendString:@"--- EZStream tasks ---"];
268+
[tasksString appendString:@"--- EZStream tasks ---"];
267269

268-
NSString * ezStreamTasksString = self.ezStreamController.ezStreamTaskPipelineManager.tasksInfoString;
269-
[tasksString appendString:ezStreamTasksString];
270+
NSString * ezStreamTasksString = self.ezStreamController.ezStreamTaskPipelineManager.tasksInfoString;
271+
[tasksString appendString:ezStreamTasksString];
270272

271-
[tasksString appendString:@"--- RTL-SDR radio tasks ---"];
272-
273-
NSString * radioTasksString = self.sdrController.radioTaskPipelineManager.tasksInfoString;
274-
[tasksString appendString:radioTasksString];
273+
[tasksString appendString:@"--- RTL-SDR radio tasks ---"];
274+
275+
NSString * radioTasksString = self.sdrController.radioTaskPipelineManager.tasksInfoString;
276+
[tasksString appendString:radioTasksString];
275277

276-
[tasksString appendString:@"--- Sox second-stage audio tasks ---"];
277-
278-
NSString * soxTasksString = self.soxController.soxControllerTaskPipelineManager.tasksInfoString;
279-
[tasksString appendString:soxTasksString];
280-
281-
dispatch_async(dispatch_get_main_queue(), ^{
282-
283-
[self.statusCurrentTasksTextView setString:tasksString];
284-
});
278+
[tasksString appendString:@"--- Sox second-stage audio tasks ---"];
279+
280+
NSString * soxTasksString = self.soxController.soxControllerTaskPipelineManager.tasksInfoString;
281+
[tasksString appendString:soxTasksString];
282+
283+
dispatch_async(dispatch_get_main_queue(), ^{
284+
285+
[self.statusCurrentTasksTextView setString:tasksString];
286+
});
287+
}
285288
}
286289

287290

LocalRadio/Base.lproj/MainMenu.xib

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1353,7 +1353,7 @@ Gw
13531353
<font key="font" metaFont="system"/>
13541354
<tabViewItems>
13551355
<tabViewItem label="LocalRadio" identifier="" id="8Qy-d0-fpa">
1356-
<view key="view" id="bIe-XZ-nnh">
1356+
<view key="view" ambiguous="YES" id="bIe-XZ-nnh">
13571357
<rect key="frame" x="10" y="33" width="197" height="0.0"/>
13581358
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
13591359
<subviews>
@@ -1378,7 +1378,7 @@ Gw
13781378
</view>
13791379
</tabViewItem>
13801380
<tabViewItem label="Status" identifier="" id="GvX-g5-9UV">
1381-
<view key="view" ambiguous="YES" id="qnk-kF-EPU">
1381+
<view key="view" id="qnk-kF-EPU">
13821382
<rect key="frame" x="10" y="33" width="450" height="548"/>
13831383
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
13841384
<subviews>
@@ -1394,7 +1394,7 @@ Gw
13941394
<autoresizingMask key="autoresizingMask"/>
13951395
<clipView key="contentView" ambiguous="YES" id="XFC-hX-hWd">
13961396
<rect key="frame" x="1" y="1" width="432" height="184"/>
1397-
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
1397+
<autoresizingMask key="autoresizingMask"/>
13981398
<subviews>
13991399
<textView ambiguous="YES" editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" findStyle="panel" allowsNonContiguousLayout="YES" id="ydX-HH-DPt">
14001400
<rect key="frame" x="0.0" y="0.0" width="432" height="184"/>
@@ -1412,7 +1412,7 @@ Gw
14121412
<autoresizingMask key="autoresizingMask"/>
14131413
</scroller>
14141414
<scroller key="verticalScroller" verticalHuggingPriority="750" doubleValue="1" horizontal="NO" id="St6-kL-Qjl">
1415-
<rect key="frame" x="417" y="1" width="16" height="184"/>
1415+
<rect key="frame" x="-15" y="1" width="16" height="0.0"/>
14161416
<autoresizingMask key="autoresizingMask"/>
14171417
</scroller>
14181418
</scrollView>

LocalRadio/IcecastController.m

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -608,19 +608,26 @@ - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
608608

609609
- (void)addCurrentParserData
610610
{
611-
if (self.currentElementName != NULL)
612-
{
613-
if (self.currentElementData != NULL)
611+
// Use try/catch to avoid a crash that can occur during app termination
612+
// if a property gets released after NULL checks, but before dictionary item added.
613+
@try {
614+
if (self.currentElementName != NULL)
614615
{
615-
if (self.inSourceElement == YES)
616-
{
617-
[self.currentSourceDictionary setObject:self.currentElementData forKey:self.currentElementName];
618-
}
619-
else
616+
if (self.currentElementData != NULL)
620617
{
621-
[self.parserOutputDictionary setObject:self.currentElementData forKey:self.currentElementName];
618+
if (self.inSourceElement == YES)
619+
{
620+
[self.currentSourceDictionary setObject:self.currentElementData forKey:self.currentElementName];
621+
}
622+
else
623+
{
624+
[self.parserOutputDictionary setObject:self.currentElementData forKey:self.currentElementName];
625+
}
622626
}
623627
}
628+
629+
}
630+
@catch (NSException *exception) {
624631
}
625632

626633
self.currentElementData = [NSMutableString string];

LocalRadio/Info.plist

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@
3434
<dict>
3535
<key>127.0.0.1</key>
3636
<dict>
37+
<key>NSAllowsArbitraryLoadsForMedia</key>
38+
<true/>
39+
<key>NSAllowsArbitraryLoadsInWebContent</key>
40+
<true/>
41+
<key>NSAllowsLocalNetworking</key>
42+
<true/>
43+
<key>NSExceptionRequiresForwardSecrecy</key>
44+
<false/>
3745
<key>NSIncludesSubdomains</key>
3846
<true/>
3947
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>

LocalRadio/Web/css/custom.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@
250250
color: #222; }
251251
.has-docked-nav .navbar {
252252
position: fixed;
253+
backface-visibility: hidden;
253254
top: 0;
254255
left: 0; }
255256
.has-docked-nav .navbar-spacer {
@@ -331,6 +332,7 @@ a.button.button-primary.two.columns {
331332
color: #33C3F0; }
332333
.has-docked-nav .navbar {
333334
position: fixed;
335+
backface-visibility: hidden;
334336
top: 0;
335337
left: 0; }
336338
.has-docked-nav .navbar-spacer {
@@ -453,6 +455,7 @@ a.button.button-primary.two.columns {
453455
color: #33C3F0; }
454456
.has-docked-nav .navbar {
455457
position: fixed;
458+
backface-visibility: hidden;
456459
top: 0;
457460
left: 0; }
458461
.has-docked-nav .navbar-spacer {

LocalRadio/Web/index.html

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656

5757
div#navigationbar {
5858
position: fixed;
59+
backface-visibility: hidden;
5960
top: 0;
6061
left: 0;
6162
width: 100%;
@@ -68,6 +69,7 @@
6869
/* parent node of iframe */
6970
div#root {
7071
position: fixed;
72+
backface-visibility: hidden;
7173
top: 50px;
7274
left: 0;
7375
width: 100%;
@@ -89,6 +91,7 @@
8991

9092
div#audioplayer {
9193
position: fixed;
94+
backface-visibility: hidden;
9295
top: calc(100% - 50px);
9396
left: 0;
9497
width: 100%;
@@ -324,7 +327,8 @@
324327

325328
if (needsAudioPlayerStart == true)
326329
{
327-
setTimeout(function() { startAudioPlayerAfterDelay(); }, 5000);
330+
//setTimeout(function() { startAudioPlayerAfterDelay(); }, 1000); // iOS rejects delayed audio play
331+
startAudioPlayerAfterDelay();
328332
}
329333
}
330334

@@ -411,10 +415,11 @@
411415
seekToEndForAudioElement(audioPlayer);
412416
}
413417

414-
audioPlayer.autoplay=true;
415-
audioPlayer.load();
418+
//audioPlayer.load();
416419

417-
audioPlayer.play(); // use promise try/catch below instead
420+
audioPlayer.play();
421+
422+
audioPlayer.autoplay=true;
418423
}
419424
}
420425

@@ -446,7 +451,8 @@
446451

447452
location.href = "index.html";
448453

449-
setTimeout(function() { startAudioPlayerAfterDelay(); }, 1000);
454+
//setTimeout(function() { startAudioPlayerAfterDelay(); }, 1000); // iOS rejects delayed audio play
455+
startAudioPlayerAfterDelay();
450456
}
451457

452458

LocalRadio/Web/js/localradio.js

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -669,16 +669,13 @@ function listenButtonClicked(form)
669669
if (this.readyState == 4 && this.status == 200) {
670670
// response received ok
671671
window.top.nowPlayingTitle = window.document.getElementById("listen_title");
672-
673-
// handle the audio tag with the new source
674-
window.top.postMessage("startaudio", "*");
675672
}
676673
};
677674
xhttp.open("POST", listenButtonClickedUrl, true);
678675
xhttp.send(jsonData);
679676

680677
// handle the audio tag with the new source
681-
//window.top.postMessage("startaudio", "*");
678+
window.top.postMessage("startaudio", "*");
682679

683680
//console.log("postMessage startaudio");
684681
}
@@ -733,16 +730,13 @@ function frequencyListenButtonClicked()
733730
if (this.readyState == 4 && this.status == 200) {
734731
// response received ok
735732
window.top.nowPlayingTitle = window.document.getElementById("listen_title");
736-
737-
// handle the audio tag with the new source
738-
window.top.postMessage("startaudio", "*");
739733
}
740734
};
741735
xhttp.open("POST", frequencyListenButtonClickedUrl, true);
742736
xhttp.send(jsonData);
743737

744738
// handle the audio tag with the new source
745-
//window.top.postMessage("startaudio", "*");
739+
window.top.postMessage("startaudio", "*");
746740

747741
//console.log("postMessage startaudio");
748742
}
@@ -769,16 +763,13 @@ function scannerListenButtonClicked(form)
769763
if (this.readyState == 4 && this.status == 200) {
770764
// response received ok
771765
window.top.nowPlayingTitle = window.document.getElementById("listen_title");
772-
773-
// handle the audio tag with the new source
774-
window.top.postMessage("startaudio", "*");
775766
}
776767
};
777768
xhttp.open("POST", scannerListenButtonClickedUrl, true);
778769
xhttp.send(jsonData);
779770

780771
// handle the audio tag with the new source
781-
//window.top.postMessage("startaudio", "*");
772+
window.top.postMessage("startaudio", "*");
782773

783774
//console.log("postMessage startaudio");
784775
}
@@ -802,16 +793,13 @@ function deviceListenButtonClicked(form)
802793
if (this.readyState == 4 && this.status == 200) {
803794
// response received ok
804795
window.top.nowPlayingTitle = window.document.getElementById("listen_title");
805-
806-
// handle the audio tag with the new source
807-
window.top.postMessage("startaudio", "*");
808796
}
809797
};
810798
xhttp.open("POST", listenButtonClickedUrl, true);
811799
xhttp.send(jsonData);
812800

813801
// handle the audio tag with the new source
814-
//window.top.postMessage("startaudio", "*");
802+
window.top.postMessage("startaudio", "*");
815803

816804
//console.log("postMessage startaudio");
817805
}

LocalRadio/WebViewDelegate.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,13 @@ - (void)webView:(WebView *)webView decidePolicyForNewWindowAction:(NSDictionary
105105

106106

107107

108+
- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation
109+
request:(NSURLRequest *)request
110+
frame:(WebFrame *)frame
111+
decisionListener:(id<WebPolicyDecisionListener>)listener
112+
{
113+
[listener use];
114+
}
115+
116+
108117
@end

0 commit comments

Comments
 (0)