Compare commits

..

1 Commits

Author SHA1 Message Date
422aefd3e0 add movies and update the script
Signed-off-by: Bogomil Vasilev <smirky@smirky.net>
2026-02-13 14:00:30 +02:00
8 changed files with 140 additions and 75 deletions

View File

@@ -36,9 +36,8 @@ movie=$(echo $movie|xargs)
printf "Playing: %s\n" "$movie" printf "Playing: %s\n" "$movie"
#smplayer -fullscreen "$movie" 1>/dev/null #smplayer -fullscreen "$movie" 1>/dev/null
mpv --fs --volume=100 "$movie" # 1>/dev/null #mpv --fs --volume=100 "$movie" # 1>/dev/null
#vlc "$movie" 1>/dev/null vlc "$movie" 1>/dev/null
#kodi "$movie" 1>/dev/null
printf "Unmounting: %s\n" "$mountpoint" printf "Unmounting: %s\n" "$mountpoint"
fusermount -u "$mountpoint" fusermount -u "$mountpoint"
printf "Removing dir: %s\n" "$mountpoint" printf "Removing dir: %s\n" "$mountpoint"

View File

@@ -56,7 +56,7 @@ class MyHTMLParser(HTMLParser):
self.a_href = False self.a_href = False
def handle_data(self, data): def handle_data(self, data):
if self.tbody and self.div and self.a_href: if self.tbody and self.div and self.a_href:
print(' \t| '.join(self.timestamps) + '\t| ' + self.get_category() + '| ' + data.strip()) print('\t| '.join(self.timestamps) + '\t| ' + self.get_category() + '| ' + data.strip())
self.a_href = False self.a_href = False
self.timestamps = [] self.timestamps = []
elif self.timestamp: elif self.timestamp:

19
checkpatch_project.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
#checkpatch --no-tree -f
checkpatch="/usr/lib/modules/$(uname -r)/build/scripts/checkpatch.pl"
if [ -z "$1" ]; then
project_dir="$PWD"
elif [ -d "$1" ]; then
project_dir="$1"
else
source_file="$1"
fi
if [ -z "$project_dir" ]; then
"${checkpatch}" --no-tree -f "${source_file}"
else
find "${project_dir}" -regex '.*\.\(c\|h\)' -exec "${checkpatch}" --no-tree -f '{}' +
fi

21
ffmpeg/ultrafast_x264_mp4.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
# Capture screen script
prefix=`date +"%G.%m.%d_%H.%M.%S"`
ffmpeg -y -f x11grab \
-video_size 1920x1080 \
-r 30 \
-i $DISPLAY \
-f pulse \
-ac 2 \
-i default \
-c:v libx264 \
-crf 0 \
-pix_fmt yuv420p \
-preset ultrafast \
-threads 0 \
$prefix.mp4
# -f alsa \
# -i hw:2,1 \
#-an \

View File

