@@ -340,8 +340,14 @@ class MacAttack(QMainWindow):
340340 QTabBar::tab {
341341 background-color: #444444;
342342 color: white;
343- padding: 5px;
344- border-radius: 3px; /* Optional: rounded corners for tab buttons */
343+ padding-top: 5px; /* Adds 5px top padding */
344+ padding-right: 5px; /* Adds 5px right padding */
345+ padding-bottom: 5px; /* Adds 5px bottom padding */
346+ padding-left: 5px; /* Adds 5px left padding */
347+ border-top-left-radius: 8px; /* Rounded top-left corner */
348+ border-top-right-radius: 8px; /* Rounded top-right corner */
349+ border-bottom-left-radius: 0px; /* No rounding on bottom-left */
350+ border-bottom-right-radius: 0px; /* No rounding on bottom-right */
345351 }
346352
347353 QTabBar::tab:selected {
@@ -369,6 +375,7 @@ class MacAttack(QMainWindow):
369375 self .main_layout .setSpacing (0 )
370376
371377 # Create the tabs (Top-level tabs)
378+ self .main_layout .addSpacing (8 ) # Adds space
372379 self .tabs = QTabWidget (self ) # This is for the "Mac Attack" and "Mac VideoPlayer" tabs
373380 self .main_layout .addWidget (self .tabs )
374381
@@ -385,6 +392,7 @@ class MacAttack(QMainWindow):
385392 self .update_mac_label_signal .connect (self .update_mac_label )
386393 self .update_output_text_signal .connect (self .update_output_text )
387394 self .update_error_text_signal .connect (self .update_error_text )
395+ self .tabs .currentChanged .connect (self .on_tab_change )
388396
389397 def update_mac_label (self , text ):
390398 """Update the MAC address label in the main thread."""
@@ -435,6 +443,30 @@ class MacAttack(QMainWindow):
435443 combined_layout .addWidget (self .start_button )
436444 combined_layout .addWidget (self .stop_button )
437445
446+ self .start_button .setDisabled (False )
447+ self .stop_button .setDisabled (True )
448+
449+
450+ # Set a stylesheet to make the background grey when disabled
451+ self .stop_button .setStyleSheet ("""
452+ QPushButton:disabled {
453+ background-color: grey;
454+ }
455+ QPushButton:enabled {
456+ background-color: red;
457+ }
458+ """ )
459+ self .start_button .setStyleSheet ("""
460+ QPushButton:disabled {
461+ background-color: grey;
462+ }
463+ QPushButton:enabled {
464+ background-color: green;
465+
466+ }
467+ """ )
468+
469+
438470 # Add spacer to the right of the Stop button
439471 right_spacer = QSpacerItem (10 , 0 , QSizePolicy .Fixed , QSizePolicy .Minimum )
440472 combined_layout .addItem (right_spacer )
@@ -469,7 +501,7 @@ class MacAttack(QMainWindow):
469501 border-right: 12px solid #2E2E2E;
470502 border-bottom: 0px;
471503 """ )
472- self .error_text .setPlainText ("Error LOG:\n It 's normal for a few errors to appear down here.\n when speed is set high \n If errors are getting spammed, lower the speed." )
504+ self .error_text .setHtml ("Error LOG:<br>It 's normal for a few errors to appear down here.<br>If <b> \" Empty response \" </b> errors are getting spammed, lower the speed." )
473505 self .error_text .setReadOnly (True )
474506 layout .addWidget (self .error_text )
475507 layout .addSpacing (15 ) # Adds space
@@ -500,6 +532,7 @@ class MacAttack(QMainWindow):
500532 self .hostname_layout = QHBoxLayout () # Create a horizontal layout
501533 self .hostname_layout .setContentsMargins (0 , 0 , 0 , 0 )
502534 self .hostname_layout .setSpacing (0 )
535+ self .left_layout .addSpacing (8 ) # Adds space
503536 self .hostname_label = QLabel ("Host:" )
504537 self .hostname_layout .addWidget (self .hostname_label )
505538 self .hostname_input = QLineEdit ()
@@ -510,20 +543,24 @@ class MacAttack(QMainWindow):
510543 self .mac_layout = QHBoxLayout ()
511544 self .mac_layout .setContentsMargins (0 , 0 , 0 , 0 )
512545 self .mac_layout .setSpacing (0 )
546+ self .left_layout .addSpacing (8 ) # Adds space
513547 self .mac_label = QLabel ("MAC:" )
514548 self .mac_layout .addWidget (self .mac_label )
515549 self .mac_input = QLineEdit ()
516550 self .mac_layout .addWidget (self .mac_input )
517551 self .left_layout .addLayout (self .mac_layout )
518-
552+
553+ self .left_layout .addSpacing (8 ) # Adds space
519554 self .get_playlist_button = QPushButton ("Get Playlist" )
520555 self .left_layout .addWidget (self .get_playlist_button )
521556 self .get_playlist_button .clicked .connect (self .get_playlist )
522-
557+ self . left_layout . addSpacing ( 8 ) # Adds space
523558 # Create a QTabWidget (for "Live", "Movies", "Series")
524559 self .tab_widget = QTabWidget ()
525560 self .left_layout .addWidget (self .tab_widget )
526-
561+ self .get_playlist_button .setFixedWidth (120 )
562+ self .left_layout .setAlignment (self .get_playlist_button , Qt .AlignCenter )
563+
527564 # Dictionary to hold tab data
528565 self .tab_data = {}
529566
@@ -583,9 +620,6 @@ class MacAttack(QMainWindow):
583620 self .video_frame = QWidget (self ) # Changed from QFrame to QWidget for direct size management
584621 self .video_frame .setStyleSheet ("background-color: black;" ) # Ensure black background for video area
585622
586- # VLC dynamic width
587- new_width = self .width () - 360
588- self .video_frame .setMinimumWidth (new_width )
589623
590624 main_layout .addWidget (self .video_frame )
591625
@@ -596,8 +630,13 @@ class MacAttack(QMainWindow):
596630 elif sys .platform == "darwin" : # for MacOS
597631 self .videoPlayer .set_nsobject (int (self .video_frame .winId ()))
598632
599- self .videoPlayer .set_media (self .instance .media_new ('https://iptv.evilvir.us/skull4K.mp4' )) # Load skull
600- self .videoPlayer .play () # Start playing the video
633+
634+ # Determine the correct path for the video
635+ if getattr (sys , 'frozen' , False ): # Check if running as a bundled executable
636+ video_path = os .path .join (sys ._MEIPASS , 'video' , 'skull.mp4' )
637+ else :
638+ video_path = os .path .join ('video' , 'skull.mp4' ) # For normal Python execution
639+ self .videoPlayer .set_media (self .instance .media_new (video_path )) # Load skull
601640
602641 self .videoPlayer .video_set_mouse_input (False )
603642 self .videoPlayer .video_set_key_input (False )
@@ -607,7 +646,7 @@ class MacAttack(QMainWindow):
607646 self .progress_animation .setDuration (1000 ) # Duration of the animation (in milliseconds)
608647 self .progress_animation .setEasingCurve (QEasingCurve .Linear ) # Smooth progress change
609648
610- def save_settings (self ):
649+ def SaveTheDay (self ):
611650 """Save user settings, including window geometry, to the configuration file."""
612651 import os
613652 import configparser
@@ -683,8 +722,8 @@ class MacAttack(QMainWindow):
683722 def TestDrive (self ):
684723 # The "Let's hit the gas and see what happens" function
685724 self .running = True
686- # self.start_button.setDisabled(True)
687- # self.start_button .setDisabled(False)
725+ self .start_button .setDisabled (True )
726+ self .stop_button .setDisabled (False )
688727
689728 self .iptv_link = self .iptv_link_entry .text ()
690729 self .parsed_url = urlparse (self .iptv_link )
@@ -693,26 +732,24 @@ class MacAttack(QMainWindow):
693732 self .base_url = f"http://{ self .host } :{ self .port } "
694733
695734 num_tests = self .concurrent_tests .value ()
696- # Limit to a maximum of 10 concurrent tests, 'cause we’re not running a circus here.
735+ # Limit to a maximum of 15 concurrent tests, 'cause we’re not running a circus here.
697736 if num_tests > 15 :
698737 num_tests = 15
699738
700- # Save current settings to a file so they don’t get lost forever
701- self .SaveTheDay ()
702-
703739 # Start threads to test MACs
704740 for _ in range (num_tests ):
705741 thread = threading .Thread (target = self .BigMacAttack )
706742 thread .daemon = True
707743 thread .start ()
708744 self .threads .append (thread )
709- self .save_settings ()
745+ self .SaveTheDay ()
710746
711747 def RandomMacGenerator (self , prefix = "00:1A:79:" ):
712748 # Create random MACs. Purely for mischief. Don't tell anyone.
713749 return f"{ prefix } { random .randint (0 , 255 ):02X} :{ random .randint (0 , 255 ):02X} :{ random .randint (0 , 255 ):02X} "
714750
715751 def BigMacAttack (self ):
752+ self .error_count = 0
716753 # BigMacAttack: Two all-beef patties, special sauce, lettuce, cheese, pickles, onions, on a sesame seed bun.
717754 while self .running : # Loop will continue as long as self.running is True
718755 mac = self .RandomMacGenerator () # Generate a random MAC
@@ -778,31 +815,20 @@ class MacAttack(QMainWindow):
778815 # Catch all relevant exceptions and ensure the loop continues
779816 except (json .decoder .JSONDecodeError , requests .exceptions .RequestException , TypeError ) as e :
780817 if "Expecting value: line 1 column 1 (char 0)" in str (e ):
781- self .update_error_text_signal .emit (
782- f"Error for MAC: { mac } : { str (e ).replace ('Expecting value: line 1 column 1 (char 0)' , 'Empty response' )} "
783- )
818+ if self .error_count >= 6 :
819+ self .update_error_text_signal .emit (
820+ f"Error for MAC: { mac } : { str (e ).replace ('Expecting value: line 1 column 1 (char 0)' , 'Empty response' )} "
821+ )
822+ self .error_count += 1 # Increment the error count
784823 else :
785- self .update_error_text_signal .emit (f"Error for MAC { mac } : { str (e )} " )
824+ if self .error_count >= 6 : #skipping emitting the first 6 errors. Because, laziness.
825+ self .update_error_text_signal .emit (f"Error for MAC { mac } : { str (e )} " )
826+ self .error_count += 1 # Increment the error count
786827
787- def SaveTheDay (self ):
788- # Saving the day by storing our preferences so we can be lazy
789- settings = {
790- 'url' : self .iptv_link_entry .text (),
791- 'speed' : self .concurrent_tests .value ()
792- }
793-
794- # Ensuring the sacred settings folder is there
795- user_profile = os .environ ['USERPROFILE' ]
796- settings_dir = os .path .join (user_profile , "Evilvir.us" )
797- os .makedirs (settings_dir , exist_ok = True )
798- settings_file = os .path .join (settings_dir , "iptv_checker_settings.json" )
799-
800- with open (settings_file , 'w' ) as file :
801- json .dump (settings , file )
802828
803829 def OutputMastermind (self ):
804830 # Fancy file-naming because why not complicate things?
805- current_time = datetime .now ().strftime ("%Y% m%d_%H%M%S" )
831+ current_time = datetime .now ().strftime ("%m%d_%H%M%S" )
806832 sanitized_url = self .base_url .replace ("http://" , "" ).replace ("https://" , "" ).replace ("/" , "_" ).replace (":" , "-" )
807833 filename = f"{ sanitized_url } _{ current_time } .txt"
808834 return filename
@@ -812,8 +838,8 @@ class MacAttack(QMainWindow):
812838 # GiveUp: Like throwing in the towel, but with less dignity. But hey, we tried, right?
813839 print ("GiveUp method has been called. We tried, but it's over." ) # Console printout
814840 self .running = False
815- # self.start_button.setDisabled(False)
816- # self.start_button .setDisabled(True)
841+ self .start_button .setDisabled (False )
842+ self .stop_button .setDisabled (True )
817843
818844 if hasattr (self , 'output_file' ) and self .output_file :
819845 self .output_file .close ()
@@ -840,7 +866,7 @@ class MacAttack(QMainWindow):
840866 mac_address = self .mac_input .text ()
841867
842868 if not hostname_input or not mac_address :
843- self .error_label .setText ("ERROR: Unable to connect to the host " )
869+ self .error_label .setText ("ERROR: Missing input. " )
844870 self .error_label .show ()
845871 logging .warning (
846872 "User attempted to get playlist without entering all required fields."
@@ -1449,17 +1475,22 @@ class MacAttack(QMainWindow):
14491475 self .error_label .hide ()
14501476 self .videoPlayer .play () # Play the video
14511477 self .tabs .tabBar ().setVisible (True )
1452-
1478+
1479+ def on_tab_change (self , index ):
1480+ """Method to handle video playback when the Mac VideoPlayer tab is selected"""
1481+ if self .tabs .tabText (index ) == "Mac VideoPlayer" :
1482+ self .videoPlayer .play () # Play the video when Mac VideoPlayer tab is selected
1483+ else :
1484+ self .videoPlayer .pause () # Pause the video when the tab is not selected
14531485 def resizeEvent (self , event ):
1454- # Calculate new width with a minimum constraint to prevent zero or negative sizes
1455- new_width = max (self .width () - 290 , 300 ) # keeping the playlist side @ 360, and make the window no smaller than 370
1456- # Set the new minimum width for the video frame
1486+ # VLC dynamic width
1487+ new_width = self .width () - 250
14571488 self .video_frame .setMinimumWidth (new_width )
14581489
14591490
14601491 def closeEvent (self , event ):
14611492 # Save settings when the window is about to close
1462- self .save_settings ()
1493+ self .SaveTheDay ()
14631494
14641495 # Accept the close event
14651496 event .accept ()
0 commit comments