how to add background music - ios

The duplicate answer does not works at all
import Cocoa
import AVFoundation
var error: NSError?
println("Hello, Audio!")
var url = NSURL(fileURLWithPath: "/Users/somebody/myfile.mid") // Change to a local midi file
var midi = AVMIDIPlayer(contentsOfURL: url, soundBankURL: nil, error: &error)
if midi == nil {
if let e = error {
println("AVMIDIPlayer failed: " + e.localizedDescription)
}
}
midi.play(nil)
while midi.playing {
// Spin (yeah, that's bad!)
}

I've made a couple of changes to your code but this seems to "work" (we'll get to that)
First off, import the MP3 file to your playground as described in this answer
Then you can use your file like so:
import UIKit
import AVFoundation
print("Hello, Audio!")
if let url = Bundle.main.url(forResource: "drum01", withExtension: "mp3") {
do {
let midi = try AVMIDIPlayer(contentsOf: url, soundBankURL: nil)
midi.play(nil)
while midi.isPlaying {
// Spin (yeah, that's bad!)
}
} catch (let error) {
print("AVMIDIPlayer failed: " + error.localizedDescription)
}
}
Notice:
printinstead of println
In Swift 3 a lot of things was renamed and some of the "old" methods that took an &error parameter was changed to use do try catch instead. Therefore the error has gone from your call and has been replaced with a try.
The above will fail! You will see error code -10870 which can be found in the AUComponent.h header file and which translates to:
kAudioUnitErr_UnknownFileType
If an audio unit uses external files as a data source, this error is returned
if a file is invalid (Apple's DLS synth returns this error)
So...this leads me to thinking you need to do one of two things, either:
find a .midi file and use that with the AVMidiPlayer
find something else to play your file, for instance AVFilePlayer or AVAudioEngine
(you can read more about error handling in Swift here).
Hope that helps you.

The mp3 file must be in the Resources folder.
You play an mp3 with code like this (not the MIDI player):
if let url = Bundle.main.url(forResource: "drum01", withExtension: "mp3") {
let player = try? AVAudioPlayer(contentsOf: url)
player?.prepareToPlay()
player?.play()
}

Related

How do you allow very large files to have time to upload to firebase before iOS terminates the task?

I have a video sharing app, and when you save a video to firebase storage it works perfectly for videos that are roughly 1 minute or shorter.
The problem that I am having, is when I try to post a longer video (1 min or greater) it never saves to firebase.
The only thing that I can think of is this error that I am getting, and this error only shows up about 30 seconds after I click the save button:
[BackgroundTask] Background Task 101 ("GTMSessionFetcher-firebasestorage.googleapis.com"), was created over 30 seconds ago. In applications running in the background, this creates a risk of termination. Remember to call UIApplication.endBackgroundTask(_:) for your task in a timely manner to avoid this.
Here is my code to save the video to firebase.
func saveMovie(path: String, file: String, url: URL) {
var backgroundTaskID: UIBackgroundTaskIdentifier?
// Perform the task on a background queue.
DispatchQueue.global().async {
// Request the task asseration and save the ID
backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "Finish doing this task", expirationHandler: {
// End the task if time expires
UIApplication.shared.endBackgroundTask(backgroundTaskID!)
backgroundTaskID = UIBackgroundTaskIdentifier.invalid
})
// Send the data synchronously
do {
let movieData = try Data(contentsOf: url)
self.storage.child(path).child("\(file).m4v").putData(movieData)
} catch let error {
fatalError("Error saving movie in saveMovie func. \(error.localizedDescription)")
}
//End the task assertion
UIApplication.shared.endBackgroundTask(backgroundTaskID!)
backgroundTaskID = UIBackgroundTaskIdentifier.invalid
}
}
Any suggestions on how I can allow my video time to upload?
Finally figured this out after a long time...
All you have to do is use .putFile("FileURL") instead of .putdata("Data"). Firebase documentation says you should use putFile() instead of putData() when uploading large files.
But the hard part is for some reason you can't directly upload the movie URL that you get from the didFinishPickingMediaWithInfo function and firebase will just give you an error. So what I did instead was get the data of the movie, save the movie data to a path in the file manager, and use the file manager path URL to upload directly to firebase which worked for me.
//Save movie to Firestore
do {
// Convert movie to Data.
let movieData = try Data(contentsOf: movie)
// Get path so we can save movieData into fileManager and upload to firebase because movie URL does not work, but fileManager url does work.
guard let path = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent(postId!) else { print("Error saving to file manager in addPost func"); return }
do {
try movieData.write(to: path)
// Save the file manager url file to firebase storage
Storage.storage().reference().child("Videos").child("\(postId!).m4v").putFile(from: path, metadata: nil) { metadata, error in
if let error = error {
print("There was an error \(error.localizedDescription)")
} else {
print("Video successfully uploaded.")
}
// Delete video from filemanager because it would take up too much space to save all videos to file manager.
do {
try FileManager.default.removeItem(atPath: path.path)
} catch let error {
print("Error deleting from file manager in addPost func \(error.localizedDescription)")
}
}
} catch let error {
print("Error writing movieData to firebase \(error.localizedDescription)")
}
} catch let error {
print("There was an error adding video in addPost func \(error.localizedDescription)")
}