@@ -55,7 +55,6 @@ class MovieList:
border: 1px solid rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.1);
padding: 0.75rem; padding: 0.75rem;
height: 100%; height: 100%;
min-height: 0;
overflow: hidden; overflow: hidden;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -71,16 +70,14 @@ class MovieList:
.dataTables_wrapper { .dataTables_wrapper {
flex: 1; flex: 1;
overflow: auto; overflow: hidden;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-height: 0;
} }
.dataTables_filter { .dataTables_filter {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
text-align: right; text-align: right;
flex-shrink: 0;
} }
.dataTables_filter label { .dataTables_filter label {
@@ -116,19 +113,22 @@ class MovieList:
padding: 0.5rem 0; padding: 0.5rem 0;
color: rgba(255, 255, 255, 0.6); color: rgba(255, 255, 255, 0.6);
font-size: 0.85rem; font-size: 0.85rem;
flex-shrink: 0;
} }
.dataTables_scroll { .dataTables_scroll {
display: none; flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
} }
.dataTables_scrollHead { .dataTables_scrollHead {
display: none; flex-shrink: 0;
} }
.dataTables_scrollBody { .dataTables_scrollBody {
display: none; flex: 1;
overflow-y: auto !important;
} }
.dataTables_scrollBody::-webkit-scrollbar { .dataTables_scrollBody::-webkit-scrollbar {
@@ -144,20 +144,7 @@ class MovieList:
border-radius: 3px; border-radius: 3px;
} }
.dataTables_wrapper::-webkit-scrollbar { table.dataTable.stripe tbody tr.odd,
width: 6px;
}
.dataTables_wrapper::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05);
}
.dataTables_wrapper::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.2);
border-radius: 3px;
}
table.dataTable.stripe tbody tr.odd,
table.dataTable.display tbody tr.odd, table.dataTable.display tbody tr.odd,
table.dataTable tbody tr { table.dataTable tbody tr {
background: transparent !important; background: transparent !important;
@@ -287,23 +274,21 @@ class MovieList:
</style> </style>
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
try { $('#sortable').DataTable({
$('#sortable').DataTable({ "paging": false,
"paging": false, "info": true,
"info": true, "searching": true,
"searching": true, "ordering": true,
"ordering": true, "order": [[0, "asc"]],
"order": [[0, "desc"]], "scrollY": "calc(100vh - 200px)",
"language": { "scrollCollapse": true,
"search": "Search:", "language": {
"info": "Showing _TOTAL_ movies", "search": "Search:",
"infoEmpty": "No movies", "info": "Showing _TOTAL_ movies",
"infoFiltered": "(filtered from _MAX_)" "infoEmpty": "No movies",
} "infoFiltered": "(filtered from _MAX_)"
}); }
} catch(e) { });
console.error("DataTables init error:", e);
}
}); });
</script> </script>
</head> </head>
@@ -390,7 +375,7 @@ class MovieList:
html_title_td = movie['title'] if 'dummy' in movie.keys() else \ html_title_td = movie['title'] if 'dummy' in movie.keys() else \
f'<a href="https://www.imdb.com/title/tt{movie.movieID}" target="_blank">{movie["title"]}</a>' f'<a href="https://www.imdb.com/title/tt{movie.movieID}" target="_blank">{movie["title"]}</a>'
self.html_table[index] = ( self.html_table[index] = (
f'\n <tr>' f'\n <tr>'
f'<td data-label="#">{index + 1}</td>' f'<td data-label="#">{index + 1}</td>'
@@ -413,42 +398,29 @@ class MovieList:
return False return False
self.movie_list = {} self.movie_list = {}
seen_titles = set() # Track unique titles
# Open the movie list & split the columns # Open the movie list & split the columns
with open(self.src, 'r', encoding='utf-8') as fp_handle: with open(self.src, 'r', encoding='utf-8') as fp_handle:
mlist_raw = fp_handle.read() mlist_raw = fp_handle.read()
idx = 0
for raw_line in mlist_raw.splitlines(): for raw_line in mlist_raw.splitlines():
# In case the line is empty # In case the line is empty
if not raw_line: if not raw_line:
continue continue
title = raw_line[0:next((i for i, ch in enumerate(raw_line) if ch in {'<', '('}), None) - 1]
# Skip if we've already seen this title
if title in seen_titles:
continue
seen_titles.add(title)
self.movie_list.update({ self.movie_list.update({
idx: { len(self.movie_list): {
'title': title, 'title': raw_line[0:next((i for i, ch in enumerate(raw_line) if ch in {'<', '('}), None) - 1],
'kind': raw_line[raw_line.find('<')+1:raw_line.rfind('>')+1].strip('<>') or 'movie', 'kind': raw_line[raw_line.find('<')+1:raw_line.rfind('>')+1].strip('<>') or 'movie',
'year': raw_line[raw_line.find('(')+1:raw_line.find(')')], 'year': raw_line[raw_line.find('(')+1:raw_line.find(')')],
'status': raw_line[raw_line.find('[')+1:raw_line.find(']')], 'status': raw_line[raw_line.find('[')+1:raw_line.find(']')],
} }
}) })
idx += 1
self.html_table = [None] * len(self.movie_list) self.html_table = [None] * len(self.movie_list)
# Progress bar # Progress bar
pbar = progressbar.ProgressBar(max_value=len(self.movie_list)) pbar = progressbar.ProgressBar(max_value=len(self.movie_list))
for idx, movie in self.movie_list.items(): for idx, movie in self.movie_list.items():
# More precise matching - look for the hidden <p> tag with exact title # More precise matching - look for the hidden <p> tag with exact title
match = [html_row for html_row in self.prev_html match = [html_row for html_row in self.prev_html
if f'<p hidden>{movie["title"]}</p>' in html_row if f'<p hidden>{movie["title"]}</p>' in html_row
and 'N/A' not in html_row] and 'N/A' not in html_row]
if match: if match:
# Update the index and status from the cached row # Update the index and status from the cached row
@@ -478,7 +450,15 @@ class MovieList:
time.sleep(2) time.sleep(2)
self.delete_finished_threads() self.delete_finished_threads()
# Don't append to self.html here - we'll do it in write() self.html += ''.join(self.html_table)
# Deduplicate entries before writing
num_entries = self.deduplicate_html()
print(f"\nDeduplicated to {num_entries} unique entries")
self.html = self.html.split('</tbody>')[0] # Remove everything after tbody if it exists
self.html += ''.join(self.html_table)
return True return True
def delete_finished_threads(self): def delete_finished_threads(self):
@@ -499,42 +479,37 @@ class MovieList:
""" Write the HTML list to index.html """ """ Write the HTML list to index.html """
out_path = dst if dst else self.dst out_path = dst if dst else self.dst
timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime()) timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime())
self.html += f'''
# Build the final HTML - don't append, rebuild from scratch
final_html = self.html.split('<tbody>')[0] + '<tbody>'
final_html += ''.join([row for row in self.html_table if row is not None])
final_html += f'''
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="timestamp">Generated {timestamp} UTC</div> <div class="timestamp">Generated {timestamp} UTC</div>
</body> </body>
</html>''' </html>'''
with open(out_path, 'wb') as fp_handle: with open(out_path, 'wb') as fp_handle:
fp_handle.write(final_html.encode('utf8')) fp_handle.write(self.html.encode('utf8'))
def read_prev_output(self): def read_prev_output(self):
""" Import a previous HTML table """ """ Import a previous HTML table """
if self.dst.exists(): if self.dst.exists():
with open(self.dst, 'rb') as fp_handle: with open(self.dst, 'rb') as fp_handle:
self.prev_html = fp_handle.read().decode('utf8').split('\n') self.prev_html = fp_handle.read().decode('utf8').split('\n')
def deduplicate_html(self): def deduplicate_html(self):
""" Remove duplicate entries from html_table based on movie titles """ """ Remove duplicate entries from html_table based on movie titles """
seen_titles = set() seen_titles = set()
deduplicated = [] deduplicated = []
for idx, row in enumerate(self.html_table): for idx, row in enumerate(self.html_table):
if row is None: if row is None:
continue continue
# Extract the hidden title from the row # Extract the hidden title from the row
if '<p hidden>' in row and '</p>' in row: if '<p hidden>' in row and '</p>' in row:
start = row.find('<p hidden>') + 10 start = row.find('<p hidden>') + 10
end = row.find('</p>', start) end = row.find('</p>', start)
title = row[start:end] title = row[start:end]
if title not in seen_titles: if title not in seen_titles:
seen_titles.add(title) seen_titles.add(title)
deduplicated.append(row) deduplicated.append(row)
@@ -544,7 +519,7 @@ class MovieList:
else: else:
# If we can't find the hidden title, keep the row anyway # If we can't find the hidden title, keep the row anyway
deduplicated.append(row) deduplicated.append(row)
# Update html_table with deduplicated content # Update html_table with deduplicated content
self.html_table = deduplicated self.html_table = deduplicated
return len(self.html_table) return len(self.html_table)

View File

@@ -466,4 +466,3 @@ Poor Things (2023) [*]
The French Dispatch (2021) [DONE] The French Dispatch (2021) [DONE]
Sentimental Value (2025) [DONE] Sentimental Value (2025) [DONE]
28 Years Later: The Bone Temple (2026) [*] 28 Years Later: The Bone Temple (2026) [*]
Youth (2015) [DONE]

View File

@@ -0,0 +1,11 @@
(function() {
var si = document.querySelector(".scroll-indicator");
var onscroll = function() {
var max = document.body.scrollHeight - window.innerHeight;
si.style.display = "block";
si.style.width = (window.pageYOffset / max * 100) + "%";
};
window.onscroll = onscroll;
onscroll();
})();

41
movie_list/style.css Normal file
View File

@@ -0,0 +1,41 @@
.scroll-indicator {
display: none;
position: fixed;
top: 0;
left: 0;
width: 50%;
height: 10px;
background: #C33;
}
th {
background-color: #4CAF50;
cursor:pointer;
text-align: center;
}
th, td {
padding: 1px;
border-bottom: 1px solid #ddd;
font-family: arial, sans-serif;
font-size: 12px;
}
body {
background-color: #3D3635;
font-family: arial, sans-serif;
color: white;
font-size: 12px;
}
td {
color: #ffffff;
background-color: #3D3635;
}
a:link, a:visited {
background-color: #3D3635;
color: white;
text-decoration: none;
display: inline-block;
}