Skip to content
This repository has been archived by the owner on Aug 10, 2022. It is now read-only.

Use temporary files to store audio stream (patch included) #65

Open
fengshaun opened this issue Nov 26, 2016 · 0 comments
Open

Use temporary files to store audio stream (patch included) #65

fengshaun opened this issue Nov 26, 2016 · 0 comments

Comments

@fengshaun
Copy link

Using a temporary file to keep the downloaded stream has the following advantages:
1- File is not saved to disk if it turns out it doesn't need to be saved (e.g. not rated)
2- If destination directory is a remote host (e.g. NFS share), then no unnecessary writes are made (i.e. if the file doesn't need to be saved).

things left to do:

  • fix tagging to also use the temporary file as opposed to the final audio file as source.
diff --git a/src/fly.c b/src/fly.c
index ea93929..1fb6de3 100644
--- a/src/fly.c
+++ b/src/fly.c
@@ -1122,47 +1122,80 @@ void BarFlyFinalize(void)
 	return;
 }
 
-int BarFlyClose(BarFly_t* fly, BarSettings_t const* settings)
+int BarFlyCopyCompleted(BarFly_t* fly, BarSettings_t const* settings)
 {
-	int exit_status = 0;
-	int status;
+	if (!fly) {
+		return 0;
+	}
 
-	assert(settings != NULL);
+	fly->status = COPYING;
+	fseek(fly->temp_file, 0, SEEK_SET);
 
-	if (fly != NULL) {
-		/*
-		 * Close the file stream.
-		 */
-		if (fly->audio_file != NULL) {
-			fclose(fly->audio_file);
-		}
+	/*
+	 * Open a stream to the file.
+	 */
+	int status = _BarFlyFileOpen(&fly->audio_file, fly->audio_file_path, settings);
 
-		/*
-		 * Delete the file if it was not complete or not loved.
-		 */
-		if (!fly->completed || (settings->downloadOnlyLoved && !fly->loved)) {
-			fly->status = DELETING;
-			status = _BarFlyFileDelete(fly, settings);
-			if (status != 0) {
-				exit_status = -1;
+	if (status == 0) {
+		char buf[BAR_FLY_COPY_BLOCK_SIZE];
+		memset(buf, 0, BAR_FLY_COPY_BLOCK_SIZE);
+		size_t s = 0, s2 = 0;
+
+		while (!feof(fly->temp_file)) {
+			s = fread(buf, 1, BAR_FLY_COPY_BLOCK_SIZE, fly->temp_file);
+
+			if (s != BAR_FLY_COPY_BLOCK_SIZE && !feof(fly->temp_file)) {
+				BarUiMsg(settings, MSG_INFO,
+						"Could not read temporary file (%d): %s\n",
+						errno,
+						strerror(errno));
+				break;
 			}
-		}
 
-		/*
-		 * Free the audio file name.
-		 */
-		if (fly->audio_file_path != NULL) {
-			free(fly->audio_file_path);
-		}
+			s2 = fwrite(buf, 1, s, fly->audio_file);
 
-		/*
-		 * Free the cover art URL.
-		 */
-		if (fly->cover_art_url != NULL) {
-			free(fly->cover_art_url);
+			if (s2 != s) {
+				BarUiMsg(settings, MSG_INFO,
+						"Could not write audio to destination %s (%d): %s\n",
+						fly->audio_file_path,
+						errno,
+						strerror(errno));
+				break;
+			}
 		}
 	}
 
+	fclose(fly->audio_file);
+}
+
+int BarFlyClose(BarFly_t* fly, BarSettings_t const* settings)
+{
+	if (!fly) {
+		return 0;
+	}
+
+	assert(settings != NULL);
+
+	int exit_status = 0;
+	int status;
+
+	/* closing the tmpfile() will delete it automatically */
+	fclose(fly->temp_file);
+
+	/*
+	 * Free the audio file name.
+	 */
+	if (fly->audio_file_path != NULL) {
+		free(fly->audio_file_path);
+	}
+
+	/*
+	 * Free the cover art URL.
+	 */
+	if (fly->cover_art_url != NULL) {
+		free(fly->cover_art_url);
+	}
+
 	return exit_status;
 }
 
@@ -1347,22 +1380,17 @@ int BarFlyOpen(BarFly_t* fly, PianoSong_t const* song,
 	if (output_fly.audio_file_path == NULL) {
 		goto error;
 	}
-	
+
 	/*
-	 * Open a stream to the file.
+	 * Get a temporary file for download.
 	 */
-	status = _BarFlyFileOpen(&output_fly.audio_file,
-			output_fly.audio_file_path, settings);
-	if (status == 0) {
-		output_fly.status = RECORDING;
-	} else if (status == -2) {
-		output_fly.status = NOT_RECORDING_EXIST;
-		output_fly.completed = true;
-	} else {
-		output_fly.completed = true;
+	output_fly.temp_file = tmpfile();
+	if (output_fly.temp_file == NULL) {
 		goto error;
 	}
 
+	output_fly.status = RECORDING;
+
 	/*
 	 * All members of the BarFly_t structure were created successfully.  Copy
 	 * them from the temporary structure to the one passed in.
@@ -1420,6 +1448,10 @@ char const* BarFlyStatusGet(BarFly_t* fly)
 			string = "Deleting";
 			break;
 
+		case (COPYING):
+			string = "Copying";
+			break;
+
 		case (TAGGING):
 			string = "Tagging";
 			break;
@@ -1476,7 +1508,7 @@ int BarFlyWrite(BarFly_t* fly, void const* data, size_t data_size)
 		}
 
 		assert(fly->audio_file != NULL);
-		status = fwrite(data, data_size, 1, fly->audio_file);
+		status = fwrite(data, data_size, 1, fly->temp_file);
 		if (status != 1) {
 			goto error;
 		}
diff --git a/src/fly.h b/src/fly.h
index e200512..e5551ac 100644
--- a/src/fly.h
+++ b/src/fly.h
@@ -52,6 +52,7 @@ typedef enum BarFlyStatus {
 	NOT_RECORDING_EXIST,
 	RECORDING,
 	DELETING,
+	COPYING,
 	TAGGING
 } BarFlyStatus_t;
 
@@ -63,11 +64,16 @@ typedef enum BarFlyStatus {
  */
 typedef struct BarFly {
 	/**
-	 * The stream to which the audio stream is written.
+	 * The file to which the final audio stream is copied.
 	 */
 	FILE* audio_file;
 
 	/**
+	 * The stream to which audio is written.
+	 */
+	FILE* temp_file;
+
+	/**
 	 * The audio file path.
 	 */
 	char* audio_file_path;
@@ -212,4 +218,13 @@ int BarFlyTag(BarFly_t* fly, BarSettings_t const* settings);
  */
 int BarFlyWrite(BarFly_t* fly, void const* data, size_t data_size);
 
+/**
+ * Copies the temporary audio file to final destination
+ *
+ * @param fly Pointer to a BarFly_t structure.
+ * @param settings Pointer to the application settings structure.
+ * @return Upon success 0 is returned otherwise -1 is returned.
+ */
+int BarFlyCopyCompleted(BarFly_t* fly, BarSettings_t const* settings);
+
 #endif /* _FLY_H */
diff --git a/src/player.c b/src/player.c
index 3c2cfdb..2ec35b1 100644
--- a/src/player.c
+++ b/src/player.c
@@ -518,8 +518,15 @@ void *BarPlayerThread (void *data) {
 	} while (wRet == WAITRESS_RET_PARTIAL_FILE || wRet == WAITRESS_RET_TIMEOUT
 			|| wRet == WAITRESS_RET_READ_ERR);
 
-	/* If the song was played all the way through tag it. */
 	if (wRet == WAITRESS_RET_OK) {
+		if (!player->settings->downloadOnlyLoved ||
+			(player->settings->downloadOnlyLoved && !player->fly.loved)) {
+			BarUiMsg(player->settings, MSG_INFO, "Saving loved song.\n",
+					player->fly.audio_file_path);
+			BarFlyCopyCompleted(&player->fly, player->settings);
+		}
+
+		/* If the song was played all the way through tag it. */
 		BarFlyTag(&player->fly, player->settings);
 	}
 
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant