python-vlc-player 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,258 @@
1
+ import vlc
2
+ from tkinter import *
3
+ import tkinter.ttk as ttk
4
+ from tkinter import filedialog, messagebox
5
+ import os
6
+ import sys
7
+ import threading
8
+ from time import sleep
9
+
10
+ class Media_Player:
11
+ def __init__(self , app):
12
+
13
+ self.instance = vlc.Instance()
14
+ self.player = self.instance.media_player_new()
15
+
16
+ self.is_paused = False
17
+ self.media = None
18
+ self.user_dragging = False
19
+ self.is_fullscreen = False
20
+
21
+ self.filename = ''
22
+
23
+ self.update_thread_started = False
24
+
25
+ self.app = app
26
+
27
+ self.app.minsize(900, 500)
28
+ self.app.geometry('1100x600')
29
+ self.app.title('video-player')
30
+
31
+
32
+ self.video_output = Frame(self.app, bg='black')
33
+ self.video_output.pack(fill=BOTH, expand=True)
34
+
35
+ self.cover_overlay = Label(self.video_output, bg="black")
36
+ self.cover_overlay.place(relx=0.5, rely=0.5, anchor=CENTER)
37
+
38
+ self.time_frame = Frame(app)
39
+ self.time_frame.pack()
40
+
41
+ self.slidet = ttk.Scale(self.time_frame, from_=0,to=1000, length=1650)
42
+ self.slidet.pack()
43
+
44
+ self.slidet.bind("<ButtonPress-1>", self.start_drag)
45
+ self.slidet.bind("<ButtonRelease-1>", self.stop_drag)
46
+
47
+ self.contoroll_frame = Frame(self.app, bg='gray')
48
+ self.contoroll_frame.pack(side=LEFT)
49
+
50
+ self.open_video = ttk.Button(self.contoroll_frame, text='Open', command=self.open_file)
51
+ self.open_video.pack(side=LEFT)
52
+
53
+ self.play_video = ttk.Button(self.contoroll_frame, text='Play', state=DISABLED, command=self.play_pause)
54
+ self.play_video.pack(side=LEFT)
55
+
56
+ self.stop_video = ttk.Button(self.contoroll_frame, text='Stop', state=DISABLED, command=self.stop)
57
+ self.stop_video.pack(side=LEFT)
58
+
59
+ self.screenshot = ttk.Button(self.contoroll_frame, text="Screenshot", command=self.take_snapshot, state=DISABLED)
60
+ self.screenshot.pack(side=LEFT)
61
+
62
+ ttk.Label(self.contoroll_frame, text='Speed').pack(side=LEFT,pady=5, padx=5)
63
+
64
+ self.speed_var = DoubleVar(value=1.0)
65
+
66
+ self.speed_scalle = ttk.Scale(self.contoroll_frame, from_=0.5, to=2.0, length=200, variable=self.speed_var, command=self.change_speed)
67
+ self.speed_scalle.pack(side=LEFT)
68
+
69
+ ttk.Label(self.contoroll_frame, text="Vol").pack(side=LEFT,pady=5, padx=5)
70
+
71
+ self.sond_var = DoubleVar(value=40)
72
+
73
+ self.sond_scalle = ttk.Scale(self.contoroll_frame, from_=0, to=200, length=200, command=self.on_volume_change, variable=self.sond_var)
74
+ self.sond_scalle.pack(side=LEFT)
75
+
76
+ self.player.audio_set_volume(40)
77
+
78
+ self.time_label = Label(self.app, text='00:00 / 00:00')
79
+ self.time_label.pack(side=LEFT,pady=5, padx=5)
80
+
81
+ self.status_label = ttk.Label(self.contoroll_frame, text='No media loaded')
82
+ self.status_label.pack(side=LEFT,pady=5, padx=5)
83
+
84
+
85
+ def seek_relative(self, seconds):
86
+ if not self.player.get_media():
87
+ return
88
+ current = self.player.get_time()
89
+ new_time = max(0, current + seconds * 1000)
90
+ self.player.set_time(int(new_time))
91
+
92
+ def change_volume_relative(self, delta):
93
+ current = self.player.audio_get_volume()
94
+ if current == -1:
95
+ current = 0
96
+ new_vol = max(0, min(200, current + delta))
97
+ self.sond_scalle.set(new_vol)
98
+ self.player.audio_set_volume(new_vol)
99
+
100
+ def exit_fullscreen(self):
101
+ if self.is_fullscreen:
102
+ self.is_fullscreen = False
103
+ self.app.attributes("-fullscreen", False)
104
+
105
+ def toggle_fullscreen(self):
106
+ self.is_fullscreen = not self.is_fullscreen
107
+ self.app.attributes("-fullscreen", self.is_fullscreen)
108
+
109
+ def open_file(self):
110
+ self.player.stop()
111
+ self.slidet.set(0)
112
+ filetypes = [
113
+ ("Video files", "*.mp4 *.mkv *.avi *.mov *.flv *.wmv"),
114
+ ("All files", "*.*"),
115
+ ('Audio files', '*.mp3 *.wma *.aac *.ogg *.ra *.m4a')
116
+ ]
117
+ self.filename = filedialog.askopenfilename(
118
+ title="📂",
119
+ filetypes=filetypes
120
+ )
121
+ if not self.filename:
122
+ return
123
+
124
+ ext = os.path.splitext(self.filename)[1].lower()
125
+
126
+ if not os.path.exists(self.filename):
127
+ messagebox.showerror("خطا", "فایل پیدا نشد!")
128
+ return
129
+ try:
130
+
131
+ # ساخت رسانه جدید و اتصال به پلیر
132
+ media = self.instance.media_new(self.filename)
133
+ self.player.set_media(media)
134
+
135
+ self._set_video_output()
136
+
137
+ # بروزرسانی وضعیت
138
+ self.status_label.config(text=os.path.basename(self.filename))
139
+ self.play_video.config(state=NORMAL, text="Pause")
140
+ self.stop_video.config(state=NORMAL)
141
+ self.screenshot.config(state=NORMAL)
142
+ self.is_paused = False
143
+ # شروع پخش
144
+ self.start_update_thread()
145
+
146
+ #if ext in [".mp3", ".m4a", ".aac", ".ogg", ".wma"]:
147
+ # self.show_audio_cover(filename)
148
+ #else:
149
+ # self.hide_cover()
150
+
151
+ self.player.play()
152
+
153
+ except Exception as e:
154
+ messagebox.showerror("خطا در پخش", str(e))
155
+
156
+ def _set_video_output(self):
157
+ if not self.video_output.winfo_ismapped():
158
+ return
159
+ handle = self.video_output.winfo_id()
160
+ if sys.platform.startswith("win"):
161
+ self.player.set_hwnd(handle)
162
+
163
+ else:
164
+ if sys.platform == "darwin":
165
+ from ctypes import c_void_p
166
+ self.player.set_nsobject(c_void_p(handle))
167
+ else:
168
+ self.player.set_xwindow(handle)
169
+
170
+ def play_pause(self):
171
+ if self.player.is_playing():
172
+ self.player.pause()
173
+ self.play_video.config(text="Play")
174
+ self.is_paused = True
175
+ self.start_update_thread()
176
+ else:
177
+ state = self.player.get_state()
178
+ if state in (vlc.State.Ended, vlc.State.Stopped):
179
+ self.player.stop()
180
+ self.player.play()
181
+ else:
182
+ self.player.play()
183
+ self.play_video.config(text="Pause")
184
+ self.is_paused = False
185
+
186
+ def stop(self):
187
+ #if media is None:
188
+ # return
189
+ self.player.stop()
190
+ self.play_video.config(text="Play")
191
+ self.is_paused = False
192
+ self.slidet.set(0)
193
+
194
+ def on_volume_change(self, event):
195
+ try:
196
+ vol = int(float(event))
197
+ self.player.audio_set_volume(vol)
198
+ except:
199
+ pass
200
+
201
+ def change_speed(self, event):
202
+ self.player.set_rate(float(event))
203
+
204
+ def start_drag(self, event):
205
+ self.user_dragging = True
206
+
207
+ def stop_drag(self, event):
208
+ if self.filename == '':
209
+ self.slidet.set(0)
210
+ else:
211
+ self.user_dragging = False
212
+ self.new_position = self.slidet.get() / 1000.0
213
+ self.player.set_position(self.new_position)
214
+
215
+ def update_thread(self):
216
+ while True:
217
+ sleep(0.5)
218
+ try:
219
+ if not self.user_dragging:
220
+ self.pos = self.player.get_position()
221
+ self.current_time = self.player.get_time() / 1000
222
+ self.app.after(0, self.update_ui, self.pos, self.current_time)
223
+ except Exception:
224
+ break
225
+
226
+ def update_ui(self, pos, current_time):
227
+ if pos > 0:
228
+ duration = int(self.player.get_length()/1000)
229
+ self.slidet.set(int(pos * 1000))
230
+
231
+ mins, secs = divmod(int(current_time), 60)
232
+ total_mins, total_secs = divmod(int(duration), 60)
233
+
234
+ self.time_label.config(text=f"{mins:02}:{secs:02} / {total_mins:02}:{total_secs:02}")
235
+
236
+ def take_snapshot(self):
237
+ self.player.video_take_snapshot(0, "snapshot.png", 0, 0)
238
+
239
+ def start_update_thread(self):
240
+ if self.update_thread_started:
241
+ return
242
+
243
+ self.update_thread_started = True
244
+
245
+ threading.Thread(
246
+ target=self.update_thread,
247
+ daemon=True
248
+ ).start()
249
+
250
+
251
+
252
+
253
+ if __name__ == '__main__':
254
+ root = Tk()
255
+
256
+ player = Media_Player(root)
257
+
258
+ root.mainloop()
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: python_vlc_player
3
+ Version: 0.0.1
4
+ Summary: A packege to make a player in python
5
+ Author: Edalat
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.9
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENCE
12
+ Requires-Dist: python-vlc
13
+ Dynamic: license-file
@@ -0,0 +1,7 @@
1
+ python_vlc_player/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ python_vlc_player/player.py,sha256=02-7EtXE5PpTYOA8k3yIqUhLR9noj3yxwEuV2NV9wKI,8494
3
+ python_vlc_player-0.0.1.dist-info/licenses/LICENCE,sha256=PmkEOcF-Jq2TXaLSrv8OTz3jB4Ci1AwWnL4Hs-gBE3o,1084
4
+ python_vlc_player-0.0.1.dist-info/METADATA,sha256=JVJMk4z_cvu8Ns-5DhjzMX-P1qL2e1vg3MSkFP7W5Yw,387
5
+ python_vlc_player-0.0.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
6
+ python_vlc_player-0.0.1.dist-info/top_level.txt,sha256=TZ3NdvC7vFH4oIVH47VtauF81tM8eGZbD46JHmF0P14,18
7
+ python_vlc_player-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 mohamad reza amiri noor
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ python_vlc_player