├── Screenshot.png ├── assets ├── album.png └── album0.png ├── requirements.txt ├── sounds ├── outfoxing.mp3 ├── param_viper.mp3 └── track_drums.mp3 ├── README.md └── main.py /Screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soris2000/Music-Player-Flet/HEAD/Screenshot.png -------------------------------------------------------------------------------- /assets/album.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soris2000/Music-Player-Flet/HEAD/assets/album.png -------------------------------------------------------------------------------- /assets/album0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soris2000/Music-Player-Flet/HEAD/assets/album0.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soris2000/Music-Player-Flet/HEAD/requirements.txt -------------------------------------------------------------------------------- /sounds/outfoxing.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soris2000/Music-Player-Flet/HEAD/sounds/outfoxing.mp3 -------------------------------------------------------------------------------- /sounds/param_viper.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soris2000/Music-Player-Flet/HEAD/sounds/param_viper.mp3 -------------------------------------------------------------------------------- /sounds/track_drums.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soris2000/Music-Player-Flet/HEAD/sounds/track_drums.mp3 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Music-Player-Flet 2 | A Music Player App made with Flet Framework 3 | 4 | #### Install All Packages from a requirements.txt File Using pip and Python: 5 | 6 | pip install -r requirements.txt 7 | 8 | #### Screenshot: 9 | ![Screenshot](Screenshot.png) 10 | 11 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import flet as ft 2 | from tinytag import TinyTag 3 | from math import pi 4 | 5 | index = 1 # index=0 pick_files_dialog 6 | state = "" 7 | 8 | tracks_list = [ 9 | "sounds/outfoxing.mp3", 10 | "sounds/param_viper.mp3", 11 | "sounds/track_drums.mp3", 12 | ] 13 | volume = 0.5 14 | 15 | 16 | def main(page: ft.Page): 17 | page.title = "Music Player" 18 | page.vertical_alignment = ft.MainAxisAlignment.CENTER 19 | page.horizontal_alignment = ft.CrossAxisAlignment.CENTER 20 | page.window_height = 400 21 | page.window_width = 750 22 | page.window_min_width = 750 23 | page.window_min_height = 400 24 | 25 | # ************************ Functions ****************************** 26 | def pick_files_result(e: ft.FilePickerResultEvent): 27 | global tracks_list 28 | if e.files: 29 | for f in e.files: 30 | src = f.path.replace("\\", "/") 31 | tracks_list.append(src) 32 | audio1 = ft.Audio( 33 | src=f"{src}", 34 | autoplay=False, 35 | volume=0.5, 36 | balance=0, 37 | on_position_changed=progress_change, 38 | on_state_changed=check_state, 39 | ) 40 | page.overlay.append(audio1) 41 | page.update() 42 | else: 43 | "Cancelled!" 44 | 45 | def check_state(e): 46 | global index 47 | if e.data == "completed": 48 | index = index + 1 49 | if index == len(page.overlay): 50 | index = 0 51 | new_track() 52 | btn_play.icon = ft.icons.PAUSE_CIRCLE 53 | page.update() 54 | 55 | def play_track(e): 56 | global index 57 | global state 58 | if state == "": 59 | state = "playing" 60 | btn_play.icon = ft.icons.PAUSE_CIRCLE 61 | page.overlay[index].play() 62 | elif state == "playing": 63 | state = "paused" 64 | btn_play.icon = ft.icons.PLAY_CIRCLE 65 | page.overlay[index].pause() 66 | else: # if state=="paused" 67 | state = "playing" 68 | btn_play.icon = ft.icons.PAUSE_CIRCLE 69 | page.overlay[index].resume() 70 | page.update() 71 | 72 | def new_track(): 73 | global index 74 | global state 75 | global volume 76 | disc_image.rotate.angle += pi * 2 77 | audio = TinyTag.get(page.overlay[index].src) 78 | track_name.value = audio.title 79 | track_artist.value = audio.artist 80 | current_time.value = "0:0" 81 | remaining_time.value = converter_time(audio.duration * 1000) 82 | progress_track.value = "0" 83 | if state == "playing": 84 | page.overlay[index].volume = volume 85 | page.overlay[index].play() 86 | 87 | def next_track(e): 88 | global index 89 | page.overlay[index].release() 90 | page.overlay[index].update() 91 | index = index + 1 92 | if index == len(page.overlay): 93 | index = 1 94 | new_track() 95 | page.update() 96 | 97 | def previous_track(e): 98 | global index 99 | page.overlay[index].release() 100 | page.overlay[index].update() 101 | index = index - 1 102 | if index == 0: 103 | index = len(page.overlay) - 1 104 | new_track() 105 | page.update() 106 | 107 | def volume_change(e): 108 | global index 109 | global volume 110 | v = e.control.value 111 | page.overlay[index].volume = 0.01 * v 112 | volume = 0.01 * v 113 | if v == 0: 114 | volume_icon.name = ft.icons.VOLUME_OFF 115 | elif 0 < v <= 50: 116 | volume_icon.name = ft.icons.VOLUME_DOWN 117 | elif 50 < v: 118 | volume_icon.name = ft.icons.VOLUME_UP 119 | page.update() 120 | 121 | def converter_time(millis): 122 | millis = int(millis) 123 | seconds = (millis / 1000) % 60 124 | seconds = int(seconds) 125 | minutes = (millis / (1000 * 60)) % 60 126 | minutes = int(minutes) 127 | return "%d:%d" % (minutes, seconds) 128 | 129 | def progress_change(e): 130 | global index 131 | audio = TinyTag.get(page.overlay[index].src) 132 | current_time.value = converter_time(e.data) 133 | remaining_time.value = converter_time((audio.duration * 1000) - int(e.data)) 134 | progress_track.value = (float(e.data) * 1.0) / float(audio.duration * 1000) 135 | page.update() 136 | 137 | # ***************** Initializing player music values ************** 138 | # load pick_files_dialog 139 | pick_files_dialog = ft.FilePicker(on_result=pick_files_result) 140 | page.overlay.append(pick_files_dialog) 141 | # Load tracks to Page overlay 142 | for i in range(0, len(tracks_list)): 143 | audio1 = ft.Audio( 144 | # src=f"sounds/{tracks_list[i]}", 145 | src=f"{tracks_list[i]}", 146 | autoplay=False, 147 | volume=0.5, 148 | balance=0, 149 | on_position_changed=progress_change, 150 | on_state_changed=check_state, 151 | ) 152 | page.overlay.append(audio1) 153 | 154 | audio_init = TinyTag.get(page.overlay[index].src) 155 | 156 | current_time = ft.Text(value="0:0") 157 | remaining_time = ft.Text(value=converter_time(audio_init.duration * 1000)) 158 | progress_track = ft.ProgressBar(width=400, value="0", height=8) 159 | track_name = ft.Text(value=audio_init.title) 160 | track_artist = ft.Text(value=audio_init.artist) 161 | btn_play = ft.IconButton( 162 | icon=ft.icons.PLAY_CIRCLE, icon_size=50, on_click=play_track 163 | ) 164 | volume_icon = ft.Icon(name=ft.icons.VOLUME_DOWN) 165 | 166 | disc_image = ft.Image( 167 | src=f"assets/album.png", 168 | width=180, 169 | height=180, 170 | fit=ft.ImageFit.CONTAIN, 171 | rotate=ft.transform.Rotate(0, alignment=ft.alignment.center), 172 | animate_rotation=ft.animation.Animation(300, ft.AnimationCurve.EASE_IN_CIRC), 173 | ) 174 | main_content = ft.Card( 175 | content=ft.Container( 176 | content=ft.Row( 177 | [ 178 | ft.Container(width=80, height=200), 179 | ft.Column( 180 | [ 181 | ft.ListTile( 182 | leading=ft.Icon(ft.icons.MUSIC_NOTE_ROUNDED), 183 | title=track_name, 184 | subtitle=track_artist, 185 | ), 186 | ft.Row( 187 | [current_time, progress_track, remaining_time], 188 | alignment=ft.MainAxisAlignment.END, 189 | ), 190 | ft.Row( 191 | [ 192 | ft.IconButton( 193 | icon=ft.icons.SKIP_PREVIOUS, 194 | icon_size=40, 195 | on_click=previous_track, 196 | ), 197 | btn_play, 198 | ft.IconButton( 199 | icon=ft.icons.SKIP_NEXT, 200 | icon_size=40, 201 | on_click=next_track, 202 | ), 203 | volume_icon, 204 | ft.Slider( 205 | width=150, 206 | active_color=ft.colors.WHITE60, 207 | min=0, 208 | max=100, 209 | divisions=100, 210 | value=50, 211 | label="{value}", 212 | on_change=volume_change, 213 | ), 214 | ft.IconButton( 215 | icon=ft.icons.PLAYLIST_ADD_ROUNDED, 216 | on_click=lambda _: pick_files_dialog.pick_files( 217 | allow_multiple=True, 218 | file_type=ft.FilePickerFileType.AUDIO, 219 | ), 220 | ), 221 | ], 222 | alignment=ft.MainAxisAlignment.END, 223 | ), 224 | ] 225 | ), 226 | ] 227 | ), 228 | ), 229 | right=0, 230 | width=580, 231 | color=ft.colors.ON_PRIMARY, 232 | height=180, 233 | ) 234 | 235 | stack = ft.Stack( 236 | controls=[ 237 | main_content, 238 | disc_image, 239 | ], 240 | width=680, 241 | height=300, 242 | ) 243 | 244 | page.add(stack) 245 | 246 | 247 | ft.app(target=main) 248 | --------------------------------------------------------------------------------