Access Windows/Mac Shared Folder Locally With smb from iOS

I am trying to build an app where I am able to access(read/write) windows/mac shared folders in my local network with swift.
Is there any possible way to do that with swift?
There is an App in the App Store called "FileExplorer" https://apps.apple.com/de/app/fe-file-explorer-file-manager/id510282524 where you can access these shared folders, but I do not know how they programmed this and with which language.
I also tried to access my shared folders via this App and yes it worked I can see my shared folders on my Phone.
But there needs to be a way to do it with swift...
I already tried different things(code bellow).
In the code bellow I tried to access the shared folder of my second mac and write the Text "Write this text to the fileURL as text in iOS using Swift" into the file named "Test.txt" and after that I want to read the same file again.
#IBAction func Button(_ sender: UIButton)
{
var uc = URLComponents()
uc.scheme = "smb"
uc.user = "user"
uc.password = "password"
uc.host = "ip-adress"
uc.path = "document-directory"
// Save data to file
let fileName = "Test"
let url = uc.url
//let DocumentDirURL = URL(fileURLWithPath: "/Users/f/d/t/App/Assets/Apps/TestApp")
let DocumentDirURL = try! URL(resolvingAliasFileAt: url!)
let fileURL = DocumentDirURL.appendingPathComponent(fileName).appendingPathExtension("txt")
print("FilePath: \(fileURL.path)")
let writeString = "Write this text to the fileURL as text in iOS using Swift"
do {
// Write to the file
try writeString.write(to: fileURL, atomically: true, encoding: String.Encoding.utf8)
} catch let error as NSError {
print("Failed writing to URL: \(fileURL), Error: " + error.localizedDescription)
}
var fullString: String = "" // Used to store the file contents
do {
// Read the file contents
fullString = try String(contentsOf: fileURL, encoding: .utf8)
} catch let error as NSError {
print("Failed reading from URL: \(fileURL), Error: " + error.localizedDescription)
}
print("File Text: \(readString)")
}
If I run the code as shown, he always gives me the error
"smb scheme is not supported" and then some additional errors that he can not write/read the file because he can not access it.
When I change the code and only search on the device I am programming on and run the simulator to search for this file everything works fine. So I have problems with "smb".
Thank you for every helpful answer.
you can use amsmb2 library to do this
you can extend the template class provided to connect to download files, write files, list directories -> on an smb share
everything is asynchronous from memory, with the librarys calls including hooks for progress updates on the ui main thread etc
i believe the amsmb2 library function your after might be uploadItem
iOS 13 includes SMB (server message block protocol) support
https://9to5mac.com/2019/06/17/ios-13-beta-2-enables-smb-server-connectivity-in-the-files-app/

Swift - How can I convert Saved Audio file conversations to Text?

I work on speech recognition. I solve the text-to-speech and speech-to-text with IOS frameworks. But now i want to convert saved audio file conversations to text. How can i solve this ? Thank you for all replies.
I have worked on same things which are working for me.
I have audio file in my project bundle which. So I have written following code to convert audio to text.
let audioURL = Bundle.main.url(forResource: "Song", withExtension: "mov")
let recognizer = SFSpeechRecognizer(locale: Locale(identifier: "en-US"))
let request = SFSpeechURLRecognitionRequest(url: audioURL!)
request.shouldReportPartialResults = true
if (recognizer?.isAvailable)! {
recognizer?.recognitionTask(with: request) { result, error in
guard error == nil else { print("Error: \(error!)"); return }
guard let result = result else { print("No result!"); return }
print(result.bestTranscription.formattedString)
}
} else {
print("Device doesn't support speech recognition")
}
First get audio url from where you have store audio file.
Then create instance of SFSpeechRecognizer with locale that you have want.
Create instance of SFSpeechURLRecognitionRequest which are used to requesting recognitionTask.
recognitionTask will give you result and error. Where result contains bestTranscription.formattedString. formmatedString is your test result of audio file.
If set request.shouldReportPartialResults = true, this will give your partial result of every line speak in audio.
I hope this will help you.

Swift File Download Issue

