diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/mpeg.c | 168 |
1 files changed, 62 insertions, 106 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c index e801f9c845..5a199a4169 100644 --- a/firmware/mpeg.c +++ b/firmware/mpeg.c | |||
@@ -102,11 +102,10 @@ struct id3tag | |||
102 | { | 102 | { |
103 | struct mp3entry id3; | 103 | struct mp3entry id3; |
104 | int mempos; | 104 | int mempos; |
105 | bool used; | 105 | int load_ahead_index; |
106 | }; | 106 | }; |
107 | 107 | ||
108 | static struct id3tag *id3tags[MAX_ID3_TAGS]; | 108 | static struct id3tag id3tags[MAX_ID3_TAGS]; |
109 | static struct id3tag _id3tags[MAX_ID3_TAGS]; | ||
110 | 109 | ||
111 | static bool v1first = false; | 110 | static bool v1first = false; |
112 | 111 | ||
@@ -132,71 +131,35 @@ static void debug_tags(void) | |||
132 | 131 | ||
133 | for(i = 0;i < MAX_ID3_TAGS;i++) | 132 | for(i = 0;i < MAX_ID3_TAGS;i++) |
134 | { | 133 | { |
135 | DEBUGF("id3tags[%d]: %08x", i, id3tags[i]); | 134 | DEBUGF("%d - %s\n", i, id3tags[i].id3.path); |
136 | if(id3tags[i]) | ||
137 | DEBUGF(" - %s", id3tags[i]->id3.path); | ||
138 | DEBUGF("\n"); | ||
139 | } | 135 | } |
140 | DEBUGF("read: %d, write :%d\n", tag_read_idx, tag_write_idx); | 136 | DEBUGF("read: %d, write :%d\n", tag_read_idx, tag_write_idx); |
141 | DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory()); | 137 | DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory()); |
142 | #endif /* #ifdef DEBUG_TAGS */ | 138 | #endif /* #ifdef DEBUG_TAGS */ |
143 | } | 139 | } |
144 | 140 | ||
145 | static bool append_tag(struct id3tag *tag) | ||
146 | { | ||
147 | if(num_tracks_in_memory() < MAX_ID3_TAGS - 1) | ||
148 | { | ||
149 | id3tags[tag_write_idx] = tag; | ||
150 | tag_write_idx = (tag_write_idx+1) & MAX_ID3_TAGS_MASK; | ||
151 | debug_tags(); | ||
152 | return true; | ||
153 | } | ||
154 | else | ||
155 | { | ||
156 | DEBUGF("Tag memory is full\n"); | ||
157 | return false; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | static void remove_current_tag(void) | 141 | static void remove_current_tag(void) |
162 | { | 142 | { |
163 | int oldidx = tag_read_idx; | ||
164 | |||
165 | if(num_tracks_in_memory() > 0) | 143 | if(num_tracks_in_memory() > 0) |
166 | { | 144 | { |
167 | /* First move the index, so nobody tries to access the tag */ | 145 | /* First move the index, so nobody tries to access the tag */ |
168 | tag_read_idx = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; | 146 | tag_read_idx = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; |
169 | |||
170 | /* Now delete it */ | ||
171 | id3tags[oldidx]->used = false; | ||
172 | id3tags[oldidx] = NULL; | ||
173 | debug_tags(); | 147 | debug_tags(); |
174 | } | 148 | } |
149 | else | ||
150 | { | ||
151 | DEBUGF("remove_current_tag: no tracks to remove\n"); | ||
152 | } | ||
175 | } | 153 | } |
176 | 154 | ||
177 | static void remove_all_non_current_tags(void) | 155 | static void remove_all_non_current_tags(void) |
178 | { | 156 | { |
179 | int i = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; | ||
180 | |||
181 | while (i != tag_write_idx) | ||
182 | { | ||
183 | id3tags[i]->used = false; | ||
184 | id3tags[i] = NULL; | ||
185 | |||
186 | i = (i+1) & MAX_ID3_TAGS_MASK; | ||
187 | } | ||
188 | |||
189 | tag_write_idx = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; | 157 | tag_write_idx = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; |
190 | debug_tags(); | 158 | debug_tags(); |
191 | } | 159 | } |
192 | 160 | ||
193 | static void remove_all_tags(void) | 161 | static void remove_all_tags(void) |
194 | { | 162 | { |
195 | int i; | ||
196 | |||
197 | for(i = 0;i < MAX_ID3_TAGS;i++) | ||
198 | remove_current_tag(); | ||
199 | |||
200 | tag_write_idx = tag_read_idx; | 163 | tag_write_idx = tag_read_idx; |
201 | 164 | ||
202 | debug_tags(); | 165 | debug_tags(); |
@@ -511,7 +474,7 @@ static int get_unplayed_space_current_song(void) | |||
511 | { | 474 | { |
512 | int track_offset = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; | 475 | int track_offset = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; |
513 | 476 | ||
514 | space = id3tags[track_offset]->mempos - mp3buf_read; | 477 | space = id3tags[track_offset].mempos - mp3buf_read; |
515 | } | 478 | } |
516 | else | 479 | else |
517 | { | 480 | { |
@@ -698,7 +661,7 @@ void rec_tick(void) | |||
698 | 661 | ||
699 | void playback_tick(void) | 662 | void playback_tick(void) |
700 | { | 663 | { |
701 | id3tags[tag_read_idx]->id3.elapsed += | 664 | id3tags[tag_read_idx].id3.elapsed += |
702 | (current_tick - last_dma_tick) * 1000 / HZ; | 665 | (current_tick - last_dma_tick) * 1000 / HZ; |
703 | last_dma_tick = current_tick; | 666 | last_dma_tick = current_tick; |
704 | } | 667 | } |
@@ -725,9 +688,9 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
725 | mp3buf_read = 0; | 688 | mp3buf_read = 0; |
726 | 689 | ||
727 | /* First, check if we are on a track boundary */ | 690 | /* First, check if we are on a track boundary */ |
728 | if (num_tracks_in_memory() > 0) | 691 | if (num_tracks_in_memory() > 1) |
729 | { | 692 | { |
730 | if (mp3buf_read == id3tags[track_offset]->mempos) | 693 | if (mp3buf_read == id3tags[track_offset].mempos) |
731 | { | 694 | { |
732 | queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0); | 695 | queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0); |
733 | track_offset = (track_offset+1) & MAX_ID3_TAGS_MASK; | 696 | track_offset = (track_offset+1) & MAX_ID3_TAGS_MASK; |
@@ -754,19 +717,19 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
754 | if (num_tracks_in_memory() > 1) | 717 | if (num_tracks_in_memory() > 1) |
755 | { | 718 | { |
756 | /* will we move across the track boundary? */ | 719 | /* will we move across the track boundary? */ |
757 | if (( mp3buf_read < id3tags[track_offset]->mempos ) && | 720 | if (( mp3buf_read < id3tags[track_offset].mempos ) && |
758 | ((mp3buf_read+last_dma_chunk_size) > | 721 | ((mp3buf_read+last_dma_chunk_size) > |
759 | id3tags[track_offset]->mempos )) | 722 | id3tags[track_offset].mempos )) |
760 | { | 723 | { |
761 | /* Make sure that we end exactly on the boundary */ | 724 | /* Make sure that we end exactly on the boundary */ |
762 | last_dma_chunk_size = id3tags[track_offset]->mempos | 725 | last_dma_chunk_size = id3tags[track_offset].mempos |
763 | - mp3buf_read; | 726 | - mp3buf_read; |
764 | } | 727 | } |
765 | } | 728 | } |
766 | 729 | ||
767 | *psize = last_dma_chunk_size & 0xffff; | 730 | *psize = last_dma_chunk_size & 0xffff; |
768 | *ppbuf = mp3buf + mp3buf_read; | 731 | *ppbuf = mp3buf + mp3buf_read; |
769 | id3tags[tag_read_idx]->id3.offset += last_dma_chunk_size; | 732 | id3tags[tag_read_idx].id3.offset += last_dma_chunk_size; |
770 | 733 | ||
771 | /* Update the watermark debug level */ | 734 | /* Update the watermark debug level */ |
772 | if(unplayed_space_left < lowest_watermark_level) | 735 | if(unplayed_space_left < lowest_watermark_level) |
@@ -804,35 +767,24 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
804 | 767 | ||
805 | static int add_track_to_tag_list(const char *filename) | 768 | static int add_track_to_tag_list(const char *filename) |
806 | { | 769 | { |
807 | struct id3tag *t = NULL; | 770 | if(num_tracks_in_memory() >= MAX_ID3_TAGS) |
808 | int i; | ||
809 | |||
810 | /* find a free tag */ | ||
811 | for (i=0; i < MAX_ID3_TAGS_MASK; i++ ) | ||
812 | if ( !_id3tags[i].used ) | ||
813 | t = &_id3tags[i]; | ||
814 | if(t) | ||
815 | { | 771 | { |
816 | /* grab id3 tag of new file and | 772 | DEBUGF("Tag memory is full\n"); |
817 | remember where in memory it starts */ | 773 | return -1; |
818 | if(mp3info(&(t->id3), filename, v1first)) | ||
819 | { | ||
820 | DEBUGF("Bad mp3\n"); | ||
821 | return -1; | ||
822 | } | ||
823 | t->mempos = mp3buf_write; | ||
824 | t->id3.elapsed = 0; | ||
825 | if(!append_tag(t)) | ||
826 | { | ||
827 | DEBUGF("Tag list is full\n"); | ||
828 | } | ||
829 | else | ||
830 | t->used = true; | ||
831 | } | 774 | } |
832 | else | 775 | |
776 | /* grab id3 tag of new file and | ||
777 | remember where in memory it starts */ | ||
778 | if(mp3info(&id3tags[tag_write_idx].id3, filename, v1first)) | ||
833 | { | 779 | { |
834 | DEBUGF("No memory available for id3 tag"); | 780 | DEBUGF("Bad mp3\n"); |
781 | return -1; | ||
835 | } | 782 | } |
783 | id3tags[tag_write_idx].mempos = mp3buf_write; | ||
784 | id3tags[tag_write_idx].id3.elapsed = 0; | ||
785 | |||
786 | tag_write_idx = (tag_write_idx+1) & MAX_ID3_TAGS_MASK; | ||
787 | debug_tags(); | ||
836 | return 0; | 788 | return 0; |
837 | } | 789 | } |
838 | 790 | ||
@@ -842,19 +794,20 @@ static int new_file(int steps) | |||
842 | int start = 0; | 794 | int start = 0; |
843 | int i; | 795 | int i; |
844 | 796 | ||
845 | /* Find out how many steps to advance. Each loaded tag has a "steps" member | 797 | /* Find out how many steps to advance. The load_ahead_index field tells |
846 | that tells us how many playlist entries it had to skip to get to | 798 | us how many playlist entries it had to skip to get to a valid one. |
847 | a valid one. We add those together to find out where to start. */ | 799 | We add those together to find out where to start. */ |
848 | i = tag_read_idx; | 800 | if(steps > 0 && num_tracks_in_memory() > 1) |
849 | while(i != tag_write_idx) | ||
850 | { | 801 | { |
851 | start += id3tags[i]->id3.index; | 802 | /* Begin with the song after the currently playing one */ |
852 | i = (i+1) & MAX_ID3_TAGS_MASK; | 803 | i = (tag_read_idx + 1) & MAX_ID3_TAGS_MASK; |
804 | while(i != tag_write_idx) | ||
805 | { | ||
806 | start += id3tags[i].load_ahead_index; | ||
807 | i = (i+1) & MAX_ID3_TAGS_MASK; | ||
808 | } | ||
853 | } | 809 | } |
854 | 810 | ||
855 | if (start < 0) | ||
856 | start = 0; | ||
857 | |||
858 | do { | 811 | do { |
859 | char *trackname; | 812 | char *trackname; |
860 | 813 | ||
@@ -862,7 +815,7 @@ static int new_file(int steps) | |||
862 | if ( !trackname ) | 815 | if ( !trackname ) |
863 | return -1; | 816 | return -1; |
864 | 817 | ||
865 | DEBUGF("playing %s\n", trackname); | 818 | DEBUGF("Loading %s\n", trackname); |
866 | 819 | ||
867 | mpeg_file = open(trackname, O_RDONLY); | 820 | mpeg_file = open(trackname, O_RDONLY); |
868 | if(mpeg_file < 0) { | 821 | if(mpeg_file < 0) { |
@@ -879,7 +832,10 @@ static int new_file(int steps) | |||
879 | if(add_track_to_tag_list(trackname)) | 832 | if(add_track_to_tag_list(trackname)) |
880 | { | 833 | { |
881 | /* Bad mp3 file */ | 834 | /* Bad mp3 file */ |
882 | steps++; | 835 | if(steps < 0) |
836 | steps--; | ||
837 | else | ||
838 | steps++; | ||
883 | close(mpeg_file); | 839 | close(mpeg_file); |
884 | mpeg_file = -1; | 840 | mpeg_file = -1; |
885 | } | 841 | } |
@@ -887,18 +843,19 @@ static int new_file(int steps) | |||
887 | { | 843 | { |
888 | /* skip past id3v2 tag */ | 844 | /* skip past id3v2 tag */ |
889 | lseek(mpeg_file, | 845 | lseek(mpeg_file, |
890 | id3tags[new_tag_idx]->id3.first_frame_offset, | 846 | id3tags[new_tag_idx].id3.first_frame_offset, |
891 | SEEK_SET); | 847 | SEEK_SET); |
892 | id3tags[new_tag_idx]->id3.index = steps; | 848 | id3tags[new_tag_idx].id3.index = steps; |
893 | id3tags[new_tag_idx]->id3.offset = 0; | 849 | id3tags[new_tag_idx].load_ahead_index = steps; |
850 | id3tags[new_tag_idx].id3.offset = 0; | ||
894 | 851 | ||
895 | if(id3tags[new_tag_idx]->id3.vbr) | 852 | if(id3tags[new_tag_idx].id3.vbr) |
896 | /* Average bitrate * 1.5 */ | 853 | /* Average bitrate * 1.5 */ |
897 | recalculate_watermark( | 854 | recalculate_watermark( |
898 | (id3tags[new_tag_idx]->id3.bitrate * 3) / 2); | 855 | (id3tags[new_tag_idx].id3.bitrate * 3) / 2); |
899 | else | 856 | else |
900 | recalculate_watermark( | 857 | recalculate_watermark( |
901 | id3tags[new_tag_idx]->id3.bitrate); | 858 | id3tags[new_tag_idx].id3.bitrate); |
902 | 859 | ||
903 | } | 860 | } |
904 | } | 861 | } |
@@ -930,8 +887,8 @@ static void update_playlist(void) | |||
930 | 887 | ||
931 | if (num_tracks_in_memory() > 0) | 888 | if (num_tracks_in_memory() > 0) |
932 | { | 889 | { |
933 | index = playlist_next(id3tags[tag_read_idx]->id3.index); | 890 | index = playlist_next(id3tags[tag_read_idx].id3.index); |
934 | id3tags[tag_read_idx]->id3.index = index; | 891 | id3tags[tag_read_idx].id3.index = index; |
935 | } | 892 | } |
936 | } | 893 | } |
937 | 894 | ||
@@ -1133,7 +1090,7 @@ static void mpeg_thread(void) | |||
1133 | 1090 | ||
1134 | /* mid-song resume? */ | 1091 | /* mid-song resume? */ |
1135 | if (start_offset) { | 1092 | if (start_offset) { |
1136 | struct mp3entry* id3 = &id3tags[tag_read_idx]->id3; | 1093 | struct mp3entry* id3 = &id3tags[tag_read_idx].id3; |
1137 | lseek(mpeg_file, start_offset, SEEK_SET); | 1094 | lseek(mpeg_file, start_offset, SEEK_SET); |
1138 | id3->offset = start_offset; | 1095 | id3->offset = start_offset; |
1139 | set_elapsed(id3); | 1096 | set_elapsed(id3); |
@@ -1141,7 +1098,7 @@ static void mpeg_thread(void) | |||
1141 | else { | 1098 | else { |
1142 | /* skip past id3v2 tag */ | 1099 | /* skip past id3v2 tag */ |
1143 | lseek(mpeg_file, | 1100 | lseek(mpeg_file, |
1144 | id3tags[tag_read_idx]->id3.first_frame_offset, | 1101 | id3tags[tag_read_idx].id3.first_frame_offset, |
1145 | SEEK_SET); | 1102 | SEEK_SET); |
1146 | 1103 | ||
1147 | } | 1104 | } |
@@ -1204,7 +1161,7 @@ static void mpeg_thread(void) | |||
1204 | mp3_play_pause(false); | 1161 | mp3_play_pause(false); |
1205 | 1162 | ||
1206 | track_change(); | 1163 | track_change(); |
1207 | mp3buf_read = id3tags[tag_read_idx]->mempos; | 1164 | mp3buf_read = id3tags[tag_read_idx].mempos; |
1208 | last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); | 1165 | last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); |
1209 | mp3_play_data(mp3buf + mp3buf_read, last_dma_chunk_size, transfer_end); | 1166 | mp3_play_data(mp3buf + mp3buf_read, last_dma_chunk_size, transfer_end); |
1210 | dma_underrun = false; | 1167 | dma_underrun = false; |
@@ -1332,7 +1289,7 @@ static void mpeg_thread(void) | |||
1332 | 1289 | ||
1333 | while (i != j) | 1290 | while (i != j) |
1334 | { | 1291 | { |
1335 | curpos += id3tags[i]->id3.filesize; | 1292 | curpos += id3tags[i].id3.filesize; |
1336 | i = (i+1) & MAX_ID3_TAGS_MASK; | 1293 | i = (i+1) & MAX_ID3_TAGS_MASK; |
1337 | } | 1294 | } |
1338 | } | 1295 | } |
@@ -1437,7 +1394,7 @@ static void mpeg_thread(void) | |||
1437 | int next = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; | 1394 | int next = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; |
1438 | 1395 | ||
1439 | /* Reset the buffer */ | 1396 | /* Reset the buffer */ |
1440 | mp3buf_write = id3tags[next]->mempos; | 1397 | mp3buf_write = id3tags[next].mempos; |
1441 | 1398 | ||
1442 | /* Reset swapwrite unless we're still swapping current | 1399 | /* Reset swapwrite unless we're still swapping current |
1443 | track */ | 1400 | track */ |
@@ -2031,7 +1988,7 @@ struct mp3entry* mpeg_current_track() | |||
2031 | return &taginfo; | 1988 | return &taginfo; |
2032 | #else | 1989 | #else |
2033 | if(num_tracks_in_memory()) | 1990 | if(num_tracks_in_memory()) |
2034 | return &(id3tags[tag_read_idx]->id3); | 1991 | return &id3tags[tag_read_idx].id3; |
2035 | else | 1992 | else |
2036 | return NULL; | 1993 | return NULL; |
2037 | #endif /* #ifdef SIMULATOR */ | 1994 | #endif /* #ifdef SIMULATOR */ |
@@ -2043,7 +2000,7 @@ struct mp3entry* mpeg_next_track() | |||
2043 | return &taginfo; | 2000 | return &taginfo; |
2044 | #else | 2001 | #else |
2045 | if(num_tracks_in_memory() > 1) | 2002 | if(num_tracks_in_memory() > 1) |
2046 | return &(id3tags[(tag_read_idx+1) & MAX_ID3_TAGS_MASK]->id3); | 2003 | return &(id3tags[(tag_read_idx+1) & MAX_ID3_TAGS_MASK].id3); |
2047 | else | 2004 | else |
2048 | return NULL; | 2005 | return NULL; |
2049 | #endif /* #ifdef SIMULATOR */ | 2006 | #endif /* #ifdef SIMULATOR */ |
@@ -2692,7 +2649,6 @@ void mpeg_init(void) | |||
2692 | sizeof(mpeg_stack), mpeg_thread_name); | 2649 | sizeof(mpeg_stack), mpeg_thread_name); |
2693 | 2650 | ||
2694 | memset(id3tags, sizeof(id3tags), 0); | 2651 | memset(id3tags, sizeof(id3tags), 0); |
2695 | memset(_id3tags, sizeof(id3tags), 0); | ||
2696 | 2652 | ||
2697 | #if CONFIG_HWCODEC == MAS3587F | 2653 | #if CONFIG_HWCODEC == MAS3587F |
2698 | if(read_hw_mask() & PR_ACTIVE_HIGH) | 2654 | if(read_hw_mask() & PR_ACTIVE_HIGH) |