diff options
-rw-r--r-- | apps/buffering.c | 42 | ||||
-rw-r--r-- | apps/buffering.h | 16 | ||||
-rw-r--r-- | apps/playback.c | 73 | ||||
-rw-r--r-- | apps/plugin.h | 2 |
4 files changed, 59 insertions, 74 deletions
diff --git a/apps/buffering.c b/apps/buffering.c index 72b3890ef0..027d33a486 100644 --- a/apps/buffering.c +++ b/apps/buffering.c | |||
@@ -93,7 +93,7 @@ struct memory_handle { | |||
93 | size_t data; /* Start index of the handle's data buffer */ | 93 | size_t data; /* Start index of the handle's data buffer */ |
94 | size_t ridx; /* Read pointer, relative to the main buffer */ | 94 | size_t ridx; /* Read pointer, relative to the main buffer */ |
95 | size_t widx; /* Write pointer, relative to the main buffer */ | 95 | size_t widx; /* Write pointer, relative to the main buffer */ |
96 | ssize_t filesize; /* File total length */ | 96 | off_t filesize; /* File total length (possibly trimmed at tail) */ |
97 | off_t start; /* Offset at which we started reading the file */ | 97 | off_t start; /* Offset at which we started reading the file */ |
98 | off_t pos; /* Read position in file */ | 98 | off_t pos; /* Read position in file */ |
99 | off_t volatile end; /* Offset at which we stopped reading the file */ | 99 | off_t volatile end; /* Offset at which we stopped reading the file */ |
@@ -917,7 +917,7 @@ management functions for all the actual handle management work. | |||
917 | return value: <0 if the file cannot be opened, or one file already | 917 | return value: <0 if the file cannot be opened, or one file already |
918 | queued to be opened, otherwise the handle for the file in the buffer | 918 | queued to be opened, otherwise the handle for the file in the buffer |
919 | */ | 919 | */ |
920 | int bufopen(const char *file, size_t offset, enum data_type type, | 920 | int bufopen(const char *file, off_t offset, enum data_type type, |
921 | void *user_data) | 921 | void *user_data) |
922 | { | 922 | { |
923 | int handle_id = ERR_BUFFER_FULL; | 923 | int handle_id = ERR_BUFFER_FULL; |
@@ -1508,31 +1508,36 @@ These functions are exported, to allow interaction with the buffer. | |||
1508 | They take care of the content of the structs, and rely on the linked list | 1508 | They take care of the content of the structs, and rely on the linked list |
1509 | management functions for all the actual handle management work. | 1509 | management functions for all the actual handle management work. |
1510 | */ | 1510 | */ |
1511 | bool buf_is_handle(int handle_id) | ||
1512 | { | ||
1513 | return find_handle(handle_id) != NULL; | ||
1514 | } | ||
1511 | 1515 | ||
1512 | ssize_t buf_handle_offset(int handle_id) | 1516 | int buf_handle_data_type(int handle_id) |
1513 | { | 1517 | { |
1514 | const struct memory_handle *h = find_handle(handle_id); | 1518 | const struct memory_handle *h = find_handle(handle_id); |
1515 | if (!h) | 1519 | if (!h) |
1516 | return ERR_HANDLE_NOT_FOUND; | 1520 | return ERR_HANDLE_NOT_FOUND; |
1517 | return h->start; | 1521 | return h->type; |
1518 | } | 1522 | } |
1519 | 1523 | ||
1520 | void buf_set_base_handle(int handle_id) | 1524 | off_t buf_filesize(int handle_id) |
1521 | { | 1525 | { |
1522 | mutex_lock(&llist_mutex); | 1526 | const struct memory_handle *h = find_handle(handle_id); |
1523 | base_handle_id = handle_id; | 1527 | if (!h) |
1524 | mutex_unlock(&llist_mutex); | 1528 | return ERR_HANDLE_NOT_FOUND; |
1529 | return h->filesize; | ||
1525 | } | 1530 | } |
1526 | 1531 | ||
1527 | enum data_type buf_handle_data_type(int handle_id) | 1532 | off_t buf_handle_offset(int handle_id) |
1528 | { | 1533 | { |
1529 | const struct memory_handle *h = find_handle(handle_id); | 1534 | const struct memory_handle *h = find_handle(handle_id); |
1530 | if (!h) | 1535 | if (!h) |
1531 | return TYPE_UNKNOWN; | 1536 | return ERR_HANDLE_NOT_FOUND; |
1532 | return h->type; | 1537 | return h->start; |
1533 | } | 1538 | } |
1534 | 1539 | ||
1535 | ssize_t buf_handle_remaining(int handle_id) | 1540 | off_t buf_handle_remaining(int handle_id) |
1536 | { | 1541 | { |
1537 | const struct memory_handle *h = find_handle(handle_id); | 1542 | const struct memory_handle *h = find_handle(handle_id); |
1538 | if (!h) | 1543 | if (!h) |
@@ -1540,11 +1545,6 @@ ssize_t buf_handle_remaining(int handle_id) | |||
1540 | return h->filesize - h->end; | 1545 | return h->filesize - h->end; |
1541 | } | 1546 | } |
1542 | 1547 | ||
1543 | bool buf_is_handle(int handle_id) | ||
1544 | { | ||
1545 | return find_handle(handle_id) != NULL; | ||
1546 | } | ||
1547 | |||
1548 | bool buf_pin_handle(int handle_id, bool pin) | 1548 | bool buf_pin_handle(int handle_id, bool pin) |
1549 | { | 1549 | { |
1550 | struct memory_handle *h = find_handle(handle_id); | 1550 | struct memory_handle *h = find_handle(handle_id); |
@@ -1576,6 +1576,14 @@ size_t buf_length(void) | |||
1576 | return buffer_len; | 1576 | return buffer_len; |
1577 | } | 1577 | } |
1578 | 1578 | ||
1579 | /* Set the handle from which useful data is counted */ | ||
1580 | void buf_set_base_handle(int handle_id) | ||
1581 | { | ||
1582 | mutex_lock(&llist_mutex); | ||
1583 | base_handle_id = handle_id; | ||
1584 | mutex_unlock(&llist_mutex); | ||
1585 | } | ||
1586 | |||
1579 | /* Return the amount of buffer space used */ | 1587 | /* Return the amount of buffer space used */ |
1580 | size_t buf_used(void) | 1588 | size_t buf_used(void) |
1581 | { | 1589 | { |
diff --git a/apps/buffering.h b/apps/buffering.h index 4d4cb39df3..fcffcf086c 100644 --- a/apps/buffering.h +++ b/apps/buffering.h | |||
@@ -75,7 +75,7 @@ bool buffering_reset(char *buf, size_t buflen); | |||
75 | * NOTE: Tail operations are only legal when the end of the file is buffered. | 75 | * NOTE: Tail operations are only legal when the end of the file is buffered. |
76 | ****************************************************************************/ | 76 | ****************************************************************************/ |
77 | 77 | ||
78 | int bufopen(const char *file, size_t offset, enum data_type type, | 78 | int bufopen(const char *file, off_t offset, enum data_type type, |
79 | void *user_data); | 79 | void *user_data); |
80 | int bufalloc(const void *src, size_t size, enum data_type type); | 80 | int bufalloc(const void *src, size_t size, enum data_type type); |
81 | bool bufclose(int handle_id); | 81 | bool bufclose(int handle_id); |
@@ -101,17 +101,19 @@ ssize_t bufcuttail(int handle_id, size_t size); | |||
101 | * buf_back_off_storage: tell buffering thread to take it easy | 101 | * buf_back_off_storage: tell buffering thread to take it easy |
102 | ****************************************************************************/ | 102 | ****************************************************************************/ |
103 | 103 | ||
104 | enum data_type buf_handle_data_type(int handle_id); | ||
105 | ssize_t buf_handle_remaining(int handle_id); | ||
106 | bool buf_is_handle(int handle_id); | 104 | bool buf_is_handle(int handle_id); |
107 | ssize_t buf_handle_offset(int handle_id); | 105 | int buf_handle_data_type(int handle_id); |
108 | void buf_set_base_handle(int handle_id); | 106 | off_t buf_filesize(int handle_id); |
109 | size_t buf_length(void); | 107 | off_t buf_handle_offset(int handle_id); |
110 | size_t buf_used(void); | 108 | off_t buf_handle_remaining(int handle_id); |
111 | bool buf_pin_handle(int handle_id, bool pin); | 109 | bool buf_pin_handle(int handle_id, bool pin); |
112 | bool buf_signal_handle(int handle_id, bool signal); | 110 | bool buf_signal_handle(int handle_id, bool signal); |
113 | 111 | ||
112 | size_t buf_length(void); | ||
113 | size_t buf_used(void); | ||
114 | |||
114 | /* Settings */ | 115 | /* Settings */ |
116 | void buf_set_base_handle(int handle_id); | ||
115 | void buf_set_watermark(size_t bytes); | 117 | void buf_set_watermark(size_t bytes); |
116 | size_t buf_get_watermark(void); | 118 | size_t buf_get_watermark(void); |
117 | 119 | ||
diff --git a/apps/playback.c b/apps/playback.c index 8b607f30f0..e8aaf3bacc 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -227,11 +227,6 @@ struct track_info | |||
227 | #endif | 227 | #endif |
228 | int audio_hid; /* Main audio data handle ID */ | 228 | int audio_hid; /* Main audio data handle ID */ |
229 | }; }; | 229 | }; }; |
230 | off_t filesize; /* File total length on disk | ||
231 | TODO: This should be stored | ||
232 | in the handle or the | ||
233 | id3 and would use less | ||
234 | ram */ | ||
235 | }; | 230 | }; |
236 | 231 | ||
237 | /* On-buffer info format; includes links */ | 232 | /* On-buffer info format; includes links */ |
@@ -459,8 +454,6 @@ static void track_info_wipe(struct track_info *infop) | |||
459 | 454 | ||
460 | FOR_EACH_TRACK_INFO_HANDLE(i) | 455 | FOR_EACH_TRACK_INFO_HANDLE(i) |
461 | infop->handle[i] = ERR_HANDLE_NOT_FOUND; | 456 | infop->handle[i] = ERR_HANDLE_NOT_FOUND; |
462 | |||
463 | infop->filesize = 0; | ||
464 | } | 457 | } |
465 | 458 | ||
466 | /** --- Track list --- **/ | 459 | /** --- Track list --- **/ |
@@ -1065,7 +1058,7 @@ static void audio_update_filebuf_watermark(int seconds) | |||
1065 | track that fits, in which case we should avoid constant buffer | 1058 | track that fits, in which case we should avoid constant buffer |
1066 | low events */ | 1059 | low events */ |
1067 | if (track_list_count() > 1) | 1060 | if (track_list_count() > 1) |
1068 | bytes = info.filesize + 1; | 1061 | bytes = buf_filesize(info.audio_hid) + 1; |
1069 | } | 1062 | } |
1070 | } | 1063 | } |
1071 | else | 1064 | else |
@@ -1613,7 +1606,7 @@ static bool audio_start_codec(bool auto_skip) | |||
1613 | id3_write(CODEC_ID3, cur_id3); | 1606 | id3_write(CODEC_ID3, cur_id3); |
1614 | 1607 | ||
1615 | ci.audio_hid = info.audio_hid; | 1608 | ci.audio_hid = info.audio_hid; |
1616 | ci.filesize = info.filesize; | 1609 | ci.filesize = buf_filesize(info.audio_hid); |
1617 | buf_set_base_handle(info.audio_hid); | 1610 | buf_set_base_handle(info.audio_hid); |
1618 | 1611 | ||
1619 | /* All required data is now available for the codec */ | 1612 | /* All required data is now available for the codec */ |
@@ -1870,33 +1863,12 @@ static int audio_load_track(void) | |||
1870 | playlist_peek_offset); | 1863 | playlist_peek_offset); |
1871 | 1864 | ||
1872 | /* Get track name from current playlist read position */ | 1865 | /* Get track name from current playlist read position */ |
1873 | int fd = -1; | 1866 | char path_buf[MAX_PATH + 1]; |
1874 | char name_buf[MAX_PATH + 1]; | 1867 | const char *path = playlist_peek(playlist_peek_offset, |
1875 | const char *trackname; | 1868 | path_buf, |
1876 | 1869 | sizeof (path_buf)); | |
1877 | while (1) | ||
1878 | { | ||
1879 | trackname = playlist_peek(playlist_peek_offset, name_buf, | ||
1880 | sizeof (name_buf)); | ||
1881 | |||
1882 | if (!trackname) | ||
1883 | break; | ||
1884 | |||
1885 | /* Test for broken playlists by probing for the files */ | ||
1886 | fd = open(trackname, O_RDONLY); | ||
1887 | if (fd >= 0) | ||
1888 | break; | ||
1889 | |||
1890 | logf("Open failed"); | ||
1891 | /* Skip invalid entry from playlist */ | ||
1892 | playlist_skip_entry(NULL, playlist_peek_offset); | ||
1893 | |||
1894 | /* Sync the playlist if it isn't finished */ | ||
1895 | if (playlist_peek(playlist_peek_offset, NULL, 0)) | ||
1896 | playlist_next(0); | ||
1897 | } | ||
1898 | 1870 | ||
1899 | if (!trackname) | 1871 | if (!path) |
1900 | { | 1872 | { |
1901 | /* No track - exhausted the playlist entries */ | 1873 | /* No track - exhausted the playlist entries */ |
1902 | logf("End-of-playlist"); | 1874 | logf("End-of-playlist"); |
@@ -1920,7 +1892,7 @@ static int audio_load_track(void) | |||
1920 | 1892 | ||
1921 | /* Successfully opened the file - get track metadata */ | 1893 | /* Successfully opened the file - get track metadata */ |
1922 | if (filling == STATE_FULL || | 1894 | if (filling == STATE_FULL || |
1923 | (info.id3_hid = bufopen(trackname, 0, TYPE_ID3, NULL)) < 0) | 1895 | (info.id3_hid = bufopen(path, 0, TYPE_ID3, NULL)) < 0) |
1924 | { | 1896 | { |
1925 | /* Buffer or track list is full */ | 1897 | /* Buffer or track list is full */ |
1926 | struct mp3entry *ub_id3; | 1898 | struct mp3entry *ub_id3; |
@@ -1929,9 +1901,15 @@ static int audio_load_track(void) | |||
1929 | 1901 | ||
1930 | /* Load the metadata for the first unbuffered track */ | 1902 | /* Load the metadata for the first unbuffered track */ |
1931 | ub_id3 = id3_get(UNBUFFERED_ID3); | 1903 | ub_id3 = id3_get(UNBUFFERED_ID3); |
1932 | id3_mutex_lock(); | 1904 | |
1933 | get_metadata(ub_id3, fd, trackname); | 1905 | int fd = open(path, O_RDONLY); |
1934 | id3_mutex_unlock(); | 1906 | if (fd >= 0) |
1907 | { | ||
1908 | id3_mutex_lock(); | ||
1909 | get_metadata(ub_id3, fd, path); | ||
1910 | id3_mutex_unlock(); | ||
1911 | close(fd); | ||
1912 | } | ||
1935 | 1913 | ||
1936 | if (filling != STATE_FULL) | 1914 | if (filling != STATE_FULL) |
1937 | { | 1915 | { |
@@ -1944,8 +1922,6 @@ static int audio_load_track(void) | |||
1944 | } | 1922 | } |
1945 | else | 1923 | else |
1946 | { | 1924 | { |
1947 | info.filesize = filesize(fd); | ||
1948 | |||
1949 | if (!track_list_commit_info(&info)) | 1925 | if (!track_list_commit_info(&info)) |
1950 | { | 1926 | { |
1951 | track_list_free_info(&info); | 1927 | track_list_free_info(&info); |
@@ -1957,7 +1933,6 @@ static int audio_load_track(void) | |||
1957 | track_list.in_progress_hid = info.self_hid; | 1933 | track_list.in_progress_hid = info.self_hid; |
1958 | } | 1934 | } |
1959 | 1935 | ||
1960 | close(fd); | ||
1961 | return LOAD_TRACK_OK; | 1936 | return LOAD_TRACK_OK; |
1962 | } | 1937 | } |
1963 | 1938 | ||
@@ -2050,23 +2025,23 @@ static int audio_finish_load_track(struct track_info *infop) | |||
2050 | #endif /* HAVE_CODEC_BUFFERING */ | 2025 | #endif /* HAVE_CODEC_BUFFERING */ |
2051 | 2026 | ||
2052 | /** Finally, load the audio **/ | 2027 | /** Finally, load the audio **/ |
2053 | size_t file_offset = 0; | 2028 | off_t file_offset = 0; |
2054 | 2029 | ||
2055 | if (track_id3->elapsed > track_id3->length) | 2030 | if (track_id3->elapsed > track_id3->length) |
2056 | track_id3->elapsed = 0; | 2031 | track_id3->elapsed = 0; |
2057 | 2032 | ||
2058 | if ((off_t)track_id3->offset >= infop->filesize) | 2033 | if ((off_t)track_id3->offset >= buf_filesize(infop->audio_hid)) |
2059 | track_id3->offset = 0; | 2034 | track_id3->offset = 0; |
2060 | 2035 | ||
2061 | logf("%s: set offset for %s to %lu\n", __func__, | 2036 | logf("%s: set offset for %s to %lu\n", __func__, |
2062 | track_id3->title, (unsigned long)track_id3->offset); | 2037 | track_id3->title, track_id3->offset); |
2063 | 2038 | ||
2064 | /* Adjust for resume rewind so we know what to buffer - starting the codec | 2039 | /* Adjust for resume rewind so we know what to buffer - starting the codec |
2065 | calls it again, so we don't save it (and they shouldn't accumulate) */ | 2040 | calls it again, so we don't save it (and they shouldn't accumulate) */ |
2066 | unsigned long elapsed, offset; | 2041 | unsigned long elapsed, offset; |
2067 | resume_rewind_adjust_progress(track_id3, &elapsed, &offset); | 2042 | resume_rewind_adjust_progress(track_id3, &elapsed, &offset); |
2068 | 2043 | ||
2069 | logf("%s: Set resume for %s to %lu %lX", __func__, | 2044 | logf("%s: Set resume for %s to %lu %lu", __func__, |
2070 | track_id3->title, elapsed, offset); | 2045 | track_id3->title, elapsed, offset); |
2071 | 2046 | ||
2072 | enum data_type audiotype = rbcodec_format_is_atomic(track_id3->codectype) ? | 2047 | enum data_type audiotype = rbcodec_format_is_atomic(track_id3->codectype) ? |
@@ -3049,7 +3024,7 @@ static void audio_on_ff_rewind(long time) | |||
3049 | 3024 | ||
3050 | /* Set the codec API to the correct metadata and track info */ | 3025 | /* Set the codec API to the correct metadata and track info */ |
3051 | ci.audio_hid = cur_info.audio_hid; | 3026 | ci.audio_hid = cur_info.audio_hid; |
3052 | ci.filesize = cur_info.filesize; | 3027 | ci.filesize = buf_filesize(cur_info.audio_hid); |
3053 | buf_set_base_handle(cur_info.audio_hid); | 3028 | buf_set_base_handle(cur_info.audio_hid); |
3054 | } | 3029 | } |
3055 | 3030 | ||
@@ -3343,9 +3318,9 @@ static void buffer_event_finished_callback(unsigned short id, void *ev_data) | |||
3343 | { | 3318 | { |
3344 | (void)id; | 3319 | (void)id; |
3345 | int hid = *(const int *)ev_data; | 3320 | int hid = *(const int *)ev_data; |
3346 | const enum data_type htype = buf_handle_data_type(hid); | 3321 | int htype = buf_handle_data_type(hid); |
3347 | 3322 | ||
3348 | logf("handle %d finished buffering (type:%u)", hid, (unsigned)htype); | 3323 | logf("handle %d finished buffering (type:%d)", hid, htype); |
3349 | 3324 | ||
3350 | /* Limit queue traffic */ | 3325 | /* Limit queue traffic */ |
3351 | switch (htype) | 3326 | switch (htype) |
diff --git a/apps/plugin.h b/apps/plugin.h index c96c4ac899..a8e7c2af64 100644 --- a/apps/plugin.h +++ b/apps/plugin.h | |||
@@ -925,7 +925,7 @@ struct plugin_api { | |||
925 | 925 | ||
926 | #if (CONFIG_CODEC == SWCODEC) | 926 | #if (CONFIG_CODEC == SWCODEC) |
927 | /* buffering API */ | 927 | /* buffering API */ |
928 | int (*bufopen)(const char *file, size_t offset, enum data_type type, | 928 | int (*bufopen)(const char *file, off_t offset, enum data_type type, |
929 | void *user_data); | 929 | void *user_data); |
930 | int (*bufalloc)(const void *src, size_t size, enum data_type type); | 930 | int (*bufalloc)(const void *src, size_t size, enum data_type type); |
931 | bool (*bufclose)(int handle_id); | 931 | bool (*bufclose)(int handle_id); |