I am trying to download a plist file from a remote location and use it in the iOS app I am creating. The file is going to be used for calendar details within the app's calendar. The goal is obviously that I can update the remote file instead of having to push updates to the app itself every time we need to make changes to calendar details.
I started with the code used in this example: Download File From A Remote URL
Here is my modified version:
// Create destination URL
let documentsUrl:URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL!
let destinationFileUrl = documentsUrl.appendingPathComponent("2017.plist")
//let destinationFileUrl = URL(string: Bundle.main.path(forResource: String(currentYear), ofType: "plist")!)
//Create URL to the source file you want to download
let fileURL = URL(string: "https://drive.google.com/open?id=0BwHDQFwaL9DuLThNYWwtQ1VXblk")
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url:fileURL!)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
}
do {
try FileManager.default.removeItem(at: destinationFileUrl)
try FileManager.default.moveItem(at: tempLocalUrl, to: destinationFileUrl)
print("File was replaced")
print(NSArray(contentsOf: tempLocalUrl))
//print(tempLocalUrl)
} catch (let writeError) {
print("Error creating a file \(String(describing: destinationFileUrl)) : \(writeError)")
}
} else {
print("Error took place while downloading a file. Error description: %#", error?.localizedDescription as Any);
}
}
task.resume()
I originally tried to overwrite the file that is bundled with the app to being with, that resulted in errors. So I instead tried to just save it in the app's documents folder and that removed that error. I had to make sure and remove any previous version of the file because it was giving me a file already exists error after the first run.
While it says everything is working (The outputs for both successful download and replaced file happen) when I print the contents of the array from the downloaded URL it just gives me nil.
This is my first attempt to use any kind of external resources in an app. Before I have always kept everything internal, so I am sure there is something glaringly obvious I am missing.
Update 1:
I realized I didn't have the correct URL to use to download a file from a Google drive. That line of code has been changed to:
let fileURL = URL(string: "https://drive.google.com/uc?export=download&id=0BwHDQFwaL9DuLThNYWwtQ1VXblk")
So now I actually am downloading the plist like I originally thought I was. Even removing the deletion issue mentioned in the first comment, I still can't get the downloaded file to actually replace the existing one.
Update 2:
I have reduced the actual file manipulation down to the following:
do {
try FileManager.default.replaceItemAt(destinationFileUrl, withItemAt: tempLocalUrl)
print("File was replaced")
print(NSArray(contentsOf: destinationFileUrl))
} catch (let writeError) {
print("Error creating a file \(String(describing: destinationFileUrl)) : \(writeError)")
}
} else {
print("Error took place while downloading a file. Error description: %#", error?.localizedDescription as Any);
}
After the replacement is performed the output of the file shows the correct new contents that were downloaded from the internet.
Later in the code when I try and access the file it seems to be nil in content again.
Look at your download completion code. You:
Delete the file at the destination URL (in case there was one
leftover)
MOVE the temp file to the destination URL (removing it from the temp
URL)
Try to load the file from the temp URL.
What's wrong with this picture?
You are trying to get the contents of the moved file. You already moved the file to destination url and then you are trying to get the contents of the file from temporary location.
For getting file data, Please try the following :
let fileData = try! String(contentsOf: destinationFileUrl, encoding: String.Encoding.utf8)
print(fileData)

Subclass of XMLParser crashes with the contentsOfURL initializer if there isn't connectivity, Internet or otherwise, to get the contents of the URL

I'm trying to sort out an issue where a feed parsing framework (FeedKit) crashes if there is no connectivity to get the contents of the specified URL (e.g. the app is offline).
So, it works when the App is online, and online only.
Whenever I try to instantiate my Parser class with the convenience initializer of the superclass XMLParser
convenience init?(contentsOf url: URL)
The framework crashes:
In order to try and isolate the problem, and exclude some error introduced in the framework, I have recreated the issue in a clean project:
A solution that works like a charm, using a plain vanilla XMLParser of the Foundation framework:
let feedURL = URL(string: "http://images.apple.com/main/rss/hotnews/hotnews.rss")!
if let parser = XMLParser(contentsOf: feedURL) { // Works as expected
print("Got instance \(parser)")
}
And another that doesn't:
class Parser: XMLParser { }
let feedURL = URL(string: "http://images.apple.com/main/rss/hotnews/hotnews.rss")!
if let parser = Parser(contentsOf: feedURL) { // Crash!
print("Got instance \(parser)")
}
In the second example, all I'm doing is subclassing the XMLParser class. No overrides or custom code whatsoever. And it still crashes.
Am I missing something?
Thank you
Edit:
Submitted a bug report to Apple with number 28904764 and opened up a Radar to this issue.
I'm confident that this is a bug on Apple's end, but would prefer to be wrong and have a fix.
This looks like a bug.
However, you can override the designated and convenience initializer of XMLParser class in Parser and implement your own logic
class Parser: XMLParser {
override init(data: Data)
{
super.init(data: data)
}
convenience init?(contentsOf url: URL){
//return data or null examining data from url
do{
let data = try Data(contentsOf: url)
self.init(data: data)
}catch{
return nil
}
}
}
And call as
let feedURL = URL(string: "http://images.apple.com/main/rss/hotnews/hotnews.rss")
if let parser = Parser(contentsOf: feedURL!){
print("Got instance \(parser)")
}else{
print("no data in url")
}
I think it was the problem with URL. I tried ur code I got the error.
Unable to read data
I tried replacing URL,
feedURL = NSURL(string:"http://images.apple.com/main/rss/hotnews/hotnews.rss#sthash.fuVEonEt.dpuf")!
parser = XMLParser(contentsOf:feedURL as URL)!
parser.delegate = self
parser.parse()
It work all fine. (I am using Swift 3)

Resources